+ lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
+ rc = l_wait_event(sai->sai_waitq,
+ ll_sai_entry_stated(sai) ||
+ sa_is_stopped(sai),
+ &lwi);
+ if (unlikely(rc == -EINTR))
+ RETURN(rc);
+ }
+
+ 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);
+ }
+ }