Chinaunix首页 | 论坛 | 博客
  • 博客访问: 419529
  • 博文数量: 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-23 20:07:13

根据parent d_entry和child d_entry的name,查找child d_entry


如图1所示,所有的dentry都会通过d_hash成员链入一个hash表,这个hash表就是dentry_hashtable。
现在来看函数__d_lookup,hash值由parent dentry的地址与name->hash生成。

点击(此处)折叠或打开

  1. struct qstr {
  2.     unsigned int hash;
  3.     unsigned int len;
  4.     const unsigned char *name;
  5. };
这里的name是一个struct qstr结构。该结构包含了路径分量的“名称”字符串,字符串的长度,以及该字符串的hash值。比如说,要访问"/usr/bin"这个目录,当确定好访问的起始路径为”/"之后,第一个访问的路径分量就是"usr"。在函数link_path_walk中已经计算出"usr"这个字符串的hash值,并把这写信息记录在struct qstr this这个变量里面。
this.hash=xxx
this.len=3
this.name="usr/bin"(这里虽然包含两个路径分量usr和bin,但len=3已经能够指出在字符串比较时,只是用"usr"字符串)
link_path_walk调用__d_lookup的过程如下:

点击(此处)折叠或打开


  1. link_path_walk-->
  2.     do_lookup(parent, &this)-->
  3.         __d_lookup(parent,name)

继续看函数__d_lookup,
unsigned int hash = name->hash;
struct hlist_head *head = d_hash(parent,hash);
就是在已知parent d_entry和路径分量的hash值情况下,再生成一个hash值。待查找的dentry一定位于dentry_hashtable[hash]这条hash链。
查找的条件是:
dentry->parent = parent
dentry->name 与qstr结构里面的name相同


点击(此处)折叠或打开

  1. struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
  2. {
  3.     unsigned int len = name->len;
  4.     unsigned int hash = name->hash;
  5.     const unsigned char *str = name->name;
  6.     struct hlist_head *head = d_hash(parent,hash);
  7.     struct dentry *found = NULL;
  8.     struct hlist_node *node;
  9.     struct dentry *dentry;

  10.     rcu_read_lock();
  11.     
  12.     hlist_for_each_entry_rcu(dentry, node, head, d_hash) {
  13.         struct qstr *qstr;
  14.        
  15.         /* 先粗略判断dentry->d_name.hash值与child dentry的name hash值相同,
  16.          且dentry->d_parent != parent
  17.         name一样,则hash值肯定是一样的,但hash值一样,name可能不一,所以后面还要严格比较name长度,以及那么的每一个字符都是一致的 */
  18.         if (dentry->d_name.hash != hash)
  19.             continue;
  20.         if (dentry->d_parent != parent)
  21.             continue;

  22.         spin_lock(&dentry->d_lock);

  23.         /*
  24.          * Recheck the dentry after taking the lock - d_move may have
  25.          * changed things. Don't bother checking the hash because we're
  26.          * about to compare the whole name anyway.
  27.          */
  28.         if (dentry->d_parent != parent)
  29.             goto next;

  30.         /* non-existing due to RCU? */
  31.         if (d_unhashed(dentry))
  32.             goto next;

  33.         /*
  34.          * It is safe to compare names since d_move() cannot
  35.          * change the qstr (protected by d_lock).
  36.          */
  37.         qstr = &dentry->d_name;/* 每一个dentry都有一个qstr结构成员,用来记录name的hash值,name的长度 */
  38.         if (parent->d_op && parent->d_op->d_compare) {
  39.             /* 如果parent所在的文件系统有自己的name比较函数,则使用之  */
  40.             if (parent->d_op->d_compare(parent, qstr, name))
  41.                 goto next;
  42.         } else {
  43.             /* 这里严格比较neme长度和name的每一个字符 */
  44.             if (qstr->len != len)
  45.                 goto next;
  46.             if (memcmp(qstr->name, str, len))
  47.                 goto next;
  48.         }

  49.         atomic_inc(&dentry->d_count);
  50.         found = dentry;
  51.         spin_unlock(&dentry->d_lock);
  52.         break;
  53. next:
  54.         spin_unlock(&dentry->d_lock);
  55.      }
  56.      rcu_read_unlock();

  57.      return found;
  58. }

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

上一篇:path_init

下一篇:do_lookup

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