Chinaunix首页 | 论坛 | 博客
  • 博客访问: 819796
  • 博文数量: 117
  • 博客积分: 2583
  • 博客等级: 少校
  • 技术积分: 1953
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-06 22:58
个人简介

Coder

文章分类
文章存档

2013年(1)

2012年(10)

2011年(12)

2010年(77)

2009年(13)

2008年(4)

分类: LINUX

2010-08-06 23:22:02

sysfs文件系统根目录项的建立


话说sysfs_fs_type get_sb 方法get_sb_single()中调用了传递进来的fill_super方法来进一步的初始化刚刚建立的super_block对象。这个方法实际上是sysfs_fill_super()函数。还是这个函数最有意思,最最实在,其定义为:

---------------------------------------------------------------------

fs/sysfs/mount.c

26 static struct vfsmount *sysfs_mount;

27 struct kmem_cache *sysfs_dir_cachep;

28

29 static const struct super_operations sysfs_ops = {

30         .statfs         = simple_statfs,

31         .drop_inode     = generic_delete_inode,

32         .delete_inode   = sysfs_delete_inode,

33 };

34

35 struct sysfs_dirent sysfs_root = {

36         .s_name         = "",

37         .s_count        = ATOMIC_INIT(1),

38         .s_flags        = SYSFS_DIR,

39         .s_mode         = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,

40         .s_ino          = 1,

41 };

 

43 static int sysfs_fill_super(struct super_block *sb, void *data, int silent)

44 {

45         struct inode *inode;

46         struct dentry *root;

47

48         sb->s_blocksize = PAGE_CACHE_SIZE;

49         sb->s_blocksize_bits = PAGE_CACHE_SHIFT;

50         sb->s_magic = SYSFS_MAGIC;

51         sb->s_op = &sysfs_ops;

52         sb->s_time_gran = 1;

53

54         /* get root inode, initialize and unlock it */

55         mutex_lock(&sysfs_mutex);

56         inode = sysfs_get_inode(sb, &sysfs_root);

57         mutex_unlock(&sysfs_mutex);

58         if (!inode) {

59                 pr_debug("sysfs: could not get root inode\n");

60                 return -ENOMEM;

61         }

62

63         /* instantiate and link root dentry */

64         root = d_alloc_root(inode);

65         if (!root) {

66                 pr_debug("%s: could not get root dentry!\n",__func__);

67                 iput(inode);

68                 return -ENOMEM;

69         }

70         root->d_fsdata = &sysfs_root;

71         sb->s_root = root;

72         return 0;

73 }

---------------------------------------------------------------------

这个函数执行如下操作:

1、设置超级块的sb->s_blocksizePAGE_CACHE_SIZEsb->s_blocksize_bits字段为PAGE_CACHE_SHIFTsb->s_magic字段为SYSFS_MAGICsb->s_op字段指向sysfs_opssb->s_time_gran字段为1

 

2、获得sysfs互斥体。

 

3、调用sysfs_get_inode(sb, &sysfs_root),根据sysfs_root的内容来建立sysfs文件系统根目录的inode对象。在这里,来解释一下sysfs_dirent结构体。它是sysfs文件系统层次结构的构建块,sysfs中的每个节点都由一个单独的sysfs_dirent结构来呈现,是sysfs自己的目录项。其定义为:

---------------------------------------------------------------------

fs/sysfs/sysfs.h

51 struct sysfs_dirent {

52         atomic_t                s_count; /* 引用计数器 */

53         atomic_t                s_active;

54 #ifdef CONFIG_DEBUG_LOCK_ALLOC

55         struct lockdep_map      dep_map;

56 #endif

57         struct sysfs_dirent     *s_parent;

58         struct sysfs_dirent     *s_sibling;

59         const char              *s_name; /* 名字 */

60

61         union {

62                 struct sysfs_elem_dir           s_dir;

63                 struct sysfs_elem_symlink       s_symlink;

64                 struct sysfs_elem_attr          s_attr;

65                 struct sysfs_elem_bin_attr      s_bin_attr;

66         };

67

68         unsigned int            s_flags; /* 节点标志(属性) */

69         unsigned short          s_mode;  /* 节点模式 */

70         ino_t                   s_ino;   /* inode节点号 */

71         struct sysfs_inode_attrs *s_iattr;

72 };

