+ out:
+ if (req != NULL && rc == 1)
+ ptlrpc_req_finished(req);
+ if (rc == 0) {
+ ll_unhash_aliases(de->d_inode);
+ /* done in ll_unhash_aliases()
+ de->d_flags |= DCACHE_LUSTRE_INVALID; */
+ } else {
+ CDEBUG(D_DENTRY, "revalidated dentry %*s (%p) parent %p "
+ "inode %p refc %d\n", de->d_name.len,
+ de->d_name.name, de, de->d_parent, de->d_inode,
+ atomic_read(&de->d_count));
+ ll_lookup_finish_locks(it, de);
+ de->d_flags &= ~DCACHE_LUSTRE_INVALID;
+ }
+ RETURN(rc);
+}
+
+/*static*/ void ll_pin(struct dentry *de, struct vfsmount *mnt, int flag)
+{
+ struct inode *inode= de->d_inode;
+ struct ll_sb_info *sbi = ll_i2sbi(inode);
+ struct ll_dentry_data *ldd = ll_d2d(de);
+ struct obd_client_handle *handle;
+ int rc = 0;
+ ENTRY;
+ LASSERT(ldd);
+
+ lock_kernel();
+ /* Strictly speaking this introduces an additional race: the
+ * increments should wait until the rpc has returned.
+ * However, given that at present the function is void, this
+ * issue is moot. */
+ if (flag == 1 && (++ldd->lld_mnt_count) > 1) {
+ unlock_kernel();
+ EXIT;
+ return;
+ }
+
+ if (flag == 0 && (++ldd->lld_cwd_count) > 1) {
+ unlock_kernel();
+ EXIT;
+ return;
+ }
+ unlock_kernel();
+
+ handle = (flag) ? &ldd->lld_mnt_och : &ldd->lld_cwd_och;
+ rc = obd_pin(sbi->ll_mdc_exp, inode->i_ino, inode->i_generation,
+ inode->i_mode & S_IFMT, handle, flag);
+
+ if (rc) {
+ lock_kernel();
+ memset(handle, 0, sizeof(*handle));
+ if (flag == 0)
+ ldd->lld_cwd_count--;
+ else
+ ldd->lld_mnt_count--;
+ unlock_kernel();
+ }
+
+ EXIT;
+ return;
+}
+
+/*static*/ void ll_unpin(struct dentry *de, struct vfsmount *mnt, int flag)
+{
+ struct ll_sb_info *sbi = ll_i2sbi(de->d_inode);
+ struct ll_dentry_data *ldd = ll_d2d(de);
+ struct obd_client_handle handle;
+ int count, rc = 0;
+ ENTRY;
+ LASSERT(ldd);
+
+ lock_kernel();
+ /* Strictly speaking this introduces an additional race: the
+ * increments should wait until the rpc has returned.
+ * However, given that at present the function is void, this
+ * issue is moot. */
+ handle = (flag) ? ldd->lld_mnt_och : ldd->lld_cwd_och;
+ if (handle.och_magic != OBD_CLIENT_HANDLE_MAGIC) {
+ /* the "pin" failed */
+ unlock_kernel();
+ EXIT;
+ return;
+ }
+
+ if (flag)
+ count = --ldd->lld_mnt_count;
+ else
+ count = --ldd->lld_cwd_count;
+ unlock_kernel();
+
+ if (count != 0) {
+ EXIT;
+ return;
+ }
+
+ rc = obd_unpin(sbi->ll_mdc_exp, &handle, flag);
+ EXIT;
+ return;
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+static int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd)
+{
+ int rc;
+ ENTRY;
+
+ if (nd && nd->flags & LOOKUP_LAST && !(nd->flags & LOOKUP_LINK_NOTLAST))
+ rc = ll_revalidate_it(dentry, nd->flags, &nd->intent);
+ else
+ rc = ll_revalidate_it(dentry, 0, NULL);
+
+ RETURN(rc);
+}
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+static void ll_dentry_iput(struct dentry *dentry, struct inode *inode)
+{
+ struct ll_sb_info *sbi = ll_i2sbi(inode);
+ struct ll_fid parent, child;
+
+ LASSERT(dentry->d_parent && dentry->d_parent->d_inode);
+ ll_inode2fid(&parent, dentry->d_parent->d_inode);
+ ll_inode2fid(&child, inode);
+ md_change_cbdata_name(sbi->ll_mdc_exp, &parent,
+ (char *)dentry->d_name.name,
+ dentry->d_name.len, &child,
+ null_if_equal, inode);
+ iput(inode);