+ 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_GETATTR};
+ struct dentry *dchild = entry->se_dentry;
+ struct inode *ichild = entry->se_inode;
+ int found = 0;
+ __u32 bits;
+
+ LASSERT(dchild != *dentryp);
+
+ if (!lookup)
+ mutex_lock(&dir->i_mutex);
+
+ rc = md_revalidate_lock(ll_i2mdexp(dir), &it,
+ ll_inode2fid(ichild),
+ &bits);
+ if (rc == 1) {
+ struct dentry *save = dchild;
+
+ ll_lookup_it_alias(&dchild, ichild,
+ bits);
+ ll_lookup_finish_locks(&it, dchild);
+ if (dchild != save)
+ dput(save);
+ found = is_same_dentry(dchild,
+ *dentryp);
+ } else {
+ /* Someone has canceled related ldlm
+ * lock before the real "revalidate"
+ * using it.
+ * Drop the inode reference count held
+ * by interpreter. */
+ iput(ichild);
+ }
+
+ if (!lookup)
+ mutex_unlock(&dir->i_mutex);
+
+ entry->se_dentry = NULL;
+ entry->se_inode = NULL;
+ if (found) {
+ if (lookup) {
+ LASSERT(dchild != *dentryp);
+ /* VFS will drop the reference
+ * count for dchild and *dentryp
+ * by itself. */
+ *dentryp = dchild;
+ } else {
+ LASSERT(dchild == *dentryp);
+ /* Drop the dentry reference
+ * count held by statahead. */
+ dput(dchild);
+ }
+ RETURN(1);
+ } else {
+ /* Drop the dentry reference count held
+ * by statahead. */
+ dput(dchild);
+ }
+ }