aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/smb2ops.c63
1 files changed, 62 insertions, 1 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index c5f521bcdee2..568f323665c8 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -1102,6 +1102,64 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
1102 return rc; 1102 return rc;
1103} 1103}
1104 1104
1105static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
1106 loff_t off, loff_t len, bool keep_size)
1107{
1108 struct inode *inode;
1109 struct cifsInodeInfo *cifsi;
1110 struct cifsFileInfo *cfile = file->private_data;
1111 long rc = -EOPNOTSUPP;
1112 unsigned int xid;
1113
1114 xid = get_xid();
1115
1116 inode = cfile->dentry->d_inode;
1117 cifsi = CIFS_I(inode);
1118
1119 /* if file not oplocked can't be sure whether asking to extend size */
1120 if (!CIFS_CACHE_READ(cifsi))
1121 if (keep_size == false)
1122 return -EOPNOTSUPP;
1123
1124 /*
1125 * Files are non-sparse by default so falloc may be a no-op
1126 * Must check if file sparse. If not sparse, and not extending
1127 * then no need to do anything since file already allocated
1128 */
1129 if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0) {
1130 if (keep_size == true)
1131 return 0;
1132 /* check if extending file */
1133 else if (i_size_read(inode) >= off + len)
1134 /* not extending file and already not sparse */
1135 return 0;
1136 /* BB: in future add else clause to extend file */
1137 else
1138 return -EOPNOTSUPP;
1139 }
1140
1141 if ((keep_size == true) || (i_size_read(inode) >= off + len)) {
1142 /*
1143 * Check if falloc starts within first few pages of file
1144 * and ends within a few pages of the end of file to
1145 * ensure that most of file is being forced to be
1146 * fallocated now. If so then setting whole file sparse
1147 * ie potentially making a few extra pages at the beginning
1148 * or end of the file non-sparse via set_sparse is harmless.
1149 */
1150 if ((off > 8192) || (off + len + 8192 < i_size_read(inode)))
1151 return -EOPNOTSUPP;
1152
1153 rc = smb2_set_sparse(xid, tcon, cfile, inode, false);
1154 }
1155 /* BB: else ... in future add code to extend file and set sparse */
1156
1157
1158 free_xid(xid);
1159 return rc;
1160}
1161
1162
1105static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode, 1163static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
1106 loff_t off, loff_t len) 1164 loff_t off, loff_t len)
1107{ 1165{
@@ -1112,7 +1170,10 @@ static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
1112 if (mode & FALLOC_FL_KEEP_SIZE) 1170 if (mode & FALLOC_FL_KEEP_SIZE)
1113 return smb3_zero_range(file, tcon, off, len, true); 1171 return smb3_zero_range(file, tcon, off, len, true);
1114 return smb3_zero_range(file, tcon, off, len, false); 1172 return smb3_zero_range(file, tcon, off, len, false);
1115 } 1173 } else if (mode == FALLOC_FL_KEEP_SIZE)
1174 return smb3_simple_falloc(file, tcon, off, len, true);
1175 else if (mode == 0)
1176 return smb3_simple_falloc(file, tcon, off, len, false);
1116 1177
1117 return -EOPNOTSUPP; 1178 return -EOPNOTSUPP;
1118} 1179}