diff options
Diffstat (limited to 'fs/nfs/unlink.c')
-rw-r--r-- | fs/nfs/unlink.c | 45 |
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 | |||
17 | struct nfs_unlinkdata { | 19 | struct 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 | */ | ||
75 | static 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 | ||
119 | static const struct rpc_call_ops nfs_unlink_ops = { | 104 | static 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 | ||
125 | static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data) | 109 | static 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; |