+ clli = agl_first_entry(sai);
+ list_del_init(&clli->lli_agl_list);
+ spin_unlock(&lli->lli_agl_lock);
+
+ ll_agl_trigger(&clli->lli_vfs_inode, sai);
+
+ spin_lock(&lli->lli_agl_lock);
+ }
+ spin_unlock(&lli->lli_agl_lock);
+}
+
+static int ll_statahead_interpret(struct ptlrpc_request *req,
+ struct md_enqueue_info *minfo, int rc)
+{
+ struct lookup_intent *it = &minfo->mi_it;
+ struct inode *dir = minfo->mi_dir;
+ struct ll_inode_info *lli = ll_i2info(dir);
+ struct ll_statahead_info *sai;
+ struct ll_sa_entry *entry;
+ int wakeup;
+ ENTRY;
+
+ if (it_disposition(it, DISP_LOOKUP_NEG))
+ rc = -ENOENT;
+
+ sai = ll_sai_get(dir);
+ LASSERT(sai != NULL);
+ LASSERT(!thread_is_stopped(&sai->sai_thread));
+
+ spin_lock(&lli->lli_sa_lock);
+ entry = ll_sa_entry_get_byindex(sai, minfo->mi_cbdata);
+ LASSERT(entry != NULL);
+ if (rc != 0) {
+ __sa_entry_post_stat(sai, entry, SA_ENTRY_INVA);
+ wakeup = (entry->se_index == sai->sai_index_wait);
+ } else {
+ entry->se_minfo = minfo;
+ entry->se_req = ptlrpc_request_addref(req);
+ /* Release the async ibits lock ASAP to avoid deadlock
+ * when statahead thread tries to enqueue lock on parent
+ * for readpage and other tries to enqueue lock on child
+ * with parent's lock held, for example: unlink. */
+ entry->se_handle = it->d.lustre.it_lock_handle;
+ ll_intent_drop_lock(it);
+ wakeup = sa_received_empty(sai);
+ list_add_tail(&entry->se_list, &sai->sai_entries_received);
+ }
+ sai->sai_replied++;
+ spin_unlock(&lli->lli_sa_lock);
+
+ ll_sa_entry_put(sai, entry);
+ if (wakeup)
+ wake_up(&sai->sai_thread.t_ctl_waitq);
+
+ if (rc != 0) {
+ ll_intent_release(it);
+ iput(dir);
+ OBD_FREE_PTR(minfo);
+ }
+ ll_sai_put(sai);
+ RETURN(rc);