2014-07-23 13:15:54

by Miklos Szeredi

[permalink] [raw]
Subject: [PATCH 0/7] first iteration of rename2 support

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


2014-07-23 13:16:09

by Miklos Szeredi

[permalink] [raw]
Subject: [PATCH 1/7] vfs: call rename2 if exists

From: Miklos Szeredi <[email protected]>

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 <[email protected]>
Acked-by: Christoph Hellwig <[email protected]>
---
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

2014-07-23 13:16:07

by Miklos Szeredi

[permalink] [raw]
Subject: [PATCH 4/7] shmem: support RENAME_NOREPLACE

From: Miklos Szeredi <[email protected]>

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

Signed-off-by: Miklos Szeredi <[email protected]>
Cc: Hugh Dickins <[email protected]>
---
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

2014-07-23 13:16:04

by Miklos Szeredi

[permalink] [raw]
Subject: [PATCH 2/7] bad_inode: add ->rename2()

From: Miklos Szeredi <[email protected]>

so we return -EIO instead of -EINVAL.

Signed-off-by: Miklos Szeredi <[email protected]>
---
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

2014-07-23 13:16:53

by Miklos Szeredi

[permalink] [raw]
Subject: [PATCH 7/7] cifs: support RENAME_NOREPLACE

From: Miklos Szeredi <[email protected]>

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 <[email protected]>
Cc: Steve French <[email protected]>
---
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

2014-07-23 13:18:06

by Miklos Szeredi

[permalink] [raw]
Subject: [PATCH 6/7] hostfs: support rename flags

From: Miklos Szeredi <[email protected]>

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 <[email protected]>
Cc: Richard Weinberger <[email protected]>
---
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

2014-07-23 13:16:01

by Miklos Szeredi

[permalink] [raw]
Subject: [PATCH 3/7] btrfs: add RENAME_NOREPLACE

From: Miklos Szeredi <[email protected]>

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 <[email protected]>
Cc: Chris Mason <[email protected]>
---
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

2014-07-23 13:18:43

by Miklos Szeredi

[permalink] [raw]
Subject: [PATCH 5/7] shmem: support RENAME_EXCHANGE

From: Miklos Szeredi <[email protected]>

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 <[email protected]>
Cc: Hugh Dickins <[email protected]>
---
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

2014-07-24 11:10:27

by Hugh Dickins

[permalink] [raw]
Subject: Re: [PATCH 4/7] shmem: support RENAME_NOREPLACE

On Wed, 23 Jul 2014, Miklos Szeredi wrote:
> From: Miklos Szeredi <[email protected]>
>
> 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 <[email protected]>
> Cc: Hugh Dickins <[email protected]>

Acked-by: Hugh Dickins <[email protected]>

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

2014-07-24 11:11:00

by Hugh Dickins

[permalink] [raw]
Subject: Re: [PATCH 5/7] shmem: support RENAME_EXCHANGE

On Wed, 23 Jul 2014, Miklos Szeredi wrote:
> From: Miklos Szeredi <[email protected]>
>
> 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 <[email protected]>
> Cc: Hugh Dickins <[email protected]>

Acked-by: Hugh Dickins <[email protected]>

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

2014-07-24 11:21:26

by Miklos Szeredi

[permalink] [raw]
Subject: Re: [PATCH 4/7] shmem: support RENAME_NOREPLACE

On Thu, Jul 24, 2014 at 1:08 PM, Hugh Dickins <[email protected]> wrote:
> On Wed, 23 Jul 2014, Miklos Szeredi wrote:
>> From: Miklos Szeredi <[email protected]>
>>
>> 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