sysfs 文件系统的建立

1.sysf文件系统的全局变量

static struct vfsmount *sysfs_mount;
struct super_block * sysfs_sb = NULL;
struct kmem_cache *sysfs_dir_cachep;

2. 文件系统类型:file_system_type

fs/sysfs/symlink.c
static struct file_system_type sysfs_fs_type = 
{
    .name        = "sysfs",
    .get_sb        = sysfs_get_sb,
    .kill_sb    = kill_anon_super,
};

 2.sysfs文件系统初始化:sysfs_init

fs/sysfs/symlink.c


struct kmem_cache *sysfs_dir_cachep;
int
__init sysfs_init(void) { int err = -ENOMEM;
    /*创建一个分配sysfs_dirent的cash, name :sysfs_dir_cache 此cashe在/proc/slabinfo中显示的名字*/ sysfs_dir_cachep
= kmem_cache_create("sysfs_dir_cache", sizeof(struct sysfs_dirent), 0, 0, NULL); if (!sysfs_dir_cachep) goto out; err = sysfs_inode_init(); if (err) goto out_err; err = register_filesystem(&sysfs_fs_type); if (!err) { sysfs_mount = kern_mount(&sysfs_fs_type); if (IS_ERR(sysfs_mount)) { printk(KERN_ERR "sysfs: could not mount!\n"); err = PTR_ERR(sysfs_mount); sysfs_mount = NULL; unregister_filesystem(&sysfs_fs_type); goto out_err; } } else goto out_err; out: return err; out_err: kmem_cache_destroy(sysfs_dir_cachep); sysfs_dir_cachep = NULL; goto out; }

  sysfs_inode_init():主要是初始化BDI(backing device infor )信息

static struct backing_dev_info sysfs_backing_dev_info = {
    .ra_pages    = 0,    /* No readahead */
    .capabilities    = BDI_CAP_NO_ACCT_AND_WRITEBACK,
};
int __init sysfs_inode_init(void)
{
    return bdi_init(&sysfs_backing_dev_info);
}
int bdi_init(struct backing_dev_info *bdi)
{
    int i;
    int err;
    bdi->dev = NULL;
    bdi->min_ratio = 0;
    bdi->max_ratio = 100;
    bdi->max_prop_frac = PROP_FRAC_BASE;
    for (i = 0; i < NR_BDI_STAT_ITEMS; i++) {
        err = percpu_counter_init(&bdi->bdi_stat[i], 0);
        if (err)
            goto err;
    }
    bdi->dirty_exceeded = 0;
    err = prop_local_init_percpu(&bdi->completions);
    if (err) {
err:
        while (i--)
            percpu_counter_destroy(&bdi->bdi_stat[i]);
    }
    return err;
}

  register_filesystem(&sysfs_fs_type);

static struct file_system_type sysfs_fs_type = {
    .name        = "sysfs",
    .get_sb        = sysfs_get_sb,
    .kill_sb    = kill_anon_super,
};
static int sysfs_get_sb(struct file_system_type *fs_type,int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
    return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt);
}

说明:
1.register_filesystem只是把文件系统描述结构,插入系统全局链表中;在该文件系统被挂载(mount)到系统时,调用文件系统结构体的getsb函数,完成对文件系统的超级块分配和初始化;
2.get_sb_single函数创建一个新的super_block,并用sysfs_fill_super填充这个super_block结构,然后使mnt->mnt_sb指向该super_block,mnt->mnt_root指向该超级块的文件系统的根目录的
目录项对象;

 sysfs_mount = kern_mount(&sysfs_fs_type);

#define kern_mount(type) kern_mount_data(type, NULL)
struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
{
    return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
}
struct vfsmount *
vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
{
    struct vfsmount *mnt;
    char *secdata = NULL;
    int error;

    if (!type)return ERR_PTR(-ENODEV);

    error = -ENOMEM;
    mnt = alloc_vfsmnt(name);
    if (!mnt)goto out;
    if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
        secdata = alloc_secdata();
        if (!secdata)
            goto out_mnt;
        error = security_sb_copy_data(data, secdata);
        if (error)
            goto out_free_secdata;
    }
    /*调用文件系统的超级块分配函数*/
    error = type->get_sb(type, flags, name, data, mnt);
    if (error < 0)
        goto out_free_secdata;
    BUG_ON(!mnt->mnt_sb);
    error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata);
    if (error)
         goto out_sb;

    mnt->mnt_mountpoint = mnt->mnt_root; //指向文件系统安装点目录的dentry
    mnt->mnt_parent = mnt;
    up_write(&mnt->mnt_sb->s_umount);//安装文件系统卸载所用的信号量
    free_secdata(secdata);
    return mnt;
out_sb:
    dput(mnt->mnt_root);
    deactivate_locked_super(mnt->mnt_sb);
out_free_secdata:
    free_secdata(secdata);
out_mnt:
    free_vfsmnt(mnt);
out:
    return ERR_PTR(error);
}

sysfs_get_sb

static int sysfs_get_sb(struct file_system_type *fs_type,
    int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
    return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt);
}
int get_sb_single(struct file_system_type *fs_type, int flags, void *data,int (*fill_super)(struct super_block *, void *, int), struct vfsmount *mnt)
{
    struct super_block *s;
    int error;
    s = sget(fs_type, compare_single, set_anon_super, NULL);
    if (IS_ERR(s))
        return PTR_ERR(s);
    if (!s->s_root) {
        s->s_flags = flags;
        error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
        if (error) {
            deactivate_locked_super(s);
            return error;
        }
        s->s_flags |= MS_ACTIVE;
    }
    do_remount_sb(s, flags, data, 0);
    simple_set_mnt(mnt, s);//系统挂载点指向超级块的根目录的dentry和超级块本身
    return 0;
}
void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb)
{
    mnt->mnt_sb = sb;
    mnt->mnt_root = dget(sb->s_root);//指向文件系统根目录的dentry
}

超级块的填充

fs/sysfs/symlink.c line29
static const struct super_operations sysfs_ops = {

    .statfs        = simple_statfs,
    .drop_inode    = generic_delete_inode,
    .delete_inode    = sysfs_delete_inode,
};
static
int sysfs_fill_super(struct super_block *sb, void *data, int silent) { struct inode *inode; struct dentry *root; sb->s_blocksize = PAGE_CACHE_SIZE; //块的大小,以字节为单位 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;//基本块设备驱动程序中块的大小,以字节为单位 sb->s_magic = SYSFS_MAGIC; //文件系统的魔数 sb->s_op = &sysfs_ops; sb->s_time_gran = 1; sysfs_sb = sb; /* get root inode, initialize and unlock it */ mutex_lock(&sysfs_mutex); inode = sysfs_get_inode(&sysfs_root); mutex_unlock(&sysfs_mutex); if (!inode) { pr_debug("sysfs: could not get root inode\n"); return -ENOMEM; } /* instantiate and link root dentry */ root = d_alloc_root(inode); if (!root) { pr_debug("%s: could not get root dentry!\n",__func__); iput(inode); return -ENOMEM; } root->d_fsdata = &sysfs_root; sb->s_root = root; return 0; }
原文地址:https://www.cnblogs.com/linengier/p/2992813.html