diff options
Diffstat (limited to 'fs/cifs/smb2ops.c')
-rw-r--r-- | fs/cifs/smb2ops.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 3fcd410cee31..101670c2c374 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -1015,6 +1015,50 @@ 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_punch_hole(struct file *file, struct cifs_tcon *tcon, | ||
1019 | loff_t offset, loff_t len) | ||
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 | __u8 set_sparse = 1; | ||
1028 | |||
1029 | xid = get_xid(); | ||
1030 | |||
1031 | inode = cfile->dentry->d_inode; | ||
1032 | cifsi = CIFS_I(inode); | ||
1033 | |||
1034 | /* Need to make file sparse, if not already, before freeing range. */ | ||
1035 | /* Consider adding equivalent for compressed since it could also work */ | ||
1036 | if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse)) | ||
1037 | return -EOPNOTSUPP; | ||
1038 | |||
1039 | cifs_dbg(FYI, "offset %lld len %lld", offset, len); | ||
1040 | |||
1041 | fsctl_buf.FileOffset = cpu_to_le64(offset); | ||
1042 | fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len); | ||
1043 | |||
1044 | rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, | ||
1045 | cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA, | ||
1046 | true /* is_fctl */, (char *)&fsctl_buf, | ||
1047 | sizeof(struct file_zero_data_information), NULL, NULL); | ||
1048 | free_xid(xid); | ||
1049 | return rc; | ||
1050 | } | ||
1051 | |||
1052 | static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode, | ||
1053 | loff_t off, loff_t len) | ||
1054 | { | ||
1055 | /* KEEP_SIZE already checked for by do_fallocate */ | ||
1056 | if (mode & FALLOC_FL_PUNCH_HOLE) | ||
1057 | return smb3_punch_hole(file, tcon, off, len); | ||
1058 | |||
1059 | return -EOPNOTSUPP; | ||
1060 | } | ||
1061 | |||
1018 | static void | 1062 | static void |
1019 | smb2_downgrade_oplock(struct TCP_Server_Info *server, | 1063 | smb2_downgrade_oplock(struct TCP_Server_Info *server, |
1020 | struct cifsInodeInfo *cinode, bool set_level2) | 1064 | struct cifsInodeInfo *cinode, bool set_level2) |
@@ -1463,6 +1507,7 @@ struct smb_version_operations smb30_operations = { | |||
1463 | .validate_negotiate = smb3_validate_negotiate, | 1507 | .validate_negotiate = smb3_validate_negotiate, |
1464 | .wp_retry_size = smb2_wp_retry_size, | 1508 | .wp_retry_size = smb2_wp_retry_size, |
1465 | .dir_needs_close = smb2_dir_needs_close, | 1509 | .dir_needs_close = smb2_dir_needs_close, |
1510 | .fallocate = smb3_fallocate, | ||
1466 | }; | 1511 | }; |
1467 | 1512 | ||
1468 | struct smb_version_values smb20_values = { | 1513 | struct smb_version_values smb20_values = { |