Branch data Line data Source code
1 : : /*
2 : : * linux/fs/nfs/unlink.c
3 : : *
4 : : * nfs sillydelete handling
5 : : *
6 : : */
7 : :
8 : : #include <linux/slab.h>
9 : : #include <linux/string.h>
10 : : #include <linux/dcache.h>
11 : : #include <linux/sunrpc/sched.h>
12 : : #include <linux/sunrpc/clnt.h>
13 : : #include <linux/nfs_fs.h>
14 : : #include <linux/sched.h>
15 : : #include <linux/wait.h>
16 : : #include <linux/namei.h>
17 : :
18 : : #include "internal.h"
19 : : #include "nfs4_fs.h"
20 : : #include "iostat.h"
21 : : #include "delegation.h"
22 : :
23 : : #include "nfstrace.h"
24 : :
25 : : /**
26 : : * nfs_free_unlinkdata - release data from a sillydelete operation.
27 : : * @data: pointer to unlink structure.
28 : : */
29 : : static void
30 : 0 : nfs_free_unlinkdata(struct nfs_unlinkdata *data)
31 : : {
32 : 0 : iput(data->dir);
33 : 0 : put_rpccred(data->cred);
34 : 0 : kfree(data->args.name.name);
35 : 0 : kfree(data);
36 : 0 : }
37 : :
38 : : #define NAME_ALLOC_LEN(len) ((len+16) & ~15)
39 : : /**
40 : : * nfs_copy_dname - copy dentry name to data structure
41 : : * @dentry: pointer to dentry
42 : : * @data: nfs_unlinkdata
43 : : */
44 : : static int nfs_copy_dname(struct dentry *dentry, struct nfs_unlinkdata *data)
45 : : {
46 : : char *str;
47 : 0 : int len = dentry->d_name.len;
48 : :
49 : 0 : str = kmemdup(dentry->d_name.name, NAME_ALLOC_LEN(len), GFP_KERNEL);
50 [ # # # # ]: 0 : if (!str)
51 : : return -ENOMEM;
52 : 0 : data->args.name.len = len;
53 : 0 : data->args.name.name = str;
54 : : return 0;
55 : : }
56 : :
57 : : static void nfs_free_dname(struct nfs_unlinkdata *data)
58 : : {
59 : 0 : kfree(data->args.name.name);
60 : 0 : data->args.name.name = NULL;
61 : 0 : data->args.name.len = 0;
62 : : }
63 : :
64 : 0 : static void nfs_dec_sillycount(struct inode *dir)
65 : : {
66 : : struct nfs_inode *nfsi = NFS_I(dir);
67 [ # # ]: 0 : if (atomic_dec_return(&nfsi->silly_count) == 1)
68 : 0 : wake_up(&nfsi->waitqueue);
69 : 0 : }
70 : :
71 : : /**
72 : : * nfs_async_unlink_done - Sillydelete post-processing
73 : : * @task: rpc_task of the sillydelete
74 : : *
75 : : * Do the directory attribute update.
76 : : */
77 : 0 : static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
78 : : {
79 : : struct nfs_unlinkdata *data = calldata;
80 : 0 : struct inode *dir = data->dir;
81 : :
82 : 0 : trace_nfs_sillyrename_unlink(data, task->tk_status);
83 [ # # ]: 0 : if (!NFS_PROTO(dir)->unlink_done(task, dir))
84 : 0 : rpc_restart_call_prepare(task);
85 : 0 : }
86 : :
87 : : /**
88 : : * nfs_async_unlink_release - Release the sillydelete data.
89 : : * @task: rpc_task of the sillydelete
90 : : *
91 : : * We need to call nfs_put_unlinkdata as a 'tk_release' task since the
92 : : * rpc_task would be freed too.
93 : : */
94 : 0 : static void nfs_async_unlink_release(void *calldata)
95 : : {
96 : : struct nfs_unlinkdata *data = calldata;
97 : 0 : struct super_block *sb = data->dir->i_sb;
98 : :
99 : 0 : nfs_dec_sillycount(data->dir);
100 : 0 : nfs_free_unlinkdata(data);
101 : 0 : nfs_sb_deactive(sb);
102 : 0 : }
103 : :
104 : 0 : static void nfs_unlink_prepare(struct rpc_task *task, void *calldata)
105 : : {
106 : : struct nfs_unlinkdata *data = calldata;
107 : 0 : NFS_PROTO(data->dir)->unlink_rpc_prepare(task, data);
108 : 0 : }
109 : :
110 : : static const struct rpc_call_ops nfs_unlink_ops = {
111 : : .rpc_call_done = nfs_async_unlink_done,
112 : : .rpc_release = nfs_async_unlink_release,
113 : : .rpc_call_prepare = nfs_unlink_prepare,
114 : : };
115 : :
116 : 0 : static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data)
117 : : {
118 : 0 : struct rpc_message msg = {
119 : 0 : .rpc_argp = &data->args,
120 : 0 : .rpc_resp = &data->res,
121 : 0 : .rpc_cred = data->cred,
122 : : };
123 : 0 : struct rpc_task_setup task_setup_data = {
124 : : .rpc_message = &msg,
125 : : .callback_ops = &nfs_unlink_ops,
126 : : .callback_data = data,
127 : : .workqueue = nfsiod_workqueue,
128 : : .flags = RPC_TASK_ASYNC,
129 : : };
130 : : struct rpc_task *task;
131 : 0 : struct dentry *alias;
132 : :
133 : 0 : alias = d_lookup(parent, &data->args.name);
134 [ # # ]: 0 : if (alias != NULL) {
135 : : int ret;
136 : : void *devname_garbage = NULL;
137 : :
138 : : /*
139 : : * Hey, we raced with lookup... See if we need to transfer
140 : : * the sillyrename information to the aliased dentry.
141 : : */
142 : : nfs_free_dname(data);
143 : : ret = nfs_copy_dname(alias, data);
144 : : spin_lock(&alias->d_lock);
145 [ # # ][ # # ]: 0 : if (ret == 0 && alias->d_inode != NULL &&
[ # # ]
146 : 0 : !(alias->d_flags & DCACHE_NFSFS_RENAMED)) {
147 : 0 : devname_garbage = alias->d_fsdata;
148 : 0 : alias->d_fsdata = data;
149 : 0 : alias->d_flags |= DCACHE_NFSFS_RENAMED;
150 : 0 : ret = 1;
151 : : } else
152 : : ret = 0;
153 : : spin_unlock(&alias->d_lock);
154 : 0 : nfs_dec_sillycount(dir);
155 : 0 : dput(alias);
156 : : /*
157 : : * If we'd displaced old cached devname, free it. At that
158 : : * point dentry is definitely not a root, so we won't need
159 : : * that anymore.
160 : : */
161 : 0 : kfree(devname_garbage);
162 : 0 : return ret;
163 : : }
164 : 0 : data->dir = igrab(dir);
165 [ # # ]: 0 : if (!data->dir) {
166 : 0 : nfs_dec_sillycount(dir);
167 : 0 : return 0;
168 : : }
169 : 0 : nfs_sb_active(dir->i_sb);
170 : 0 : data->args.fh = NFS_FH(dir);
171 : 0 : nfs_fattr_init(data->res.dir_attr);
172 : :
173 : 0 : NFS_PROTO(dir)->unlink_setup(&msg, dir);
174 : :
175 : 0 : task_setup_data.rpc_client = NFS_CLIENT(dir);
176 : 0 : task = rpc_run_task(&task_setup_data);
177 [ # # ]: 0 : if (!IS_ERR(task))
178 : 0 : rpc_put_task_async(task);
179 : : return 1;
180 : : }
181 : :
182 : 0 : static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
183 : : {
184 : : struct dentry *parent;
185 : : struct inode *dir;
186 : : int ret = 0;
187 : :
188 : :
189 : 0 : parent = dget_parent(dentry);
190 [ # # ]: 0 : if (parent == NULL)
191 : : goto out_free;
192 : 0 : dir = parent->d_inode;
193 : : /* Non-exclusive lock protects against concurrent lookup() calls */
194 : : spin_lock(&dir->i_lock);
195 [ # # ]: 0 : if (atomic_inc_not_zero(&NFS_I(dir)->silly_count) == 0) {
196 : : /* Deferred delete */
197 : 0 : hlist_add_head(&data->list, &NFS_I(dir)->silly_list);
198 : : spin_unlock(&dir->i_lock);
199 : : ret = 1;
200 : 0 : goto out_dput;
201 : : }
202 : : spin_unlock(&dir->i_lock);
203 : 0 : ret = nfs_do_call_unlink(parent, dir, data);
204 : : out_dput:
205 : 0 : dput(parent);
206 : : out_free:
207 : 0 : return ret;
208 : : }
209 : :
210 : 0 : void nfs_wait_on_sillyrename(struct dentry *dentry)
211 : : {
212 : 0 : struct nfs_inode *nfsi = NFS_I(dentry->d_inode);
213 : :
214 [ # # ][ # # ]: 0 : wait_event(nfsi->waitqueue, atomic_read(&nfsi->silly_count) <= 1);
215 : 0 : }
216 : :
217 : 0 : void nfs_block_sillyrename(struct dentry *dentry)
218 : : {
219 : 0 : struct nfs_inode *nfsi = NFS_I(dentry->d_inode);
220 : :
221 [ # # ][ # # ]: 0 : wait_event(nfsi->waitqueue, atomic_cmpxchg(&nfsi->silly_count, 1, 0) == 1);
222 : 0 : }
223 : :
224 : 0 : void nfs_unblock_sillyrename(struct dentry *dentry)
225 : : {
226 : 0 : struct inode *dir = dentry->d_inode;
227 : : struct nfs_inode *nfsi = NFS_I(dir);
228 : : struct nfs_unlinkdata *data;
229 : :
230 : 0 : atomic_inc(&nfsi->silly_count);
231 : : spin_lock(&dir->i_lock);
232 [ # # ]: 0 : while (!hlist_empty(&nfsi->silly_list)) {
233 [ # # ]: 0 : if (!atomic_inc_not_zero(&nfsi->silly_count))
234 : : break;
235 : 0 : data = hlist_entry(nfsi->silly_list.first, struct nfs_unlinkdata, list);
236 : : hlist_del(&data->list);
237 : : spin_unlock(&dir->i_lock);
238 [ # # ]: 0 : if (nfs_do_call_unlink(dentry, dir, data) == 0)
239 : 0 : nfs_free_unlinkdata(data);
240 : : spin_lock(&dir->i_lock);
241 : : }
242 : : spin_unlock(&dir->i_lock);
243 : 0 : }
244 : :
245 : : /**
246 : : * nfs_async_unlink - asynchronous unlinking of a file
247 : : * @dir: parent directory of dentry
248 : : * @dentry: dentry to unlink
249 : : */
250 : : static int
251 : 0 : nfs_async_unlink(struct inode *dir, struct dentry *dentry)
252 : : {
253 : : struct nfs_unlinkdata *data;
254 : : int status = -ENOMEM;
255 : : void *devname_garbage = NULL;
256 : :
257 : : data = kzalloc(sizeof(*data), GFP_KERNEL);
258 [ # # ]: 0 : if (data == NULL)
259 : : goto out;
260 : :
261 : 0 : data->cred = rpc_lookup_cred();
262 [ # # ]: 0 : if (IS_ERR(data->cred)) {
263 : : status = PTR_ERR(data->cred);
264 : : goto out_free;
265 : : }
266 : 0 : data->res.dir_attr = &data->dir_attr;
267 : :
268 : : status = -EBUSY;
269 : : spin_lock(&dentry->d_lock);
270 [ # # ]: 0 : if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
271 : : goto out_unlock;
272 : 0 : dentry->d_flags |= DCACHE_NFSFS_RENAMED;
273 : 0 : devname_garbage = dentry->d_fsdata;
274 : 0 : dentry->d_fsdata = data;
275 : : spin_unlock(&dentry->d_lock);
276 : : /*
277 : : * If we'd displaced old cached devname, free it. At that
278 : : * point dentry is definitely not a root, so we won't need
279 : : * that anymore.
280 : : */
281 : 0 : kfree(devname_garbage);
282 : : return 0;
283 : : out_unlock:
284 : : spin_unlock(&dentry->d_lock);
285 : 0 : put_rpccred(data->cred);
286 : : out_free:
287 : 0 : kfree(data);
288 : : out:
289 : : return status;
290 : : }
291 : :
292 : : /**
293 : : * nfs_complete_unlink - Initialize completion of the sillydelete
294 : : * @dentry: dentry to delete
295 : : * @inode: inode
296 : : *
297 : : * Since we're most likely to be called by dentry_iput(), we
298 : : * only use the dentry to find the sillydelete. We then copy the name
299 : : * into the qstr.
300 : : */
301 : : void
302 : 0 : nfs_complete_unlink(struct dentry *dentry, struct inode *inode)
303 : : {
304 : : struct nfs_unlinkdata *data = NULL;
305 : :
306 : : spin_lock(&dentry->d_lock);
307 [ # # ]: 0 : if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
308 : 0 : dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
309 : 0 : data = dentry->d_fsdata;
310 : 0 : dentry->d_fsdata = NULL;
311 : : }
312 : : spin_unlock(&dentry->d_lock);
313 : :
314 [ # # ][ # # ]: 0 : if (data != NULL && (NFS_STALE(inode) || !nfs_call_unlink(dentry, data)))
[ # # ]
315 : 0 : nfs_free_unlinkdata(data);
316 : 0 : }
317 : :
318 : : /* Cancel a queued async unlink. Called when a sillyrename run fails. */
319 : : static void
320 : 0 : nfs_cancel_async_unlink(struct dentry *dentry)
321 : : {
322 : : spin_lock(&dentry->d_lock);
323 [ # # ]: 0 : if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
324 : 0 : struct nfs_unlinkdata *data = dentry->d_fsdata;
325 : :
326 : 0 : dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
327 : 0 : dentry->d_fsdata = NULL;
328 : : spin_unlock(&dentry->d_lock);
329 : 0 : nfs_free_unlinkdata(data);
330 : 0 : return;
331 : : }
332 : : spin_unlock(&dentry->d_lock);
333 : : }
334 : :
335 : : /**
336 : : * nfs_async_rename_done - Sillyrename post-processing
337 : : * @task: rpc_task of the sillyrename
338 : : * @calldata: nfs_renamedata for the sillyrename
339 : : *
340 : : * Do the directory attribute updates and the d_move
341 : : */
342 : 0 : static void nfs_async_rename_done(struct rpc_task *task, void *calldata)
343 : : {
344 : : struct nfs_renamedata *data = calldata;
345 : 0 : struct inode *old_dir = data->old_dir;
346 : 0 : struct inode *new_dir = data->new_dir;
347 : 0 : struct dentry *old_dentry = data->old_dentry;
348 : :
349 : 0 : trace_nfs_sillyrename_rename(old_dir, old_dentry,
350 : 0 : new_dir, data->new_dentry, task->tk_status);
351 [ # # ]: 0 : if (!NFS_PROTO(old_dir)->rename_done(task, old_dir, new_dir)) {
352 : 0 : rpc_restart_call_prepare(task);
353 : 0 : return;
354 : : }
355 : :
356 [ # # ]: 0 : if (task->tk_status != 0)
357 : 0 : nfs_cancel_async_unlink(old_dentry);
358 : : }
359 : :
360 : : /**
361 : : * nfs_async_rename_release - Release the sillyrename data.
362 : : * @calldata: the struct nfs_renamedata to be released
363 : : */
364 : 0 : static void nfs_async_rename_release(void *calldata)
365 : : {
366 : : struct nfs_renamedata *data = calldata;
367 : 0 : struct super_block *sb = data->old_dir->i_sb;
368 : :
369 [ # # ]: 0 : if (data->old_dentry->d_inode)
370 : : nfs_mark_for_revalidate(data->old_dentry->d_inode);
371 : :
372 : 0 : dput(data->old_dentry);
373 : 0 : dput(data->new_dentry);
374 : 0 : iput(data->old_dir);
375 : 0 : iput(data->new_dir);
376 : 0 : nfs_sb_deactive(sb);
377 : 0 : put_rpccred(data->cred);
378 : 0 : kfree(data);
379 : 0 : }
380 : :
381 : 0 : static void nfs_rename_prepare(struct rpc_task *task, void *calldata)
382 : : {
383 : : struct nfs_renamedata *data = calldata;
384 : 0 : NFS_PROTO(data->old_dir)->rename_rpc_prepare(task, data);
385 : 0 : }
386 : :
387 : : static const struct rpc_call_ops nfs_rename_ops = {
388 : : .rpc_call_done = nfs_async_rename_done,
389 : : .rpc_release = nfs_async_rename_release,
390 : : .rpc_call_prepare = nfs_rename_prepare,
391 : : };
392 : :
393 : : /**
394 : : * nfs_async_rename - perform an asynchronous rename operation
395 : : * @old_dir: directory that currently holds the dentry to be renamed
396 : : * @new_dir: target directory for the rename
397 : : * @old_dentry: original dentry to be renamed
398 : : * @new_dentry: dentry to which the old_dentry should be renamed
399 : : *
400 : : * It's expected that valid references to the dentries and inodes are held
401 : : */
402 : : static struct rpc_task *
403 : 0 : nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
404 : : struct dentry *old_dentry, struct dentry *new_dentry)
405 : : {
406 : : struct nfs_renamedata *data;
407 : 0 : struct rpc_message msg = { };
408 : 0 : struct rpc_task_setup task_setup_data = {
409 : : .rpc_message = &msg,
410 : : .callback_ops = &nfs_rename_ops,
411 : : .workqueue = nfsiod_workqueue,
412 : : .rpc_client = NFS_CLIENT(old_dir),
413 : : .flags = RPC_TASK_ASYNC,
414 : : };
415 : :
416 : : data = kzalloc(sizeof(*data), GFP_KERNEL);
417 [ # # ]: 0 : if (data == NULL)
418 : : return ERR_PTR(-ENOMEM);
419 : 0 : task_setup_data.callback_data = data;
420 : :
421 : 0 : data->cred = rpc_lookup_cred();
422 [ # # ]: 0 : if (IS_ERR(data->cred)) {
423 : : struct rpc_task *task = ERR_CAST(data->cred);
424 : 0 : kfree(data);
425 : 0 : return task;
426 : : }
427 : :
428 : 0 : msg.rpc_argp = &data->args;
429 : 0 : msg.rpc_resp = &data->res;
430 : 0 : msg.rpc_cred = data->cred;
431 : :
432 : : /* set up nfs_renamedata */
433 : 0 : data->old_dir = old_dir;
434 : 0 : ihold(old_dir);
435 : 0 : data->new_dir = new_dir;
436 : 0 : ihold(new_dir);
437 : 0 : data->old_dentry = dget(old_dentry);
438 : 0 : data->new_dentry = dget(new_dentry);
439 : 0 : nfs_fattr_init(&data->old_fattr);
440 : 0 : nfs_fattr_init(&data->new_fattr);
441 : :
442 : : /* set up nfs_renameargs */
443 : 0 : data->args.old_dir = NFS_FH(old_dir);
444 : 0 : data->args.old_name = &old_dentry->d_name;
445 : 0 : data->args.new_dir = NFS_FH(new_dir);
446 : 0 : data->args.new_name = &new_dentry->d_name;
447 : :
448 : : /* set up nfs_renameres */
449 : 0 : data->res.old_fattr = &data->old_fattr;
450 : 0 : data->res.new_fattr = &data->new_fattr;
451 : :
452 : 0 : nfs_sb_active(old_dir->i_sb);
453 : :
454 : 0 : NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dir);
455 : :
456 : 0 : return rpc_run_task(&task_setup_data);
457 : : }
458 : :
459 : : #define SILLYNAME_PREFIX ".nfs"
460 : : #define SILLYNAME_PREFIX_LEN ((unsigned)sizeof(SILLYNAME_PREFIX) - 1)
461 : : #define SILLYNAME_FILEID_LEN ((unsigned)sizeof(u64) << 1)
462 : : #define SILLYNAME_COUNTER_LEN ((unsigned)sizeof(unsigned int) << 1)
463 : : #define SILLYNAME_LEN (SILLYNAME_PREFIX_LEN + \
464 : : SILLYNAME_FILEID_LEN + \
465 : : SILLYNAME_COUNTER_LEN)
466 : :
467 : : /**
468 : : * nfs_sillyrename - Perform a silly-rename of a dentry
469 : : * @dir: inode of directory that contains dentry
470 : : * @dentry: dentry to be sillyrenamed
471 : : *
472 : : * NFSv2/3 is stateless and the server doesn't know when the client is
473 : : * holding a file open. To prevent application problems when a file is
474 : : * unlinked while it's still open, the client performs a "silly-rename".
475 : : * That is, it renames the file to a hidden file in the same directory,
476 : : * and only performs the unlink once the last reference to it is put.
477 : : *
478 : : * The final cleanup is done during dentry_iput.
479 : : *
480 : : * (Note: NFSv4 is stateful, and has opens, so in theory an NFSv4 server
481 : : * could take responsibility for keeping open files referenced. The server
482 : : * would also need to ensure that opened-but-deleted files were kept over
483 : : * reboots. However, we may not assume a server does so. (RFC 5661
484 : : * does provide an OPEN4_RESULT_PRESERVE_UNLINKED flag that a server can
485 : : * use to advertise that it does this; some day we may take advantage of
486 : : * it.))
487 : : */
488 : : int
489 : 0 : nfs_sillyrename(struct inode *dir, struct dentry *dentry)
490 : : {
491 : : static unsigned int sillycounter;
492 : : unsigned char silly[SILLYNAME_LEN + 1];
493 : : unsigned long long fileid;
494 : 0 : struct dentry *sdentry;
495 : : struct rpc_task *task;
496 : : int error = -EBUSY;
497 : :
498 : : dfprintk(VFS, "NFS: silly-rename(%pd2, ct=%d)\n",
499 : : dentry, d_count(dentry));
500 : : nfs_inc_stats(dir, NFSIOS_SILLYRENAME);
501 : :
502 : : /*
503 : : * We don't allow a dentry to be silly-renamed twice.
504 : : */
505 [ # # ]: 0 : if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
506 : : goto out;
507 : :
508 : 0 : fileid = NFS_FILEID(dentry->d_inode);
509 : :
510 : : /* Return delegation in anticipation of the rename */
511 : 0 : NFS_PROTO(dentry->d_inode)->return_delegation(dentry->d_inode);
512 : :
513 : : sdentry = NULL;
514 : : do {
515 : : int slen;
516 : 0 : dput(sdentry);
517 : 0 : sillycounter++;
518 : 0 : slen = scnprintf(silly, sizeof(silly),
519 : : SILLYNAME_PREFIX "%0*llx%0*x",
520 : : SILLYNAME_FILEID_LEN, fileid,
521 : : SILLYNAME_COUNTER_LEN, sillycounter);
522 : :
523 : : dfprintk(VFS, "NFS: trying to rename %pd to %s\n",
524 : : dentry, silly);
525 : :
526 : 0 : sdentry = lookup_one_len(silly, dentry->d_parent, slen);
527 : : /*
528 : : * N.B. Better to return EBUSY here ... it could be
529 : : * dangerous to delete the file while it's in use.
530 : : */
531 [ # # ]: 0 : if (IS_ERR(sdentry))
532 : : goto out;
533 [ # # ]: 0 : } while (sdentry->d_inode != NULL); /* need negative lookup */
534 : :
535 : : /* queue unlink first. Can't do this from rpc_release as it
536 : : * has to allocate memory
537 : : */
538 : 0 : error = nfs_async_unlink(dir, dentry);
539 [ # # ]: 0 : if (error)
540 : : goto out_dput;
541 : :
542 : : /* populate unlinkdata with the right dname */
543 : : error = nfs_copy_dname(sdentry,
544 : 0 : (struct nfs_unlinkdata *)dentry->d_fsdata);
545 [ # # ]: 0 : if (error) {
546 : 0 : nfs_cancel_async_unlink(dentry);
547 : 0 : goto out_dput;
548 : : }
549 : :
550 : : /* run the rename task, undo unlink if it fails */
551 : 0 : task = nfs_async_rename(dir, dir, dentry, sdentry);
552 [ # # ]: 0 : if (IS_ERR(task)) {
553 : : error = -EBUSY;
554 : 0 : nfs_cancel_async_unlink(dentry);
555 : 0 : goto out_dput;
556 : : }
557 : :
558 : : /* wait for the RPC task to complete, unless a SIGKILL intervenes */
559 : : error = rpc_wait_for_completion_task(task);
560 [ # # ]: 0 : if (error == 0)
561 : 0 : error = task->tk_status;
562 [ # # # ]: 0 : switch (error) {
563 : : case 0:
564 : : /* The rename succeeded */
565 : : nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
566 : 0 : d_move(dentry, sdentry);
567 : 0 : break;
568 : : case -ERESTARTSYS:
569 : : /* The result of the rename is unknown. Play it safe by
570 : : * forcing a new lookup */
571 : 0 : d_drop(dentry);
572 : 0 : d_drop(sdentry);
573 : : }
574 : 0 : rpc_put_task(task);
575 : : out_dput:
576 : 0 : dput(sdentry);
577 : : out:
578 : 0 : return error;
579 : : }
|