---------------------------------------------------------------------

接下来来看sysfs_get_inode()的定义:

---------------------------------------------------------------------

fs/sysfs/inode.c

285 /**

286  *      sysfs_get_inode - get inode for sysfs_dirent

287  *      @sb: super block

288  *      @sd: sysfs_dirent to allocate inode for

289  *

290  *      Get inode for @sd.  If such inode doesn't exist, a new inode

291  *      is allocated and basics are initialized.  New inode is

292  *      returned locked.

293  *

294  *      LOCKING:

295  *      Kernel thread context (may sleep).

296  *

297  *      RETURNS:

298  *      Pointer to allocated inode on success, NULL on failure.

299  */

300 struct inode * sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd)

301 {

302         struct inode *inode;

303

304         inode = iget_locked(sb, sd->s_ino);

305         if (inode && (inode->i_state & I_NEW))

306                 sysfs_init_inode(sd, inode);

307

308         return inode;

309 }

---------------------------------------------------------------------

这个函数执行如下操作:

a. 调用iget_locked(sb, sd->s_ino)来获得inode对象。它本质上先在inode哈希表中查找特定文件系统中对应inode号的inode对象。若找不到,则在inodeslab缓冲池中分配新的inode对象,初始化它并返回其地址。由sysfs_root 的定义,我们知道sysfs根目录的inode号为1

 

b.调用sysfs_init_inode(sd, inode)函数来初始化刚刚为根目录创建的inode。这个函数我们也得仔细瞧瞧:

---------------------------------------------------------------------

fs/sysfs/inode.c

28 static const struct address_space_operations sysfs_aops = {

29         .readpage       = simple_readpage,

30         .write_begin    = simple_write_begin,

31         .write_end      = simple_write_end,

32 };

33

34 static struct backing_dev_info sysfs_backing_dev_info = {

35         .name           = "sysfs",

36         .ra_pages       = 0,    /* No readahead */

37         .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,

38 };

39

40 static const struct inode_operations sysfs_inode_operations ={

41         .permission     = sysfs_permission,

42         .setattr        = sysfs_setattr,

43         .getattr        = sysfs_getattr,

44         .setxattr       = sysfs_setxattr,

45 };

 

216 static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode)

217 {

218         struct sysfs_inode_attrs *iattrs = sd->s_iattr;

219

220         inode->i_mode = sd->s_mode;

221         if (iattrs) {

222                 /* sysfs_dirent has non-default attributes

223                  * get them from persistent copy in sysfs_dirent

224                  */

225                 set_inode_attr(inode, &iattrs->ia_iattr);

226                 security_inode_notifysecctx(inode,

227                                             iattrs->ia_secdata,

228                                             iattrs->ia_secdata_len);

229         }

230

231         if (sysfs_type(sd) == SYSFS_DIR)

232                 inode->i_nlink = sysfs_count_nlink(sd);

233 }

 

248 static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)

