- if (ll_sai_entry_stated(sai)) {
- struct ll_sai_entry *entry;
-
- entry = cfs_list_entry(sai->sai_entries_stated.next,
- struct ll_sai_entry, se_list);
- /* This is for statahead lookup */
- if (entry->se_inode != NULL) {
- struct lookup_intent it = {.it_op = IT_LOOKUP};
- struct dentry *dchild = entry->se_dentry;
- struct inode *ichild = entry->se_inode;
- struct ll_dentry_data *lld = ll_d2d(dchild);
- struct ll_inode_info *sei = ll_i2info(ichild);
- struct dentry *save = dchild;
- int invalid = 0;
- __u32 bits = MDS_INODELOCK_LOOKUP |
- MDS_INODELOCK_UPDATE;
- int found = 0;
-
- LASSERT(dchild != *dentryp);
-
- if (!lookup)
- mutex_lock(&dir->i_mutex);
-
- /*
- * Make sure dentry is still valid.
- * For statahead lookup case, we need both
- * LOOKUP lock and UPDATE lock which obtained
- * by statahead thread originally.
- *
- * Consider following racer case:
- * 1. statahead thread on client1 get lock with
- * both LOOKUK and UPDATE bits for "aaa"
- * 2. rename thread on client2 cancel such lock
- * from client1, then rename "aaa" to "bbb"
- * 3. ls thread on client1 obtain LOOKUP lock
- * for "bbb" again
- * 4. here the dentry "aaa" created by statahead
- * thread should be invalid even related
- * LOOKUP lock valid for the same inode
- */
- rc = md_revalidate_lock(ll_i2mdexp(dir), &it,
- ll_inode2fid(ichild),
- &bits);
- cfs_spin_lock(&sei->lli_sa_lock);
- if (!cfs_list_empty(&lld->lld_sa_alias))
- cfs_list_del_init(&lld->lld_sa_alias);
- else
- invalid = 1;
- cfs_spin_unlock(&sei->lli_sa_lock);
- if (rc != 1)
- /* Someone has cancelled the original
- * lock before the real "revalidate"
- * using it. Drop it. */
- goto out_mutex;
-
- if (invalid) {
- /* Someone has cancelled the original
- * lock, and reobtained it, the dentry
- * maybe invalid anymore, Drop it. */
- ll_intent_drop_lock(&it);
- goto out_mutex;
- }
-
- ll_lookup_it_alias(&dchild, ichild, bits);
- found = is_same_dentry(*dentryp, dchild, lookup);
- ll_lookup_finish_locks(&it, dchild);
- if (dchild != save)
- dput(save);
- ichild = NULL;
-
-out_mutex:
- if (!lookup)
- mutex_unlock(&dir->i_mutex);
- /* Drop the inode reference count held by
- * interpreter. */
- if (ichild != NULL)
- iput(ichild);
-
- entry->se_dentry = NULL;
- entry->se_inode = NULL;
- if (found) {
- if (lookup) {
- LASSERT(*dentryp != dchild);
- /* VFS will drop the reference
- * count for dchild and *dentryp
- * by itself. */
- *dentryp = dchild;
- } else {
- LASSERT(*dentryp == dchild);
- /* Drop the dentry reference
- * count held by statahead. */
- dput(dchild);
- }
- RETURN(1);
- } else {
- /* Drop the dentry reference count held
- * by statahead. */
- dput(dchild);
- }
- }
- }
-