linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] first iteration of rename2 support
@ 2014-07-23 13:15 Miklos Szeredi
  2014-07-23 13:15 ` [PATCH 1/7] vfs: call rename2 if exists Miklos Szeredi
                   ` (6 more replies)
  0 siblings, 7 replies; 11+ messages in thread
From: Miklos Szeredi @ 2014-07-23 13:15 UTC (permalink / raw)
  To: linux-kernel, hch, viro, linux-fsdevel

Add support for rename flags to a couple more filesystems, while gradually
migrating away from ->rename() to ->rename2().

RENAME_NOREPLACE is really easy for the majority (here only btrfs, shmem, hostfs
and cifs are done), so more of the this is coming if this series is well
received.

  git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git renameat2

Thanks,
Miklos
---

Miklos Szeredi (7):
      vfs: call rename2 if exists
      bad_inode: add ->rename2()
      btrfs: add RENAME_NOREPLACE
      shmem: support RENAME_NOREPLACE
      shmem: support RENAME_EXCHANGE
      hostfs: support rename flags
      cifs: support RENAME_NOREPLACE

---
 fs/bad_inode.c          |  7 ++++---
 fs/btrfs/inode.c        | 12 +++++++++++-
 fs/cifs/cifsfs.c        |  2 +-
 fs/cifs/cifsfs.h        |  4 ++--
 fs/cifs/inode.c         | 14 ++++++++++++--
 fs/ext4/namei.c         |  1 -
 fs/fuse/dir.c           |  7 -------
 fs/hostfs/hostfs.h      |  1 +
 fs/hostfs/hostfs_kern.c | 30 ++++++++++++++++++++----------
 fs/hostfs/hostfs_user.c | 28 ++++++++++++++++++++++++++++
 fs/namei.c              |  5 +++--
 mm/shmem.c              | 32 ++++++++++++++++++++++++++++++--
 12 files changed, 112 insertions(+), 31 deletions(-)


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/7] vfs: call rename2 if exists
  2014-07-23 13:15 [PATCH 0/7] first iteration of rename2 support Miklos Szeredi
@ 2014-07-23 13:15 ` Miklos Szeredi
  2014-07-23 13:15 ` [PATCH 2/7] bad_inode: add ->rename2() Miklos Szeredi
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Miklos Szeredi @ 2014-07-23 13:15 UTC (permalink / raw)
  To: linux-kernel, hch, viro, linux-fsdevel; +Cc: Miklos Szeredi

From: Miklos Szeredi <mszeredi@suse.cz>

Christoph Hellwig suggests:

1) make vfs_rename call ->rename2 if it exists instead of ->rename
2) switch all filesystems that you're adding NOREPLACE support for to
   use ->rename2
3) see how many ->rename instances we'll have left after a few
   iterations of 2.

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Acked-by: Christoph Hellwig <hch@lst.de>
---
 fs/ext4/namei.c | 1 -
 fs/fuse/dir.c   | 7 -------
 fs/namei.c      | 5 +++--
 3 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 3520ab8a6639..b147a67baa0d 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -3455,7 +3455,6 @@ const struct inode_operations ext4_dir_inode_operations = {
 	.rmdir		= ext4_rmdir,
 	.mknod		= ext4_mknod,
 	.tmpfile	= ext4_tmpfile,
-	.rename		= ext4_rename,
 	.rename2	= ext4_rename2,
 	.setattr	= ext4_setattr,
 	.setxattr	= generic_setxattr,
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 0c6048247a34..de1d84af9f7c 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -845,12 +845,6 @@ static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
 	return err;
 }
 
