nfs: abstract out code needed to complete a sillyrename
authorJeff Layton <jlayton@redhat.com>
Mon, 17 Mar 2014 11:06:54 +0000 (07:06 -0400)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 17 Mar 2014 19:14:16 +0000 (15:14 -0400)
The async rename code is currently "polluted" with some parts that are
really just for sillyrenames. Add a new "complete" operation vector to
the nfs_renamedata to separate out the stuff that just needs to be done
for a sillyrename.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Tested-by: Anna Schumaker <Anna.Schumaker@netapp.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/unlink.c
include/linux/nfs_xdr.h

index 11d78944de795be25d3232b795f677fd0fe64efa..3e6798c9ba1faeb43763f34c46f63168b6b0e577 100644 (file)
@@ -353,8 +353,8 @@ static void nfs_async_rename_done(struct rpc_task *task, void *calldata)
                return;
        }
 
-       if (task->tk_status != 0)
-               nfs_cancel_async_unlink(old_dentry);
+       if (data->complete)
+               data->complete(task, data);
 }
 
 /**
@@ -401,7 +401,8 @@ static const struct rpc_call_ops nfs_rename_ops = {
  */
 static struct rpc_task *
 nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
-                struct dentry *old_dentry, struct dentry *new_dentry)
+                struct dentry *old_dentry, struct dentry *new_dentry,
+                void (*complete)(struct rpc_task *, struct nfs_renamedata *))
 {
        struct nfs_renamedata *data;
        struct rpc_message msg = { };
@@ -438,6 +439,7 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
        data->new_dentry = dget(new_dentry);
        nfs_fattr_init(&data->old_fattr);
        nfs_fattr_init(&data->new_fattr);
+       data->complete = complete;
 
        /* set up nfs_renameargs */
        data->args.old_dir = NFS_FH(old_dir);
@@ -456,6 +458,17 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
        return rpc_run_task(&task_setup_data);
 }
 
+/*
+ * Perform tasks needed when a sillyrename is done such as cancelling the
+ * queued async unlink if it failed.
+ */
+static void
+nfs_complete_sillyrename(struct rpc_task *task, struct nfs_renamedata *data)
+{
+       if (task->tk_status != 0)
+               nfs_cancel_async_unlink(data->old_dentry);
+}
+
 #define SILLYNAME_PREFIX ".nfs"
 #define SILLYNAME_PREFIX_LEN ((unsigned)sizeof(SILLYNAME_PREFIX) - 1)
 #define SILLYNAME_FILEID_LEN ((unsigned)sizeof(u64) << 1)
@@ -548,7 +561,8 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
        }
 
        /* run the rename task, undo unlink if it fails */
-       task = nfs_async_rename(dir, dir, dentry, sdentry);
+       task = nfs_async_rename(dir, dir, dentry, sdentry,
+                                       nfs_complete_sillyrename);
        if (IS_ERR(task)) {
                error = -EBUSY;
                nfs_cancel_async_unlink(dentry);
index b2fb167b2e6d99ed71a1ab6ddeae6c7c3885600a..0534184b65ce6ed4e9d97ba17389cbddbaa6f940 100644 (file)
@@ -1397,6 +1397,7 @@ struct nfs_renamedata {
        struct inode            *new_dir;
        struct dentry           *new_dentry;
        struct nfs_fattr        new_fattr;
+       void (*complete)(struct rpc_task *, struct nfs_renamedata *);
 };
 
 struct nfs_access_entry;