根据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生成。
-
struct qstr {
-
unsigned int hash;
-
unsigned int len;
-
const unsigned char *name;
-
};
这里的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的过程如下:
-
-
link_path_walk-->
-
do_lookup(parent, &this)-->
-
__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相同
这
点击(此处)折叠或打开
-
struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
-
{
-
unsigned int len = name->len;
-
unsigned int hash = name->hash;
-
const unsigned char *str = name->name;
-
struct hlist_head *head = d_hash(parent,hash);
-
struct dentry *found = NULL;
-
struct hlist_node *node;
-
struct dentry *dentry;
-
-
rcu_read_lock();
-
-
hlist_for_each_entry_rcu(dentry, node, head, d_hash) {
-
struct qstr *qstr;
-
-
/* 先粗略判断dentry->d_name.hash值与child dentry的name hash值相同,
-
且dentry->d_parent != parent
-
name一样,则hash值肯定是一样的,但hash值一样,name可能不一样,所以后面还要严格比较name长度,以及那么的每一个字符都是一致的 */
-
if (dentry->d_name.hash != hash)
-
continue;
-
if (dentry->d_parent != parent)
-
continue;
-
-
spin_lock(&dentry->d_lock);
-
-
/*
-
* Recheck the dentry after taking the lock - d_move may have
-
* changed things. Don't bother checking the hash because we're
-
* about to compare the whole name anyway.
-
*/
-
if (dentry->d_parent != parent)
-
goto next;
-
-
/* non-existing due to RCU? */
-
if (d_unhashed(dentry))
-
goto next;
-
-
/*
-
* It is safe to compare names since d_move() cannot
-
* change the qstr (protected by d_lock).
-
*/
-
qstr = &dentry->d_name;/* 每一个dentry都有一个qstr结构成员,用来记录name的hash值,name的长度 */
-
if (parent->d_op && parent->d_op->d_compare) {
-
/* 如果parent所在的文件系统有自己的name比较函数,则使用之 */
-
if (parent->d_op->d_compare(parent, qstr, name))
-
goto next;
-
} else {
-
/* 这里严格比较neme长度和name的每一个字符 */
-
if (qstr->len != len)
-
goto next;
-
if (memcmp(qstr->name, str, len))
-
goto next;
-
}
-
-
atomic_inc(&dentry->d_count);
-
found = dentry;
-
spin_unlock(&dentry->d_lock);
-
break;
-
next:
-
spin_unlock(&dentry->d_lock);
-
}
-
rcu_read_unlock();
-
-
return found;
-
}
阅读(1453) | 评论(0) | 转发(0) |