Chinaunix首页 | 论坛 | 博客
  • 博客访问: 417650
  • 博文数量: 99
  • 博客积分: 65
  • 博客等级: 民兵
  • 技术积分: 1012
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-20 16:30
个人简介

linux kernel 工程师

文章分类

全部博文(99)

文章存档

2018年(5)

2017年(12)

2016年(27)

2015年(10)

2014年(43)

2012年(2)

我的朋友

分类: LINUX

2016-12-25 13:33:23

do_lookup实现路径分量dentry的查找。
基本思路是
1. 先调用__d_lookup在hash表里查找。这里的查找只是在内存中查找,相当于在cache里面查找。
2. 如果__d_lookup没有找到,则需要到实际的文件系统中读取。

点击(此处)折叠或打开

  1. /*
  2.  * It's more convoluted than I'd like it to be, but... it's still fairly
  3.  * small and for now I'd prefer to have fast path as straight as possible.
  4.  * It _is_ time-critical.
  5.  */
  6. static int do_lookup(struct nameidata *nd, struct qstr *name,
  7.          struct path *path)
  8. {
  9.     struct vfsmount *mnt = nd->path.mnt;
  10.     struct dentry *dentry, *parent;
  11.     struct inode *dir;
  12.     /*
  13.      * See if the low-level filesystem might want
  14.      * to use its own hash..
  15.      */
  16.     /* nd->path.dentry代表的是parent dentry,如果父节点代表的文件系统有自己的hash函数,在这里需要更新qstr *name里面的hash值 
  17.         比如说要查找"/mnt/tmp1"里面的tmp1分量,那么nd->path.dentry就是"/mnt"的dentry
  18.     */
  19.     if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) {
  20.         int err = nd->path.dentry->d_op->d_hash(nd->path.dentry, name);
  21.         if (err < 0)
  22.             return err;
  23.     }

    /* 先调用__d_lookup在hash表里查找。这里的查找只是在内存中查找,相当于在cache里面查找。 */

  1.     dentry = __d_lookup(nd->path.dentry, name);
  2.     if (!dentry)/* 如果内存里查找不到,需要goto need_lookup处,执行文件系统的查找 */
  3.         goto need_lookup;
  4.     if (dentry->d_op && dentry->d_op->d_revalidate)
  5.         goto need_revalidate;
  6. done:
  7.     /* 这里代表查找成功,更新path
  8.        比如说要查找"/mnt/tmp1"里面的"tmp1"分量, 到这里就找到了"tmp1"这个分量的dentry和mnt结构
  9.     */
  10.     path->mnt = mnt;
  11.     path->dentry = dentry;
  12.     /* 假如/mnt/tmp1是一个mount point,比如 执行过"mount /dev/sdc1 /mnt/tmp1 */
  13.     __follow_mount(path);
  14.     return 0;

  15. need_lookup:
  16.     /* 比如说要查找"/mnt/tmp1"里面的tmp1分量, __d_lookup没有查找成功,这里的parent是"/mnt"对应的dentry
  17.         dir是/mnt对应的inode
  18.     */
  19.     parent = nd->path.dentry;
  20.     dir = parent->d_inode;

  21.     mutex_lock(&dir->i_mutex);
  22.     /*
  23.      * First re-do the cached lookup just in case it was created
  24.      * while we waited for the directory semaphore..
  25.      *
  26.      * This could use version numbering or similar to
  27.      * avoid unnecessary cache lookups.
  28.      *
  29.      * The "dcache_lock" is purely to protect the RCU list walker
  30.      * from concurrent renames at this point (we mustn't get false
  31.      * negatives from the RCU list walk here, unlike the optimistic
  32.      * fast walk).
  33.      *
  34.      * so doing d_lookup() (with seqlock), instead of lockfree __d_lookup
  35.      */
  36.     dentry = d_lookup(parent, name);
  37.     if (!dentry) {
  38.         struct dentry *new;

  39.         /* Don't create child dentry for a dead directory. */
  40.         dentry = ERR_PTR(-ENOENT);
  41.         if (IS_DEADDIR(dir))
  42.             goto out_unlock;
  43.        
  44.         /* 分配一个dentry结构 */
  45.         new = d_alloc(parent, name);
  46.         dentry = ERR_PTR(-ENOMEM);
  47.         if (new) {
  48.             /* 这里才是到文件系统里面查找
  49.                比如说proc fs,对应的lookup函数是proc_root_lookupproc_root_lookup执行成功后会返回NULL,失败返回一个非NULL值 */
  50.             dentry = dir->i_op->lookup(dir, new, nd);
  51.             if (dentry)    /* 执行失败,最终会把new释放掉 */
  52.                 dput(new);
  53.             else /* 执行成功 */
  54.                 dentry = new;
  55.         }
  56. out_unlock:
  57.         mutex_unlock(&dir->i_mutex);
  58.         if (IS_ERR(dentry))
  59.             goto fail;
  60.         goto done;
  61.     }

  62.     /*
  63.      * Nasty case: the cache was re-populated while
  64.      * we waited on the semaphore. Need to revalidate.
  65.      */
  66.     mutex_unlock(&dir->i_mutex);
  67.     if (dentry->d_op && dentry->d_op->d_revalidate) {
  68.         dentry = do_revalidate(dentry, nd);
  69.         if (!dentry)
  70.             dentry = ERR_PTR(-ENOENT);
  71.     }
  72.     if (IS_ERR(dentry))
  73.         goto fail;
  74.     goto done;

  75. need_revalidate:
  76.     dentry = do_revalidate(dentry, nd);
  77.     if (!dentry)
  78.         goto need_lookup;
  79.     if (IS_ERR(dentry))
  80.         goto fail;
  81.     goto done;

  82. fail:
  83.     return PTR_ERR(dentry);
  84. }

阅读(3650) | 评论(0) | 转发(0) |
0

上一篇:__d_lookup

下一篇:d_alloc

给主人留下些什么吧!~~