249 {

250         struct bin_attribute *bin_attr;

251

252         inode->i_private = sysfs_get(sd);

253         inode->i_mapping->a_ops = &sysfs_aops;

254         inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;

255         inode->i_op = &sysfs_inode_operations;

256

257         set_default_inode_attr(inode, sd->s_mode);

258         sysfs_refresh_inode(sd, inode);

259

260         /* initialize inode according to type */

261         switch (sysfs_type(sd)) {

262         case SYSFS_DIR:

263                 inode->i_op = &sysfs_dir_inode_operations;

264                 inode->i_fop = &sysfs_dir_operations;

265                 break;

266         case SYSFS_KOBJ_ATTR:

267                 inode->i_size = PAGE_SIZE;

268                 inode->i_fop = &sysfs_file_operations;

269                 break;

270         case SYSFS_KOBJ_BIN_ATTR:

271                 bin_attr = sd->s_bin_attr.bin_attr;

272                 inode->i_size = bin_attr->size;

273                 inode->i_fop = &bin_fops;

274                 break;

275         case SYSFS_KOBJ_LINK:

276                 inode->i_op = &sysfs_symlink_inode_operations;

277                 break;

278         default:

279                 BUG();

280         }

281

282         unlock_new_inode(inode);

283 }

---------------------------------------------------------------------

这个函数执行如下操作:

(1)、增加sysfs根目录的sysfs_dirent对象sysfs_root的引用计数,并使根目录inodeinode->i_private字段指向这个sysfs_dirent对象。

(2)、设置根目录inodeinode->i_mapping->a_ops字段为&sysfs_aopsinode->i_mapping->backing_dev_info字段为&sysfs_backing_dev_infoinode->i_op字段为&sysfs_inode_operations(sysfs默认的inode操作集)

 

(3)、调用set_default_inode_attr(inode, sd->s_mode)sysfs_rootinode模式字段值赋给新建的inodei_mode字段,设置inodeinode->i_atimeinode->i_mtimeinode->i_ctime字段为当前时间CURRENT_TIME

 

(4)、调用sysfs_refresh_inode(sd, inode)函数来刷新inode,这个函数本质上再一次将sysfs_rootinode模式字段值赋给新建的inodei_mode字段,然后设置inode的引用计数字段i_nlink(目录的子目录个数加2)。

 

(5)、设置inodei_op&sysfs_dir_inode_operations,覆盖掉先前的设置,设置i_fop字段为&sysfs_dir_operations

 

c. sysfs_get_inode()返回经过了初始化的inode

 

4sysfs_fill_super()释放sysfs互斥体sysfs_mutex

 

5、调用d_alloc_root(inode)根据inode来为sysfs创建根目录项。这个函数定义如下:

---------------------------------------------------------------------

fs/dcache.c

1096 /**

1097  * d_alloc_root - allocate root dentry

1098  * @root_inode: inode to allocate the root for

1099  *

1100  * Allocate a root ("/") dentry for the inode given. The inode is

1101  * instantiated and returned. %NULL is returned if there is

1102  * insufficient memory or the inode passed is %NULL.

1103  */

1104 

1105 struct dentry * d_alloc_root(struct inode * root_inode)

1106 {

1107         struct dentry *res = NULL;

1108

1109         if (root_inode) {

1110                 static const struct qstr name = { .name = "/", .len = 1 };

1111

1112                 res = d_alloc(NULL, &name);

1113                 if (res) {

1114                         res->d_sb = root_inode->i_sb;

1115                         res->d_parent = res;

1116                         d_instantiate(res, root_inode);

1117                 }

1118         }

1119         return res;

1120 }

1121 EXPORT_SYMBOL(d_alloc_root);

---------------------------------------------------------------------

这个函数执行如下操作:

a.调用d_alloc(NULL, &name)来从目录项缓存中分配dentry对象。这个函数定义为:

---------------------------------------------------------------------

fs/dcache.c

915 /**

916  * d_alloc      -       allocate a dcache entry

917  * @parent: parent of entry to allocate

918  * @name: qstr of the name

919  *

920  * Allocates a dentry. It returns %NULL if there is insufficient memory

921  * available. On a success the dentry is returned. The name passed in is

922  * copied and the copy passed in may be reused after this call.

923  */

924 

925 struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)

926 {

927         struct dentry *dentry;

928         char *dname;

929

930         dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL);

931         if (!dentry)

932                 return NULL;

