c - mtdoops.c 中的 find_next_position() 函数

标签 c linux kernel panic

我正在尝试了解 mtdoops.c 文件的功能。

MTD 设备分区被看作是一个用于存储内核 oops 消息的循环缓冲区。

在写入任何新的内核 oops 消息之前,我们使用以下函数检查 mtd 分区中的空闲页面。

下面是find_next_position函数的函数代码。

static void find_next_position(struct mtdoops_context *cxt)
{
    struct mtd_info *mtd = cxt->mtd;
    int ret, page, maxpos = 0;
    u32 count[2], maxcount = 0xffffffff;
    size_t retlen;

    for (page = 0; page < cxt->oops_pages; page++) {
            if (mtd_block_isbad(mtd, page * record_size))
                    continue;
            /* Assume the page is used */
            mark_page_used(cxt, page);
            ret = mtd_read(mtd, page * record_size, MTDOOPS_HEADER_SIZE,
                           &retlen, (u_char *)&count[0]);
            if (retlen != MTDOOPS_HEADER_SIZE ||
                            (ret < 0 && !mtd_is_bitflip(ret))) {
                    printk(KERN_ERR "mtdoops: read failure at %ld (%td of %d read), err %d\n",
                           page * record_size, retlen,
                           MTDOOPS_HEADER_SIZE, ret);
                    continue;
            }

            if (count[0] == 0xffffffff && count[1] == 0xffffffff)
                    mark_page_unused(cxt, page);
            if (count[0] == 0xffffffff || count[1] != MTDOOPS_KERNMSG_MAGIC)
                    continue;
            if (maxcount == 0xffffffff) {
                    maxcount = count[0];
                    maxpos = page;
            } else if (count[0] < 0x40000000 && maxcount > 0xc0000000) {
                    maxcount = count[0];
                    maxpos = page;
            } else if (count[0] > maxcount && count[0] < 0xc0000000) {
                    maxcount = count[0];
                    maxpos = page;
            } else if (count[0] > maxcount && count[0] > 0xc0000000
                                    && maxcount > 0x80000000) {
                    maxcount = count[0];
                    maxpos = page;
            }
    }
    if (maxcount == 0xffffffff) {
            cxt->nextpage = cxt->oops_pages - 1;
            cxt->nextcount = 0;
    }
    else {
            cxt->nextpage = maxpos;
            cxt->nextcount = maxcount;
    }

    mtdoops_inc_counter(cxt);

这里我们循环遍历 mtd 分区中的所有可用页面。

cxt->oops_pages = (mtd device partition size) / record size where record size is 4096.

从代码中我们可以了解到,MTD头信息和魔法指针信息存储在每个页面的前16位。

Please help to understand the functionality of this function.

1) Could not understand the hardcodings like 0xffffffff, 0x40000000 , 0xc0000000.

2) All the if/else condition is assigning same values . why only those values are being checked ?

3) could not get sufficient information about MTD_HEADER format.

完整的 mtdoops.c 源代码如下。

http://lxr.free-electrons.com/source/drivers/mtd/mtdoops.c

如果有任何与 mtdoops 相关的文档链接可以提供很大帮助。提前致谢。

最佳答案

该函数搜索计数器 count[0] 生成的最后一条记录,它被解释为一种序列号。由于此计数器在达到 0xffffffff 时可以回绕,因此 maxcount 应该逐步跟随 count[0],而不是成为所有序列号的最大值。这就是为什么如果 counter count[0] = 2,在 maxcount 已经达到之后满足,比如说 (0xffffffff - 2),maxcount 应该变成 2(第二个“else-if”)

} else if (count[0] < 0x40000000 && maxcount > 0xc0000000) {

所有这些 ifdef-s 都用于处理计数器的环绕。 我同意这段代码写得不是很好。最后两个“if else-s”,恕我直言,可以一次完成

} else if (count[0] > maxcount) {

我无法想象什么时候的情况

else if (count[0] > maxcount && count[0] > 0xc0000000
    && maxcount < 0x80000000) {

可以满足。

值 0xffffffff、0x40000000、0xc0000000 只是方便使用的值。同样成功,可以使用 0xc0000020 代替 0xc0000000。

我可以在这个函数中看到另一个奇怪的东西,比如

if (mtd_block_isbad(mtd, page * record_size))
    continue

仍然遍历页面而不是跳过整个坏 block 。

关于c - mtdoops.c 中的 find_next_position() 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33450420/

相关文章:

c++ - 在类内部分配函数指针

c - 为什么我会得到 Seg-Fa

c - c 中的链接结构

c - 关于系统调用的性能报告

c++ - 使用 glibc 和 libstdc++ 静态链接

linux - 如何将 TESSERACT PATH 添加到我的环境中?

windows - 为什么 Windows 在内核中处理滚动条?

c++ - 父进程没有捕获他所有的子进程

python从mysql获取用户并在linux上创建它们

kernel - 中断在硬件虚拟化中是如何工作的?