From nobody Sun Feb 8 05:44:22 2026 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=20Roh=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-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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=C3=A1r --- 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(struc= t btrfs_inode *binode) return iflags; } =20 +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 fi= leattr *fa) { struct btrfs_inode *binode =3D BTRFS_I(d_inode(dentry)); =20 - fileattr_fill_flags(fa, btrfs_inode_flags_to_fsflags(binode)); + fileattr_fill_flags(fa, btrfs_inode_flags_to_fsflags(binode), btrfs_suppo= rted_fsflags()); return 0; } =20 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 f= ileattr *fa) { unsigned int i_flags; unsigned int flags =3D 0; + unsigned int mask =3D FS_IMMUTABLE_FL; =20 i_flags =3D d_inode(dentry)->i_flags; if (i_flags & S_IMMUTABLE) flags |=3D FS_IMMUTABLE_FL; =20 - fileattr_fill_flags(fa, flags); + fileattr_fill_flags(fa, flags, mask); =20 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 filea= ttr *fa) { struct ext2_inode_info *ei =3D EXT2_I(d_inode(dentry)); =20 - 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); =20 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 fil= eattr *fa) if (S_ISREG(inode->i_mode)) flags &=3D ~FS_PROJINHERIT_FL; =20 - 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 =3D from_kprojid(&init_user_ns, ei->i_projid); =20 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 f= ileattr *fa) if (is_inode_flag_set(inode, FI_PIN_FILE)) fsflags |=3D FS_NOCOW_FL; =20 - fileattr_fill_flags(fa, fsflags & F2FS_GETTABLE_FS_FL); + fileattr_fill_flags(fa, fsflags & F2FS_GETTABLE_FS_FL, F2FS_GETTABLE_FS_F= L); =20 if (f2fs_sb_has_project_quota(F2FS_I_SB(inode))) fa->fsx_projid =3D 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 f= ileattr *fa) if (err) goto cleanup; =20 - fileattr_fill_flags(fa, flags); + fileattr_fill_flags(fa, flags, ~0); } else { err =3D fuse_priv_ioctl(inode, ff, FS_IOC_FSGETXATTR, &xfa, sizeof(xfa)); if (err) goto cleanup; =20 - fileattr_fill_xflags(fa, xfa.fsx_xflags); + if (!(xfa.fsx_xflags & FS_XFLAG_HASEXTFIELDS)) { + xfa.fsx_xflags_mask =3D 0; + xfa.fsx_xflags2 =3D 0; + xfa.fsx_xflags2_mask =3D 0; + } + + fileattr_fill_xflags(fa, xfa.fsx_xflags, xfa.fsx_xflags_mask, xfa.fsx_xf= lags2, xfa.fsx_xflags2_mask); fa->fsx_extsize =3D xfa.fsx_extsize; fa->fsx_nextents =3D xfa.fsx_nextents; fa->fsx_projid =3D xfa.fsx_projid; @@ -564,6 +570,9 @@ int fuse_fileattr_set(struct mnt_idmap *idmap, xfa.fsx_nextents =3D fa->fsx_nextents; xfa.fsx_projid =3D fa->fsx_projid; xfa.fsx_cowextsize =3D fa->fsx_cowextsize; + xfa.fsx_xflags2 =3D fa->fsx_xflags2; + xfa.fsx_xflags2_mask =3D fa->fsx_xflags2_mask; + xfa.fsx_xflags_mask =3D fa->fsx_xflags_mask; =20 err =3D 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}, }; =20 +static inline u32 gfs2_supported_fsflags(void) +{ + int i; + u32 fsflags =3D 0; + + for (i =3D 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++) + fsflags |=3D fsflag_gfs2flag[i].fsflag; + return fsflags; +} + static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsfla= gs) { int i; @@ -162,6 +172,7 @@ int gfs2_fileattr_get(struct dentry *dentry, struct fil= eattr *fa) struct gfs2_holder gh; int error; u32 fsflags; + u32 fsmask; =20 if (d_is_special(dentry)) return -ENOTTY; @@ -172,8 +183,9 @@ int gfs2_fileattr_get(struct dentry *dentry, struct fil= eattr *fa) goto out_uninit; =20 fsflags =3D gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags); + fsmask =3D gfs2_supported_fsflags(); =20 - fileattr_fill_flags(fa, fsflags); + fileattr_fill_flags(fa, fsflags, fsmask); =20 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 =3D d_inode(dentry); struct hfsplus_inode_info *hip =3D HFSPLUS_I(inode); unsigned int flags =3D 0; + unsigned int mask =3D FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL; =20 if (inode->i_flags & S_IMMUTABLE) flags |=3D FS_IMMUTABLE_FL; @@ -667,7 +668,7 @@ int hfsplus_fileattr_get(struct dentry *dentry, struct = fileattr *fa) if (hip->userflags & HFSPLUS_FLG_NODUMP) flags |=3D FS_NODUMP_FL; =20 - fileattr_fill_flags(fa, flags); + fileattr_fill_flags(fa, flags, mask); =20 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 zero= ed. */ -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 =3D true; fa->fsx_xflags =3D xflags; + fa->fsx_xflags2 =3D xflags2; + fa->fsx_xflags_mask =3D xflags_mask; + fa->fsx_xflags2_mask =3D xflags2_mask; + if (fa->fsx_xflags2 !=3D 0 || fa->fsx_xflags_mask !=3D 0 || fa->fsx_xflag= s2_mask !=3D 0) + fa->fsx_xflags |=3D FS_XFLAG_HASEXTFIELDS; if (fa->fsx_xflags & FS_XFLAG_IMMUTABLE) fa->flags |=3D 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 =3D true; fa->flags =3D flags; + + fa->fsx_xflags |=3D FS_XFLAG_HASEXTFIELDS; + if (fa->flags & FS_COMPR_FL) fa->fsx_xflags |=3D FS_XFLAG_COMPRESSED; if (fa->flags & FS_SYNC_FL) @@ -518,6 +528,25 @@ void fileattr_fill_flags(struct fileattr *fa, u32 flag= s) fa->fsx_xflags |=3D FS_XFLAG_DAX; if (fa->flags & FS_PROJINHERIT_FL) fa->fsx_xflags |=3D FS_XFLAG_PROJINHERIT; + + if (mask & FS_COMPR_FL) + fa->fsx_xflags_mask |=3D FS_XFLAG_COMPRESSED; + if (mask & FS_SYNC_FL) + fa->fsx_xflags_mask |=3D FS_XFLAG_SYNC; + if (mask & FS_IMMUTABLE_FL) + fa->fsx_xflags_mask |=3D FS_XFLAG_IMMUTABLE; + if (mask & FS_APPEND_FL) + fa->fsx_xflags_mask |=3D FS_XFLAG_APPEND; + if (mask & FS_NODUMP_FL) + fa->fsx_xflags_mask |=3D FS_XFLAG_NODUMP; + if (mask & FS_NOATIME_FL) + fa->fsx_xflags_mask |=3D FS_XFLAG_NOATIME; + if (mask & FS_ENCRYPT_FL) + fa->fsx_xflags_mask |=3D FS_XFLAG_ENCRYPTED; + if (mask & FS_DAX_FL) + fa->fsx_xflags_mask |=3D FS_XFLAG_DAX; + if (mask & FS_PROJINHERIT_FL) + fa->fsx_xflags_mask |=3D FS_XFLAG_PROJINHERIT; } EXPORT_SYMBOL(fileattr_fill_flags); =20 @@ -558,6 +587,11 @@ int copy_fsxattr_to_user(const struct fileattr *fa, st= ruct fsxattr __user *ufa) xfa.fsx_nextents =3D fa->fsx_nextents; xfa.fsx_projid =3D fa->fsx_projid; xfa.fsx_cowextsize =3D fa->fsx_cowextsize; + if (xfa.fsx_xflags & FS_XFLAG_HASEXTFIELDS) { + xfa.fsx_xflags2 =3D fa->fsx_xflags2; + xfa.fsx_xflags2_mask =3D fa->fsx_xflags2_mask; + xfa.fsx_xflags_mask =3D fa->fsx_xflags_mask; + } =20 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; =20 - fileattr_fill_xflags(fa, xfa.fsx_xflags); + if (!(xfa.fsx_xflags & FS_XFLAG_HASEXTFIELDS)) { + xfa.fsx_xflags_mask =3D 0; + xfa.fsx_xflags2 =3D 0; + xfa.fsx_xflags2_mask =3D 0; + } + + fileattr_fill_xflags(fa, xfa.fsx_xflags, xfa.fsx_xflags_mask, xfa.fsx_xfl= ags2, xfa.fsx_xflags2_mask); fa->fsx_extsize =3D xfa.fsx_extsize; fa->fsx_nextents =3D xfa.fsx_nextents; fa->fsx_projid =3D 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 |=3D old_ma.fsx_xflags & ~FS_XFLAG_COMMON; + fa->fsx_xflags_mask =3D fa->fsx_xflags ^ old_ma.fsx_xflags; fa->fsx_extsize =3D old_ma.fsx_extsize; fa->fsx_nextents =3D old_ma.fsx_nextents; fa->fsx_projid =3D old_ma.fsx_projid; fa->fsx_cowextsize =3D old_ma.fsx_cowextsize; + fa->fsx_xflags2 =3D 0; + fa->fsx_xflags2_mask =3D 0; } else { + if (fa->fsx_xflags & FS_XFLAG_HASEXTFIELDS) { + fa->fsx_xflags =3D (fa->fsx_xflags & fa->fsx_xflags_mask) | (old_ma.fs= x_xflags & ~fa->fsx_xflags_mask); + fa->fsx_xflags2 =3D (fa->fsx_xflags2 & fa->fsx_xflags2_mask) | (old_ma= .fsx_xflags2 & ~fa->fsx_xflags2_mask); + } else { + fa->fsx_xflags_mask =3D fa->fsx_xflags ^ old_ma.fsx_xflags; + fa->fsx_xflags2 =3D old_ma.fsx_xflags2; + fa->fsx_xflags2_mask =3D 0; + } fa->flags |=3D old_ma.flags & ~FS_COMMON_FL; } err =3D fileattr_set_prepare(inode, &old_ma, fa); @@ -732,7 +783,7 @@ static int ioctl_setflags(struct file *file, unsigned i= nt __user *argp) if (!err) { err =3D mnt_want_write_file(file); if (!err) { - fileattr_fill_flags(&fa, flags); + fileattr_fill_flags(&fa, flags, FS_COMMON_FL); err =3D 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}, }; =20 +static long jfs_supported_ext2_flags(void) +{ + int index=3D0; + long mapped=3D0; + + while (jfs_map[index].jfs_flag) { + mapped |=3D jfs_map[index].ext2_flag; + index++; + } + return mapped; +} + static long jfs_map_ext2(unsigned long flags, int from) { int index=3D0; @@ -65,7 +77,7 @@ int jfs_fileattr_get(struct dentry *dentry, struct fileat= tr *fa) if (d_is_special(dentry)) return -ENOTTY; =20 - fileattr_fill_flags(fa, jfs_map_ext2(flags, 0)); + fileattr_fill_flags(fa, jfs_map_ext2(flags, 0), jfs_supported_ext2_flags(= )); =20 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 fi= leattr *fa) { struct inode *inode =3D d_inode(dentry); =20 - 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); =20 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 filea= ttr *fa) struct inode *inode =3D d_inode(dentry); struct ntfs_inode *ni =3D ntfs_i(inode); u32 flags =3D 0; + u32 mask =3D FS_IMMUTABLE_FL | FS_APPEND_FL | FS_COMPR_FL | FS_ENCRYPT_FL; =20 if (inode->i_flags & S_IMMUTABLE) flags |=3D FS_IMMUTABLE_FL; @@ -70,7 +71,7 @@ int ntfs_fileattr_get(struct dentry *dentry, struct filea= ttr *fa) if (is_encrypted(ni)) flags |=3D FS_ENCRYPT_FL; =20 - fileattr_fill_flags(fa, flags); + fileattr_fill_flags(fa, flags, mask); =20 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 file= attr *fa) flags =3D OCFS2_I(inode)->ip_attr; ocfs2_inode_unlock(inode, 0); =20 - fileattr_fill_flags(fa, flags & OCFS2_FL_VISIBLE); + fileattr_fill_flags(fa, flags & OCFS2_FL_VISIBLE, OCFS2_FL_VISIBLE); =20 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) =20 gossip_debug(GOSSIP_FILE_DEBUG, "%s: flags=3D%u\n", __func__, (u32) val); =20 - fileattr_fill_flags(fa, val); + fileattr_fill_flags(fa, val, FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NOATIME_= FL); return 0; } =20 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 =3D d_inode(dentry); int flags =3D ubifs2ioctl(ubifs_inode(inode)->flags); + int mask =3D ubifs2ioctl(~0); =20 if (d_is_special(dentry)) return -ENOTTY; =20 dbg_gen("get flags: %#x, i_flags %#x", flags, inode->i_flags); - fileattr_fill_flags(fa, flags); + fileattr_fill_flags(fa, flags, mask); =20 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 =3D ip->i_mount; struct xfs_ifork *ifp =3D xfs_ifork_ptr(ip, whichfork); + struct xfs_inode ip_all_xflags =3D { .i_diflags =3D XFS_DIFLAG_ANY, + .i_diflags2 =3D XFS_DIFLAG2_ANY, + .i_forkoff =3D 1 }; =20 - fileattr_fill_xflags(fa, xfs_ip2xflags(ip)); + fileattr_fill_xflags(fa, xfs_ip2xflags(ip), xfs_ip2xflags(&ip_all_xflags)= , 0, 0); =20 if (ip->i_diflags & XFS_DIFLAG_EXTSIZE) { fa->fsx_extsize =3D 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 { =20 int copy_fsxattr_to_user(const struct fileattr *fa, struct fsxattr __user = *ufa); =20 -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); =20 /** * 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 !=3D 0 || - fa->fsx_projid !=3D 0 || fa->fsx_cowextsize !=3D 0); + fa->fsx_projid !=3D 0 || fa->fsx_cowextsize !=3D 0 || + fa->fsx_xflags2 !=3D 0 || fa->fsx_xflags2_mask !=3D 0 || + (fa->fsx_xflags_mask & ~FS_XFLAG_COMMON)); } =20 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 =3D SHMEM_I(d_inode(dentry)); =20 - fileattr_fill_flags(fa, info->fsflags & SHMEM_FL_USER_VISIBLE); + fileattr_fill_flags(fa, info->fsflags & SHMEM_FL_USER_VISIBLE, SHMEM_FL_U= SER_VISIBLE); =20 return 0; } --=20 2.20.1