aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2010-09-17 17:31:57 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-09-17 17:31:57 -0400
commitd3d4152a5d59af9e13a73efa9e9c24383fbe307f (patch)
tree552ea5586bb64f8fef93825c72e88b9248d02b79
parent779c51795bfb35c2403c924b9de90ca9356bc693 (diff)
nfs: make sillyrename an async operation
A synchronous rename can be interrupted by a SIGKILL. If that happens during a sillyrename operation, it's possible for the rename call to be sent to the server, but the task exits before processing the reply. If this happens, the sillyrenamed file won't get cleaned up during nfs_dentry_iput and the server is left with a dangling .nfs* file hanging around. Fix this problem by turning sillyrename into an asynchronous operation and have the task doing the sillyrename just wait on the reply. If the task is killed before the sillyrename completes, it'll still proceed to completion. Signed-off-by: Jeff Layton <jlayton@redhat.com> Reviewed-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/nfs3proc.c23
-rw-r--r--fs/nfs/nfs4proc.c30
-rw-r--r--fs/nfs/proc.c19
-rw-r--r--fs/nfs/unlink.c200
-rw-r--r--include/linux/nfs_xdr.h2
5 files changed, 263 insertions, 11 deletions
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index bb41d88e1567..4e9d941ab548 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -438,6 +438,27 @@ nfs3_proc_unlink_done(struct rpc_task *task, struct inode *dir)
438 return 1; 438 return 1;
439} 439}
440 440
441static void
442nfs3_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
443{
444 msg->rpc_proc = &nfs3_procedures[NFS3PROC_RENAME];
445}
446
447static int
448nfs3_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
449 struct inode *new_dir)
450{
451 struct nfs_renameres *res;
452
453 if (nfs3_async_handle_jukebox(task, old_dir))
454 return 0;
455 res = task->tk_msg.rpc_resp;
456
457 nfs_post_op_update_inode(old_dir, res->old_fattr);
458 nfs_post_op_update_inode(new_dir, res->new_fattr);
459 return 1;
460}
461
441static int 462static int
442nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name, 463nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
443 struct inode *new_dir, struct qstr *new_name) 464 struct inode *new_dir, struct qstr *new_name)
@@ -842,6 +863,8 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
842 .unlink_setup = nfs3_proc_unlink_setup, 863 .unlink_setup = nfs3_proc_unlink_setup,
843 .unlink_done = nfs3_proc_unlink_done, 864 .unlink_done = nfs3_proc_unlink_done,
844 .rename = nfs3_proc_rename, 865 .rename = nfs3_proc_rename,
866 .rename_setup = nfs3_proc_rename_setup,
867 .rename_done = nfs3_proc_rename_done,
845 .link = nfs3_proc_link, 868 .link = nfs3_proc_link,
846 .symlink = nfs3_proc_symlink, 869 .symlink = nfs3_proc_symlink,
847 .mkdir = nfs3_proc_mkdir, 870 .mkdir = nfs3_proc_mkdir,
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a3c21cc4677b..c46e45e9b33f 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2566,6 +2566,34 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
2566 return 1; 2566 return 1;
2567} 2567}
2568 2568
2569static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
2570{
2571 struct nfs_server *server = NFS_SERVER(dir);
2572 struct nfs_renameargs *arg = msg->rpc_argp;
2573 struct nfs_renameres *res = msg->rpc_resp;
2574
2575 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME];
2576 arg->bitmask = server->attr_bitmask;
2577 res->server = server;
2578}
2579
2580static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
2581 struct inode *new_dir)
2582{
2583 struct nfs_renameres *res = task->tk_msg.rpc_resp;
2584
2585 if (!nfs4_sequence_done(task, &res->seq_res))
2586 return 0;
2587 if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
2588 return 0;
2589
2590 update_changeattr(old_dir, &res->old_cinfo);
2591 nfs_post_op_update_inode(old_dir, res->old_fattr);
2592 update_changeattr(new_dir, &res->new_cinfo);
2593 nfs_post_op_update_inode(new_dir, res->new_fattr);
2594 return 1;
2595}
2596
2569static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, 2597static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
2570 struct inode *new_dir, struct qstr *new_name) 2598 struct inode *new_dir, struct qstr *new_name)
2571{ 2599{
@@ -5338,6 +5366,8 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
5338 .unlink_setup = nfs4_proc_unlink_setup, 5366 .unlink_setup = nfs4_proc_unlink_setup,
5339 .unlink_done = nfs4_proc_unlink_done, 5367 .unlink_done = nfs4_proc_unlink_done,
5340 .rename = nfs4_proc_rename, 5368 .rename = nfs4_proc_rename,
5369 .rename_setup = nfs4_proc_rename_setup,
5370 .rename_done = nfs4_proc_rename_done,
5341 .link = nfs4_proc_link, 5371 .link = nfs4_proc_link,
5342 .symlink = nfs4_proc_symlink, 5372 .symlink = nfs4_proc_symlink,
5343 .mkdir = nfs4_proc_mkdir, 5373 .mkdir = nfs4_proc_mkdir,
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 0aff10c3bbce..e5e84aa2af17 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -365,6 +365,23 @@ static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir)
365 return 1; 365 return 1;
366} 366}
367 367
368static void
369nfs_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
370{
371 msg->rpc_proc = &nfs_procedures[NFSPROC_RENAME];
372}
373
374static int
375nfs_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
376 struct inode *new_dir)
377{
378 if (nfs_async_handle_expired_key(task))
379 return 0;
380 nfs_mark_for_revalidate(old_dir);
381 nfs_mark_for_revalidate(new_dir);
382 return 1;
383}
384
368static int 385static int
369nfs_proc_rename(struct inode *old_dir, struct qstr *old_name, 386nfs_proc_rename(struct inode *old_dir, struct qstr *old_name,
370 struct inode *new_dir, struct qstr *new_name) 387 struct inode *new_dir, struct qstr *new_name)
@@ -703,6 +720,8 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
703 .unlink_setup = nfs_proc_unlink_setup, 720 .unlink_setup = nfs_proc_unlink_setup,
704 .unlink_done = nfs_proc_unlink_done, 721 .unlink_done = nfs_proc_unlink_done,
705 .rename = nfs_proc_rename, 722 .rename = nfs_proc_rename,
723 .rename_setup = nfs_proc_rename_setup,
724 .rename_done = nfs_proc_rename_done,
706 .link = nfs_proc_link, 725 .link = nfs_proc_link,
707 .symlink = nfs_proc_symlink, 726 .symlink = nfs_proc_symlink,
708 .mkdir = nfs_proc_mkdir, 727 .mkdir = nfs_proc_mkdir,
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index c3ce865294f1..698b3e6367ff 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -307,6 +307,174 @@ nfs_complete_unlink(struct dentry *dentry, struct inode *inode)
307 nfs_free_unlinkdata(data); 307 nfs_free_unlinkdata(data);
308} 308}
309 309
310/* Cancel a queued async unlink. Called when a sillyrename run fails. */
311static void
312nfs_cancel_async_unlink(struct dentry *dentry)
313{
314 spin_lock(&dentry->d_lock);
315 if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
316 struct nfs_unlinkdata *data = dentry->d_fsdata;
317
318 dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
319 spin_unlock(&dentry->d_lock);
320 nfs_free_unlinkdata(data);
321 return;
322 }
323 spin_unlock(&dentry->d_lock);
324}
325
326struct nfs_renamedata {
327 struct nfs_renameargs args;
328 struct nfs_renameres res;
329 struct rpc_cred *cred;
330 struct inode *old_dir;
331 struct dentry *old_dentry;
332 struct nfs_fattr old_fattr;
333 struct inode *new_dir;
334 struct dentry *new_dentry;
335 struct nfs_fattr new_fattr;
336};
337
338/**
339 * nfs_async_rename_done - Sillyrename post-processing
340 * @task: rpc_task of the sillyrename
341 * @calldata: nfs_renamedata for the sillyrename
342 *
343 * Do the directory attribute updates and the d_move
344 */
345static void nfs_async_rename_done(struct rpc_task *task, void *calldata)
346{
347 struct nfs_renamedata *data = calldata;
348 struct inode *old_dir = data->old_dir;
349 struct inode *new_dir = data->new_dir;
350
351 if (!NFS_PROTO(old_dir)->rename_done(task, old_dir, new_dir)) {
352 nfs_restart_rpc(task, NFS_SERVER(old_dir)->nfs_client);
353 return;
354 }
355
356 if (task->tk_status != 0) {
357 nfs_cancel_async_unlink(data->old_dentry);
358 return;
359 }
360
361 nfs_set_verifier(data->old_dentry, nfs_save_change_attribute(old_dir));
362 d_move(data->old_dentry, data->new_dentry);
363}
364
365/**
366 * nfs_async_rename_release - Release the sillyrename data.
367 * @calldata: the struct nfs_renamedata to be released
368 */
369static void nfs_async_rename_release(void *calldata)
370{
371 struct nfs_renamedata *data = calldata;
372 struct super_block *sb = data->old_dir->i_sb;
373
374 if (data->old_dentry->d_inode)
375 nfs_mark_for_revalidate(data->old_dentry->d_inode);
376
377 dput(data->old_dentry);
378 dput(data->new_dentry);
379 iput(data->old_dir);
380 iput(data->new_dir);
381 nfs_sb_deactive(sb);
382 put_rpccred(data->cred);
383 kfree(data);
384}
385
386#if defined(CONFIG_NFS_V4_1)
387static void nfs_rename_prepare(struct rpc_task *task, void *calldata)
388{
389 struct nfs_renamedata *data = calldata;
390 struct nfs_server *server = NFS_SERVER(data->old_dir);
391
392 if (nfs4_setup_sequence(server, &data->args.seq_args,
393 &data->res.seq_res, 1, task))
394 return;
395 rpc_call_start(task);
396}
397#endif /* CONFIG_NFS_V4_1 */
398
399static const struct rpc_call_ops nfs_rename_ops = {
400 .rpc_call_done = nfs_async_rename_done,
401 .rpc_release = nfs_async_rename_release,
402#if defined(CONFIG_NFS_V4_1)
403 .rpc_call_prepare = nfs_rename_prepare,
404#endif /* CONFIG_NFS_V4_1 */
405};
406
407/**
408 * nfs_async_rename - perform an asynchronous rename operation
409 * @old_dir: directory that currently holds the dentry to be renamed
410 * @new_dir: target directory for the rename
411 * @old_dentry: original dentry to be renamed
412 * @new_dentry: dentry to which the old_dentry should be renamed
413 *
414 * It's expected that valid references to the dentries and inodes are held
415 */
416static struct rpc_task *
417nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
418 struct dentry *old_dentry, struct dentry *new_dentry)
419{
420 struct nfs_renamedata *data;
421 struct rpc_message msg = { };
422 struct rpc_task_setup task_setup_data = {
423 .rpc_message = &msg,
424 .callback_ops = &nfs_rename_ops,
425 .workqueue = nfsiod_workqueue,
426 .rpc_client = NFS_CLIENT(old_dir),
427 .flags = RPC_TASK_ASYNC,
428 };
429 struct rpc_task *task;
430
431 data = kmalloc(sizeof(*data), GFP_KERNEL);
432 if (data == NULL)
433 return ERR_PTR(-ENOMEM);
434 task_setup_data.callback_data = data,
435
436 data->cred = rpc_lookup_cred();
437 if (IS_ERR(data->cred)) {
438 task = (struct rpc_task *)data->cred;
439 kfree(data);
440 return task;
441 }
442
443 msg.rpc_argp = &data->args;
444 msg.rpc_resp = &data->res;
445 msg.rpc_cred = data->cred;
446
447 /* set up nfs_renamedata */
448 data->old_dir = old_dir;
449 atomic_inc(&old_dir->i_count);
450 data->new_dir = new_dir;
451 atomic_inc(&new_dir->i_count);
452 data->old_dentry = dget(old_dentry);
453 data->new_dentry = dget(new_dentry);
454 nfs_fattr_init(&data->old_fattr);
455 nfs_fattr_init(&data->new_fattr);
456
457 /* set up nfs_renameargs */
458 data->args.old_dir = NFS_FH(old_dir);
459 data->args.old_name = &old_dentry->d_name;
460 data->args.new_dir = NFS_FH(new_dir);
461 data->args.new_name = &new_dentry->d_name;
462
463 /* set up nfs_renameres */
464 data->res.old_fattr = &data->old_fattr;
465 data->res.new_fattr = &data->new_fattr;
466
467 nfs_sb_active(old_dir->i_sb);
468
469 NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dir);
470
471 task = rpc_run_task(&task_setup_data);
472 if (IS_ERR(task))
473 nfs_async_rename_release(data);
474
475 return task;
476}
477
310/** 478/**
311 * nfs_sillyrename - Perform a silly-rename of a dentry 479 * nfs_sillyrename - Perform a silly-rename of a dentry
312 * @dir: inode of directory that contains dentry 480 * @dir: inode of directory that contains dentry
@@ -328,8 +496,8 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
328 const int countersize = sizeof(sillycounter)*2; 496 const int countersize = sizeof(sillycounter)*2;
329 const int slen = sizeof(".nfs")+fileidsize+countersize-1; 497 const int slen = sizeof(".nfs")+fileidsize+countersize-1;
330 char silly[slen+1]; 498 char silly[slen+1];
331 struct qstr qsilly;
332 struct dentry *sdentry; 499 struct dentry *sdentry;
500 struct rpc_task *task;
333 int error = -EIO; 501 int error = -EIO;
334 502
335 dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n", 503 dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
@@ -371,17 +539,27 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
371 goto out; 539 goto out;
372 } while (sdentry->d_inode != NULL); /* need negative lookup */ 540 } while (sdentry->d_inode != NULL); /* need negative lookup */
373 541
374 qsilly.name = silly; 542 /* queue unlink first. Can't do this from rpc_release as it
375 qsilly.len = strlen(silly); 543 * has to allocate memory
376 error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, dir, &qsilly); 544 */
377 if (dentry->d_inode) 545 error = nfs_async_unlink(dir, dentry);
378 nfs_mark_for_revalidate(dentry->d_inode); 546 if (error)
379 if (!error) { 547 goto out_dput;
380 nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 548
381 d_move(dentry, sdentry); 549 /* run the rename task, undo unlink if it fails */
382 error = nfs_async_unlink(dir, dentry); 550 task = nfs_async_rename(dir, dir, dentry, sdentry);
383 /* If we return 0 we don't unlink */ 551 if (IS_ERR(task)) {
552 error = -EBUSY;
553 nfs_cancel_async_unlink(dentry);
554 goto out_dput;
384 } 555 }
556
557 /* wait for the RPC task to complete, unless a SIGKILL intervenes */
558 error = rpc_wait_for_completion_task(task);
559 if (error == 0)
560 error = task->tk_status;
561 rpc_put_task(task);
562out_dput:
385 dput(sdentry); 563 dput(sdentry);
386out: 564out:
387 return error; 565 return error;
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 9ad132e13d12..172df83ac54b 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1018,6 +1018,8 @@ struct nfs_rpc_ops {
1018 int (*unlink_done) (struct rpc_task *, struct inode *); 1018 int (*unlink_done) (struct rpc_task *, struct inode *);
1019 int (*rename) (struct inode *, struct qstr *, 1019 int (*rename) (struct inode *, struct qstr *,
1020 struct inode *, struct qstr *); 1020 struct inode *, struct qstr *);
1021 void (*rename_setup) (struct rpc_message *msg, struct inode *dir);
1022 int (*rename_done) (struct rpc_task *task, struct inode *old_dir, struct inode *new_dir);
1021 int (*link) (struct inode *, struct inode *, struct qstr *); 1023 int (*link) (struct inode *, struct inode *, struct qstr *);
1022 int (*symlink) (struct inode *, struct dentry *, struct page *, 1024 int (*symlink) (struct inode *, struct dentry *, struct page *,
1023 unsigned int, struct iattr *); 1025 unsigned int, struct iattr *);