对于一个文件路径的分量,如果其不为'.'和'..'则属于普通文件名,普通文件名的解析由do_lookup()函数来处理
staticint do_lookup(struct nameidata *nd, struct qstr *name,
struct path *path)
{
struct vfsmount *mnt = nd->path.mnt;
struct dentry *dentry = __d_lookup(nd->path.dentry, name);//查找name对应的dentry
if (!dentry)//dentry不存在,跳转至need_lookup
goto need_lookup;
/*如果底层文件系统中定义了d_revalidate函数,则要判断目录项是否有效,以保证一致性,
该函数是针对于网络文件系统存在的*/
if (dentry->d_op && dentry->d_op->d_revalidate)
goto need_revalidate;
done:
path->mnt = mnt;
path->dentry = dentry;
/*这里由于path往下走了一层,因此要调用__follow_mount()判断dentry对应的目录下是否挂载了其他的文件系统,
以保证对应的mnt是正确的*/
__follow_mount(path);
return 0;
need_lookup:
/*没有找到name对应的dentry,则要创建新的dentry并从磁盘中读取数据保存在dentry中*/
dentry = real_lookup(nd->path.dentry, name, nd);
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);
}
可以想象,搜索一个文件(目录)时,首先肯定要在dentry缓存中查找,当缓存中查找不到对应的dentry时,才需要从磁盘中查找,并新建一个dentry,将磁盘中的数据保存到其中。找到了目标dentry后,就将相应的信息保存到path中,这里因为路径向下进了一层,因此要判断下层目录是否有新的文件系统挂载的问题,和上文讨论的类似,因此要通过__follow_mount()函数判断是否有文件系统挂载在该目录下,另外,对于网络文件系统,还要通过文件系统中定义的d_revalidate()函数来判断该dentry是否有效以保证一致性。
相关阅读: ?where=nkey&keyword=3305
先来看看在dentry缓存中查找的过程
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);//通过parent的地址和hash(hash是name的哈希值)进行定位  
    struct dentry *found = NULL;  
    struct hlist_node *node;  
    struct dentry *dentry;  
  
    rcu_read_lock();  
      
    hlist_for_each_entry_rcu(dentry, node, head, d_hash) {//扫描head对应的碰撞溢出表  
        struct qstr *qstr;  
  
        if (dentry->d_name.hash != hash)//name的hash值不相符,则放弃该dentry  
            continue;  
        if (dentry->d_parent != parent)//父目录不一样,则放弃该dentry  
            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). 
        */  
        /*当确保了父目录和文件名的哈希值与目标dentry的一致性后,接下来就只用匹配文件名了*/  
        qstr = &dentry->d_name;//取当前dentry的文件名  
        /*如果父目录文件系统定义了比较文件名的方法,则调用之*/  
        if (parent->d_op && parent->d_op->d_compare) {  
            if (parent->d_op->d_compare(parent, qstr, name))  
                goto next;  
        } else {//如果没定义  
            if (qstr->len != len)//先确定长度是否相等  
                goto next;  
            if (memcmp(qstr->name, str, len))//再比较内存  
                goto next;  
        }  
  
        atomic_inc(&dentry->d_count);  
        found = dentry; //这里表明找到了目标dentry  
        spin_unlock(&dentry->d_lock);  
        break;  
next:  
        spin_unlock(&dentry->d_lock);  
    }  
    rcu_read_unlock();  
  
    return found;  
} 

