* [PATCH] smb/client: use writable handle for FS_IOC_SETFLAGS compression
@ 2026-06-04 15:18 Huiwen He
0 siblings, 0 replies; only message in thread
From: Huiwen He @ 2026-06-04 15:18 UTC (permalink / raw)
To: smfrench, linkinjeon, pc, ronniesahlberg, sprasad, tom, bharathsm,
senozhatsky, dhowells, metze, chenxiaosong
Cc: linux-cifs
From: Huiwen He <hehuiwen@kylinos.cn>
Setting the compressed flag on a CIFS mount can fail with -EACCES:
$ touch test.bin
$ chattr +c test.bin
chattr: Permission denied while setting flags on test.bin
This can be reproduced against a Samba share backed by a filesystem that
supports compression, such as btrfs.
FS_IOC_SETFLAGS is issued on the file handle opened by userspace. chattr
opens the target read-only before setting FS_COMPR_FL, so the SMB client
currently sends FSCTL_SET_COMPRESSION on a handle that may not have
FILE_WRITE_DATA access. Samba requires FILE_WRITE_DATA for
FSCTL_SET_COMPRESSION and rejects the request.
Use the current handle only if it already has FILE_WRITE_DATA. Otherwise
try an existing writable handle for the inode. If none is available, open
a temporary FILE_WRITE_DATA handle for the compression request.
After FSCTL_SET_COMPRESSION succeeds, update the cached compressed
attribute immediately, matching how smb2_set_sparse() updates
FILE_ATTRIBUTE_SPARSE_FILE after a successful FSCTL_SET_SPARSE.
Signed-off-by: Huiwen He <hehuiwen@kylinos.cn>
Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
---
fs/smb/client/ioctl.c | 73 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 71 insertions(+), 2 deletions(-)
diff --git a/fs/smb/client/ioctl.c b/fs/smb/client/ioctl.c
index 17408bb8ab65..9afc43ac2bde 100644
--- a/fs/smb/client/ioctl.c
+++ b/fs/smb/client/ioctl.c
@@ -67,6 +67,72 @@ static long cifs_ioctl_query_info(unsigned int xid, struct file *filep,
return rc;
}
+static int cifs_ioctl_set_compression(unsigned int xid, struct file *filep,
+ struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile)
+{
+ struct inode *inode = file_inode(filep);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct TCP_Server_Info *server = tcon->ses->server;
+ struct cifs_open_parms oparms;
+ struct cifsFileInfo *wfile;
+ struct cifsFileInfo tmp_cfile = {};
+ struct cifs_tcon *wtcon;
+ struct cifs_fid fid = {};
+ const char *full_path;
+ __u32 oplock = 0;
+ void *page;
+ int rc;
+
+ if (!server->ops->set_compression)
+ return -EOPNOTSUPP;
+
+ if (cfile && (cfile->fid.access & FILE_WRITE_DATA)) {
+ rc = server->ops->set_compression(xid, tcon, cfile);
+ if (rc != -EACCES)
+ return rc;
+ }
+
+ rc = cifs_get_writable_file(CIFS_I(inode), FIND_FSUID_ONLY, &wfile);
+ if (!rc) {
+ wtcon = tlink_tcon(wfile->tlink);
+ if (wtcon->ses->server->ops->set_compression)
+ rc = wtcon->ses->server->ops->set_compression(xid,
+ wtcon, wfile);
+ else
+ rc = -EOPNOTSUPP;
+ cifsFileInfo_put(wfile);
+ if (rc != -EACCES)
+ return rc;
+ }
+
+ if (!server->ops->open || !server->ops->close)
+ return -EOPNOTSUPP;
+
+ page = alloc_dentry_path();
+ full_path = build_path_from_dentry(filep->f_path.dentry, page);
+ if (IS_ERR(full_path)) {
+ free_dentry_path(page);
+ return PTR_ERR(full_path);
+ }
+
+ oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA,
+ FILE_OPEN, 0, ACL_NO_MODE);
+ oparms.fid = &fid;
+
+ rc = server->ops->open(xid, &oparms, &oplock, NULL);
+ if (rc)
+ goto out;
+
+ tmp_cfile.fid = fid;
+ rc = server->ops->set_compression(xid, tcon, &tmp_cfile);
+
+ server->ops->close(xid, tcon, &fid);
+out:
+ free_dentry_path(page);
+ return rc;
+}
+
static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
unsigned long srcfd)
{
@@ -427,8 +493,11 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
/* Try to set compress flag */
if (tcon->ses->server->ops->set_compression) {
- rc = tcon->ses->server->ops->set_compression(
- xid, tcon, pSMBFile);
+ rc = cifs_ioctl_set_compression(xid, filep, tcon,
+ pSMBFile);
+ if (rc == 0)
+ CIFS_I(inode)->cifsAttrs |=
+ FILE_ATTRIBUTE_COMPRESSED;
cifs_dbg(FYI, "set compress flag rc %d\n", rc);
}
break;
--
2.43.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-06-04 15:19 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-04 15:18 [PATCH] smb/client: use writable handle for FS_IOC_SETFLAGS compression Huiwen He
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox