[PATCH (Untested!)] cifs: support RENAME_NOREPLACE

From: Miklos Szeredi
Date: Tue May 13 2014 - 10:04:14 EST


From: Miklos Szeredi <mszeredi@xxxxxxx>

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@xxxxxxx>
---
fs/cifs/cifsfs.c | 8 ++++++++
fs/cifs/cifsfs.h | 4 ++--
fs/cifs/inode.c | 14 ++++++++++++--
3 files changed, 22 insertions(+), 4 deletions(-)

--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -827,6 +827,13 @@ static int cifs_setlease(struct file *fi
return -EAGAIN;
}

+static int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
+ struct inode *target_dir, struct dentry *target_dentry)
+{
+ return cifs_rename2(source_dir, source_dentry,
+ target_dir, target_dentry, 0);
+}
+
struct file_system_type cifs_fs_type = {
.owner = THIS_MODULE,
.name = "cifs",
@@ -845,6 +852,7 @@ const struct inode_operations cifs_dir_i
.mkdir = cifs_mkdir,
.rmdir = cifs_rmdir,
.rename = cifs_rename,
+ .rename2 = cifs_rename2,
.permission = cifs_permission,
/* revalidate:cifs_revalidate, */
.setattr = cifs_setattr,
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -60,8 +60,8 @@ extern int cifs_hardlink(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);
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1623,8 +1623,9 @@ cifs_do_rename(const unsigned int xid, s
}

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;
@@ -1636,6 +1637,9 @@ cifs_rename(struct inode *source_dir, st
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))
@@ -1663,6 +1667,12 @@ cifs_rename(struct inode *source_dir, st
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
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/