From patchwork Sun Feb 16 16:40:26 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 13976582 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8333F1EB2A; Sun, 16 Feb 2025 16:42:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739724139; cv=none; b=dwFrJ42gXTEPOc5widIdTpoblSYD8HK+NcMaZmZpV6Zh2DDvlrzdcox+63IQIrpQt1R/7o9+sdGDvLtkYfpHw7+HkL1fchyHsJ400IhpXLXPBP9wReaRKo9YMpLJ0sa7BcyifV3T01AD9Ah/60uBokBVt9W0HO3PPQqCR/4aYzs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739724139; c=relaxed/simple; bh=5hnPF+bgOORINojs0uGlAFdWczPtX8nHtq7D6DocPNM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=Nxfthe3u1HNnWkaPbkSedqAFrKOx7TRXjDfSxzlsDnhE3TCjK+dZvhQRo02YMg/qoHHVKHntgW9gtlDQQZTYHZFRO9jqCVNsarvSSF4PIAzoVGBFe1ybd+0A37SFmC5wUfAX3JmtFogb008VQJRSdObWQZA3SbHNSra+zGgUvyk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MTcz0maW; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MTcz0maW" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AD7FFC4CEE4; Sun, 16 Feb 2025 16:42:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739724138; bh=5hnPF+bgOORINojs0uGlAFdWczPtX8nHtq7D6DocPNM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MTcz0maWsdhmg3AJNIGRxpTATB9dR2/+o0onL8Vhkr6ODd7inNBTejcchP4XBh5vp J+f89A0Oob2jT/Wj3dS2WWMXtDH54mji72Om/Cv1Pswxl31DTW8a2CrpxTonb5Gh9R zhgavxGoujJkPJYwJHYkcaO7fwCakg2c4wLfq9XaVuoGqMWNC3M8s54twRwt5EhV/l wBoov0RBekvhC7mP1AWJwE94/SbX5kTIjMFEs3dRv9xTFzjszj89EgdQnQRDHYcNAj ATR46WIEHeagviEbuQvRdjlDg8D4a8xHhJwL5BFuvtwGnLZwzVUyQubYLyiGV0PyY1 Njw2wK2ZRKxGA== Received: by pali.im (Postfix) id CE943A7F; Sun, 16 Feb 2025 17:42:05 +0100 (CET) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Amir Goldstein , "Darrick J. Wong" , ronnie sahlberg , Chuck Lever , Christian Brauner , Jan Kara , Steve French , Alexander Viro Cc: linux-fsdevel@vger.kernel.org, linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 1/4] fs: Add FS_XFLAG_COMPRESSED & FS_XFLAG_ENCRYPTED for FS_IOC_FS[GS]ETXATTR API Date: Sun, 16 Feb 2025 17:40:26 +0100 Message-Id: <20250216164029.20673-2-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250216164029.20673-1-pali@kernel.org> References: <20250216164029.20673-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This allows to get or set FS_COMPR_FL and FS_ENCRYPT_FL bits via FS_IOC_FSGETXATTR/FS_IOC_FSSETXATTR API. Signed-off-by: Pali Rohár --- fs/ioctl.c | 8 ++++++++ include/linux/fileattr.h | 4 ++-- include/uapi/linux/fs.h | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/fs/ioctl.c b/fs/ioctl.c index 638a36be31c1..9f3609b50779 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -480,6 +480,10 @@ void fileattr_fill_xflags(struct fileattr *fa, u32 xflags) fa->flags |= FS_DAX_FL; if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT) fa->flags |= FS_PROJINHERIT_FL; + if (fa->fsx_xflags & FS_XFLAG_COMPRESSED) + fa->flags |= FS_COMPR_FL; + if (fa->fsx_xflags & FS_XFLAG_ENCRYPTED) + fa->flags |= FS_ENCRYPT_FL; } EXPORT_SYMBOL(fileattr_fill_xflags); @@ -496,6 +500,8 @@ void fileattr_fill_flags(struct fileattr *fa, u32 flags) memset(fa, 0, sizeof(*fa)); fa->flags_valid = true; fa->flags = flags; + if (fa->flags & FS_COMPR_FL) + fa->fsx_xflags |= FS_XFLAG_COMPRESSED; if (fa->flags & FS_SYNC_FL) fa->fsx_xflags |= FS_XFLAG_SYNC; if (fa->flags & FS_IMMUTABLE_FL) @@ -506,6 +512,8 @@ void fileattr_fill_flags(struct fileattr *fa, u32 flags) fa->fsx_xflags |= FS_XFLAG_NODUMP; if (fa->flags & FS_NOATIME_FL) fa->fsx_xflags |= FS_XFLAG_NOATIME; + if (fa->flags & FS_ENCRYPT_FL) + fa->fsx_xflags |= FS_XFLAG_ENCRYPTED; if (fa->flags & FS_DAX_FL) fa->fsx_xflags |= FS_XFLAG_DAX; if (fa->flags & FS_PROJINHERIT_FL) diff --git a/include/linux/fileattr.h b/include/linux/fileattr.h index 47c05a9851d0..c297e6151703 100644 --- a/include/linux/fileattr.h +++ b/include/linux/fileattr.h @@ -7,12 +7,12 @@ #define FS_COMMON_FL \ (FS_SYNC_FL | FS_IMMUTABLE_FL | FS_APPEND_FL | \ FS_NODUMP_FL | FS_NOATIME_FL | FS_DAX_FL | \ - FS_PROJINHERIT_FL) + FS_PROJINHERIT_FL | FS_COMPR_FL | FS_ENCRYPT_FL) #define FS_XFLAG_COMMON \ (FS_XFLAG_SYNC | FS_XFLAG_IMMUTABLE | FS_XFLAG_APPEND | \ FS_XFLAG_NODUMP | FS_XFLAG_NOATIME | FS_XFLAG_DAX | \ - FS_XFLAG_PROJINHERIT) + FS_XFLAG_PROJINHERIT | FS_XFLAG_COMPRESSED | FS_XFLAG_ENCRYPTED) /* * Merged interface for miscellaneous file attributes. 'flags' originates from diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 2bbe00cf1248..367bc5289c47 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -167,6 +167,8 @@ struct fsxattr { #define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */ #define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */ #define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */ +#define FS_XFLAG_COMPRESSED 0x00020000 /* compressed file */ +#define FS_XFLAG_ENCRYPTED 0x00040000 /* encrypted file */ #define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ /* the read-only stuff doesn't really belong here, but any other place is From patchwork Sun Feb 16 16:40:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 13976583 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8338C18DB21; Sun, 16 Feb 2025 16:42:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739724139; cv=none; b=Lw5EeXY2n4gA6sLm5QY/2d/ycVfDzdp2G2AxJA1ttL5JyDL5djd/yjEgrg0XhWwJcHrXC9zvjePPJs/zCY4xLWOWpbtmpr1bjJKq4ivdfYjfWo9Dssc7MKuyJ6anuzZ5t6n0LYyfAwj8oFE0uF7IGsNKnreTSU7xp1AOF9yatqI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739724139; c=relaxed/simple; bh=RehJg42gCsvkynnxL7TMvNf8fOoQVcslCQrnQS0ZVM4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=QED2ZeeKxrRhFuBZspl2G69Lyd8nyeDU0J+s+kuhz0EUxA0Zx0uVtwpB/9WK7DSDDSwpc5ba+/g80LCX/ns9xK0IcssAXVUjKB7mPNVDrWwRnKUC31gso3/mMORx8PDbXvrjBiEqjr0nknJLcPjq9RD+ENBzUakdyGAOHYrCb/c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KDrEhEm0; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KDrEhEm0" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AB60BC4CEDD; Sun, 16 Feb 2025 16:42:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739724139; bh=RehJg42gCsvkynnxL7TMvNf8fOoQVcslCQrnQS0ZVM4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KDrEhEm0rQviO8QW9L7hEqiN4HMa5zWgmkKlglyPeZ4KjMA8wP1UW6s3FjGjCT07c pWQKBIDE56OFtKW9LQAV2mDJ201Yrk/Iw/7pM/Xc4F5v4UpwtLE3qxI/tjEdw5sqUn KN1AYWLG4n6boWhQELGJSG3HsbGfWkYaBEonXorK7jd6/HyufSn+vUvC6zdDQD+nno jBvkLhe1usB/fiFyVHfgOb0gc1dVo5NBs2uXK2El1smjXSUAgT9oKGZhl8DqtHHhvP oBf9z3ll1emcfJ7yrF8ejo8MJ1eL6GR8RXxCFNepB/rI5CbnR4Yj56FkuIui2KBm5l ILzapKOfEjh8Q== Received: by pali.im (Postfix) id 14E2DA81; Sun, 16 Feb 2025 17:42:06 +0100 (CET) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Amir Goldstein , "Darrick J. Wong" , ronnie sahlberg , Chuck Lever , Christian Brauner , Jan Kara , Steve French , Alexander Viro Cc: linux-fsdevel@vger.kernel.org, linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 2/4] fs: Extend FS_IOC_FS[GS]ETXATTR API for Windows attributes Date: Sun, 16 Feb 2025 17:40:27 +0100 Message-Id: <20250216164029.20673-3-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250216164029.20673-1-pali@kernel.org> References: <20250216164029.20673-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 struct fsxattr has 8 reserved padding bytes. Use these bytes for defining new fields fsx_xflags2, fsx_xflags2_mask and fsx_xflags_mask in backward compatible manner. If the new FS_XFLAG_HASEXTFIELDS flag in fsx_xflags is not set then these new fields are treated as not present, like before this change. New field fsx_xflags_mask for SET operation specifies which flags in fsx_xflags are going to be changed. This would allow userspace application to change just subset of all flags. For GET operation this field specifies which FS_XFLAG_* flags are supported by the file. New field fsx_xflags2 specify new flags FS_XFLAG2_* which defines some of Windows FILE_ATTRIBUTE_* attributes, which are mostly not going to be interpreted or used by the kernel, and are mostly going to be used by userspace. Field fsx_xflags2_mask then specify mask for them. This change defines just API without filesystem support for them. These attributes can be implemented later for Windows filesystems like FAT, NTFS, exFAT, UDF, SMB, NFS4 which all native storage for those attributes (or at least some subset of them). Signed-off-by: Pali Rohár --- include/uapi/linux/fs.h | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 367bc5289c47..93e947d6e604 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -145,15 +145,26 @@ struct fsxattr { __u32 fsx_nextents; /* nextents field value (get) */ __u32 fsx_projid; /* project identifier (get/set) */ __u32 fsx_cowextsize; /* CoW extsize field value (get/set)*/ - unsigned char fsx_pad[8]; + __u16 fsx_xflags2; /* xflags2 field value (get/set)*/ + __u16 fsx_xflags2_mask;/*mask for xflags2 (get/set)*/ + __u32 fsx_xflags_mask;/* mask for xflags (get/set)*/ + /* + * For FS_IOC_FSSETXATTR ioctl, fsx_xflags_mask and fsx_xflags2_mask + * fields specify which FS_XFLAG_* and FS_XFLAG2_* flags from fsx_xflags + * and fsx_xflags2 fields are going to be changed. + * + * For FS_IOC_FSGETXATTR ioctl, fsx_xflags_mask and fsx_xflags2_mask + * fields specify which FS_XFLAG_* and FS_XFLAG2_* flags are supported. + */ }; /* - * Flags for the fsx_xflags field + * Flags for the fsx_xflags and fsx_xflags_mask fields */ #define FS_XFLAG_REALTIME 0x00000001 /* data in realtime volume */ #define FS_XFLAG_PREALLOC 0x00000002 /* preallocated file extents */ -#define FS_XFLAG_IMMUTABLE 0x00000008 /* file cannot be modified */ +#define FS_XFLAG_IMMUTABLEUSER 0x00000004 /* file cannot be modified, changing this bit does not require CAP_LINUX_IMMUTABLE, equivalent of Windows FILE_ATTRIBUTE_READONLY */ +#define FS_XFLAG_IMMUTABLE 0x00000008 /* file cannot be modified, changing this bit requires CAP_LINUX_IMMUTABLE */ #define FS_XFLAG_APPEND 0x00000010 /* all writes append */ #define FS_XFLAG_SYNC 0x00000020 /* all writes synchronous */ #define FS_XFLAG_NOATIME 0x00000040 /* do not update access time */ @@ -167,10 +178,25 @@ struct fsxattr { #define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */ #define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */ #define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */ -#define FS_XFLAG_COMPRESSED 0x00020000 /* compressed file */ -#define FS_XFLAG_ENCRYPTED 0x00040000 /* encrypted file */ +#define FS_XFLAG_COMPRESSED 0x00020000 /* compressed file, equivalent of Windows FILE_ATTRIBUTE_COMPRESSED */ +#define FS_XFLAG_ENCRYPTED 0x00040000 /* encrypted file, equivalent of Windows FILE_ATTRIBUTE_ENCRYPTED */ +#define FS_XFLAG_CHECKSUMS 0x00080000 /* checksum for data and metadata, equivalent of Windows FILE_ATTRIBUTE_INTEGRITY_STREAM */ +#define FS_XFLAG_HASEXTFIELDS 0x40000000 /* fields fsx_xflags_mask, fsx_xflags2 and fsx_xflags2_mask are present */ #define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ +/* + * Flags for the fsx_xflags2 and fsx_xflags2_mask fields + */ +#define FS_XFLAG2_HIDDEN 0x0001 /* inode is hidden, equivalent of Widows FILE_ATTRIBUTE_HIDDEN */ +#define FS_XFLAG2_SYSTEM 0x0002 /* inode is part of operating system, equivalent of Windows FILE_ATTRIBUTE_SYSTEM */ +#define FS_XFLAG2_ARCHIVE 0x0004 /* inode was not archived yet, equivalent of Windows FILE_ATTRIBUTE_ARCHIVE */ +#define FS_XFLAG2_TEMPORARY 0x0008 /* inode content does not have to preserved across reboots, equivalent of Windows FILE_ATTRIBUTE_TEMPORARY */ +#define FS_XFLAG2_NOTINDEXED 0x0010 /* inode will not be indexed by content indexing service, equivalent of Windows FILE_ATTRIBUTE_NOT_CONTENT_INDEXED */ +#define FS_XFLAG2_NOSCRUBDATA 0x0020 /* file inode will not be checked by scrubber (proactive background data integrity scanner), for directory inode it means that newly created child would have this flag set, equivalent of Windows FILE_ATTRIBUTE_NO_SCRUB_DATA */ +#define FS_XFLAG2_OFFLINE 0x0040 /* inode is marked as HSM offline, equivalent of Windows FILE_ATTRIBUTE_OFFLINE */ +#define FS_XFLAG2_PINNED 0x0080 /* inode data content must be always stored in local HSM storage, equivalent of Windows FILE_ATTRIBUTE_PINNED */ +#define FS_XFLAG2_UNPINNED 0x0100 /* inode data content can be removed from local HSM storage, equivalent of Windows FILE_ATTRIBUTE_UNPINNED */ + /* the read-only stuff doesn't really belong here, but any other place is probably as bad and I don't want to create yet another include file. */ From patchwork Sun Feb 16 16:40:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 13976585 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B175D19C553; Sun, 16 Feb 2025 16:42:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739724139; cv=none; b=ZfwIJfi73PIiO6rCAIEuQDQbQw3wux2JOUD9K+U0HGDHiPTDlO3uS5vSUnVUu17f1zN2ZY626WPiL7LHIM45I3+UtpEcRlslB4zAJAjCsYaNzjADSDojS4fWRUjrGrCPWiMdM2q5qhb4d8Awu1E9ylZknst6euh8jxk3gQP3dTM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739724139; c=relaxed/simple; bh=0yhYVM7S/m/+LJAHD9tUolFgs28ihCKY3cuMIALsEMA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=FkGLp9bh3ZquCGcaM9rLrbpDDV5BC4RWWjMOJ3TxJSxtKbsxmc0FwPGLKBYpefV3BWk2Uf35K970UZPoXP/P6bt8gksYIS7c8VLDC53lpa/kBSG3ZNODLgzIY8QKfC5XsnZoIp/qneHq/tRFThcdiqbKhVO21TzLc0zeWX0G/Ug= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XkD1u8Uj; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="XkD1u8Uj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DF8DEC4CEEA; Sun, 16 Feb 2025 16:42:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739724139; bh=0yhYVM7S/m/+LJAHD9tUolFgs28ihCKY3cuMIALsEMA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XkD1u8Ujfskss72KlFF/phFTWZIlVlWE5byAHiOT8NAmxQumtmgJNzIx9qMUBlYCb nOXjF2PCksj1J8ax2IrDbp0ccLcSquKRAzItwHtzmxF9FosCda9nMUcA5SOE3npE/E QUzP/ZSObf73f8hHpnMYuyqWuxEGaT35y0qnRMcVCaM+Ud9wueeQHUHcXKt/8WF7P8 gHDAFS7jcp/mZJkP0PQc7cuWmoUolz8c/gvuOT0MWYXr+wOtFnhZbcaKH3cGdAZbK8 iOr+evE7/Q6Zbj3AmopfJAY8NPI2Ht59imj1MkDPgazvj9a1r5Qv4Tnhdf2QRsKNlZ GmsdJTJNsJ3vA== Received: by pali.im (Postfix) id 588DFDB5; Sun, 16 Feb 2025 17:42:06 +0100 (CET) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Amir Goldstein , "Darrick J. Wong" , ronnie sahlberg , Chuck Lever , Christian Brauner , Jan Kara , Steve French , Alexander Viro Cc: linux-fsdevel@vger.kernel.org, linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 3/4] fs: Implement support for fsx_xflags_mask, fsx_xflags2 and fsx_xflags2_mask into vfs Date: Sun, 16 Feb 2025 17:40:28 +0100 Message-Id: <20250216164029.20673-4-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250216164029.20673-1-pali@kernel.org> References: <20250216164029.20673-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This change adds support for new struct fileattr fields fsx_xflags_mask, fsx_xflags2 and fsx_xflags2_mask into FS_IOC_FSGETXATTR and FS_IOC_FSSETXATTR ioctls. All filesystem will start reporting values in new *_mask fields. This change does not contain support for any new flag yet. This will be in some followup changes. Signed-off-by: Pali Rohár --- fs/btrfs/ioctl.c | 9 +++++- fs/efivarfs/inode.c | 3 +- fs/ext2/ioctl.c | 2 +- fs/ext4/ioctl.c | 2 +- fs/f2fs/file.c | 2 +- fs/fuse/ioctl.c | 13 ++++++-- fs/gfs2/file.c | 14 ++++++++- fs/hfsplus/inode.c | 3 +- fs/ioctl.c | 65 +++++++++++++++++++++++++++++++++++----- fs/jfs/ioctl.c | 14 ++++++++- fs/nilfs2/ioctl.c | 2 +- fs/ntfs3/file.c | 3 +- fs/ocfs2/ioctl.c | 2 +- fs/orangefs/inode.c | 2 +- fs/ubifs/ioctl.c | 3 +- fs/xfs/xfs_ioctl.c | 5 +++- include/linux/fileattr.h | 11 +++++-- mm/shmem.c | 2 +- 18 files changed, 130 insertions(+), 27 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 6c18bad53cd3..600f502ffb46 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -164,6 +164,13 @@ static unsigned int btrfs_inode_flags_to_fsflags(struct btrfs_inode *binode) return iflags; } +static inline unsigned int btrfs_supported_fsflags(void) +{ + return FS_SYNC_FL | FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL | + FS_NOATIME_FL | FS_DIRSYNC_FL | FS_NOCOW_FL | FS_VERITY_FL | + FS_NOCOMP_FL | FS_COMPR_FL; +} + /* * Update inode->i_flags based on the btrfs internal flags. */ @@ -250,7 +257,7 @@ int btrfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) { struct btrfs_inode *binode = BTRFS_I(d_inode(dentry)); - fileattr_fill_flags(fa, btrfs_inode_flags_to_fsflags(binode)); + fileattr_fill_flags(fa, btrfs_inode_flags_to_fsflags(binode), btrfs_supported_fsflags()); return 0; } diff --git a/fs/efivarfs/inode.c b/fs/efivarfs/inode.c index 98a7299a9ee9..a8a3962b7751 100644 --- a/fs/efivarfs/inode.c +++ b/fs/efivarfs/inode.c @@ -142,12 +142,13 @@ efivarfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) { unsigned int i_flags; unsigned int flags = 0; + unsigned int mask = FS_IMMUTABLE_FL; i_flags = d_inode(dentry)->i_flags; if (i_flags & S_IMMUTABLE) flags |= FS_IMMUTABLE_FL; - fileattr_fill_flags(fa, flags); + fileattr_fill_flags(fa, flags, mask); return 0; } diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c index 44e04484e570..7a70f16c2824 100644 --- a/fs/ext2/ioctl.c +++ b/fs/ext2/ioctl.c @@ -22,7 +22,7 @@ int ext2_fileattr_get(struct dentry *dentry, struct fileattr *fa) { struct ext2_inode_info *ei = EXT2_I(d_inode(dentry)); - fileattr_fill_flags(fa, ei->i_flags & EXT2_FL_USER_VISIBLE); + fileattr_fill_flags(fa, ei->i_flags & EXT2_FL_USER_VISIBLE, EXT2_FL_USER_VISIBLE); return 0; } diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 7b9ce71c1c81..a199d0b74449 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -989,7 +989,7 @@ int ext4_fileattr_get(struct dentry *dentry, struct fileattr *fa) if (S_ISREG(inode->i_mode)) flags &= ~FS_PROJINHERIT_FL; - fileattr_fill_flags(fa, flags); + fileattr_fill_flags(fa, flags, EXT4_FL_USER_VISIBLE); if (ext4_has_feature_project(inode->i_sb)) fa->fsx_projid = from_kprojid(&init_user_ns, ei->i_projid); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index f92a9fba9991..03e1b31d1cbb 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -3297,7 +3297,7 @@ int f2fs_fileattr_get(struct dentry *dentry, struct fileattr *fa) if (is_inode_flag_set(inode, FI_PIN_FILE)) fsflags |= FS_NOCOW_FL; - fileattr_fill_flags(fa, fsflags & F2FS_GETTABLE_FS_FL); + fileattr_fill_flags(fa, fsflags & F2FS_GETTABLE_FS_FL, F2FS_GETTABLE_FS_FL); if (f2fs_sb_has_project_quota(F2FS_I_SB(inode))) fa->fsx_projid = from_kprojid(&init_user_ns, fi->i_projid); diff --git a/fs/fuse/ioctl.c b/fs/fuse/ioctl.c index 2d9abf48828f..be0901d7c61e 100644 --- a/fs/fuse/ioctl.c +++ b/fs/fuse/ioctl.c @@ -520,14 +520,20 @@ int fuse_fileattr_get(struct dentry *dentry, struct fileattr *fa) if (err) goto cleanup; - fileattr_fill_flags(fa, flags); + fileattr_fill_flags(fa, flags, ~0); } else { err = fuse_priv_ioctl(inode, ff, FS_IOC_FSGETXATTR, &xfa, sizeof(xfa)); if (err) goto cleanup; - fileattr_fill_xflags(fa, xfa.fsx_xflags); + if (!(xfa.fsx_xflags & FS_XFLAG_HASEXTFIELDS)) { + xfa.fsx_xflags_mask = 0; + xfa.fsx_xflags2 = 0; + xfa.fsx_xflags2_mask = 0; + } + + fileattr_fill_xflags(fa, xfa.fsx_xflags, xfa.fsx_xflags_mask, xfa.fsx_xflags2, xfa.fsx_xflags2_mask); fa->fsx_extsize = xfa.fsx_extsize; fa->fsx_nextents = xfa.fsx_nextents; fa->fsx_projid = xfa.fsx_projid; @@ -564,6 +570,9 @@ int fuse_fileattr_set(struct mnt_idmap *idmap, xfa.fsx_nextents = fa->fsx_nextents; xfa.fsx_projid = fa->fsx_projid; xfa.fsx_cowextsize = fa->fsx_cowextsize; + xfa.fsx_xflags2 = fa->fsx_xflags2; + xfa.fsx_xflags2_mask = fa->fsx_xflags2_mask; + xfa.fsx_xflags_mask = fa->fsx_xflags_mask; err = fuse_priv_ioctl(inode, ff, FS_IOC_FSSETXATTR, &xfa, sizeof(xfa)); diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index c9bb3be21d2b..29d243ade026 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -139,6 +139,16 @@ static struct { {FS_JOURNAL_DATA_FL, GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA}, }; +static inline u32 gfs2_supported_fsflags(void) +{ + int i; + u32 fsflags = 0; + + for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++) + fsflags |= fsflag_gfs2flag[i].fsflag; + return fsflags; +} + static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags) { int i; @@ -162,6 +172,7 @@ int gfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa) struct gfs2_holder gh; int error; u32 fsflags; + u32 fsmask; if (d_is_special(dentry)) return -ENOTTY; @@ -172,8 +183,9 @@ int gfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa) goto out_uninit; fsflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags); + fsmask = gfs2_supported_fsflags(); - fileattr_fill_flags(fa, fsflags); + fileattr_fill_flags(fa, fsflags, fsmask); gfs2_glock_dq(&gh); out_uninit: diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index f331e9574217..bb430a920f2b 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -659,6 +659,7 @@ int hfsplus_fileattr_get(struct dentry *dentry, struct fileattr *fa) struct inode *inode = d_inode(dentry); struct hfsplus_inode_info *hip = HFSPLUS_I(inode); unsigned int flags = 0; + unsigned int mask = FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL; if (inode->i_flags & S_IMMUTABLE) flags |= FS_IMMUTABLE_FL; @@ -667,7 +668,7 @@ int hfsplus_fileattr_get(struct dentry *dentry, struct fileattr *fa) if (hip->userflags & HFSPLUS_FLG_NODUMP) flags |= FS_NODUMP_FL; - fileattr_fill_flags(fa, flags); + fileattr_fill_flags(fa, flags, mask); return 0; } diff --git a/fs/ioctl.c b/fs/ioctl.c index 9f3609b50779..ef4d7d3d417b 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -458,14 +458,19 @@ static int ioctl_file_dedupe_range(struct file *file, * @fa: fileattr pointer * @xflags: FS_XFLAG_* flags * - * Set ->fsx_xflags, ->fsx_valid and ->flags (translated xflags). All - * other fields are zeroed. + * Set ->fsx_xflags, ->fsx_xflags2, ->fsx->xflags_mask, ->fsx_xflags2_mask, + * ->fsx_valid and ->flags (translated xflags). All other fields are zeroed. */ -void fileattr_fill_xflags(struct fileattr *fa, u32 xflags) +void fileattr_fill_xflags(struct fileattr *fa, u32 xflags, u32 xflags_mask, u16 xflags2, u16 xflags2_mask) { memset(fa, 0, sizeof(*fa)); fa->fsx_valid = true; fa->fsx_xflags = xflags; + fa->fsx_xflags2 = xflags2; + fa->fsx_xflags_mask = xflags_mask; + fa->fsx_xflags2_mask = xflags2_mask; + if (fa->fsx_xflags2 != 0 || fa->fsx_xflags_mask != 0 || fa->fsx_xflags2_mask != 0) + fa->fsx_xflags |= FS_XFLAG_HASEXTFIELDS; if (fa->fsx_xflags & FS_XFLAG_IMMUTABLE) fa->flags |= FS_IMMUTABLE_FL; if (fa->fsx_xflags & FS_XFLAG_APPEND) @@ -491,15 +496,20 @@ EXPORT_SYMBOL(fileattr_fill_xflags); * fileattr_fill_flags - initialize fileattr with flags * @fa: fileattr pointer * @flags: FS_*_FL flags + * @mask: FS_*_FL flags mask * - * Set ->flags, ->flags_valid and ->fsx_xflags (translated flags). + * Set ->flags, ->flags_valid and ->fsx_xflags (translated flags), + * fa->fsx_xflags_mask (translated flags mask). * All other fields are zeroed. */ -void fileattr_fill_flags(struct fileattr *fa, u32 flags) +void fileattr_fill_flags(struct fileattr *fa, u32 flags, u32 mask) { memset(fa, 0, sizeof(*fa)); fa->flags_valid = true; fa->flags = flags; + + fa->fsx_xflags |= FS_XFLAG_HASEXTFIELDS; + if (fa->flags & FS_COMPR_FL) fa->fsx_xflags |= FS_XFLAG_COMPRESSED; if (fa->flags & FS_SYNC_FL) @@ -518,6 +528,25 @@ void fileattr_fill_flags(struct fileattr *fa, u32 flags) fa->fsx_xflags |= FS_XFLAG_DAX; if (fa->flags & FS_PROJINHERIT_FL) fa->fsx_xflags |= FS_XFLAG_PROJINHERIT; + + if (mask & FS_COMPR_FL) + fa->fsx_xflags_mask |= FS_XFLAG_COMPRESSED; + if (mask & FS_SYNC_FL) + fa->fsx_xflags_mask |= FS_XFLAG_SYNC; + if (mask & FS_IMMUTABLE_FL) + fa->fsx_xflags_mask |= FS_XFLAG_IMMUTABLE; + if (mask & FS_APPEND_FL) + fa->fsx_xflags_mask |= FS_XFLAG_APPEND; + if (mask & FS_NODUMP_FL) + fa->fsx_xflags_mask |= FS_XFLAG_NODUMP; + if (mask & FS_NOATIME_FL) + fa->fsx_xflags_mask |= FS_XFLAG_NOATIME; + if (mask & FS_ENCRYPT_FL) + fa->fsx_xflags_mask |= FS_XFLAG_ENCRYPTED; + if (mask & FS_DAX_FL) + fa->fsx_xflags_mask |= FS_XFLAG_DAX; + if (mask & FS_PROJINHERIT_FL) + fa->fsx_xflags_mask |= FS_XFLAG_PROJINHERIT; } EXPORT_SYMBOL(fileattr_fill_flags); @@ -558,6 +587,11 @@ int copy_fsxattr_to_user(const struct fileattr *fa, struct fsxattr __user *ufa) xfa.fsx_nextents = fa->fsx_nextents; xfa.fsx_projid = fa->fsx_projid; xfa.fsx_cowextsize = fa->fsx_cowextsize; + if (xfa.fsx_xflags & FS_XFLAG_HASEXTFIELDS) { + xfa.fsx_xflags2 = fa->fsx_xflags2; + xfa.fsx_xflags2_mask = fa->fsx_xflags2_mask; + xfa.fsx_xflags_mask = fa->fsx_xflags_mask; + } if (copy_to_user(ufa, &xfa, sizeof(xfa))) return -EFAULT; @@ -574,7 +608,13 @@ static int copy_fsxattr_from_user(struct fileattr *fa, if (copy_from_user(&xfa, ufa, sizeof(xfa))) return -EFAULT; - fileattr_fill_xflags(fa, xfa.fsx_xflags); + if (!(xfa.fsx_xflags & FS_XFLAG_HASEXTFIELDS)) { + xfa.fsx_xflags_mask = 0; + xfa.fsx_xflags2 = 0; + xfa.fsx_xflags2_mask = 0; + } + + fileattr_fill_xflags(fa, xfa.fsx_xflags, xfa.fsx_xflags_mask, xfa.fsx_xflags2, xfa.fsx_xflags2_mask); fa->fsx_extsize = xfa.fsx_extsize; fa->fsx_nextents = xfa.fsx_nextents; fa->fsx_projid = xfa.fsx_projid; @@ -692,11 +732,22 @@ int vfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry, /* initialize missing bits from old_ma */ if (fa->flags_valid) { fa->fsx_xflags |= old_ma.fsx_xflags & ~FS_XFLAG_COMMON; + fa->fsx_xflags_mask = fa->fsx_xflags ^ old_ma.fsx_xflags; fa->fsx_extsize = old_ma.fsx_extsize; fa->fsx_nextents = old_ma.fsx_nextents; fa->fsx_projid = old_ma.fsx_projid; fa->fsx_cowextsize = old_ma.fsx_cowextsize; + fa->fsx_xflags2 = 0; + fa->fsx_xflags2_mask = 0; } else { + if (fa->fsx_xflags & FS_XFLAG_HASEXTFIELDS) { + fa->fsx_xflags = (fa->fsx_xflags & fa->fsx_xflags_mask) | (old_ma.fsx_xflags & ~fa->fsx_xflags_mask); + fa->fsx_xflags2 = (fa->fsx_xflags2 & fa->fsx_xflags2_mask) | (old_ma.fsx_xflags2 & ~fa->fsx_xflags2_mask); + } else { + fa->fsx_xflags_mask = fa->fsx_xflags ^ old_ma.fsx_xflags; + fa->fsx_xflags2 = old_ma.fsx_xflags2; + fa->fsx_xflags2_mask = 0; + } fa->flags |= old_ma.flags & ~FS_COMMON_FL; } err = fileattr_set_prepare(inode, &old_ma, fa); @@ -732,7 +783,7 @@ static int ioctl_setflags(struct file *file, unsigned int __user *argp) if (!err) { err = mnt_want_write_file(file); if (!err) { - fileattr_fill_flags(&fa, flags); + fileattr_fill_flags(&fa, flags, FS_COMMON_FL); err = vfs_fileattr_set(idmap, dentry, &fa); mnt_drop_write_file(file); } diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c index f7bd7e8f5be4..86184e32015c 100644 --- a/fs/jfs/ioctl.c +++ b/fs/jfs/ioctl.c @@ -39,6 +39,18 @@ static struct { {0, 0}, }; +static long jfs_supported_ext2_flags(void) +{ + int index=0; + long mapped=0; + + while (jfs_map[index].jfs_flag) { + mapped |= jfs_map[index].ext2_flag; + index++; + } + return mapped; +} + static long jfs_map_ext2(unsigned long flags, int from) { int index=0; @@ -65,7 +77,7 @@ int jfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) if (d_is_special(dentry)) return -ENOTTY; - fileattr_fill_flags(fa, jfs_map_ext2(flags, 0)); + fileattr_fill_flags(fa, jfs_map_ext2(flags, 0), jfs_supported_ext2_flags()); return 0; } diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index a66d62a51f77..2f1d5d765dcb 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -122,7 +122,7 @@ int nilfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) { struct inode *inode = d_inode(dentry); - fileattr_fill_flags(fa, NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE); + fileattr_fill_flags(fa, NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE, FS_FL_USER_VISIBLE); return 0; } diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 3f96a11804c9..a8f4d0b08d83 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -57,6 +57,7 @@ int ntfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) struct inode *inode = d_inode(dentry); struct ntfs_inode *ni = ntfs_i(inode); u32 flags = 0; + u32 mask = FS_IMMUTABLE_FL | FS_APPEND_FL | FS_COMPR_FL | FS_ENCRYPT_FL; if (inode->i_flags & S_IMMUTABLE) flags |= FS_IMMUTABLE_FL; @@ -70,7 +71,7 @@ int ntfs_fileattr_get(struct dentry *dentry, struct fileattr *fa) if (is_encrypted(ni)) flags |= FS_ENCRYPT_FL; - fileattr_fill_flags(fa, flags); + fileattr_fill_flags(fa, flags, mask); return 0; } diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index 7ae96fb8807a..fa48d1b92aab 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -77,7 +77,7 @@ int ocfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa) flags = OCFS2_I(inode)->ip_attr; ocfs2_inode_unlock(inode, 0); - fileattr_fill_flags(fa, flags & OCFS2_FL_VISIBLE); + fileattr_fill_flags(fa, flags & OCFS2_FL_VISIBLE, OCFS2_FL_VISIBLE); return status; } diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c index aae6d2b8767d..36104a08d654 100644 --- a/fs/orangefs/inode.c +++ b/fs/orangefs/inode.c @@ -923,7 +923,7 @@ static int orangefs_fileattr_get(struct dentry *dentry, struct fileattr *fa) gossip_debug(GOSSIP_FILE_DEBUG, "%s: flags=%u\n", __func__, (u32) val); - fileattr_fill_flags(fa, val); + fileattr_fill_flags(fa, val, FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NOATIME_FL); return 0; } diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c index 2c99349cf537..7d445c03a877 100644 --- a/fs/ubifs/ioctl.c +++ b/fs/ubifs/ioctl.c @@ -134,12 +134,13 @@ int ubifs_fileattr_get(struct dentry *dentry, struct fileattr *fa) { struct inode *inode = d_inode(dentry); int flags = ubifs2ioctl(ubifs_inode(inode)->flags); + int mask = ubifs2ioctl(~0); if (d_is_special(dentry)) return -ENOTTY; dbg_gen("get flags: %#x, i_flags %#x", flags, inode->i_flags); - fileattr_fill_flags(fa, flags); + fileattr_fill_flags(fa, flags, mask); return 0; } diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index ed85322507dd..9c5e75568c94 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -448,8 +448,11 @@ xfs_fill_fsxattr( { struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); + struct xfs_inode ip_all_xflags = { .i_diflags = XFS_DIFLAG_ANY, + .i_diflags2 = XFS_DIFLAG2_ANY, + .i_forkoff = 1 }; - fileattr_fill_xflags(fa, xfs_ip2xflags(ip)); + fileattr_fill_xflags(fa, xfs_ip2xflags(ip), xfs_ip2xflags(&ip_all_xflags), 0, 0); if (ip->i_diflags & XFS_DIFLAG_EXTSIZE) { fa->fsx_extsize = XFS_FSB_TO_B(mp, ip->i_extsize); diff --git a/include/linux/fileattr.h b/include/linux/fileattr.h index c297e6151703..f2107598ed6b 100644 --- a/include/linux/fileattr.h +++ b/include/linux/fileattr.h @@ -28,6 +28,9 @@ struct fileattr { u32 fsx_nextents; /* nextents field value (get) */ u32 fsx_projid; /* project identifier (get/set) */ u32 fsx_cowextsize; /* CoW extsize field value (get/set)*/ + u16 fsx_xflags2; /* xflags2 field value (get/set)*/ + u16 fsx_xflags2_mask;/*mask for xflags2 (get/set)*/ + u32 fsx_xflags_mask;/* mask for xflags (get/set)*/ /* selectors: */ bool flags_valid:1; bool fsx_valid:1; @@ -35,8 +38,8 @@ struct fileattr { int copy_fsxattr_to_user(const struct fileattr *fa, struct fsxattr __user *ufa); -void fileattr_fill_xflags(struct fileattr *fa, u32 xflags); -void fileattr_fill_flags(struct fileattr *fa, u32 flags); +void fileattr_fill_xflags(struct fileattr *fa, u32 xflags, u32 xflags_mask, u16 xflags2, u16 xflags2_mask); +void fileattr_fill_flags(struct fileattr *fa, u32 flags, u32 mask); /** * fileattr_has_fsx - check for extended flags/attributes @@ -49,7 +52,9 @@ static inline bool fileattr_has_fsx(const struct fileattr *fa) { return fa->fsx_valid && ((fa->fsx_xflags & ~FS_XFLAG_COMMON) || fa->fsx_extsize != 0 || - fa->fsx_projid != 0 || fa->fsx_cowextsize != 0); + fa->fsx_projid != 0 || fa->fsx_cowextsize != 0 || + fa->fsx_xflags2 != 0 || fa->fsx_xflags2_mask != 0 || + (fa->fsx_xflags_mask & ~FS_XFLAG_COMMON)); } int vfs_fileattr_get(struct dentry *dentry, struct fileattr *fa); diff --git a/mm/shmem.c b/mm/shmem.c index 4ea6109a8043..b991f49ee638 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -4178,7 +4178,7 @@ static int shmem_fileattr_get(struct dentry *dentry, struct fileattr *fa) { struct shmem_inode_info *info = SHMEM_I(d_inode(dentry)); - fileattr_fill_flags(fa, info->fsflags & SHMEM_FL_USER_VISIBLE); + fileattr_fill_flags(fa, info->fsflags & SHMEM_FL_USER_VISIBLE, SHMEM_FL_USER_VISIBLE); return 0; } From patchwork Sun Feb 16 16:40:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 13976586 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CC1D219C558; Sun, 16 Feb 2025 16:42:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739724139; cv=none; b=p4LvEHQ97MAkVSe/9q4OYqMt2x+cyinaRFWiFeME7WQh2k8Ab6CCJeJmWQz8NpfS2S8n3UU0aDdEVxhbObYEoAFm0dby3wrYBEy3IGtiimmMaLnS1IK4h3elALZ1k7M37fN7Wh12Jga/QolCB8vX5T3d5VQdp36jyuuYC4zcTXs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739724139; c=relaxed/simple; bh=RGGcyeHiog1KdXGjsvhFU0C6fu7FKSWGs4nXS+PgjfU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=MUQrerH6TSJtOwOANHL3mOcq63GqtsJwWYuosGWP4ROSfnumm/Ar0iSmy8kcSidpMlejTztZqeT9sNm9jfP6BRZpz8JHkgxKo2IQgWoIo8FRmKjEeFqLVQAxkZQ9myknfXgK7kAZCrmCqGslfvJ5r/N7PwXhBovF+R0YXjdXK5M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XbYMQD7G; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="XbYMQD7G" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 25AD1C4CEE8; Sun, 16 Feb 2025 16:42:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1739724139; bh=RGGcyeHiog1KdXGjsvhFU0C6fu7FKSWGs4nXS+PgjfU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XbYMQD7G8F3Hv+GsBBgFG5Xc7/hqAFD4+PE+XD88b9nu06i0Zy4PXyGKd+t7d9fJf 5pNNTLrrDZxdJo9NlTisUa/L91ib/x526j0cdxFlV2rXNVeq/IKR+L9Xuz9S1xq9Qu v63Rj3cUqGolEWgGrvFsU6JYOc27kAxhQnbF9+W9vQNqXbAiZ6LffmVOanXlJSe2ya 0cTA3vkZTYuFEapj6YdheLOZlhW8A4xcQSbm+fY5yc8Un99FQknQ4Dt4W2tJZkqPtf x8oerz50XwyNnD9BF2hbMK3DqdQOokJSqxwm7INf5HYwlzavndLAZaRF9YAZRs6jWP G7slU7mA1z03g== Received: by pali.im (Postfix) id 9E644F2E; Sun, 16 Feb 2025 17:42:06 +0100 (CET) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Amir Goldstein , "Darrick J. Wong" , ronnie sahlberg , Chuck Lever , Christian Brauner , Jan Kara , Steve French , Alexander Viro Cc: linux-fsdevel@vger.kernel.org, linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 4/4] cifs: Implement FS_IOC_FS[GS]ETXATTR API for Windows attributes Date: Sun, 16 Feb 2025 17:40:29 +0100 Message-Id: <20250216164029.20673-5-pali@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250216164029.20673-1-pali@kernel.org> References: <20250216164029.20673-1-pali@kernel.org> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Signed-off-by: Pali Rohár --- fs/smb/client/cifsfs.c | 4 + fs/smb/client/cifsfs.h | 2 + fs/smb/client/cifsglob.h | 4 +- fs/smb/client/cifsproto.h | 2 +- fs/smb/client/cifssmb.c | 4 +- fs/smb/client/inode.c | 181 ++++++++++++++++++++++++++++++++++++++ fs/smb/client/ioctl.c | 8 +- fs/smb/client/smb1ops.c | 4 +- fs/smb/client/smb2ops.c | 8 +- fs/smb/client/smb2pdu.c | 4 +- fs/smb/client/smb2proto.h | 2 +- fs/smb/common/smb2pdu.h | 2 + 12 files changed, 209 insertions(+), 16 deletions(-) diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index ea31d693ea9f..b441675f9afd 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -1182,6 +1182,8 @@ const struct inode_operations cifs_dir_inode_ops = { .listxattr = cifs_listxattr, .get_acl = cifs_get_acl, .set_acl = cifs_set_acl, + .fileattr_get = cifs_fileattr_get, + .fileattr_set = cifs_fileattr_set, }; const struct inode_operations cifs_file_inode_ops = { @@ -1192,6 +1194,8 @@ const struct inode_operations cifs_file_inode_ops = { .fiemap = cifs_fiemap, .get_acl = cifs_get_acl, .set_acl = cifs_set_acl, + .fileattr_get = cifs_fileattr_get, + .fileattr_set = cifs_fileattr_set, }; const char *cifs_get_link(struct dentry *dentry, struct inode *inode, diff --git a/fs/smb/client/cifsfs.h b/fs/smb/client/cifsfs.h index 831fee962c4d..b1e6025e2cbc 100644 --- a/fs/smb/client/cifsfs.h +++ b/fs/smb/client/cifsfs.h @@ -77,6 +77,8 @@ extern int cifs_setattr(struct mnt_idmap *, struct dentry *, struct iattr *); extern int cifs_fiemap(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); +extern int cifs_fileattr_get(struct dentry *dentry, struct fileattr *fa); +extern int cifs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry, struct fileattr *fa); extern const struct inode_operations cifs_file_inode_ops; extern const struct inode_operations cifs_symlink_inode_ops; diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index b764bfe916b4..233a0a13b0e2 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -426,7 +426,7 @@ struct smb_version_operations { int (*set_file_info)(struct inode *, const char *, FILE_BASIC_INFO *, const unsigned int); int (*set_compression)(const unsigned int, struct cifs_tcon *, - struct cifsFileInfo *); + struct cifsFileInfo *, bool); /* check if we can send an echo or nor */ bool (*can_echo)(struct TCP_Server_Info *); /* send echo request */ @@ -538,7 +538,7 @@ struct smb_version_operations { int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *, bool allocate_crypto); int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon, - struct cifsFileInfo *src_file); + struct cifsFileInfo *src_file, bool enable); int (*enum_snapshots)(const unsigned int xid, struct cifs_tcon *tcon, struct cifsFileInfo *src_file, void __user *); int (*notify)(const unsigned int xid, struct file *pfile, diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index 47ecc0884a74..f5f6be6f343e 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -506,7 +506,7 @@ extern struct inode *cifs_create_reparse_inode(struct cifs_open_info_data *data, struct kvec *reparse_iov, struct kvec *xattr_iov); extern int CIFSSMB_set_compression(const unsigned int xid, - struct cifs_tcon *tcon, __u16 fid); + struct cifs_tcon *tcon, __u16 fid, bool enable); extern int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, FILE_ALL_INFO *buf); extern int SMBOldOpen(const unsigned int xid, struct cifs_tcon *tcon, diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c index 3dbff55b639d..643a55db3ca9 100644 --- a/fs/smb/client/cifssmb.c +++ b/fs/smb/client/cifssmb.c @@ -3454,7 +3454,7 @@ struct inode *cifs_create_reparse_inode(struct cifs_open_info_data *data, int CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon, - __u16 fid) + __u16 fid, bool enable) { int rc = 0; int bytes_returned; @@ -3467,7 +3467,7 @@ CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon, if (rc) return rc; - pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT); + pSMB->compression_state = cpu_to_le16(enable ? COMPRESSION_FORMAT_DEFAULT : COMPRESSION_FORMAT_NONE); pSMB->TotalParameterCount = 0; pSMB->TotalDataCount = cpu_to_le32(2); diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c index dfad9284a87c..d07ebb99c262 100644 --- a/fs/smb/client/inode.c +++ b/fs/smb/client/inode.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "cifsfs.h" #include "cifspdu.h" @@ -83,6 +84,7 @@ static void cifs_set_ops(struct inode *inode) inode->i_op = &cifs_symlink_inode_ops; break; default: + inode->i_op = &cifs_file_inode_ops; init_special_inode(inode, inode->i_mode, inode->i_rdev); break; } @@ -3282,3 +3284,182 @@ cifs_setattr(struct mnt_idmap *idmap, struct dentry *direntry, /* BB: add cifs_setattr_legacy for really old servers */ return rc; } + +int cifs_fileattr_get(struct dentry *dentry, struct fileattr *fa) +{ + struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); + struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); + struct inode *inode = d_inode(dentry); + u32 attrs = CIFS_I(inode)->cifsAttrs; + u32 fsattrs = le32_to_cpu(tcon->fsAttrInfo.Attributes); + u32 xflags = 0; + u32 xflags_mask = FS_XFLAG_IMMUTABLEUSER; + u16 xflags2 = 0; + u16 xflags2_mask = FS_XFLAG2_HIDDEN | FS_XFLAG2_SYSTEM | FS_XFLAG2_ARCHIVE | + FS_XFLAG2_TEMPORARY | FS_XFLAG2_NOTINDEXED | + FS_XFLAG2_NOSCRUBDATA | FS_XFLAG2_OFFLINE | + FS_XFLAG2_PINNED | FS_XFLAG2_UNPINNED; + + if (fsattrs & FILE_FILE_COMPRESSION) + xflags_mask |= FS_XFLAG_COMPRESSED; + if (fsattrs & FILE_SUPPORTS_ENCRYPTION) + xflags_mask |= FS_XFLAG_COMPRESSED; + if (fsattrs & FILE_SUPPORT_INTEGRITY_STREAMS) + xflags_mask |= FS_XFLAG_CHECKSUMS; + + if (attrs & FILE_ATTRIBUTE_READONLY) + xflags |= FS_XFLAG_IMMUTABLEUSER; + if (attrs & FILE_ATTRIBUTE_HIDDEN) + xflags2 |= FS_XFLAG2_HIDDEN; + if (attrs & FILE_ATTRIBUTE_SYSTEM) + xflags2 |= FS_XFLAG2_SYSTEM; + if (attrs & FILE_ATTRIBUTE_ARCHIVE) + xflags2 |= FS_XFLAG2_ARCHIVE; + if (attrs & FILE_ATTRIBUTE_TEMPORARY) + xflags2 |= FS_XFLAG2_TEMPORARY; + if (attrs & FILE_ATTRIBUTE_COMPRESSED) + xflags |= FS_XFLAG_COMPRESSED; + if (attrs & FILE_ATTRIBUTE_OFFLINE) + xflags2 |= FS_XFLAG2_OFFLINE; + if (attrs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) + xflags2 |= FS_XFLAG2_NOTINDEXED; + if (attrs & FILE_ATTRIBUTE_ENCRYPTED) + xflags |= FS_XFLAG_ENCRYPTED; + if (attrs & FILE_ATTRIBUTE_INTEGRITY_STREAM) + xflags |= FS_XFLAG_CHECKSUMS; + if (attrs & FILE_ATTRIBUTE_NO_SCRUB_DATA) + xflags2 |= FS_XFLAG2_NOSCRUBDATA; + if (attrs & FILE_ATTRIBUTE_PINNED) + xflags2 |= FS_XFLAG2_PINNED; + if (attrs & FILE_ATTRIBUTE_UNPINNED) + xflags2 |= FS_XFLAG2_UNPINNED; + + fileattr_fill_xflags(fa, xflags, xflags_mask, xflags2, xflags2_mask); + return 0; +} + +#define MODIFY_ATTRS_COND(attrs, xflags, xflag, attr) (attrs) ^= ((-(!!((xflags) & (xflag))) ^ (attrs)) & (attr)) + +int cifs_fileattr_set(struct mnt_idmap *idmap, + struct dentry *dentry, struct fileattr *fa) +{ + struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); + struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); + struct inode *inode = d_inode(dentry); + u32 attrs = CIFS_I(inode)->cifsAttrs; + struct cifsFileInfo open_file_tmp = {}; + struct cifsFileInfo *open_file = NULL; + struct cifs_open_parms oparms; + FILE_BASIC_INFO info_buf = {}; + bool do_close = false; + const char *full_path; + unsigned int xid; + __u32 oplock; + void *page; + int rc; + + if ((fa->fsx_xflags_mask & ~(FS_XFLAG_IMMUTABLEUSER | FS_XFLAG_COMPRESSED | + FS_XFLAG_ENCRYPTED | FS_XFLAG_CHECKSUMS)) || + (fa->fsx_xflags2_mask & ~(FS_XFLAG2_HIDDEN | FS_XFLAG2_SYSTEM | FS_XFLAG2_ARCHIVE | + FS_XFLAG2_TEMPORARY | FS_XFLAG2_NOTINDEXED | + FS_XFLAG2_NOSCRUBDATA | FS_XFLAG2_OFFLINE | + FS_XFLAG2_PINNED | FS_XFLAG2_UNPINNED)) || + (fa->flags & ~FS_COMMON_FL)) + return -EOPNOTSUPP; + + if (fa->fsx_xflags_mask & FS_XFLAG_IMMUTABLEUSER) + MODIFY_ATTRS_COND(attrs, fa->fsx_xflags, FS_XFLAG_IMMUTABLEUSER, FILE_ATTRIBUTE_READONLY); + if (fa->fsx_xflags2_mask & FS_XFLAG2_HIDDEN) + MODIFY_ATTRS_COND(attrs, fa->fsx_xflags2, FS_XFLAG2_HIDDEN, FILE_ATTRIBUTE_HIDDEN); + if (fa->fsx_xflags2_mask & FS_XFLAG2_SYSTEM) + MODIFY_ATTRS_COND(attrs, fa->fsx_xflags2, FS_XFLAG2_SYSTEM, FILE_ATTRIBUTE_SYSTEM); + if (fa->fsx_xflags2_mask & FS_XFLAG2_ARCHIVE) + MODIFY_ATTRS_COND(attrs, fa->fsx_xflags2, FS_XFLAG2_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE); + if (fa->fsx_xflags2_mask & FS_XFLAG2_TEMPORARY) + MODIFY_ATTRS_COND(attrs, fa->fsx_xflags2, FS_XFLAG2_TEMPORARY, FILE_ATTRIBUTE_TEMPORARY); + if (fa->fsx_xflags2_mask & FS_XFLAG2_NOTINDEXED) + MODIFY_ATTRS_COND(attrs, fa->fsx_xflags2, FS_XFLAG2_NOTINDEXED, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); + if (fa->fsx_xflags2_mask & FS_XFLAG2_NOSCRUBDATA) + MODIFY_ATTRS_COND(attrs, fa->fsx_xflags2, FS_XFLAG2_NOSCRUBDATA, FILE_ATTRIBUTE_NO_SCRUB_DATA); + if (fa->fsx_xflags2_mask & FS_XFLAG2_OFFLINE) + MODIFY_ATTRS_COND(attrs, fa->fsx_xflags2, FS_XFLAG2_OFFLINE, FILE_ATTRIBUTE_OFFLINE); + if (fa->fsx_xflags2_mask & FS_XFLAG2_PINNED) + MODIFY_ATTRS_COND(attrs, fa->fsx_xflags2, FS_XFLAG2_PINNED, FILE_ATTRIBUTE_PINNED); + if (fa->fsx_xflags2_mask & FS_XFLAG2_UNPINNED) + MODIFY_ATTRS_COND(attrs, fa->fsx_xflags2, FS_XFLAG2_UNPINNED, FILE_ATTRIBUTE_UNPINNED); + + page = alloc_dentry_path(); + + full_path = build_path_from_dentry(dentry, page); + if (IS_ERR(full_path)) { + rc = PTR_ERR(full_path); + goto out_page; + } + + xid = get_xid(); + + if (attrs != CIFS_I(inode)->cifsAttrs) { + info_buf.Attributes = cpu_to_le32(attrs); + if (tcon->ses->server->ops->set_file_info) + rc = tcon->ses->server->ops->set_file_info(inode, full_path, &info_buf, xid); + else + rc = -EOPNOTSUPP; + if (rc) + goto out_xid; + CIFS_I(inode)->cifsAttrs = attrs; + } + + if (fa->fsx_xflags_mask & (FS_XFLAG_COMPRESSED | FS_XFLAG_ENCRYPTED | FS_XFLAG_CHECKSUMS)) { + open_file = find_writable_file(CIFS_I(inode), FIND_WR_FSUID_ONLY); + if (!open_file) { + oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA, FILE_OPEN, 0, ACL_NO_MODE); + oparms.fid = &open_file_tmp.fid; + oplock = 0; + oparms.create_options = cifs_create_options(cifs_sb, 0); + rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL); + if (rc) + goto out_file; + do_close = true; + open_file = &open_file_tmp; + } + } + + if (fa->fsx_xflags_mask & FS_XFLAG_COMPRESSED) { + if (tcon->ses->server->ops->set_compression) + rc = tcon->ses->server->ops->set_compression(xid, tcon, open_file, fa->fsx_xflags & FS_XFLAG_COMPRESSED); + else + rc = -EOPNOTSUPP; + if (rc) + goto out_file; + CIFS_I(inode)->cifsAttrs |= FILE_ATTRIBUTE_COMPRESSED; + } + + if (fa->fsx_xflags_mask & FS_XFLAG_ENCRYPTED) { + /* TODO */ + rc = -EOPNOTSUPP; + if (rc) + goto out_file; + CIFS_I(inode)->cifsAttrs |= FILE_ATTRIBUTE_ENCRYPTED; + } + + if (fa->fsx_xflags_mask & FS_XFLAG_CHECKSUMS) { + if (tcon->ses->server->ops->set_integrity) + rc = tcon->ses->server->ops->set_integrity(xid, tcon, open_file, fa->fsx_xflags & FS_XFLAG_CHECKSUMS); + else + rc = -EOPNOTSUPP; + if (rc) + goto out_file; + CIFS_I(inode)->cifsAttrs |= FILE_ATTRIBUTE_INTEGRITY_STREAM; + } + +out_file: + if (do_close) + tcon->ses->server->ops->close(xid, tcon, oparms.fid); + else if (open_file) + cifsFileInfo_put(open_file); +out_xid: + free_xid(xid); +out_page: + free_dentry_path(page); + return rc; +} diff --git a/fs/smb/client/ioctl.c b/fs/smb/client/ioctl.c index 56439da4f119..7c245085f891 100644 --- a/fs/smb/client/ioctl.c +++ b/fs/smb/client/ioctl.c @@ -356,12 +356,14 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) struct cifs_tcon *tcon; struct tcon_link *tlink; struct cifs_sb_info *cifs_sb; +#if 0 __u64 ExtAttrBits = 0; #ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY __u64 caps; #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ #endif /* CONFIG_CIFS_POSIX */ +#endif xid = get_xid(); @@ -372,6 +374,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) trace_smb3_ioctl(xid, pSMBFile->fid.persistent_fid, command); switch (command) { +#if 0 case FS_IOC_GETFLAGS: if (pSMBFile == NULL) break; @@ -429,10 +432,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); + xid, tcon, pSMBFile, true); cifs_dbg(FYI, "set compress flag rc %d\n", rc); } break; +#endif case CIFS_IOC_COPYCHUNK_FILE: rc = cifs_ioctl_copychunk(xid, filep, arg); break; @@ -445,7 +449,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) tcon = tlink_tcon(pSMBFile->tlink); if (tcon->ses->server->ops->set_integrity) rc = tcon->ses->server->ops->set_integrity(xid, - tcon, pSMBFile); + tcon, pSMBFile, true); else rc = -EOPNOTSUPP; break; diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index ba6452d89df3..2e854bde67de 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -1245,9 +1245,9 @@ smb_set_file_info(struct inode *inode, const char *full_path, static int cifs_set_compression(const unsigned int xid, struct cifs_tcon *tcon, - struct cifsFileInfo *cfile) + struct cifsFileInfo *cfile, bool enable) { - return CIFSSMB_set_compression(xid, tcon, cfile->fid.netfid); + return CIFSSMB_set_compression(xid, tcon, cfile->fid.netfid, enable); } static int diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index f8445a9ff9a1..9c66e413c59c 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -2106,20 +2106,20 @@ smb2_duplicate_extents(const unsigned int xid, static int smb2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, - struct cifsFileInfo *cfile) + struct cifsFileInfo *cfile, bool enable) { return SMB2_set_compression(xid, tcon, cfile->fid.persistent_fid, - cfile->fid.volatile_fid); + cfile->fid.volatile_fid, enable); } static int smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon, - struct cifsFileInfo *cfile) + struct cifsFileInfo *cfile, bool enable) { struct fsctl_set_integrity_information_req integr_info; unsigned int ret_data_len; - integr_info.ChecksumAlgorithm = cpu_to_le16(CHECKSUM_TYPE_UNCHANGED); + integr_info.ChecksumAlgorithm = cpu_to_le16(enable ? CHECKSUM_TYPE_CRC64 : CHECKSUM_TYPE_NONE); integr_info.Flags = 0; integr_info.Reserved = 0; diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index a75947797d58..57d716cfc800 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -3537,14 +3537,14 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, - u64 persistent_fid, u64 volatile_fid) + u64 persistent_fid, u64 volatile_fid, bool enable) { int rc; struct compress_ioctl fsctl_input; char *ret_data = NULL; fsctl_input.CompressionState = - cpu_to_le16(COMPRESSION_FORMAT_DEFAULT); + cpu_to_le16(enable ? COMPRESSION_FORMAT_DEFAULT : COMPRESSION_FORMAT_NONE); rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid, FSCTL_SET_COMPRESSION, diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h index cec5921bfdd2..6086bbdeeae0 100644 --- a/fs/smb/client/smb2proto.h +++ b/fs/smb/client/smb2proto.h @@ -250,7 +250,7 @@ extern int SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, struct smb2_file_full_ea_info *buf, int len); extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, - u64 persistent_fid, u64 volatile_fid); + u64 persistent_fid, u64 volatile_fid, bool enable); extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, const u64 persistent_fid, const u64 volatile_fid, const __u8 oplock_level); diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h index ab902b155650..a24194bef849 100644 --- a/fs/smb/common/smb2pdu.h +++ b/fs/smb/common/smb2pdu.h @@ -1077,6 +1077,8 @@ struct smb2_server_client_notification { #define FILE_ATTRIBUTE_ENCRYPTED 0x00004000 #define FILE_ATTRIBUTE_INTEGRITY_STREAM 0x00008000 #define FILE_ATTRIBUTE_NO_SCRUB_DATA 0x00020000 +#define FILE_ATTRIBUTE_PINNED 0x00080000 +#define FILE_ATTRIBUTE_UNPINNED 0x00100000 #define FILE_ATTRIBUTE__MASK 0x00007FB7 #define FILE_ATTRIBUTE_READONLY_LE cpu_to_le32(0x00000001)