933

934         if (name->len > DNAME_INLINE_LEN-1) {

935                 dname = kmalloc(name->len + 1, GFP_KERNEL);

936                 if (!dname) {

937                         kmem_cache_free(dentry_cache, dentry);

938                         return NULL;

939                 }

940         } else  {

941                 dname = dentry->d_iname;

942         }      

943         dentry->d_name.name = dname;

944

945         dentry->d_name.len = name->len;

946         dentry->d_name.hash = name->hash;

947         memcpy(dname, name->name, name->len);

948         dname[name->len] = 0;

949

950         atomic_set(&dentry->d_count, 1);

951         dentry->d_flags = DCACHE_UNHASHED;

952         spin_lock_init(&dentry->d_lock);

953         dentry->d_inode = NULL;

954         dentry->d_parent = NULL;

955         dentry->d_sb = NULL;

956         dentry->d_op = NULL;

957         dentry->d_fsdata = NULL;

958         dentry->d_mounted = 0;

959         INIT_HLIST_NODE(&dentry->d_hash);

960         INIT_LIST_HEAD(&dentry->d_lru);

961         INIT_LIST_HEAD(&dentry->d_subdirs);

962         INIT_LIST_HEAD(&dentry->d_alias);

963

964         if (parent) {

965                 dentry->d_parent = dget(parent);

966                 dentry->d_sb = parent->d_sb;

967         } else {

968                 INIT_LIST_HEAD(&dentry->d_u.d_child);

969         }

970

971         spin_lock(&dcache_lock);

972         if (parent)

973                 list_add(&dentry->d_u.d_child, &parent->d_subdirs);

974         dentry_stat.nr_dentry++;

975         spin_unlock(&dcache_lock);

976

977         return dentry;

978 }

979 EXPORT_SYMBOL(d_alloc);

---------------------------------------------------------------------

这个函数的操作基本上都比较明确。

 

b.设置目录项的d_sb为,root_inode->i_sb,设置目录项的父目录项指向其本身。前面为根目录建立inode的时候,调用iget_locked()函数,传递的参数是超级块对象地址和索引节点号。

 

c.调用d_instantiate(res, root_inode)为一个目录项填充信息。其定义为:

---------------------------------------------------------------------

fs/dcache.c

992 /* the caller must hold dcache_lock */

993 static void __d_instantiate(struct dentry *dentry, struct inode *inode)

994 {

995         if (inode)

996                 list_add(&dentry->d_alias, &inode->i_dentry);

997         dentry->d_inode = inode;

998         fsnotify_d_instantiate(dentry, inode);

999 }

1000

1001 /**

1002  * d_instantiate - fill in inode information for a dentry

1003  * @entry: dentry to complete

1004  * @inode: inode to attach to this dentry

1005  *

1006  * Fill in inode information in the entry.

1007  *

1008  * This turns negative dentries into productive full members

1009  * of society.

1010  *

1011  * NOTE! This assumes that the inode count has been incremented

1012  * (or otherwise set) by the caller to indicate that it is now

1013  * in use by the dcache.

1014  */

1015 

1016 void d_instantiate(struct dentry *entry, struct inode * inode)

1017 {

1018         BUG_ON(!list_empty(&entry->d_alias));

1019         spin_lock(&dcache_lock);

1020         __d_instantiate(entry, inode);

1021         spin_unlock(&dcache_lock);

1022         security_d_instantiate(entry, inode);

1023 }

---------------------------------------------------------------------

这个函数完成的工作主要是将目录项添加进inode的目录项链表i_dentry,并使目录项的d_inode指向inode

 

6、设置根目录目录项的文件系统私有字段d_fsdatainodei_private一样指向sysfs_root。设置sysfs超级块的根目录字段s_root指向刚刚创建的目录项root

总之sysfs_fill_super()为文件系统创建适当的根目录inode及根目录目录项。

阅读(2029) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~