装载:http://book.51cto.com/art/201401/427827.htm
然后调用lookup_one_len获得一个dentry结构。lookup_one_len函数首先在父目录下根据名字查找dentry结构,如果存在同名的dentry结构就返回指针,如果不存在就创建一个dentry。lookup_one_len的代码如代码清单2-16所示
代码清单2-16 查找同名dentry的lookup_one_len函数
struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
1272 {
……/*省略参数定义*/
1277 this.name = name;
1278 this.len = len;
1279 if (!len)
1280 goto access;
1281 /*这里根据名字计算hasn值,看看是怎么计算的*/
1282 hash = init_name_hash();
1283 while (len--) {
1284 c = *(const unsigned char *)name++;
1285 if (c == '/' || c == '\0')
1286 goto access;
1287 hash = partial_name_hash(c, hash);
1288 }
1289 this.hash = end_name_hash(hash);
1290
1291 return __lookup_hash(&this, base, NULL);
第1282~1289行的作用是计算名字的hash值。因为初始hash函数init_name_hash和最终hash函数end_name_hash都不执行任何的计算,所以最终得到的hash值是将名字中的每个字符做固定的数学运算得到的。
__lookup_hash函数是通过hash值查找同名字的dentry结构,它的代码如代码清单2-17所示。
代码清单2-17 在hash链表中查找的__lookup_hash函数
static struct dentry * __lookup_hash(struct qstr *name,
struct dentry * base, struct nameidata *nd)
{
struct dentry * dentry;
struct inode *inode;
int err;
inode = base->d_inode;
err = permission(inode, MAY_EXEC, nd);
dentry = ERR_PTR(err);
if (err)
goto out;
/*
* See if the low-level filesystem might want
* to use its own hash..
*/
if (base->d_op && base->d_op->d_hash) {
err = base->d_op->d_hash(base, name);
dentry = ERR_PTR(err);
if (err < 0)
goto out;
}
_lookup_hash函数第一部分是检查inode的权限,然后检查文件系统是否提供了特有的hash函数,如果有hash函数,则调用重新计算hash值
dentry = cached_lookup(base, name, nd);
if (!dentry) {
/*如果没有找到。说明这个目录不存在,则创建一个dentry*/
struct dentry *new = d_alloc(base, name);
dentry = ERR_PTR(-ENOMEM);
if (!new)
goto out;
dentry = inode->i_op->lookup(inode, new, nd);
if (!dentry)
dentry = new;
else
dput(new);
}
out:
return dentry;
}
cached_lookup在dentry cache里面查找同名的dentry结构,如果返回为空,说明不存在同名的dentry结构,那么调用d_alloc创建一个新的dentry结构。
创建dentry结构完成后,需要再次调用文件系统的lookup查找是否有同名的dentry存在。这样做为了防止同名的dentry已经被其他用户提前创建了。
cached_lookup函数的代码如代码清单2-18所示。
代码清单2-18 cached_lookup函数
static struct dentry * cached_lookup(struct dentry * parent,
struct qstr * name, struct nameidata *nd)
{
struct dentry * dentry = __d_lookup(parent, name);
/* lockess __d_lookup may fail due to concurrent d_move()
* in some unrelated directory, so try with d_lookup
*/
/*注意原来的解释,为何再次查找?因为要防止一个并发的move操作*/
if (!dentry)
dentry = d_lookup(parent, name);
……/*省略校验的代码*/
}