sb->s_iflags has unclear locking rules. Some users modify it under sb_lock, some under sb->s_umount rwsem, some without any lock. Readers are generally not holding any locks either. The flags are rarely modified so this does not lead to any practical problems but it is a mess. To reconcile the situation, handle sb->i_flags without any locks by using atomic bit operations. Since the flags are rarely modified, this does not introduce any noticeable performance overhead and resolves all possible issues when different users of sb->s_iflags could possibly stomp on each other's toes. Define new constants using bit numbers and functions to tests, set and clear the flags. Signed-off-by: Jan Kara <jack@xxxxxxx> --- include/linux/fs.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/include/linux/fs.h b/include/linux/fs.h index fd34b5755c0b..ff45a97b39cb 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1190,6 +1190,25 @@ extern int send_sigurg(struct fown_struct *fown); #define SB_I_RETIRED 0x00000800 /* superblock shouldn't be reused */ #define SB_I_NOUMASK 0x00001000 /* VFS does not apply umask */ +enum { + _SB_I_CGROUPWB, /* cgroup-aware writeback enabled */ + _SB_I_NOEXEC, /* Ignore executables on this fs */ + _SB_I_NODEV, /* Ignore devices on this fs */ + _SB_I_STABLE_WRITES, /* don't modify blks until WB is done */ + + /* sb->s_iflags to limit user namespace mounts */ + _SB_I_USERNS_VISIBLE, /* fstype already mounted */ + _SB_I_IMA_UNVERIFIABLE_SIGNATURE, + _SB_I_UNTRUSTED_MOUNTER, + _SB_I_EVM_HMAC_UNSUPPORTED, + + _SB_I_SKIP_SYNC, /* Skip superblock at global sync */ + _SB_I_PERSB_BDI, /* has a per-sb bdi */ + _SB_I_TS_EXPIRY_WARNED, /* warned about timestamp range expiry */ + _SB_I_RETIRED, /* superblock shouldn't be reused */ + _SB_I_NOUMASK, /* VFS does not apply umask */ +}; + /* Possible states of 'frozen' field */ enum { SB_UNFROZEN = 0, /* FS is unfrozen */ @@ -1351,6 +1370,21 @@ struct super_block { struct list_head s_inodes_wb; /* writeback inodes */ } __randomize_layout; +static inline bool sb_test_iflag(const struct super_block *sb, int flag) +{ + return test_bit(flag, &sb->s_iflags); +} + +static inline void sb_set_iflag(struct super_block *sb, int flag) +{ + set_bit(flag, &sb->s_iflags); +} + +static inline void sb_clear_iflag(struct super_block *sb, int flag) +{ + clear_bit(flag, &sb->s_iflags); +} + static inline struct user_namespace *i_user_ns(const struct inode *inode) { return inode->i_sb->s_user_ns; -- 2.35.3