+ CDEBUG(D_INFO, "intent %p released\n", it);
+ ll_intent_drop_lock(it);
+#ifdef LUSTRE_KERNEL_VERSION
+ it->it_magic = 0;
+ it->it_op_release = 0;
+#endif
+ /* We are still holding extra reference on a request, need to free it */
+ if (it_disposition(it, DISP_ENQ_OPEN_REF)) /* open req for llfile_open*/
+ ptlrpc_req_finished(it->d.lustre.it_data);
+ if (it_disposition(it, DISP_ENQ_CREATE_REF)) /* create rec */
+ ptlrpc_req_finished(it->d.lustre.it_data);
+ if (it_disposition(it, DISP_ENQ_COMPLETE)) /* saved req from revalidate
+ * to lookup */
+ ptlrpc_req_finished(it->d.lustre.it_data);
+
+ it->d.lustre.it_disposition = 0;
+ it->d.lustre.it_data = NULL;
+ EXIT;
+}
+
+/* Drop dentry if it is not used already, unhash otherwise.
+ Should be called with dcache lock held!
+ Returns: 1 if dentry was dropped, 0 if unhashed. */
+int ll_drop_dentry(struct dentry *dentry)
+{
+ lock_dentry(dentry);
+ if (atomic_read(&dentry->d_count) == 0) {
+ CDEBUG(D_DENTRY, "deleting dentry %.*s (%p) parent %p "
+ "inode %p\n", dentry->d_name.len,
+ dentry->d_name.name, dentry, dentry->d_parent,
+ dentry->d_inode);
+ dget_locked(dentry);
+ __d_drop(dentry);
+ unlock_dentry(dentry);
+ spin_unlock(&dcache_lock);
+ dput(dentry);
+ spin_lock(&dcache_lock);
+ return 1;
+ }
+ /* disconected dentry can not be find without lookup, because we
+ * not need his to unhash or mark invalid. */
+ if (dentry->d_flags & DCACHE_DISCONNECTED) {
+ unlock_dentry(dentry);
+ RETURN (0);
+ }
+
+#ifdef LUSTRE_KERNEL_VERSION
+ if (!(dentry->d_flags & DCACHE_LUSTRE_INVALID)) {
+#else
+ if (!d_unhashed(dentry)) {
+#endif
+ CDEBUG(D_DENTRY, "unhashing dentry %.*s (%p) parent %p "
+ "inode %p refc %d\n", dentry->d_name.len,
+ dentry->d_name.name, dentry, dentry->d_parent,
+ dentry->d_inode, atomic_read(&dentry->d_count));
+ /* actually we don't unhash the dentry, rather just
+ * mark it inaccessible for to __d_lookup(). otherwise
+ * sys_getcwd() could return -ENOENT -bzzz */
+#ifdef LUSTRE_KERNEL_VERSION
+ dentry->d_flags |= DCACHE_LUSTRE_INVALID;
+#endif
+ if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode))
+ __d_drop(dentry);
+
+ }
+ unlock_dentry(dentry);
+ return 0;
+}
+
+void ll_unhash_aliases(struct inode *inode)
+{
+ struct list_head *tmp, *head;
+ ENTRY;
+
+ if (inode == NULL) {
+ CERROR("unexpected NULL inode, tell phil\n");