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

Coder

文章分类
文章存档

2013年(1)

2012年(10)

2011年(12)

2010年(77)

2009年(13)

2008年(4)

分类: LINUX

2010-08-09 21:32:26

怎么能够让那些未知的问题一直困扰着我们呢,接着来探讨sysfs文件系统目录inode的创建。一切秘密都在需要时。

在路径名查找的过程中, do_lookup()函数根据传递的父目录路径的信息和所要查找的名字信息来查找路径,它接收三个参数,一为nameidata 结构指针nd,该指针指向的对象的path字段中保存有父目录路径的信息,包括dentryvfsmount等;二为name,指向所要查找的文件或目录的名字;三为path结构指针,用于存放查找的结构。若在dentry缓存中查找未果的话,则do_lookup()函数将会调用父目录的inodelookup()方法来进行实际的查找,包括读取父目录文件内容等更加和具体文件系统相关的操作。(参见前面“do_lookup()路径名查找”博文)。对于sysfs来说即是sysfs_lookup()函数。在开始看这个sysfs_lookup()函数之前,还是要先看下do_lookup()函数都为我们的sysfs_lookup()做了什么:它已经根据父目录路径和名字创建了目录项了。

 

来看sysfs_lookup()函数定义:

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

fs/sysfs/dir.c

629 static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,

630                                 struct nameidata *nd)

631 {

632         struct dentry *ret = NULL;

633         struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata;

634         struct sysfs_dirent *sd;

635         struct inode *inode;

636

637         mutex_lock(&sysfs_mutex);

638

639         sd = sysfs_find_dirent(parent_sd, dentry->d_name.name);

640

641         /* no such entry */

642         if (!sd) {

643                 ret = ERR_PTR(-ENOENT);

644                 goto out_unlock;

645         }

646

647         /* attach dentry and inode */

648         inode = sysfs_get_inode(dir->i_sb, sd);

649         if (!inode) {

650                 ret = ERR_PTR(-ENOMEM);

651                 goto out_unlock;

652         }

653

654         /* instantiate and hash dentry */

655         ret = d_find_alias(inode);

656         if (!ret) {

657                 dentry->d_op = &sysfs_dentry_ops;

658                 dentry->d_fsdata = sysfs_get(sd);

659                 d_add(dentry, inode);

660         } else {

661                 d_move(ret, dentry);

662                 iput(inode);

663         }

664

665  out_unlock:

666         mutex_unlock(&sysfs_mutex);

667         return ret;

668 }

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

不知道哪个大傻瓜写的这么个函数,参数名起的,一点提示性都没有。从do_lookup()来看,个参数倒是会清晰一些:dir,即是要在其中查找目录项的目录(父目录)的inodedentry,是新创建的要保存我们查找的结构的,它的d_parent字段也是经过了适当的设置的了;nd,其path字段中保存了父目录路径的信息。

 

这个函数主要完成以下操作:

1、获得父目录的sysfs_dirent。在“Sysfs文件系统根目录项的建立”博文中,我们看到在sysfs文件系统中inodei_private字段和dentryd_fsdata都是指向对应的sysfs_dirent的,所以可以从dentry->d_parent->d_fsdata中获得父目录的sysfs_dirent对象。

 

2、调用sysfs_find_dirent(parent_sd, dentry->d_name.name)来查找sysfs_dirent。这个函数根据父目录的sysfs_dirent和文件或目录的名字来查找sysfs_direntsysfs_find_dirent()函数定义如下:

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

fs/sysfs/dir.c

522 /**

523  *      sysfs_find_dirent - find sysfs_dirent with the given name

524  *      @parent_sd: sysfs_dirent to search under

525  *      @name: name to look for

526  *

527  *      Look for sysfs_dirent with name @name under @parent_sd.

528  *

529  *      LOCKING:

530  *      mutex_lock(sysfs_mutex)

531  *

532  *      RETURNS:

533  *      Pointer to sysfs_dirent if found, NULL if not.

534  */

