Updated version of Ronnie's patch for FALLOC_FL_INSERT_RANGE and FALLOC_FL_COLLAPSE_RANGE attached (cleaned up the two redundant length checks noticed out by Aurelien, and fixed the endian check warnings pointed out by sparse). They fix at least six xfstests (but still more xfstests to work through that seem to have other new feature dependencies beyond fcollapse) # ./check -cifs generic/072 generic/145 generic/147 generic/153 generic/351 generic/458 FSTYP -- cifs PLATFORM -- Linux/x86_64 smfrench-Virtual-Machine 5.12.0-051200rc4-generic #202103212230 SMP Sun Mar 21 22:33:27 UTC 2021 generic/072 7s ... 6s generic/145 0s ... 1s generic/147 1s ... 0s generic/153 0s ... 1s generic/351 5s ... 3s generic/458 1s ... 1s Ran: generic/072 generic/145 generic/147 generic/153 generic/351 generic/458 Passed all 6 tests -- Thanks, Steve
From 64086228480f8d3ba80eb930b40f501afbb1e83b Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> Date: Sat, 27 Mar 2021 05:52:29 +1000 Subject: [PATCH 1/2] cifs: add support for FALLOC_FL_COLLAPSE_RANGE Emulated for SMB3 and later via server side copy and setsize. Eventually this could be compounded. Reported-by: kernel test robot <lkp@xxxxxxxxx> Reported-by: Dan Carpenter <dan.carpenter@xxxxxxxxxx> Signed-off-by: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- fs/cifs/smb2ops.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index f703204fb185..c6a49c31dc0e 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -3652,6 +3652,39 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, return rc; } +static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon, + loff_t off, loff_t len) +{ + int rc; + unsigned int xid; + struct cifsFileInfo *cfile = file->private_data; + __le64 eof; + + xid = get_xid(); + + if (off >= i_size_read(file->f_inode) || + off + len >= i_size_read(file->f_inode)) { + rc = -EINVAL; + goto out; + } + + rc = smb2_copychunk_range(xid, cfile, cfile, off + len, + i_size_read(file->f_inode) - off - len, off); + if (rc < 0) + goto out; + + eof = cpu_to_le64(i_size_read(file->f_inode) - len); + rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, + cfile->fid.volatile_fid, cfile->pid, &eof); + if (rc < 0) + goto out; + + rc = 0; + out: + free_xid(xid); + return rc; +} + static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offset, int whence) { struct cifsFileInfo *wrcfile, *cfile = file->private_data; @@ -3823,6 +3856,8 @@ static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode, return smb3_zero_range(file, tcon, off, len, false); } else if (mode == FALLOC_FL_KEEP_SIZE) return smb3_simple_falloc(file, tcon, off, len, true); + else if (mode == FALLOC_FL_COLLAPSE_RANGE) + return smb3_collapse_range(file, tcon, off, len); else if (mode == 0) return smb3_simple_falloc(file, tcon, off, len, false); -- 2.27.0
From e3cdd1c943e65c391af36f573599b69dde80fcb0 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> Date: Sat, 27 Mar 2021 06:31:30 +1000 Subject: [PATCH 2/2] cifs: add FALLOC_FL_INSERT_RANGE support Emulated via server side copy and setsize for SMB3 and later. In the future we could compound this (and/or optionally use DUPLICATE_EXTENTS if supported by the server). Signed-off-by: Ronnie Sahlberg <lsahlber@xxxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- fs/cifs/smb2ops.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index c6a49c31dc0e..4837ac9b4837 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -3685,6 +3685,44 @@ static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon, return rc; } +static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon, + loff_t off, loff_t len) +{ + int rc; + unsigned int xid; + struct cifsFileInfo *cfile = file->private_data; + __le64 eof; + __u64 count; + + xid = get_xid(); + + if (off >= i_size_read(file->f_inode)) { + rc = -EINVAL; + goto out; + } + + count = i_size_read(file->f_inode) - off; + eof = cpu_to_le64(i_size_read(file->f_inode) + len); + + rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, + cfile->fid.volatile_fid, cfile->pid, &eof); + if (rc < 0) + goto out; + + rc = smb2_copychunk_range(xid, cfile, cfile, off, count, off + len); + if (rc < 0) + goto out; + + rc = smb3_zero_range(file, tcon, off, len, 1); + if (rc < 0) + goto out; + + rc = 0; + out: + free_xid(xid); + return rc; +} + static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offset, int whence) { struct cifsFileInfo *wrcfile, *cfile = file->private_data; @@ -3858,6 +3896,8 @@ static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode, return smb3_simple_falloc(file, tcon, off, len, true); else if (mode == FALLOC_FL_COLLAPSE_RANGE) return smb3_collapse_range(file, tcon, off, len); + else if (mode == FALLOC_FL_INSERT_RANGE) + return smb3_insert_range(file, tcon, off, len); else if (mode == 0) return smb3_simple_falloc(file, tcon, off, len, false); -- 2.27.0