summaryrefslogtreecommitdiff
path: root/fs/cifs
diff options
context:
space:
mode:
authorSteve French <smfrench@gmail.com>2014-08-13 17:16:29 -0500
committerSteve French <smfrench@gmail.com>2014-08-15 23:01:00 -0500
commitd43cc79343dfabf9f168531d3f5cff313205c8fb (patch)
tree7f17f1c5b8f8ce58ecb9d4faad57b38387be3533 /fs/cifs
parent3d1a3745d8ca7ccdf00905b01fd5ab42ff523a94 (diff)
Cleanup sparse file support by creating worker function for it
Simply move code to new function (for clarity). Function sets or clears the sparse file attribute flag. Signed-off-by: Steve French <smfrench@gmail.com> Reviewed-by: David Disseldorp <ddiss@samba.org>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/smb2ops.c80
1 files changed, 49 insertions, 31 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 74634369c21e..85be34ad8d76 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -731,6 +731,52 @@ smb2_sync_write(const unsigned int xid, struct cifsFileInfo *cfile,
return SMB2_write(xid, parms, written, iov, nr_segs);
}
+/* Set or clear the SPARSE_FILE attribute based on value passed in setsparse */
+static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile, struct inode *inode, __u8 setsparse)
+{
+ struct cifsInodeInfo *cifsi;
+ int rc;
+
+ cifsi = CIFS_I(inode);
+
+ /* if file already sparse don't bother setting sparse again */
+ if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && setsparse)
+ return true; /* already sparse */
+
+ if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && !setsparse)
+ return true; /* already not sparse */
+
+ /*
+ * Can't check for sparse support on share the usual way via the
+ * FS attribute info (FILE_SUPPORTS_SPARSE_FILES) on the share
+ * since Samba server doesn't set the flag on the share, yet
+ * supports the set sparse FSCTL and returns sparse correctly
+ * in the file attributes. If we fail setting sparse though we
+ * mark that server does not support sparse files for this share
+ * to avoid repeatedly sending the unsupported fsctl to server
+ * if the file is repeatedly extended.
+ */
+ if (tcon->broken_sparse_sup)
+ return false;
+
+ rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, FSCTL_SET_SPARSE,
+ true /* is_fctl */, &setsparse, 1, NULL, NULL);
+ if (rc) {
+ tcon->broken_sparse_sup = true;
+ cifs_dbg(FYI, "set sparse rc = %d\n", rc);
+ return false;
+ }
+
+ if (setsparse)
+ cifsi->cifsAttrs |= FILE_ATTRIBUTE_SPARSE_FILE;
+ else
+ cifsi->cifsAttrs &= (~FILE_ATTRIBUTE_SPARSE_FILE);
+
+ return true;
+}
+
static int
smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
struct cifsFileInfo *cfile, __u64 size, bool set_alloc)
@@ -745,40 +791,12 @@ smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
inode = cfile->dentry->d_inode;
if (!set_alloc && (size > inode->i_size + 8192)) {
- struct cifsInodeInfo *cifsi;
__u8 set_sparse = 1;
- int rc;
-
- cifsi = CIFS_I(inode);
-
- /* if file already sparse or no server support don't bother */
- if (cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE)
- goto smb2_set_eof;
-
- /*
- * Can't check for sparse support on share the usual way via the
- * FS attribute info (FILE_SUPPORTS_SPARSE_FILES) on the share
- * since Samba server doesn't set the flag on the share, yet
- * supports the set sparse FSCTL and returns sparse correctly
- * in the file attributes. If we fail setting sparse though we
- * mark that server does not support sparse files for this share
- * to avoid repeatedly sending the unsupported fsctl to server
- * if the file is repeatedly extended.
- */
- if (tcon->broken_sparse_sup)
- goto smb2_set_eof;
-
- rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid, FSCTL_SET_SPARSE,
- true /* is_fctl */, &set_sparse, 1, NULL, NULL);
- if (rc) {
- tcon->broken_sparse_sup = true;
- cifs_dbg(FYI, "set sparse rc = %d\n", rc);
- } else
- cifsi->cifsAttrs |= FILE_ATTRIBUTE_SPARSE_FILE;
+
+ /* whether set sparse succeeds or not, extend the file */
+ smb2_set_sparse(xid, tcon, cfile, inode, set_sparse);
}
-smb2_set_eof:
return SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
cfile->fid.volatile_fid, cfile->pid, &eof, false);
}