1

我试图了解 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 设备分区大小) / 记录大小,其中记录大小为 4096。

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

请帮助了解此功能的功能。

1) 无法理解 0xffffffff、0x40000000、0xc0000000 等硬编码。

2)所有 if/else 条件都分配了相同的值。为什么只检查那些值?

3) 无法获得有关 MTD_HEADER 格式的足够信息。

mtdoops.c 的完整源代码可以在下面找到。

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

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

4

1 回答 1

1

该函数搜索由计数器 count[0] 生成的最后一条记录,该记录被解释为一种序列号。因为这个计数器可以在达到 0xffffffff 时回绕,所以 maxcount 应该逐渐跟随 count[0] ,而不是所有序列号的最大值。这就是为什么如果计数器 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

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

于 2016-05-12T12:09:55.673 回答