当注册新的文件系统时,会调用register_filesystem函数,这个函数会检查是否已经存在相同的名字,如果不存在则将该文件系统挂到全局的filesystem链表上

  1. /**
  2. * register_filesystem - register a new filesystem
  3. * @fs: the file system structure
  4. *
  5. * Adds the file system passed to the list of file systems the kernel
  6. * is aware of for mount and other syscalls. Returns 0 on success,
  7. * or a negative errno code on an error.
  8. *
  9. * The &struct file_system_type that is passed is linked into the kernel
  10. * structures and must not be freed until the file system has been
  11. * unregistered.
  12. */
  13. int register_filesystem(struct file_system_type * fs)
  14. {
  15. int res = 0;
  16. struct file_system_type ** p;
  17. BUG_ON(strchr(fs->name, '.'));
  18. if (fs->next)
  19. return -EBUSY;
  20. write_lock(&file_systems_lock);
  21. p = find_filesystem(fs->name, strlen(fs->name));
  22. if (*p)
  23. res = -EBUSY;
  24. else
  25. *p = fs;
  26. write_unlock(&file_systems_lock);
  27. return res;
  28. }
  29. EXPORT_SYMBOL(register_filesystem);

fuse 模块初始化

static int __init fuse_init(void)
{
    int res;

    printk(KERN_INFO "fuse init (API version %i.%i)\n",
           FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);

    INIT_LIST_HEAD(&fuse_conn_list);
    res = fuse_fs_init();
    if (res)
        goto err;

    res = fuse_dev_init();
    if (res)
        goto err_fs_cleanup;

    res = fuse_sysfs_init();
    if (res)
        goto err_dev_cleanup;

    res = fuse_ctl_init();
    if (res)
        goto err_sysfs_cleanup;

    sanitize_global_limit(&max_user_bgreq);
    sanitize_global_limit(&max_user_congthresh);

    return 0;

 err_sysfs_cleanup:
    fuse_sysfs_cleanup();
 err_dev_cleanup:
    fuse_dev_cleanup();
 err_fs_cleanup:
    fuse_fs_cleanup();
 err:
    return res;
}

fuse_fs_init 初始化注册fuse文件系统
fuse_sysfs_init 注册到 /sys/fs/fuse/connections sysfs,这是一个kobject

static int fuse_sysfs_init(void)
{
    int err;

    fuse_kobj = kobject_create_and_add("fuse", fs_kobj);
    if (!fuse_kobj) {
        err = -ENOMEM;
        goto out_err;
    }

    err = sysfs_create_mount_point(fuse_kobj, "connections");
    if (err)
        goto out_fuse_unregister;

    return 0;

 out_fuse_unregister:
    kobject_put(fuse_kobj);
 out_err:
    return err;
}

kobject_create_and_add(“fuse”, fs_kobj) 就是将 fuse加到 /sys/fs sysfs文件系统
kobject_put 为回收内存

最后是fuse_ctl_init,注册了fusectl 文件系统

static struct dentry *fuse_mount(struct file_system_type *fs_type,
               int flags, const char *dev_name,
               void *raw_data)
{
    return mount_nodev(fs_type, flags, raw_data, fuse_fill_super);
}

fuse在mount的时候调用的是mount_nodev, 
mount_nodev: mount a filesystem that is not backed by a device

在fuse_mount的时候就会调用 fuse_fill_super 来填充fuse的super_block
fuse_fill_super的过程除了填充superblock,还会初始化fuse_connection, fusedev, 初始化bdi

static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb)
{
    int err;
    char *suffix = "";

    if (sb->s_bdev) {
        suffix = "-fuseblk";
        /*
         * sb->s_bdi points to blkdev's bdi however we want to redirect
         * it to our private bdi...
         */
        bdi_put(sb->s_bdi);
        sb->s_bdi = &noop_backing_dev_info;
    }
    err = super_setup_bdi_name(sb, "%u:%u%s", MAJOR(fc->dev),
                   MINOR(fc->dev), suffix);
    if (err)
        return err;

    sb->s_bdi->ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_SIZE;
    /* fuse does it's own writeback accounting */
    sb->s_bdi->capabilities = BDI_CAP_NO_ACCT_WB | BDI_CAP_STRICTLIMIT;

    /*
     * For a single fuse filesystem use max 1% of dirty +
     * writeback threshold.
     *
     * This gives about 1M of write buffer for memory maps on a
     * machine with 1G and 10% dirty_ratio, which should be more
     * than enough.
     *
     * Privileged users can raise it by writing to
     *
     *    /sys/class/bdi/<bdi>/max_ratio
     */
    bdi_set_max_ratio(sb->s_bdi, 1);

    return 0;
}

初始化root dentry

因为root节点没有 revalidate,所以,这里专门搞了一个root_dentry_operations

const struct dentry_operations fuse_dentry_operations = {
    .d_revalidate    = fuse_dentry_revalidate,
    .d_init        = fuse_dentry_init,
    .d_release    = fuse_dentry_release,
};

const struct dentry_operations fuse_root_dentry_operations = {
    .d_init        = fuse_dentry_init,
    .d_release    = fuse_dentry_release,
};
root = fuse_get_root_inode(sb, d.rootmode);
    sb->s_d_op = &fuse_root_dentry_operations;
    root_dentry = d_make_root(root);
    if (!root_dentry)
        goto err_dev_free;
    /* Root dentry doesn't have .d_revalidate */
    sb->s_d_op = &fuse_dentry_operations;

在创建好root_dentry后,再将s_d_op改为 fuse_dentry_operations

然后初始化init_req
将fc添加到 fuse_ctl connections