對於一個文件路徑的分量,如果其不為'.'和'..'則屬於普通文件名,普通文件名的解析由do_lookup()函數來處理
可以想象,搜索一個文件(目錄)時,首先肯定要在dentry緩存中查找,當緩存中查找不到對應的dentry時,才需要從磁盤中查找,並新建一個dentry,將磁盤中的數據保存到其中。找到了目標dentry後,就將相應的信息保存到path中,這裡因為路徑向下進了一層,因此要判斷下層目錄是否有新的文件系統掛載的問題,和上文討論的類似,因此要通過__follow_mount()函數判斷是否有文件系統掛載在該目錄下,另外,對於網絡文件系統,還要通過文件系統中定義的d_revalidate()函數來判斷該dentry是否有效以保證一致性。
相關閱讀: http://www.linuxidc.com/search.aspx?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;
}