From: "J. Bruce Fields" <bfields@redhat.com>
To: Al Viro <viro@zeniv.linux.org.uk>
Cc: linux-nfs@vger.kernel.org, linux-fsdevel@vger.kernel.org,
jlayton@redhat.com, Dave Chinner <david@fromorbit.com>,
"J. Bruce Fields" <bfields@redhat.com>,
David Howells <dhowells@redhat.com>
Subject: [PATCH 10/16] locks: break delegations on rename
Date: Wed, 17 Jul 2013 16:50:11 -0400 [thread overview]
Message-ID: <1374094217-31493-12-git-send-email-bfields@redhat.com> (raw)
In-Reply-To: <1374094217-31493-1-git-send-email-bfields@redhat.com>
From: "J. Bruce Fields" <bfields@redhat.com>
Cc: David Howells <dhowells@redhat.com>
Acked-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
---
fs/cachefiles/namei.c | 2 +-
fs/namei.c | 47 +++++++++++++++++++++++++++++++++++++++++++----
fs/nfsd/vfs.c | 2 +-
include/linux/fs.h | 2 +-
4 files changed, 46 insertions(+), 7 deletions(-)
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index 6846fcef..1363eae 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -396,7 +396,7 @@ try_again:
cachefiles_io_error(cache, "Rename security error %d", ret);
} else {
ret = vfs_rename(dir->d_inode, rep,
- cache->graveyard->d_inode, grave);
+ cache->graveyard->d_inode, grave, NULL);
if (ret != 0 && ret != -ENOMEM)
cachefiles_io_error(cache,
"Rename failed with error %d", ret);
diff --git a/fs/namei.c b/fs/namei.c
index d3b6a35..0554c9a 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3834,7 +3834,8 @@ out:
}
static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+ struct inode *new_dir, struct dentry *new_dentry,
+ struct inode **delegated_inode)
{
struct inode *target = new_dentry->d_inode;
struct inode *source = old_dentry->d_inode;
@@ -3851,6 +3852,14 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
goto out;
+ error = try_break_deleg(source, delegated_inode);
+ if (error)
+ goto out;
+ if (target) {
+ error = try_break_deleg(target, delegated_inode);
+ if (error)
+ goto out;
+ }
error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
if (error)
goto out;
@@ -3865,8 +3874,30 @@ out:
return error;
}
+/**
+ * vfs_rename - rename a filesystem object
+ * @old_dir: parent of source
+ * @old_dentry: source
+ * @new_dir: parent of destination
+ * @new_dentry: destination
+ * @delegated_inode: returns an inode needing a delegation break
+ *
+ * The caller must hold multiple mutexes--see lock_rename()).
+ *
+ * If vfs_rename discovers a delegation in need of breaking at either
+ * the source or destination, it will return -EWOULDBLOCK and return a
+ * reference to the inode in delegated_inode. The caller should then
+ * break the delegation and retry. Because breaking a delegation may
+ * take a long time, the caller should drop all locks before doing
+ * so.
+ *
+ * Alternatively, a caller may pass NULL for delegated_inode. This may
+ * be appropriate for callers that expect the underlying filesystem not
+ * to be NFS exported.
+ */
int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+ struct inode *new_dir, struct dentry *new_dentry,
+ struct inode **delegated_inode)
{
int error;
int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
@@ -3894,7 +3925,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (is_dir)
error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
else
- error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
+ error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,delegated_inode);
if (!error)
fsnotify_move(old_dir, new_dir, old_name, is_dir,
new_dentry->d_inode, old_dentry);
@@ -3910,6 +3941,7 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
struct dentry *old_dentry, *new_dentry;
struct dentry *trap;
struct nameidata oldnd, newnd;
+ struct inode *delegated_inode = NULL;
struct filename *from;
struct filename *to;
unsigned int lookup_flags = 0;
@@ -3949,6 +3981,7 @@ retry:
newnd.flags &= ~LOOKUP_PARENT;
newnd.flags |= LOOKUP_RENAME_TARGET;
+retry_deleg:
trap = lock_rename(new_dir, old_dir);
old_dentry = lookup_hash(&oldnd);
@@ -3985,13 +4018,19 @@ retry:
if (error)
goto exit5;
error = vfs_rename(old_dir->d_inode, old_dentry,
- new_dir->d_inode, new_dentry);
+ new_dir->d_inode, new_dentry,
+ &delegated_inode);
exit5:
dput(new_dentry);
exit4:
dput(old_dentry);
exit3:
unlock_rename(new_dir, old_dir);
+ if (delegated_inode) {
+ error = break_deleg_wait(&delegated_inode);
+ if (!error)
+ goto retry_deleg;
+ }
mnt_drop_write(oldnd.path.mnt);
exit2:
if (retry_estale(error, lookup_flags))
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index ff1fc44..fbf22d2 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1837,7 +1837,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
if (host_err)
goto out_dput_new;
}
- host_err = vfs_rename(fdir, odentry, tdir, ndentry);
+ host_err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
if (!host_err) {
host_err = commit_metadata(tfhp);
if (!host_err)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 43a3506..74aa0c7 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1470,7 +1470,7 @@ extern int vfs_symlink(struct inode *, struct dentry *, const char *);
extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
extern int vfs_rmdir(struct inode *, struct dentry *);
extern int vfs_unlink(struct inode *, struct dentry *, struct inode **);
-extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
+extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **);
/*
* VFS dentry helper functions.
--
1.7.9.5
next prev parent reply other threads:[~2013-07-17 20:50 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-17 20:50 [PATCH 00/16] Implement NFSv4 delegations, take 9 J. Bruce Fields
2013-07-17 20:50 ` [PATCH] nfsd4: fix minorversion support interface J. Bruce Fields
2013-07-17 21:08 ` J. Bruce Fields
2013-07-17 20:50 ` [PATCH 02/16] vfs: don't use PARENT/CHILD lock classes for non-directories J. Bruce Fields
2013-07-17 20:50 ` [PATCH 03/16] vfs: rename I_MUTEX_QUOTA now that it's not used for quotas J. Bruce Fields
2013-07-17 20:50 ` [PATCH 04/16] vfs: take i_mutex on renamed file J. Bruce Fields
2013-07-17 20:50 ` [PATCH 08/16] locks: break delegations on unlink J. Bruce Fields
[not found] ` <1374094217-31493-1-git-send-email-bfields-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2013-07-17 20:50 ` [PATCH 01/16] vfs: pull ext4's double-i_mutex-locking into common code J. Bruce Fields
2013-07-17 20:50 ` [PATCH 05/16] locks: introduce new FL_DELEG lock flag J. Bruce Fields
2013-07-17 20:50 ` [PATCH 06/16] locks: implement delegations J. Bruce Fields
2013-07-17 20:50 ` [PATCH 07/16] namei: minor vfs_unlink cleanup J. Bruce Fields
2013-07-17 20:50 ` [PATCH 09/16] locks: helper functions for delegation breaking J. Bruce Fields
[not found] ` <1374094217-31493-11-git-send-email-bfields-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2013-07-26 10:50 ` Jeff Layton
2013-07-17 20:50 ` [PATCH 11/16] locks: break delegations on link J. Bruce Fields
2013-07-17 20:50 ` [PATCH 12/16] locks: break delegations on any attribute modification J. Bruce Fields
[not found] ` <1374094217-31493-14-git-send-email-bfields-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2013-07-26 10:50 ` Jeff Layton
2013-07-17 20:50 ` [PATCH 14/16] nfsd4: delay setting current_fh in open J. Bruce Fields
[not found] ` <1374094217-31493-16-git-send-email-bfields-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2013-07-26 11:11 ` Jeff Layton
2013-07-26 16:04 ` J. Bruce Fields
2013-07-17 20:50 ` [PATCH 15/16] nfsd4: close open-deleg/unlink/rename race J. Bruce Fields
2013-07-26 11:23 ` Jeff Layton
[not found] ` <20130726072326.56113a2c-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
2013-07-26 16:04 ` J. Bruce Fields
2013-07-26 21:14 ` J. Bruce Fields
2013-07-17 20:50 ` J. Bruce Fields [this message]
2013-07-17 20:50 ` [PATCH 13/16] nfsd4: minor nfs4_setlease cleanup J. Bruce Fields
2013-07-26 10:53 ` Jeff Layton
2013-07-17 20:50 ` [PATCH 16/16] nfsd4: break only delegations when appropriate J. Bruce Fields
[not found] ` <1374094217-31493-18-git-send-email-bfields-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2013-07-26 11:24 ` Jeff Layton
2013-07-17 21:09 ` [PATCH 00/16] Implement NFSv4 delegations, take 9 J. Bruce Fields
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1374094217-31493-12-git-send-email-bfields@redhat.com \
--to=bfields@redhat.com \
--cc=david@fromorbit.com \
--cc=dhowells@redhat.com \
--cc=jlayton@redhat.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).