简体   繁体   English

`do_new_mount_fc()`如何挂载像ext4这样的真实文件系统?

[英]How does `do_new_mount_fc()` mount real file systems like ext4?

In relatively old Linux kernel source codes, the do_new_mount() will call vfs_kern_mount() , which will finally do mount_fs() .在相对较旧的 Linux kernel 源代码中, do_new_mount()将调用vfs_kern_mount() ,最终将执行mount_fs() And this function will call the real file system's function like below而这个 function 将调用真实文件系统的 function 如下所示


struct dentry *
mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
{
    struct dentry *root;
    struct super_block *sb;
......
    root = type->mount(type, flags, name, data);
......
    sb = root->d_sb;
......
}

But in relatively new Linux kernel source code, the do_new_mount() will call do_new_mount_fc() instead, and I can not find how this function call the real file system's mount function like above. But in relatively new Linux kernel source code, the do_new_mount() will call do_new_mount_fc() instead, and I can not find how this function call the real file system's mount function like above.

Can you tell me how it works now?你能告诉我它现在是如何工作的吗?

You don't find the "usual" function calls because of the recent transition to the new Filesystem Mount API through "filesystem context".由于最近通过“文件系统上下文”过渡到新的文件系统挂载 API ,因此您找不到“通常的” function 调用。 You can find more info in the relevant (quite massive) patchwork .您可以在相关(相当庞大的)拼凑中找到更多信息。

I'm not going to explain the whole thing as the kernel documentation that I linked above should already give a pretty good explanation (and I also am no Linux FS internals expert).我不打算解释整个事情,因为我在上面链接的 kernel 文档应该已经给出了很好的解释(而且我也不是 Linux FS 内部专家)。

The "filesystem context" is basically a structure containing useful information that is passed around and updated incrementally as needed. “文件系统上下文”基本上是一个包含有用信息的结构,这些信息可以根据需要进行传递和增量更新。 So what happens now is that thevfs_get_tree() function is responsible for creating the mountable root of the filesystem, and saving it in the fs_context structure that is then passed to do_new_mount_fc() and used to do the actual mount.所以现在发生的是vfs_get_tree() function 负责创建文件系统的可挂载根,并将其保存在fs_context结构中,然后传递给do_new_mount_fc()并用于执行实际挂载。

(*) int vfs_get_tree(struct fs_context *fc);

     Get or create the mountable root and superblock, using the parameters in
     the filesystem context to select/configure the superblock.  This invokes
     the ->get_tree() method.

So now in do_new_mount() you see that function being called right before do_new_mount_fc() :所以现在在do_new_mount()你看到 function 在do_new_mount_fc()之前被调用:

    fc = fs_context_for_mount(type, sb_flags);
    put_filesystem(type);
    if (IS_ERR(fc))
        return PTR_ERR(fc);

    if (subtype)
        err = vfs_parse_fs_string(fc, "subtype",
                      subtype, strlen(subtype));
    if (!err && name)
        err = vfs_parse_fs_string(fc, "source", name, strlen(name));
    if (!err)
        err = parse_monolithic_mount_data(fc, data);
    if (!err && !mount_capable(fc))
        err = -EPERM;
    if (!err)
        err = vfs_get_tree(fc); // <<<<<<<<<<<<<<<<<<<<<<< HERE
    if (!err)
        err = do_new_mount_fc(fc, path, mnt_flags);

    put_fs_context(fc);
    return err;
}

The vfs_get_tree() function calls fc->ops->get_tree() which is the method responsible for creating root (if it doesn't already exist) and assigning it to fc->root . vfs_get_tree() function 调用fc->ops->get_tree() ,这是负责创建root (如果它不存在)并将其分配给fc->root的方法。

    error = fc->ops->get_tree(fc); // Here fc->root gets assigned.
    if (error < 0)
        return error;

The transition to this new API is still not complete for all filesystems.对于所有文件系统,向这个新的 API 的过渡仍未完成。 For the filesystems that still use the old API (for example ext4), the fs_context_for_mount() function (called at the beginning in do_new_mount() ) creates the filesystem context through alloc_fs_context() , which checks whether or not the filesystem supports the new API, and if not it uses a default legacy version of the filesystem context operations (in fact, you can also see the comment in this last link which says "TODO: Make all filesystems support this unconditionally" ). For the filesystems that still use the old API (for example ext4), the fs_context_for_mount() function (called at the beginning in do_new_mount() ) creates the filesystem context through alloc_fs_context() , which checks whether or not the filesystem supports the new API ,如果不是,它使用文件系统上下文操作的默认旧版本(事实上,您还可以在最后一个链接中看到注释“TODO: Make all filesystems support this unconditionally” )。

For get_tree() , the legacy version is legacy_get_tree() , which indeed does exacly what you would expect calling fc->fs_type->mount(...) .对于get_tree() ,旧版本是legacy_get_tree() ,它确实完全符合您调用fc->fs_type->mount(...)的预期。

/*
 * Get a mountable root with the legacy mount command.
 */
static int legacy_get_tree(struct fs_context *fc)
{
    struct legacy_fs_context *ctx = fc->fs_private;
    struct super_block *sb;
    struct dentry *root;

    root = fc->fs_type->mount(fc->fs_type, fc->sb_flags,
                      fc->source, ctx->legacy_data);
    if (IS_ERR(root))
        return PTR_ERR(root);

    sb = root->d_sb;
    BUG_ON(!sb);

    fc->root = root;
    return 0;
}

Sooner or later, all filesystems will be updated to use the new API with filesystem context, those legacy_* functions will be removed completely and we will see a init_fs_context method in the ext4 file_system_type .迟早,所有文件系统都将更新为使用带有文件系统上下文的新 API,这些legacy_*函数将被完全删除,我们将在ext4 file_system_type中看到一个init_fs_context方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM