do_lookup实现路径分量dentry的查找。
基本思路是
1. 先调用__d_lookup在hash表里查找。这里的查找只是在内存中查找,相当于在cache里面查找。
2. 如果__d_lookup没有找到,则需要到实际的文件系统中读取。
-
/*
-
* It's more convoluted than I'd like it to be, but... it's still fairly
-
* small and for now I'd prefer to have fast path as straight as possible.
-
* It _is_ time-critical.
-
*/
-
static int do_lookup(struct nameidata *nd, struct qstr *name,
-
struct path *path)
-
{
-
struct vfsmount *mnt = nd->path.mnt;
-
struct dentry *dentry, *parent;
-
struct inode *dir;
-
/*
-
* See if the low-level filesystem might want
-
* to use its own hash..
-
*/
-
/* nd->path.dentry代表的是parent dentry,如果父节点代表的文件系统有自己的hash函数,在这里需要更新qstr *name里面的hash值
-
比如说要查找"/mnt/tmp1"里面的tmp1分量,那么nd->path.dentry就是"/mnt"的dentry
-
*/
-
if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) {
-
int err = nd->path.dentry->d_op->d_hash(nd->path.dentry, name);
-
if (err < 0)
-
return err;
-
}
/* 先调用__d_lookup在hash表里查找。这里的查找只是在内存中查找,相当于在cache里面查找。 */
-
dentry = __d_lookup(nd->path.dentry, name);
-
if (!dentry)/* 如果内存里查找不到,需要goto need_lookup处,执行文件系统的查找 */
-
goto need_lookup;
-
if (dentry->d_op && dentry->d_op->d_revalidate)
-
goto need_revalidate;
-
done:
-
/* 这里代表查找成功,更新path
-
比如说要查找"/mnt/tmp1"里面的"tmp1"分量, 到这里就找到了"tmp1"这个分量的dentry和mnt结构
-
*/
-
path->mnt = mnt;
-
path->dentry = dentry;
-
/* 假如/mnt/tmp1是一个mount point,比如 执行过"mount /dev/sdc1 /mnt/tmp1 */
-
__follow_mount(path);
-
return 0;
-
-
need_lookup:
-
/* 比如说要查找"/mnt/tmp1"里面的tmp1分量, __d_lookup没有查找成功,这里的parent是"/mnt"对应的dentry
-
dir是/mnt对应的inode
-
*/
-
parent = nd->path.dentry;
-
dir = parent->d_inode;
-
-
mutex_lock(&dir->i_mutex);
-
/*
-
* First re-do the cached lookup just in case it was created
-
* while we waited for the directory semaphore..
-
*
-
* This could use version numbering or similar to
-
* avoid unnecessary cache lookups.
-
*
-
* The "dcache_lock" is purely to protect the RCU list walker
-
* from concurrent renames at this point (we mustn't get false
-
* negatives from the RCU list walk here, unlike the optimistic
-
* fast walk).
-
*
-
* so doing d_lookup() (with seqlock), instead of lockfree __d_lookup
-
*/
-
dentry = d_lookup(parent, name);
-
if (!dentry) {
-
struct dentry *new;
-
-
/* Don't create child dentry for a dead directory. */
-
dentry = ERR_PTR(-ENOENT);
-
if (IS_DEADDIR(dir))
-
goto out_unlock;
-
-
/* 分配一个dentry结构 */
-
new = d_alloc(parent, name);
-
dentry = ERR_PTR(-ENOMEM);
-
if (new) {
-
/* 这里才是到文件系统里面查找
-
比如说proc fs,对应的lookup函数是proc_root_lookup,proc_root_lookup执行成功后会返回NULL,失败返回一个非NULL值 */
-
dentry = dir->i_op->lookup(dir, new, nd);
-
if (dentry) /* 执行失败,最终会把new释放掉 */
-
dput(new);
-
else /* 执行成功 */
-
dentry = new;
-
}
-
out_unlock:
-
mutex_unlock(&dir->i_mutex);
-
if (IS_ERR(dentry))
-
goto fail;
-
goto done;
-
}
-
-
/*
-
* Nasty case: the cache was re-populated while
-
* we waited on the semaphore. Need to revalidate.
-
*/
-
mutex_unlock(&dir->i_mutex);
-
if (dentry->d_op && dentry->d_op->d_revalidate) {
-
dentry = do_revalidate(dentry, nd);
-
if (!dentry)
-
dentry = ERR_PTR(-ENOENT);
-
}
-
if (IS_ERR(dentry))
-
goto fail;
-
goto done;
-
-
need_revalidate:
-
dentry = do_revalidate(dentry, nd);
-
if (!dentry)
-
goto need_lookup;
-
if (IS_ERR(dentry))
-
goto fail;
-
goto done;
-
-
fail:
-
return PTR_ERR(dentry);
-
}
阅读(3691) | 评论(0) | 转发(0) |