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;}