Skip to content

Commit 3017562

Browse files
committed
[SMB3] Enable fallocate -z support for SMB3 mounts
fallocate -z (FALLOC_FL_ZERO_RANGE) can map to SMB3 FSCTL_SET_ZERO_DATA SMB3 FSCTL but FALLOC_FL_ZERO_RANGE when called without the FALLOC_FL_KEEPSIZE flag set could want the file size changed so we can not support that subcase unless the file is cached (and thus we know the file size). Signed-off-by: Steve French <smfrench@gmail.com> Reviewed-by: Pavel Shilovsky <pshilovsky@samba.org>
1 parent 31742c5 commit 3017562

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

fs/cifs/smb2ops.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,56 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
10151015
return rc;
10161016
}
10171017

1018+
static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
1019+
loff_t offset, loff_t len, bool keep_size)
1020+
{
1021+
struct inode *inode;
1022+
struct cifsInodeInfo *cifsi;
1023+
struct cifsFileInfo *cfile = file->private_data;
1024+
struct file_zero_data_information fsctl_buf;
1025+
long rc;
1026+
unsigned int xid;
1027+
1028+
xid = get_xid();
1029+
1030+
inode = cfile->dentry->d_inode;
1031+
cifsi = CIFS_I(inode);
1032+
1033+
/* if file not oplocked can't be sure whether asking to extend size */
1034+
if (!CIFS_CACHE_READ(cifsi))
1035+
if (keep_size == false)
1036+
return -EOPNOTSUPP;
1037+
1038+
/*
1039+
* Must check if file sparse since fallocate -z (zero range) assumes
1040+
* non-sparse allocation
1041+
*/
1042+
if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE))
1043+
return -EOPNOTSUPP;
1044+
1045+
/*
1046+
* need to make sure we are not asked to extend the file since the SMB3
1047+
* fsctl does not change the file size. In the future we could change
1048+
* this to zero the first part of the range then set the file size
1049+
* which for a non sparse file would zero the newly extended range
1050+
*/
1051+
if (keep_size == false)
1052+
if (i_size_read(inode) < offset + len)
1053+
return -EOPNOTSUPP;
1054+
1055+
cifs_dbg(FYI, "offset %lld len %lld", offset, len);
1056+
1057+
fsctl_buf.FileOffset = cpu_to_le64(offset);
1058+
fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
1059+
1060+
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
1061+
cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
1062+
true /* is_fctl */, (char *)&fsctl_buf,
1063+
sizeof(struct file_zero_data_information), NULL, NULL);
1064+
free_xid(xid);
1065+
return rc;
1066+
}
1067+
10181068
static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
10191069
loff_t offset, loff_t len)
10201070
{
@@ -1055,6 +1105,11 @@ static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
10551105
/* KEEP_SIZE already checked for by do_fallocate */
10561106
if (mode & FALLOC_FL_PUNCH_HOLE)
10571107
return smb3_punch_hole(file, tcon, off, len);
1108+
else if (mode & FALLOC_FL_ZERO_RANGE) {
1109+
if (mode & FALLOC_FL_KEEP_SIZE)
1110+
return smb3_zero_range(file, tcon, off, len, true);
1111+
return smb3_zero_range(file, tcon, off, len, false);
1112+
}
10581113

10591114
return -EOPNOTSUPP;
10601115
}

0 commit comments

Comments
 (0)