aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/unlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/unlink.c')
-rw-r--r--fs/nfs/unlink.c45
1 files changed, 23 insertions, 22 deletions
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 233ad38161f9..757415363422 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -14,6 +14,8 @@
14#include <linux/sched.h> 14#include <linux/sched.h>
15#include <linux/wait.h> 15#include <linux/wait.h>
16 16
17#include "internal.h"
18
17struct nfs_unlinkdata { 19struct nfs_unlinkdata {
18 struct hlist_node list; 20 struct hlist_node list;
19 struct nfs_removeargs args; 21 struct nfs_removeargs args;
@@ -69,24 +71,6 @@ static void nfs_dec_sillycount(struct inode *dir)
69} 71}
70 72
71/** 73/**
72 * nfs_async_unlink_init - Initialize the RPC info
73 * task: rpc_task of the sillydelete
74 */
75static void nfs_async_unlink_init(struct rpc_task *task, void *calldata)
76{
77 struct nfs_unlinkdata *data = calldata;
78 struct inode *dir = data->dir;
79 struct rpc_message msg = {
80 .rpc_argp = &data->args,
81 .rpc_resp = &data->res,
82 .rpc_cred = data->cred,
83 };
84
85 NFS_PROTO(dir)->unlink_setup(&msg, dir);
86 rpc_call_setup(task, &msg, 0);
87}
88
89/**
90 * nfs_async_unlink_done - Sillydelete post-processing 74 * nfs_async_unlink_done - Sillydelete post-processing
91 * @task: rpc_task of the sillydelete 75 * @task: rpc_task of the sillydelete
92 * 76 *
@@ -113,32 +97,45 @@ static void nfs_async_unlink_release(void *calldata)
113 struct nfs_unlinkdata *data = calldata; 97 struct nfs_unlinkdata *data = calldata;
114 98
115 nfs_dec_sillycount(data->dir); 99 nfs_dec_sillycount(data->dir);
100 nfs_sb_deactive(NFS_SERVER(data->dir));
116 nfs_free_unlinkdata(data); 101 nfs_free_unlinkdata(data);
117} 102}
118 103
119static const struct rpc_call_ops nfs_unlink_ops = { 104static const struct rpc_call_ops nfs_unlink_ops = {
120 .rpc_call_prepare = nfs_async_unlink_init,
121 .rpc_call_done = nfs_async_unlink_done, 105 .rpc_call_done = nfs_async_unlink_done,
122 .rpc_release = nfs_async_unlink_release, 106 .rpc_release = nfs_async_unlink_release,
123}; 107};
124 108
125static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data) 109static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data)
126{ 110{
111 struct rpc_message msg = {
112 .rpc_argp = &data->args,
113 .rpc_resp = &data->res,
114 .rpc_cred = data->cred,
115 };
116 struct rpc_task_setup task_setup_data = {
117 .rpc_message = &msg,
118 .callback_ops = &nfs_unlink_ops,
119 .callback_data = data,
120 .flags = RPC_TASK_ASYNC,
121 };
127 struct rpc_task *task; 122 struct rpc_task *task;
128 struct dentry *alias; 123 struct dentry *alias;
129 124
130 alias = d_lookup(parent, &data->args.name); 125 alias = d_lookup(parent, &data->args.name);
131 if (alias != NULL) { 126 if (alias != NULL) {
132 int ret = 0; 127 int ret = 0;
128
133 /* 129 /*
134 * Hey, we raced with lookup... See if we need to transfer 130 * Hey, we raced with lookup... See if we need to transfer
135 * the sillyrename information to the aliased dentry. 131 * the sillyrename information to the aliased dentry.
136 */ 132 */
137 nfs_free_dname(data); 133 nfs_free_dname(data);
138 spin_lock(&alias->d_lock); 134 spin_lock(&alias->d_lock);
139 if (!(alias->d_flags & DCACHE_NFSFS_RENAMED)) { 135 if (alias->d_inode != NULL &&
136 !(alias->d_flags & DCACHE_NFSFS_RENAMED)) {
140 alias->d_fsdata = data; 137 alias->d_fsdata = data;
141 alias->d_flags ^= DCACHE_NFSFS_RENAMED; 138 alias->d_flags |= DCACHE_NFSFS_RENAMED;
142 ret = 1; 139 ret = 1;
143 } 140 }
144 spin_unlock(&alias->d_lock); 141 spin_unlock(&alias->d_lock);
@@ -151,10 +148,14 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
151 nfs_dec_sillycount(dir); 148 nfs_dec_sillycount(dir);
152 return 0; 149 return 0;
153 } 150 }
151 nfs_sb_active(NFS_SERVER(dir));
154 data->args.fh = NFS_FH(dir); 152 data->args.fh = NFS_FH(dir);
155 nfs_fattr_init(&data->res.dir_attr); 153 nfs_fattr_init(&data->res.dir_attr);
156 154
157 task = rpc_run_task(NFS_CLIENT(dir), RPC_TASK_ASYNC, &nfs_unlink_ops, data); 155 NFS_PROTO(dir)->unlink_setup(&msg, dir);
156
157 task_setup_data.rpc_client = NFS_CLIENT(dir);
158 task = rpc_run_task(&task_setup_data);
158 if (!IS_ERR(task)) 159 if (!IS_ERR(task))
159 rpc_put_task(task); 160 rpc_put_task(task);
160 return 1; 161 return 1;