Skip to content

Commit 0d6d519

Browse files
haryvengregkh
authored andcommitted
smb/client: preserve errors from smb2_set_sparse()
[ Upstream commit 2a4b3d2 ] smb2_set_sparse() converts every FSCTL_SET_SPARSE failure to false and marks sparse support as broken for the share. Callers therefore report EOPNOTSUPP even for errors such as ENOSPC or EACCES, and later sparse operations remain disabled until the share is unmounted. Return the SMB2 ioctl error directly. Set broken_sparse_sup only for EOPNOTSUPP, which indicates that the server does not support the request. Update smb3_punch_hole() to propagate the error returned by smb2_set_sparse(). Fixes: 3d1a374 ("Add sparse file support to SMB2/SMB3 mounts") Signed-off-by: Huiwen He <hehuiwen@kylinos.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent ea8e946 commit 0d6d519

1 file changed

Lines changed: 15 additions & 15 deletions

File tree

fs/smb/client/smb2ops.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1967,8 +1967,9 @@ smb2_sync_write(const unsigned int xid, struct cifs_fid *pfid,
19671967
}
19681968

19691969
/* Set or clear the SPARSE_FILE attribute based on value passed in setsparse */
1970-
static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
1971-
struct cifsFileInfo *cfile, struct inode *inode, __u8 setsparse)
1970+
static int smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
1971+
struct cifsFileInfo *cfile, struct inode *inode,
1972+
__u8 setsparse)
19721973
{
19731974
struct cifsInodeInfo *cifsi;
19741975
int rc;
@@ -1977,39 +1978,39 @@ static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
19771978

19781979
/* if file already sparse don't bother setting sparse again */
19791980
if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && setsparse)
1980-
return true; /* already sparse */
1981+
return 0; /* already sparse */
19811982

19821983
if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && !setsparse)
1983-
return true; /* already not sparse */
1984+
return 0; /* already not sparse */
19841985

19851986
/*
19861987
* Can't check for sparse support on share the usual way via the
19871988
* FS attribute info (FILE_SUPPORTS_SPARSE_FILES) on the share
19881989
* since Samba server doesn't set the flag on the share, yet
19891990
* supports the set sparse FSCTL and returns sparse correctly
1990-
* in the file attributes. If we fail setting sparse though we
1991-
* mark that server does not support sparse files for this share
1992-
* to avoid repeatedly sending the unsupported fsctl to server
1993-
* if the file is repeatedly extended.
1991+
* in the file attributes. If the server returns EOPNOTSUPP, mark
1992+
* that sparse files are not supported on this share to avoid
1993+
* repeatedly sending the unsupported FSCTL.
19941994
*/
19951995
if (tcon->broken_sparse_sup)
1996-
return false;
1996+
return -EOPNOTSUPP;
19971997

19981998
rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
19991999
cfile->fid.volatile_fid, FSCTL_SET_SPARSE,
20002000
&setsparse, 1, CIFSMaxBufSize, NULL, NULL);
20012001
if (rc) {
2002-
tcon->broken_sparse_sup = true;
2002+
if (rc == -EOPNOTSUPP)
2003+
tcon->broken_sparse_sup = true;
20032004
cifs_dbg(FYI, "set sparse rc = %d\n", rc);
2004-
return false;
2005+
return rc;
20052006
}
20062007

20072008
if (setsparse)
20082009
cifsi->cifsAttrs |= FILE_ATTRIBUTE_SPARSE_FILE;
20092010
else
20102011
cifsi->cifsAttrs &= (~FILE_ATTRIBUTE_SPARSE_FILE);
20112012

2012-
return true;
2013+
return 0;
20132014
}
20142015

20152016
static int
@@ -3322,10 +3323,9 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
33223323
inode_lock(inode);
33233324
/* Need to make file sparse, if not already, before freeing range. */
33243325
/* Consider adding equivalent for compressed since it could also work */
3325-
if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse)) {
3326-
rc = -EOPNOTSUPP;
3326+
rc = smb2_set_sparse(xid, tcon, cfile, inode, set_sparse);
3327+
if (rc)
33273328
goto out;
3328-
}
33293329

33303330
filemap_invalidate_lock(inode->i_mapping);
33313331
/*

0 commit comments

Comments
 (0)