首页 > 解决方案 > 内核模块检查文件是否存在

问题描述

我正在对内核模块nandsim进行一些扩展,并且在打开文件之前找不到正确的方法来测试文件是否存在。我已经阅读了这个问题,它涵盖了基本的打开/读/写操作是如何进行的,但是我无法确定正常的 open(2) 标志是否以及如何应用在这里。

我很清楚在内核模块中读写文件是不好的做法;这段代码已经存在于内核中并且已经在读写文件了。我只是想对已经存在的内容进行一些调整。目前,当模块加载并指示使用缓存文件(调用 modprobe 时指定为字符串路径)时,它使用 filp_open() 打开文件,如果文件不存在则创建:

/* in nandsim.c */
...
module_param(cache_file,   charp, 0400);
...
MODULE_PARM_DESC(cache_file,    "File to use to cache nand pages instead of memory");
...
struct file *cfile;
cfile = filp_open(cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0600);

你可能会问,“你真的想在这里做什么?” 我想为缓存文件包含一个标头,以便在需要重置系统时可以重用它。通过在此文件的开头包含有关 nand 页几何和页数的信息,我可以更轻松地模拟许多错误情况,否则这些情况在 nandsim 框架中是不可能的。如果我可以在文件操作期间关闭 nandsim 模块,或者修改支持文件以模拟真实世界的故障模式,我可以重新创建这些错误条件的净效应。这将允许我使用 nandsim 使模拟设备重新联机,并评估容错文件系统的工作情况。

我的想法是按如下方式对其进行修改,以便尝试强制创建已经存在的文件时会失败:

struct file *cfile;
cfile = filp_open(cache_file, O_CREAT | O_EXCL | O_RDWR | O_LARGEFILE, 0600);
if(IS_ERR(cfile)){
    printk(KERN_INFO "File didn't exist: %ld", PTR_ERR(cfile));
    /* Do header setup for first-time run of NAND simulation */
}
else{
    /* Read header and validate against system parameters.  Recover operations */
}

我看到的是一个错误,但这不是我所期望的。它报告 errno 14, EFAULT(错误地址)而不是 errno 17 EEXIST(文件存在)。我不想用这个来运行,因为我希望它尽可能地惯用和正确。

还有其他方法我应该这样做吗?

我是否需要以某种方式指定文件路径在用户地址空间中?如果是这样,为什么代码中的情况不是这样?

O_RDWR编辑:通过尝试仅使用and打开,我能够得到一个可靠的错误O_LARGEFILE,这导致ENOENT. 仍然不清楚为什么我最初的方法是不正确的,也不清楚实现我的目标的最佳方法是什么。也就是说,如果更有经验的人可以对此发表评论,我可以将其添加为解决方案。

标签: clinux-kernellinux-device-driverkernel-module

解决方案


实际上,filp_open需要一个位于内核地址空间中的文件路径。证明是使用getname_kernel. 您可以通过以下方式为您的用例模仿这一点:

struct filename *name = getname(cache_file);
struct file *cfile = ERR_CAST(name);

if (!IS_ERR(name)) {
        cfile = file_open_name(name, O_CREAT | O_EXCL | O_RDWR | O_LARGEFILE, 0600);
        if (IS_ERR(cfile))
                return PTR_ERR(cfile);

        putname(name);
}

请注意,它getname需要一个用户空间地址,并且等效于getname_kernel.


推荐阅读