aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteve French <smfrench@gmail.com>2014-08-17 19:16:40 -0400
committerSteve French <smfrench@gmail.com>2014-08-17 19:16:40 -0400
commit30175628bf7f521e9ee31ac98fa6d6fe7441a556 (patch)
tree6f3099407d45e8cc4d6b438f6587ddce8ef96cba /fs
parent31742c5a331766bc7df6b0d525df00c6cd20d5a6 (diff)
[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>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/smb2ops.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 101670c2c374..5a48aa290dfe 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -1015,6 +1015,56 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
1015 return rc; 1015 return rc;
1016} 1016}
1017 1017
1018static 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
1018static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, 1068static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
1019 loff_t offset, loff_t len) 1069 loff_t offset, loff_t len)
1020{ 1070{
@@ -1055,6 +1105,11 @@ static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
1055 /* KEEP_SIZE already checked for by do_fallocate */ 1105 /* KEEP_SIZE already checked for by do_fallocate */
1056 if (mode & FALLOC_FL_PUNCH_HOLE) 1106 if (mode & FALLOC_FL_PUNCH_HOLE)
1057 return smb3_punch_hole(file, tcon, off, len); 1107 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 }
1058 1113
1059 return -EOPNOTSUPP; 1114 return -EOPNOTSUPP;
1060} 1115}