如下只是自己分析sysfs_init源码的注释,如有不对处,请帮忙指出,谢谢。
1. sysfs_init
-
int __init sysfs_init(void)
-
{
-
int err = -ENOMEM;
-
-
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);/* 将sysfs文件系统注册到vfs中 */
-
if (!err) {
-
sysfs_mnt = kern_mount(&sysfs_fs_type);/* 加载sysfs文件系统 */
-
if (IS_ERR(sysfs_mnt)) {
-
printk(KERN_ERR "sysfs: could not mount!\n");
-
err = PTR_ERR(sysfs_mnt);
-
sysfs_mnt = 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;
-
}
第17的kern_mount函数的解析可以看:blog.chinaunix.net/uid-29325905-id-5105756.html
总结:sysfs_init,主要将sysfs文件系统注册到系统中,并加载了一个sysfs的文件系统。
2. sysfs_mount
-
static struct dentry *sysfs_mount(struct file_system_type *fs_type,
-
int flags, const char *dev_name, void *data)/* 获取sysfs文件系统的super_block实例,并获取该实例中的root inode与dentry实例 */
-
{
-
struct sysfs_super_info *info;
-
enum kobj_ns_type type;
-
struct super_block *sb;
-
int error;
-
-
if (!(flags & MS_KERNMOUNT) && !current_user_ns()->may_mount_sysfs)
-
return ERR_PTR(-EPERM);
-
-
info = kzalloc(sizeof(*info), GFP_KERNEL);/* 从12到17行,获取sysfs文件系统的一个类似索引结构 */
-
if (!info)
-
return ERR_PTR(-ENOMEM);
-
-
for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++)
-
info->ns[type] = kobj_ns_grab_current(type);
-
-
sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info); /* 按照@info的索引,从@fs_type文件系统中按照@sysfs_test_super方法查找对应super_block,如果没有则申请一个super_block并按照@sysfs_set_super方法设置 */
-
if (IS_ERR(sb) || sb->s_fs_info != info)
-
free_sysfs_super_info(info);
-
if (IS_ERR(sb))
-
return ERR_CAST(sb);
-
if (!sb->s_root) {
-
error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);/* 给@sb实例获取对应的的root inode和dentry */
-
if (error) {
-
deactivate_locked_super(sb);
-
return ERR_PTR(error);
-
}
-
sb->s_flags |= MS_ACTIVE;
-
}
-
-
return dget(sb->s_root);
-
}
总结:每次加载一个sysfs文件系统时,都会调用到该方法。该方法实现了获取super_block和root inode,root dentry.
3.sysfs_fill_super
-
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;/* 初始化super_block. */
-
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-
sb->s_magic = SYSFS_MAGIC;
-
sb->s_op = &sysfs_ops;
-
sb->s_time_gran = 1;
-
-
/* get root inode, initialize and unlock it */
-
mutex_lock(&sysfs_mutex);
-
inode = sysfs_get_inode(sb, &sysfs_root);/* 获取super_block的root inode实例 */
-
mutex_unlock(&sysfs_mutex);
-
if (!inode) {
-
pr_debug("sysfs: could not get root inode\n");
-
return -ENOMEM;
-
}
-
-
/* instantiate and link root dentry */
-
root = d_make_root(inode);/* 由root inode获取root dentry实例 */
-
if (!root) {
-
pr_debug("%s: could not get root dentry!\n",__func__);
-
return -ENOMEM;
-
}
-
root->d_fsdata = &sysfs_root;
-
sb->s_root = root;
-
sb->s_d_op = &sysfs_dentry_ops;
-
return 0;
-
}
总结:该方法是由super_block实例来获取root inode,root dentry.
4.sysfs_get_inode
-
struct inode * sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd)
-
{
-
struct inode *inode;
-
-
inode = iget_locked(sb, sd->s_ino);/* 通过super_block实例获取 sd->s_ino相关的inode, 该情况下是获取super_block的root node*/
-
if (inode && (inode->i_state & I_NEW))
-
sysfs_init_inode(sd, inode);
-
-
return inode;
-
}
5.iget_locked (fs/inode.c)
-
struct inode *iget_locked(struct super_block *sb, unsigned long ino)
-
{
-
struct hlist_head *head = inode_hashtable + hash(sb, ino);
-
struct inode *inode;
-
-
spin_lock(&inode_hash_lock);
-
inode = find_inode_fast(sb, head, ino); /* 从inode hash链表@head查找出于@ino相关的inode实例,如果有找到就直接返回该实例 */
-
spin_unlock(&inode_hash_lock);
-
if (inode) {
-
wait_on_inode(inode);
-
return inode;
-
}
-
-
inode = alloc_inode(sb); /* 申请一个inode实例 */
-
if (inode) {
-
struct inode *old;
-
-
spin_lock(&inode_hash_lock);
-
/* We released the lock, so.. */
-
old = find_inode_fast(sb, head, ino);/* 与7行重复动作,再次确定 */
-
if (!old) {
-
inode->i_ino = ino;/* 给new inode赋予一个唯一的编号标示 */
-
spin_lock(&inode->i_lock);
-
inode->i_state = I_NEW;
-
hlist_add_head(&inode->i_hash, head);/* 将inode加入hash链表中 */
-
spin_unlock(&inode->i_lock);
-
inode_sb_list_add(inode);/* 将inode加入对应super_block->s_inodes链表中 */
-
spin_unlock(&inode_hash_lock);
-
-
/* Return the locked inode with I_NEW set, the
-
* caller is responsible for filling in the contents
-
*/
-
return inode;
-
}
-
-
/*
-
* Uhhuh, somebody else created the same inode under
-
* us. Use the old inode instead of the one we just
-
* allocated.
-
*/
-
spin_unlock(&inode_hash_lock);
-
destroy_inode(inode);
-
inode = old;
-
wait_on_inode(inode);
-
}
-
return inode;
-
}
-
EXPORT_SYMBOL(iget_locked);
6.sysfs_init_inode
-
static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
-
{
-
struct bin_attribute *bin_attr;
-
-
inode->i_private = sysfs_get(sd);/* 根据sysfs系统的要求,再次初始化inode实例 */
-
inode->i_mapping->a_ops = &sysfs_aops;
-
inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
-
inode->i_op = &sysfs_inode_operations;
-
-
set_default_inode_attr(inode, sd->s_mode);/* 将sd->s_mode设置为inode的默认属性 */
-
sysfs_refresh_inode(sd, inode);
-
-
/* initialize inode according to type */
-
switch (sysfs_type(sd)) {/* 根据sd实例的sysfs_type再次初始化inode实例 */
-
case SYSFS_DIR:
-
inode->i_op = &sysfs_dir_inode_operations;
-
inode->i_fop = &sysfs_dir_operations;
-
break;
-
case SYSFS_KOBJ_ATTR:
-
inode->i_size = PAGE_SIZE;
-
inode->i_fop = &sysfs_file_operations;
-
break;
-
case SYSFS_KOBJ_BIN_ATTR:
-
bin_attr = sd->s_bin_attr.bin_attr;
-
inode->i_size = bin_attr->size;
-
inode->i_fop = &bin_fops;
-
break;
-
case SYSFS_KOBJ_LINK:
-
inode->i_op = &sysfs_symlink_inode_operations;
-
break;
-
default:
-
BUG();
-
}
-
-
unlock_new_inode(inode);
-
}
阅读(1134) | 评论(0) | 转发(0) |