From 962b9df4720f468fc4577026687debba7d421a60 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 8 Jul 2026 21:55:15 +0900 Subject: [PATCH] ksmbd: preserve compression state across opens The compression state can be emulated with the DOS attribute xattr when the backing filesystem cannot store it directly. Do not limit that state to shares with store dos attributes enabled, otherwise a file reopened through another handle can lose FILE_ATTRIBUTE_COMPRESSED in file information responses. Load only the compressed bit from the DOS attribute xattr when store dos attributes is disabled. Keep the normal DOS attribute behavior unchanged when it is enabled. Also avoid clearing an already restored compressed bit just because the backing filesystem does not report FS_COMPR_FL. Signed-off-by: Namjae Jeon --- fs/smb/server/smb2pdu.c | 22 +++++++++++----------- fs/smb/server/vfs.c | 6 +----- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index 46e492595e87..a2ce35ca42c1 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -2975,10 +2975,6 @@ static bool smb2_parent_compressed(struct ksmbd_tree_connect *tcon, goto out; } - if (!test_share_config_flag(tcon->share_conf, - KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) - goto out; - rc = ksmbd_vfs_get_dos_attrib_xattr(mnt_idmap(path->mnt), parent, &da); if (rc > 0 && da.attr & FILE_ATTRIBUTE_COMPRESSED) compressed = true; @@ -2992,15 +2988,13 @@ static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon, const struct path *path, struct ksmbd_file *fp) { struct xattr_dos_attrib da; + bool store_dos_attrs = test_share_config_flag(tcon->share_conf, + KSMBD_SHARE_FLAG_STORE_DOS_ATTRS); int rc; fp->f_ci->m_fattr &= ~(FILE_ATTRIBUTE_HIDDEN_LE | FILE_ATTRIBUTE_SYSTEM_LE); /* get FileAttributes from XATTR_NAME_DOS_ATTRIBUTE */ - if (!test_share_config_flag(tcon->share_conf, - KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) - return; - rc = ksmbd_vfs_get_dos_attrib_xattr(mnt_idmap(path->mnt), path->dentry, &da); if (rc > 0) { @@ -3014,9 +3008,15 @@ static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon, */ if (!(server_conf.share_fake_fscaps & FILE_SUPPORTS_SPARSE_FILES)) da.attr &= ~FILE_ATTRIBUTE_SPARSE_FILE; - fp->f_ci->m_fattr = cpu_to_le32(da.attr); - fp->create_time = da.create_time; - fp->itime = da.itime; + if (store_dos_attrs) { + fp->f_ci->m_fattr = cpu_to_le32(da.attr); + fp->create_time = da.create_time; + fp->itime = da.itime; + } else if (da.attr & FILE_ATTRIBUTE_COMPRESSED) { + fp->f_ci->m_fattr |= FILE_ATTRIBUTE_COMPRESSED_LE; + } else { + fp->f_ci->m_fattr &= ~FILE_ATTRIBUTE_COMPRESSED_LE; + } } } diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c index 29fa0e62e72e..df09d6cf5111 100644 --- a/fs/smb/server/vfs.c +++ b/fs/smb/server/vfs.c @@ -2013,8 +2013,6 @@ void ksmbd_vfs_update_compressed_fattr(struct dentry *dentry, __le32 *fattr) if (fa.flags & FS_COMPR_FL) *fattr |= FILE_ATTRIBUTE_COMPRESSED_LE; - else - *fattr &= ~FILE_ATTRIBUTE_COMPRESSED_LE; } int ksmbd_vfs_get_compression(struct ksmbd_file *fp, u16 *fmt) @@ -2106,9 +2104,7 @@ update_fattr: else fp->f_ci->m_fattr |= FILE_ATTRIBUTE_COMPRESSED_LE; - if (fp->f_ci->m_fattr != old_fattr && - test_share_config_flag(work->tcon->share_conf, - KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) { + if (fp->f_ci->m_fattr != old_fattr) { struct xattr_dos_attrib da = {0}; rc = ksmbd_vfs_get_dos_attrib_xattr(idmap, dentry, &da);