diff options
author | Steve French <smfrench@gmail.com> | 2014-08-17 19:16:40 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2014-08-17 19:16:40 -0400 |
commit | 30175628bf7f521e9ee31ac98fa6d6fe7441a556 (patch) | |
tree | 6f3099407d45e8cc4d6b438f6587ddce8ef96cba /fs | |
parent | 31742c5a331766bc7df6b0d525df00c6cd20d5a6 (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.c | 55 |
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 | ||
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 | |||
1018 | static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, | 1068 | static 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 | } |