aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/smb2ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/smb2ops.c')
-rw-r--r--fs/cifs/smb2ops.c45
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
1018static 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
1052static 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
1018static void 1062static void
1019smb2_downgrade_oplock(struct TCP_Server_Info *server, 1063smb2_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
1468struct smb_version_values smb20_values = { 1513struct smb_version_values smb20_values = {