535 struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,

536                                        const unsigned char *name)

537 {

538         struct sysfs_dirent *sd;

539

540         for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling)

541                 if (!strcmp(sd->s_name, name))

542                         return sd;

543         return NULL;

544 }

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

前面添加kobject的过程,我们看到,其实主要就是为对应的kobject创建sysfs_dirent,并将该sysfs_dirent对象添加进父kobject对应的sysfs_dirent的子sysfs_dirent链表中。sysfs_find_dirent()函数完成的主要工作,也就是要根据名字来查出sysfs_dirent对象地址来。

 

3、如果sysfs_find_dirent()查找失败,则返回-ENOENT

 

4、调用sysfs_get_inode(dir->i_sb, sd)函数来创建inode。我们要找的就是它啊,在需要的时候,它为kobject所对应的目录创建inode。在“inode对象的建立”及“Sysfs文件系统根目录项的建立”博文中有说明,这里就不啰嗦了。

 

5、调用d_find_alias(inode)函数为inode对象找到一个位于哈希链表中的、且在该索引节点的别名链表i_dentry中的dentry对象。

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

fs/dcache.c

335 /**

336  * d_find_alias - grab a hashed alias of inode

337  * @inode: inode in question

338  * @want_discon:  flag, used by d_splice_alias, to request

339  *          that only a DISCONNECTED alias be returned.

340  *

341  * If inode has a hashed alias, or is a directory and has any alias,

342  * acquire the reference to alias and return it. Otherwise return

343  * NULL.Notice that if inode is a directory there can be only one alias

344  * and it can be unhashed only if it has no children, or if it is the

345  * root of a filesystem.

346  *

347  * If the inode has an IS_ROOT, DCACHE_DISCONNECTED alias, then prefer

348  * any other hashed alias over that one unless @want_discon is set,

349  * in which case only return an IS_ROOT, DCACHE_DISCONNECTED alias.

350  */

351

352 static struct dentry * __d_find_alias(struct inode *inode, int want_discon)

353 {

354         struct list_head *head, *next, *tmp;

355         struct dentry *alias, *discon_alias=NULL;

356

357         head = &inode->i_dentry;

358         next = inode->i_dentry.next;

359         while (next != head) {

360                 tmp = next;

361                 next = tmp->next;

362                 prefetch(next);

363                 alias = list_entry(tmp, struct dentry, d_alias);

364                 if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) {

365                         if (IS_ROOT(alias) &&

366                             (alias->d_flags & DCACHE_DISCONNECTED))

367                                 discon_alias = alias;

368                         else if (!want_discon) {

369                                 __dget_locked(alias);

370                                 return alias;

371                         }

372                 }

373         }

374         if (discon_alias)

375                 __dget_locked(discon_alias);

376         return discon_alias;

377 }

378

379 struct dentry * d_find_alias(struct inode *inode)

380 {

381         struct dentry *de = NULL;

382

383         if (!list_empty(&inode->i_dentry)) {

384                 spin_lock(&dcache_lock);

385                 de = __d_find_alias(inode, 0);

386                 spin_unlock(&dcache_lock);

387         }

388         return de;

389 }

390 EXPORT_SYMBOL(d_find_alias);

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

 

6、设置dentry->d_op指向sysfs_dentry_ops,设置dentry->d_fsdata指向对应的sysfs_dirent

 

7、调用d_add(dentry, inode)来向哈希队列添加dentryd_add()定义为:

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

include/linux/dcache.h

267 /**

268  * d_add - add dentry to hash queues

269  * @entry: dentry to add

270  * @inode: The inode to attach to this dentry

271  *

272  * This adds the entry to the hash queues and initializes @inode.

273  * The entry was actually filled in earlier during d_alloc().

274  */

275 

276 static inline void d_add(struct dentry *entry, struct inode *inode)

277 {

278         d_instantiate(entry, inode);

279         d_rehash(entry);

280 }

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

 

8、返回0

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