+ struct inode *cache_new_inode = new_dentry->d_inode ?
+ I2CI(new_dentry->d_inode) : NULL;
+
+ struct dentry *cache_old_dentry = NULL;
+ struct dentry *cache_new_dentry = NULL;
+ struct dentry *cache_new_parent = NULL;
+ struct dentry *cache_old_parent = NULL;
+ void *handle = NULL;
+ int rc = 0;
+
+ if (!cache_old_dir || !cache_new_dir || !cache_old_inode)
+ RETURN(-ENOENT);
+
+ handle = smfs_trans_start(old_dir, FSFILT_OP_RENAME, NULL);
+ if (IS_ERR(handle)) {
+ CERROR("smfs_do_mkdir: no space for transaction\n");
+ RETURN(-ENOSPC);
+ }
+ lock_kernel();
+
+
+ SMFS_HOOK(old_dir, old_dentry, new_dir, new_dentry, HOOK_RENAME, handle,
+ PRE_HOOK, rc, exit);
+
+ cache_old_parent = pre_smfs_dentry(NULL, cache_old_dir, old_dentry, NULL);
+ cache_old_dentry = pre_smfs_dentry(cache_old_parent, cache_old_inode,
+ old_dentry, NULL);
+ if (!cache_old_parent || !cache_old_dentry)
+ GOTO(exit, rc = -ENOMEM);
+
+ cache_new_parent = pre_smfs_dentry(NULL, cache_new_dir, new_dentry, NULL);
+ cache_new_dentry = pre_smfs_dentry(cache_new_parent, cache_new_inode,
+ new_dentry, NULL);
+ if (!cache_new_parent || !cache_new_dentry)
+ GOTO(exit, rc = -ENOMEM);
+
+ pre_smfs_inode(old_dir, cache_old_dir);
+ pre_smfs_inode(new_dir, cache_new_dir);
+
+ if (cache_old_dir->i_op->rename)
+ rc = cache_old_dir->i_op->rename(cache_old_dir, cache_old_dentry,
+ cache_new_dir, cache_new_dentry);
+
+ post_smfs_inode(old_dir, cache_old_dir);
+ post_smfs_inode(new_dir, cache_new_dir);
+
+ SMFS_HOOK(old_dir, old_dentry, new_dir, new_dentry, HOOK_RENAME, handle,
+ POST_HOOK, rc, exit);
+
+ if (new_dentry->d_inode)
+ post_smfs_inode(new_dentry->d_inode, cache_new_dentry->d_inode);
+exit:
+ unlock_kernel();
+ post_smfs_dentry(cache_old_dentry);
+ post_smfs_dentry(cache_old_parent);
+ post_smfs_dentry(cache_new_dentry);
+ post_smfs_dentry(cache_new_parent);
+ smfs_trans_commit(old_dir, handle, 0);
+ RETURN(rc);