-static int fuse_rename(struct inode *olddir, struct dentry *oldent,
-		       struct inode *newdir, struct dentry *newent)
-{
-	return fuse_rename2(olddir, oldent, newdir, newent, 0);
-}
-
 static int fuse_link(struct dentry *entry, struct inode *newdir,
 		     struct dentry *newent)
 {
@@ -2024,7 +2018,6 @@ static const struct inode_operations fuse_dir_inode_operations = {
 	.symlink	= fuse_symlink,
 	.unlink		= fuse_unlink,
 	.rmdir		= fuse_rmdir,
-	.rename		= fuse_rename,
 	.rename2	= fuse_rename2,
 	.link		= fuse_link,
 	.setattr	= fuse_setattr,
diff --git a/fs/namei.c b/fs/namei.c
index 985c6f368485..b268e7758a48 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4074,7 +4074,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	if (error)
 		return error;
 
-	if (!old_dir->i_op->rename)
+	if (!old_dir->i_op->rename && !old_dir->i_op->rename2)
 		return -EPERM;
 
 	if (flags && !old_dir->i_op->rename2)
@@ -4133,10 +4133,11 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 		if (error)
 			goto out;
 	}
-	if (!flags) {
+	if (!old_dir->i_op->rename2) {
 		error = old_dir->i_op->rename(old_dir, old_dentry,
 					      new_dir, new_dentry);
 	} else {
+		WARN_ON(old_dir->i_op->rename != NULL);
 		error = old_dir->i_op->rename2(old_dir, old_dentry,
 					       new_dir, new_dentry, flags);
 	}
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/7] bad_inode: add ->rename2()
  2014-07-23 13:15 [PATCH 0/7] first iteration of rename2 support Miklos Szeredi
  2014-07-23 13:15 ` [PATCH 1/7] vfs: call rename2 if exists Miklos Szeredi
@ 2014-07-23 13:15 ` Miklos Szeredi
  2014-07-23 13:15 ` [PATCH 3/7] btrfs: add RENAME_NOREPLACE Miklos Szeredi
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Miklos Szeredi @ 2014-07-23 13:15 UTC (permalink / raw)
  To: linux-kernel, hch, viro, linux-fsdevel; +Cc: Miklos Szeredi

From: Miklos Szeredi <mszeredi@suse.cz>

so we return -EIO instead of -EINVAL.

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
 fs/bad_inode.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 7c93953030fb..afd2b4408adf 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -218,8 +218,9 @@ static int bad_inode_mknod (struct inode *dir, struct dentry *dentry,
 	return -EIO;
 }
 
-static int bad_inode_rename (struct inode *old_dir, struct dentry *old_dentry,
-		struct inode *new_dir, struct dentry *new_dentry)
+static int bad_inode_rename2(struct inode *old_dir, struct dentry *old_dentry,
+			     struct inode *new_dir, struct dentry *new_dentry,
+			     unsigned int flags)
 {
 	return -EIO;
 }
@@ -279,7 +280,7 @@ static const struct inode_operations bad_inode_ops =
 	.mkdir		= bad_inode_mkdir,
 	.rmdir		= bad_inode_rmdir,
 	.mknod		= bad_inode_mknod,
-	.rename		= bad_inode_rename,
+	.rename2	= bad_inode_rename2,
 	.readlink	= bad_inode_readlink,
 	/* follow_link must be no-op, otherwise unmounting this inode
 	   won't work */
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/7] btrfs: add RENAME_NOREPLACE
  2014-07-23 13:15 [PATCH 0/7] first iteration of rename2 support Miklos Szeredi
  2014-07-23 13:15 ` [PATCH 1/7] vfs: call rename2 if exists Miklos Szeredi
  2014-07-23 13:15 ` [PATCH 2/7] bad_inode: add ->rename2() Miklos Szeredi
@ 2014-07-23 13:15 ` Miklos Szeredi
  2014-07-23 13:15 ` [PATCH 4/7] shmem: support RENAME_NOREPLACE Miklos Szeredi
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Miklos Szeredi @ 2014-07-23 13:15 UTC (permalink / raw)
  To: linux-kernel, hch, viro, linux-fsdevel; +Cc: Miklos Szeredi, Chris Mason

From: Miklos Szeredi <mszeredi@suse.cz>

RENAME_NOREPLACE is trivial to implement for most filesystems: switch over
to ->rename2() and check for the supported flags.  The rest is done by the
VFS.

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Cc: Chris Mason <clm@fb.com>
---
 fs/btrfs/inode.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 3668048e16f8..3183742d6f0d 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -8476,6 +8476,16 @@ out_notrans:
 	return ret;
 }
 
+static int btrfs_rename2(struct inode *old_dir, struct dentry *old_dentry,
+			 struct inode *new_dir, struct dentry *new_dentry,
+			 unsigned int flags)
+{
+	if (flags & ~RENAME_NOREPLACE)
+		return -EINVAL;
+
+	return btrfs_rename(old_dir, old_dentry, new_dir, new_dentry);
+}
+
 static void btrfs_run_delalloc_work(struct btrfs_work *work)
 {
 	struct btrfs_delalloc_work *delalloc_work;
@@ -9019,7 +9029,7 @@ static const struct inode_operations btrfs_dir_inode_operations = {
 	.link		= btrfs_link,
 	.mkdir		= btrfs_mkdir,
 	.rmdir		= btrfs_rmdir,
-	.rename		= btrfs_rename,
+	.rename2	= btrfs_rename2,
 	.symlink	= btrfs_symlink,
 	.setattr	= btrfs_setattr,
 	.mknod		= btrfs_mknod,
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/7] shmem: support RENAME_NOREPLACE
  2014-07-23 13:15 [PATCH 0/7] first iteration of rename2 support Miklos Szeredi
                   ` (2 preceding siblings ...)
  2014-07-23 13:15 ` [PATCH 3/7] btrfs: add RENAME_NOREPLACE Miklos Szeredi
@ 2014-07-23 13:15 ` Miklos Szeredi
  2014-07-24 11:08   ` Hugh Dickins
  2014-07-23 13:15 ` [PATCH 5/7] shmem: support RENAME_EXCHANGE Miklos Szeredi
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 11+ messages in thread
From: Miklos Szeredi @ 2014-07-23 13:15 UTC (permalink / raw)
  To: linux-kernel, hch, viro, linux-fsdevel; +Cc: Miklos Szeredi, Hugh Dickins

From: Miklos Szeredi <mszeredi@suse.cz>

Expand noreplace_rename2() because next patch will implement one more flag.

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Cc: Hugh Dickins <hughd@google.com>
---
 mm/shmem.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index 1140f49b6ded..791b05514f9a 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2022,11 +2022,14 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
  * it exists so that the VFS layer correctly free's it when it
  * gets overwritten.
  */
-static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
+static int shmem_rename2(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags)
 {
 	struct inode *inode = old_dentry->d_inode;
 	int they_are_dirs = S_ISDIR(inode->i_mode);
 
+	if (flags & ~(RENAME_NOREPLACE))
+		return -EINVAL;
+
 	if (!simple_empty(new_dentry))
 		return -ENOTEMPTY;
 
@@ -2709,7 +2712,7 @@ static const struct inode_operations shmem_dir_inode_operations = {
 	.mkdir		= shmem_mkdir,
 	.rmdir		= shmem_rmdir,
 	.mknod		= shmem_mknod,
-	.rename		= shmem_rename,
+	.rename2	= shmem_rename2,
 	.tmpfile	= shmem_tmpfile,
 #endif
 #ifdef CONFIG_TMPFS_XATTR
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/7] shmem: support RENAME_EXCHANGE
  2014-07-23 13:15 [PATCH 0/7] first iteration of rename2 support Miklos Szeredi
                   ` (3 preceding siblings ...)
  2014-07-23 13:15 ` [PATCH 4/7] shmem: support RENAME_NOREPLACE Miklos Szeredi
@ 2014-07-23 13:15 ` Miklos Szeredi
  2014-07-24 11:09   ` Hugh Dickins
  2014-07-23 13:15 ` [PATCH 6/7] hostfs: support rename flags Miklos Szeredi
  2014-07-23 13:15 ` [PATCH 7/7] cifs: support RENAME_NOREPLACE Miklos Szeredi
  6 siblings, 1 reply; 11+ messages in thread
From: Miklos Szeredi @ 2014-07-23 13:15 UTC (permalink / raw)
  To: linux-kernel, hch, viro, linux-fsdevel; +Cc: Miklos Szeredi, Hugh Dickins

From: Miklos Szeredi <mszeredi@suse.cz>

This is really simple in tmpfs since the VFS already takes care of
shuffling the dentries.  Just adjust nlink on parent directories and touch
c & mtimes.

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Cc: Hugh Dickins <hughd@google.com>
---
 mm/shmem.c | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index 791b05514f9a..75d5ac806f1e 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2016,6 +2016,28 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
 	return shmem_unlink(dir, dentry);
 }
 
+static int shmem_exchange(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
+{
+	bool old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
+	bool new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
+
+	if (old_dir != new_dir && old_is_dir != new_is_dir) {
+		if (old_is_dir) {
+			drop_nlink(old_dir);
+			inc_nlink(new_dir);
+		} else {
+			drop_nlink(new_dir);
+			inc_nlink(old_dir);
+		}
+	}
+	old_dir->i_ctime = old_dir->i_mtime =
+	new_dir->i_ctime = new_dir->i_mtime =
+	old_dentry->d_inode->i_ctime =
+	new_dentry->d_inode->i_ctime = CURRENT_TIME;
+
+	return 0;
+}
+
 /*
  * The VFS layer already does all the dentry stuff for rename,
  * we just have to decrement the usage count for the target if
@@ -2027,9 +2049,12 @@ static int shmem_rename2(struct inode *old_dir, struct dentry *old_dentry, struc
 	struct inode *inode = old_dentry->d_inode;
 	int they_are_dirs = S_ISDIR(inode->i_mode);
 
-	if (flags & ~(RENAME_NOREPLACE))
+	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
 		return -EINVAL;
 
+	if (flags & RENAME_EXCHANGE)
+		return shmem_exchange(old_dir, old_dentry, new_dir, new_dentry);
+
 	if (!simple_empty(new_dentry))
 		return -ENOTEMPTY;
 
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 6/7] hostfs: support rename flags
  2014-07-23 13:15 [PATCH 0/7] first iteration of rename2 support Miklos Szeredi
                   ` (4 preceding siblings ...)
  2014-07-23 13:15 ` [PATCH 5/7] shmem: support RENAME_EXCHANGE Miklos Szeredi
@ 2014-07-23 13:15 ` Miklos Szeredi
  2014-07-23 13:15 ` [PATCH 7/7] cifs: support RENAME_NOREPLACE Miklos Szeredi
  6 siblings, 0 replies; 11+ messages in thread
From: Miklos Szeredi @ 2014-07-23 13:15 UTC (permalink / raw)
  To: linux-kernel, hch, viro, linux-fsdevel; +Cc: Miklos Szeredi, Richard Weinberger

From: Miklos Szeredi <mszeredi@suse.cz>

Support RENAME_NOREPLACE and RENAME_EXCHANGE flags on hostfs if the
underlying filesystem supports it.

Since renameat2(2) is not yet in any libc, use syscall(2) to invoke the
renameat2 syscall.

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Cc: Richard Weinberger <richard@nod.at>
---
 fs/hostfs/hostfs.h      |  1 +
 fs/hostfs/hostfs_kern.c | 30 ++++++++++++++++++++----------
 fs/hostfs/hostfs_user.c | 28 ++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+), 10 deletions(-)

diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h
index 9c88da0e855a..4fcd40d6f308 100644
--- a/fs/hostfs/hostfs.h
+++ b/fs/hostfs/hostfs.h
@@ -89,6 +89,7 @@ extern int do_mknod(const char *file, int mode, unsigned int major,
 extern int link_file(const char *from, const char *to);
 extern int hostfs_do_readlink(char *file, char *buf, int size);
 extern int rename_file(char *from, char *to);
+extern int rename2_file(char *from, char *to, unsigned int flags);
 extern int do_statfs(char *root, long *bsize_out, long long *blocks_out,
 		     long long *bfree_out, long long *bavail_out,
 		     long long *files_out, long long *ffree_out,
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index bb529f3b7f2b..fd62cae0fdcb 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -741,21 +741,31 @@ static int hostfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
 	return err;
 }
 
-static int hostfs_rename(struct inode *from_ino, struct dentry *from,
-			 struct inode *to_ino, struct dentry *to)
+static int hostfs_rename2(struct inode *old_dir, struct dentry *old_dentry,
+			  struct inode *new_dir, struct dentry *new_dentry,
+			  unsigned int flags)
 {
-	char *from_name, *to_name;
+	char *old_name, *new_name;
 	int err;
 
-	if ((from_name = dentry_name(from)) == NULL)
+	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
+		return -EINVAL;
+
+	old_name = dentry_name(old_dentry);
+	if (old_name == NULL)
 		return -ENOMEM;
-	if ((to_name = dentry_name(to)) == NULL) {
-		__putname(from_name);
+	new_name = dentry_name(new_dentry);
+	if (new_name == NULL) {
+		__putname(old_name);
 		return -ENOMEM;
 	}
-	err = rename_file(from_name, to_name);
-	__putname(from_name);
-	__putname(to_name);
+	if (!flags)
+		err = rename_file(old_name, new_name);
+	else
+		err = rename2_file(old_name, new_name, flags);
+
+	__putname(old_name);
+	__putname(new_name);
 	return err;
 }
 
@@ -867,7 +877,7 @@ static const struct inode_operations hostfs_dir_iops = {
 	.mkdir		= hostfs_mkdir,
 	.rmdir		= hostfs_rmdir,
 	.mknod		= hostfs_mknod,
-	.rename		= hostfs_rename,
+	.rename2	= hostfs_rename2,
 	.permission	= hostfs_permission,
 	.setattr	= hostfs_setattr,
 };
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
index 67838f3aa20a..9765dab95cbd 100644
--- a/fs/hostfs/hostfs_user.c
+++ b/fs/hostfs/hostfs_user.c
@@ -14,6 +14,7 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/vfs.h>
+#include <sys/syscall.h>
 #include "hostfs.h"
 #include <utime.h>
 
@@ -360,6 +361,33 @@ int rename_file(char *from, char *to)
 	return 0;
 }
 
+int rename2_file(char *from, char *to, unsigned int flags)
+{
+	int err;
+
+#ifndef SYS_renameat2
+#  ifdef __x86_64__
+#    define SYS_renameat2 316
+#  endif
+#  ifdef __i386__
+#    define SYS_renameat2 353
+#  endif
+#endif
+
+#ifdef SYS_renameat2
+	err = syscall(SYS_renameat2, AT_FDCWD, from, AT_FDCWD, to, flags);
+	if (err < 0) {
+		if (errno != ENOSYS)
+			return -errno;
+		else
+			return -EINVAL;
+	}
+	return 0;
+#else
+	return -EINVAL;
+#endif
+}
+
 int do_statfs(char *root, long *bsize_out, long long *blocks_out,
 	      long long *bfree_out, long long *bavail_out,
 	      long long *files_out, long long *ffree_out,
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 7/7] cifs: support RENAME_NOREPLACE
  2014-07-23 13:15 [PATCH 0/7] first iteration of rename2 support Miklos Szeredi
                   ` (5 preceding siblings ...)
  2014-07-23 13:15 ` [PATCH 6/7] hostfs: support rename flags Miklos Szeredi
@ 2014-07-23 13:15 ` Miklos Szeredi
  6 siblings, 0 replies; 11+ messages in thread
From: Miklos Szeredi @ 2014-07-23 13:15 UTC (permalink / raw)
  To: linux-kernel, hch, viro, linux-fsdevel; +Cc: Miklos Szeredi, Steve French

From: Miklos Szeredi <mszeredi@suse.cz>

This flag gives CIFS the ability to support its native rename semantics.

Implementation is simple: just bail out before trying to hack around the
noreplace semantics.

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Cc: Steve French <smfrench@gmail.com>
---
 fs/cifs/cifsfs.c |  2 +-
 fs/cifs/cifsfs.h |  4 ++--
 fs/cifs/inode.c  | 14 ++++++++++++--
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 888398067420..ac4f260155c8 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -848,7 +848,7 @@ const struct inode_operations cifs_dir_inode_ops = {
 	.link = cifs_hardlink,
 	.mkdir = cifs_mkdir,
 	.rmdir = cifs_rmdir,
-	.rename = cifs_rename,
+	.rename2 = cifs_rename2,
 	.permission = cifs_permission,
 /*	revalidate:cifs_revalidate,   */
 	.setattr = cifs_setattr,
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 70f178a7c759..ed58c88f5f5d 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -68,8 +68,8 @@ extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
 extern int cifs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
 extern int cifs_mkdir(struct inode *, struct dentry *, umode_t);
 extern int cifs_rmdir(struct inode *, struct dentry *);
-extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
-		       struct dentry *);
+extern int cifs_rename2(struct inode *, struct dentry *, struct inode *,
+			struct dentry *, unsigned int);
 extern int cifs_revalidate_file_attr(struct file *filp);
 extern int cifs_revalidate_dentry_attr(struct dentry *);
 extern int cifs_revalidate_file(struct file *filp);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index a174605f6afa..bec0a0831be6 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1627,8 +1627,9 @@ do_rename_exit:
 }
 
 int
-cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
-	    struct inode *target_dir, struct dentry *target_dentry)
+cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
+	     struct inode *target_dir, struct dentry *target_dentry,
+	     unsigned int flags)
 {
 	char *from_name = NULL;
 	char *to_name = NULL;
@@ -1640,6 +1641,9 @@ cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
 	unsigned int xid;
 	int rc, tmprc;
 
+	if (flags & ~RENAME_NOREPLACE)
+		return -EINVAL;
+
 	cifs_sb = CIFS_SB(source_dir->i_sb);
 	tlink = cifs_sb_tlink(cifs_sb);
 	if (IS_ERR(tlink))
@@ -1667,6 +1671,12 @@ cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
 	rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
 			    to_name);
 
+	/*
+	 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
+	 */
+	if (flags & RENAME_NOREPLACE)
+		goto cifs_rename_exit;
+
 	if (rc == -EEXIST && tcon->unix_ext) {
 		/*
 		 * Are src and dst hardlinks of same inode? We can only tell
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/7] shmem: support RENAME_NOREPLACE
  2014-07-23 13:15 ` [PATCH 4/7] shmem: support RENAME_NOREPLACE Miklos Szeredi
@ 2014-07-24 11:08   ` Hugh Dickins
  2014-07-24 11:21     ` Miklos Szeredi
  0 siblings, 1 reply; 11+ messages in thread
From: Hugh Dickins @ 2014-07-24 11:08 UTC (permalink / raw)
  To: Miklos Szeredi
  Cc: linux-kernel, hch, viro, linux-fsdevel, Miklos Szeredi, Hugh Dickins

On Wed, 23 Jul 2014, Miklos Szeredi wrote:
> From: Miklos Szeredi <mszeredi@suse.cz>
> 
> Expand noreplace_rename2() because next patch will implement one more flag.

noreplace_rename2()??  I understand the code better than this comment.

> 
> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
> Cc: Hugh Dickins <hughd@google.com>

Acked-by: Hugh Dickins <hughd@google.com>

though I wouldn't object to a comment, perhaps just in the commit message,
like you have in ext4: Existence checking was done by the VFS, otherwise
"RENAME_NOREPLACE" is equivalent to regular rename.

> ---
>  mm/shmem.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 1140f49b6ded..791b05514f9a 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -2022,11 +2022,14 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
>   * it exists so that the VFS layer correctly free's it when it
>   * gets overwritten.
>   */
> -static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
> +static int shmem_rename2(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags)
>  {
>  	struct inode *inode = old_dentry->d_inode;
>  	int they_are_dirs = S_ISDIR(inode->i_mode);
>  
> +	if (flags & ~(RENAME_NOREPLACE))
> +		return -EINVAL;
> +
>  	if (!simple_empty(new_dentry))
>  		return -ENOTEMPTY;
>  
> @@ -2709,7 +2712,7 @@ static const struct inode_operations shmem_dir_inode_operations = {
>  	.mkdir		= shmem_mkdir,
>  	.rmdir		= shmem_rmdir,
>  	.mknod		= shmem_mknod,
> -	.rename		= shmem_rename,
> +	.rename2	= shmem_rename2,
>  	.tmpfile	= shmem_tmpfile,
>  #endif
>  #ifdef CONFIG_TMPFS_XATTR
> -- 
> 1.8.1.4

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 5/7] shmem: support RENAME_EXCHANGE
  2014-07-23 13:15 ` [PATCH 5/7] shmem: support RENAME_EXCHANGE Miklos Szeredi
@ 2014-07-24 11:09   ` Hugh Dickins
  0 siblings, 0 replies; 11+ messages in thread
From: Hugh Dickins @ 2014-07-24 11:09 UTC (permalink / raw)
  To: Miklos Szeredi
  Cc: linux-kernel, hch, viro, linux-fsdevel, Miklos Szeredi, Hugh Dickins

On Wed, 23 Jul 2014, Miklos Szeredi wrote:
> From: Miklos Szeredi <mszeredi@suse.cz>
> 
> This is really simple in tmpfs since the VFS already takes care of
> shuffling the dentries.  Just adjust nlink on parent directories and touch
> c & mtimes.
> 
> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
> Cc: Hugh Dickins <hughd@google.com>

Acked-by: Hugh Dickins <hughd@google.com>

> ---
>  mm/shmem.c | 27 ++++++++++++++++++++++++++-
>  1 file changed, 26 insertions(+), 1 deletion(-)
> 
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 791b05514f9a..75d5ac806f1e 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -2016,6 +2016,28 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
>  	return shmem_unlink(dir, dentry);
>  }
>  
> +static int shmem_exchange(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
> +{
> +	bool old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
> +	bool new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
> +
> +	if (old_dir != new_dir && old_is_dir != new_is_dir) {
> +		if (old_is_dir) {
> +			drop_nlink(old_dir);
> +			inc_nlink(new_dir);
> +		} else {
> +			drop_nlink(new_dir);
> +			inc_nlink(old_dir);
> +		}
> +	}
> +	old_dir->i_ctime = old_dir->i_mtime =
> +	new_dir->i_ctime = new_dir->i_mtime =
> +	old_dentry->d_inode->i_ctime =
> +	new_dentry->d_inode->i_ctime = CURRENT_TIME;
> +
> +	return 0;
> +}
> +
>  /*
>   * The VFS layer already does all the dentry stuff for rename,
>   * we just have to decrement the usage count for the target if
> @@ -2027,9 +2049,12 @@ static int shmem_rename2(struct inode *old_dir, struct dentry *old_dentry, struc
>  	struct inode *inode = old_dentry->d_inode;
>  	int they_are_dirs = S_ISDIR(inode->i_mode);
>  
> -	if (flags & ~(RENAME_NOREPLACE))
> +	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
>  		return -EINVAL;
>  
> +	if (flags & RENAME_EXCHANGE)
> +		return shmem_exchange(old_dir, old_dentry, new_dir, new_dentry);
> +
>  	if (!simple_empty(new_dentry))
>  		return -ENOTEMPTY;
>  
> -- 
> 1.8.1.4

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/7] shmem: support RENAME_NOREPLACE
  2014-07-24 11:08   ` Hugh Dickins
@ 2014-07-24 11:21     ` Miklos Szeredi
  0 siblings, 0 replies; 11+ messages in thread
From: Miklos Szeredi @ 2014-07-24 11:21 UTC (permalink / raw)
  To: Hugh Dickins
  Cc: Kernel Mailing List, Christoph Hellwig, Al Viro, Linux-Fsdevel,
	Miklos Szeredi

On Thu, Jul 24, 2014 at 1:08 PM, Hugh Dickins <hughd@google.com> wrote:
> On Wed, 23 Jul 2014, Miklos Szeredi wrote:
>> From: Miklos Szeredi <mszeredi@suse.cz>
>>
>> Expand noreplace_rename2() because next patch will implement one more flag.
>
> noreplace_rename2()??  I understand the code better than this comment.

Fixed, and acks added.  Thanks!

Miklos

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2014-07-24 11:21 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-23 13:15 [PATCH 0/7] first iteration of rename2 support Miklos Szeredi
2014-07-23 13:15 ` [PATCH 1/7] vfs: call rename2 if exists Miklos Szeredi
2014-07-23 13:15 ` [PATCH 2/7] bad_inode: add ->rename2() Miklos Szeredi
2014-07-23 13:15 ` [PATCH 3/7] btrfs: add RENAME_NOREPLACE Miklos Szeredi
2014-07-23 13:15 ` [PATCH 4/7] shmem: support RENAME_NOREPLACE Miklos Szeredi
2014-07-24 11:08   ` Hugh Dickins
2014-07-24 11:21     ` Miklos Szeredi
2014-07-23 13:15 ` [PATCH 5/7] shmem: support RENAME_EXCHANGE Miklos Szeredi
2014-07-24 11:09   ` Hugh Dickins
2014-07-23 13:15 ` [PATCH 6/7] hostfs: support rename flags Miklos Szeredi
2014-07-23 13:15 ` [PATCH 7/7] cifs: support RENAME_NOREPLACE Miklos Szeredi

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).