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.c35
1 files changed, 30 insertions, 5 deletions
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 11d78944de79..de54129336c6 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -14,6 +14,7 @@
14#include <linux/sched.h> 14#include <linux/sched.h>
15#include <linux/wait.h> 15#include <linux/wait.h>
16#include <linux/namei.h> 16#include <linux/namei.h>
17#include <linux/fsnotify.h>
17 18
18#include "internal.h" 19#include "internal.h"
19#include "nfs4_fs.h" 20#include "nfs4_fs.h"
@@ -353,8 +354,8 @@ static void nfs_async_rename_done(struct rpc_task *task, void *calldata)
353 return; 354 return;
354 } 355 }
355 356
356 if (task->tk_status != 0) 357 if (data->complete)
357 nfs_cancel_async_unlink(old_dentry); 358 data->complete(task, data);
358} 359}
359 360
360/** 361/**
@@ -399,9 +400,10 @@ static const struct rpc_call_ops nfs_rename_ops = {
399 * 400 *
400 * It's expected that valid references to the dentries and inodes are held 401 * It's expected that valid references to the dentries and inodes are held
401 */ 402 */
402static struct rpc_task * 403struct rpc_task *
403nfs_async_rename(struct inode *old_dir, struct inode *new_dir, 404nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
404 struct dentry *old_dentry, struct dentry *new_dentry) 405 struct dentry *old_dentry, struct dentry *new_dentry,
406 void (*complete)(struct rpc_task *, struct nfs_renamedata *))
405{ 407{
406 struct nfs_renamedata *data; 408 struct nfs_renamedata *data;
407 struct rpc_message msg = { }; 409 struct rpc_message msg = { };
@@ -438,6 +440,7 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
438 data->new_dentry = dget(new_dentry); 440 data->new_dentry = dget(new_dentry);
439 nfs_fattr_init(&data->old_fattr); 441 nfs_fattr_init(&data->old_fattr);
440 nfs_fattr_init(&data->new_fattr); 442 nfs_fattr_init(&data->new_fattr);
443 data->complete = complete;
441 444
442 /* set up nfs_renameargs */ 445 /* set up nfs_renameargs */
443 data->args.old_dir = NFS_FH(old_dir); 446 data->args.old_dir = NFS_FH(old_dir);
@@ -456,6 +459,27 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
456 return rpc_run_task(&task_setup_data); 459 return rpc_run_task(&task_setup_data);
457} 460}
458 461
462/*
463 * Perform tasks needed when a sillyrename is done such as cancelling the
464 * queued async unlink if it failed.
465 */
466static void
467nfs_complete_sillyrename(struct rpc_task *task, struct nfs_renamedata *data)
468{
469 struct dentry *dentry = data->old_dentry;
470
471 if (task->tk_status != 0) {
472 nfs_cancel_async_unlink(dentry);
473 return;
474 }
475
476 /*
477 * vfs_unlink and the like do not issue this when a file is
478 * sillyrenamed, so do it here.
479 */
480 fsnotify_nameremove(dentry, 0);
481}
482
459#define SILLYNAME_PREFIX ".nfs" 483#define SILLYNAME_PREFIX ".nfs"
460#define SILLYNAME_PREFIX_LEN ((unsigned)sizeof(SILLYNAME_PREFIX) - 1) 484#define SILLYNAME_PREFIX_LEN ((unsigned)sizeof(SILLYNAME_PREFIX) - 1)
461#define SILLYNAME_FILEID_LEN ((unsigned)sizeof(u64) << 1) 485#define SILLYNAME_FILEID_LEN ((unsigned)sizeof(u64) << 1)
@@ -548,7 +572,8 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
548 } 572 }
549 573
550 /* run the rename task, undo unlink if it fails */ 574 /* run the rename task, undo unlink if it fails */
551 task = nfs_async_rename(dir, dir, dentry, sdentry); 575 task = nfs_async_rename(dir, dir, dentry, sdentry,
576 nfs_complete_sillyrename);
552 if (IS_ERR(task)) { 577 if (IS_ERR(task)) {
553 error = -EBUSY; 578 error = -EBUSY;
554 nfs_cancel_async_unlink(dentry); 579 nfs_cancel_async_unlink(dentry);