Skip to content

Commit 9b5f6c9

Browse files
harshadjstytso
authored andcommitted
ext4: make s_mount_flags modifications atomic
Fast commit file system states are recorded in sbi->s_mount_flags. Fast commit expects these bit manipulations to be atomic. This patch adds helpers to make those modifications atomic. Suggested-by: Jan Kara <jack@suse.cz> Signed-off-by: Harshad Shirwadkar <harshadshirwadkar@gmail.com> Link: https://lore.kernel.org/r/20201106035911.1942128-21-harshadshirwadkar@gmail.com Signed-off-by: Theodore Ts'o <tytso@mit.edu>
1 parent da0c5d2 commit 9b5f6c9

7 files changed

Lines changed: 52 additions & 34 deletions

File tree

fs/ext4/ext4.h

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,16 +1419,6 @@ struct ext4_super_block {
14191419

14201420
#ifdef __KERNEL__
14211421

1422-
/*
1423-
* run-time mount flags
1424-
*/
1425-
#define EXT4_MF_MNTDIR_SAMPLED 0x0001
1426-
#define EXT4_MF_FS_ABORTED 0x0002 /* Fatal error detected */
1427-
#define EXT4_MF_FC_INELIGIBLE 0x0004 /* Fast commit ineligible */
1428-
#define EXT4_MF_FC_COMMITTING 0x0008 /* File system underoing a fast
1429-
* commit.
1430-
*/
1431-
14321422
#ifdef CONFIG_FS_ENCRYPTION
14331423
#define DUMMY_ENCRYPTION_ENABLED(sbi) ((sbi)->s_dummy_enc_policy.policy != NULL)
14341424
#else
@@ -1463,7 +1453,7 @@ struct ext4_sb_info {
14631453
struct buffer_head * __rcu *s_group_desc;
14641454
unsigned int s_mount_opt;
14651455
unsigned int s_mount_opt2;
1466-
unsigned int s_mount_flags;
1456+
unsigned long s_mount_flags;
14671457
unsigned int s_def_mount_opt;
14681458
ext4_fsblk_t s_sb_block;
14691459
atomic64_t s_resv_clusters;
@@ -1691,6 +1681,34 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
16911681
_v; \
16921682
})
16931683

1684+
/*
1685+
* run-time mount flags
1686+
*/
1687+
enum {
1688+
EXT4_MF_MNTDIR_SAMPLED,
1689+
EXT4_MF_FS_ABORTED, /* Fatal error detected */
1690+
EXT4_MF_FC_INELIGIBLE, /* Fast commit ineligible */
1691+
EXT4_MF_FC_COMMITTING /* File system underoing a fast
1692+
* commit.
1693+
*/
1694+
};
1695+
1696+
static inline void ext4_set_mount_flag(struct super_block *sb, int bit)
1697+
{
1698+
set_bit(bit, &EXT4_SB(sb)->s_mount_flags);
1699+
}
1700+
1701+
static inline void ext4_clear_mount_flag(struct super_block *sb, int bit)
1702+
{
1703+
clear_bit(bit, &EXT4_SB(sb)->s_mount_flags);
1704+
}
1705+
1706+
static inline int ext4_test_mount_flag(struct super_block *sb, int bit)
1707+
{
1708+
return test_bit(bit, &EXT4_SB(sb)->s_mount_flags);
1709+
}
1710+
1711+
16941712
/*
16951713
* Simulate_fail codes
16961714
*/

fs/ext4/fast_commit.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ void ext4_fc_mark_ineligible(struct super_block *sb, int reason)
261261
(EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY))
262262
return;
263263

264-
sbi->s_mount_flags |= EXT4_MF_FC_INELIGIBLE;
264+
ext4_set_mount_flag(sb, EXT4_MF_FC_INELIGIBLE);
265265
WARN_ON(reason >= EXT4_FC_REASON_MAX);
266266
sbi->s_fc_stats.fc_ineligible_reason_count[reason]++;
267267
}
@@ -294,14 +294,14 @@ void ext4_fc_stop_ineligible(struct super_block *sb)
294294
(EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY))
295295
return;
296296

297-
EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FC_INELIGIBLE;
297+
ext4_set_mount_flag(sb, EXT4_MF_FC_INELIGIBLE);
298298
atomic_dec(&EXT4_SB(sb)->s_fc_ineligible_updates);
299299
}
300300

301301
static inline int ext4_fc_is_ineligible(struct super_block *sb)
302302
{
303-
return (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FC_INELIGIBLE) ||
304-
atomic_read(&EXT4_SB(sb)->s_fc_ineligible_updates);
303+
return (ext4_test_mount_flag(sb, EXT4_MF_FC_INELIGIBLE) ||
304+
atomic_read(&EXT4_SB(sb)->s_fc_ineligible_updates));
305305
}
306306

307307
/*
@@ -349,7 +349,7 @@ static int ext4_fc_track_template(
349349
spin_lock(&sbi->s_fc_lock);
350350
if (list_empty(&EXT4_I(inode)->i_fc_list))
351351
list_add_tail(&EXT4_I(inode)->i_fc_list,
352-
(sbi->s_mount_flags & EXT4_MF_FC_COMMITTING) ?
352+
(ext4_test_mount_flag(inode->i_sb, EXT4_MF_FC_COMMITTING)) ?
353353
&sbi->s_fc_q[FC_Q_STAGING] :
354354
&sbi->s_fc_q[FC_Q_MAIN]);
355355
spin_unlock(&sbi->s_fc_lock);
@@ -402,7 +402,7 @@ static int __track_dentry_update(struct inode *inode, void *arg, bool update)
402402
node->fcd_name.len = dentry->d_name.len;
403403

404404
spin_lock(&sbi->s_fc_lock);
405-
if (sbi->s_mount_flags & EXT4_MF_FC_COMMITTING)
405+
if (ext4_test_mount_flag(inode->i_sb, EXT4_MF_FC_COMMITTING))
406406
list_add_tail(&node->fcd_list,
407407
&sbi->s_fc_dentry_q[FC_Q_STAGING]);
408408
else
@@ -857,7 +857,7 @@ static int ext4_fc_submit_inode_data_all(journal_t *journal)
857857
int ret = 0;
858858

859859
spin_lock(&sbi->s_fc_lock);
860-
sbi->s_mount_flags |= EXT4_MF_FC_COMMITTING;
860+
ext4_set_mount_flag(sb, EXT4_MF_FC_COMMITTING);
861861
list_for_each(pos, &sbi->s_fc_q[FC_Q_MAIN]) {
862862
ei = list_entry(pos, struct ext4_inode_info, i_fc_list);
863863
ext4_set_inode_state(&ei->vfs_inode, EXT4_STATE_FC_COMMITTING);
@@ -1206,8 +1206,8 @@ static void ext4_fc_cleanup(journal_t *journal, int full)
12061206
list_splice_init(&sbi->s_fc_q[FC_Q_STAGING],
12071207
&sbi->s_fc_q[FC_Q_STAGING]);
12081208

1209-
sbi->s_mount_flags &= ~EXT4_MF_FC_COMMITTING;
1210-
sbi->s_mount_flags &= ~EXT4_MF_FC_INELIGIBLE;
1209+
ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING);
1210+
ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE);
12111211

12121212
if (full)
12131213
sbi->s_fc_bytes = 0;

fs/ext4/file.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -780,13 +780,13 @@ static int ext4_sample_last_mounted(struct super_block *sb,
780780
handle_t *handle;
781781
int err;
782782

783-
if (likely(sbi->s_mount_flags & EXT4_MF_MNTDIR_SAMPLED))
783+
if (likely(ext4_test_mount_flag(sb, EXT4_MF_MNTDIR_SAMPLED)))
784784
return 0;
785785

786786
if (sb_rdonly(sb) || !sb_start_intwrite_trylock(sb))
787787
return 0;
788788

789-
sbi->s_mount_flags |= EXT4_MF_MNTDIR_SAMPLED;
789+
ext4_set_mount_flag(sb, EXT4_MF_MNTDIR_SAMPLED);
790790
/*
791791
* Sample where the filesystem has been mounted and
792792
* store it in the superblock for sysadmin convenience

fs/ext4/fsync.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
143143
if (sb_rdonly(inode->i_sb)) {
144144
/* Make sure that we read updated s_mount_flags value */
145145
smp_rmb();
146-
if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
146+
if (ext4_test_mount_flag(inode->i_sb, EXT4_MF_FS_ABORTED))
147147
ret = -EROFS;
148148
goto out;
149149
}

fs/ext4/inode.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2442,7 +2442,7 @@ static int mpage_map_and_submit_extent(handle_t *handle,
24422442
struct super_block *sb = inode->i_sb;
24432443

24442444
if (ext4_forced_shutdown(EXT4_SB(sb)) ||
2445-
EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)
2445+
ext4_test_mount_flag(sb, EXT4_MF_FS_ABORTED))
24462446
goto invalidate_dirty_pages;
24472447
/*
24482448
* Let the uper layers retry transient errors.
@@ -2676,7 +2676,7 @@ static int ext4_writepages(struct address_space *mapping,
26762676
* the stack trace.
26772677
*/
26782678
if (unlikely(ext4_forced_shutdown(EXT4_SB(mapping->host->i_sb)) ||
2679-
sbi->s_mount_flags & EXT4_MF_FS_ABORTED)) {
2679+
ext4_test_mount_flag(inode->i_sb, EXT4_MF_FS_ABORTED))) {
26802680
ret = -EROFS;
26812681
goto out_writepages;
26822682
}

fs/ext4/mballoc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4477,7 +4477,7 @@ static inline void ext4_mb_show_pa(struct super_block *sb)
44774477
{
44784478
ext4_group_t i, ngroups;
44794479

4480-
if (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)
4480+
if (ext4_test_mount_flag(sb, EXT4_MF_FS_ABORTED))
44814481
return;
44824482

44834483
ngroups = ext4_get_groups_count(sb);
@@ -4508,7 +4508,7 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
45084508
{
45094509
struct super_block *sb = ac->ac_sb;
45104510

4511-
if (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)
4511+
if (ext4_test_mount_flag(sb, EXT4_MF_FS_ABORTED))
45124512
return;
45134513

45144514
mb_debug(sb, "Can't allocate:"

fs/ext4/super.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ static void ext4_handle_error(struct super_block *sb)
686686
if (!test_opt(sb, ERRORS_CONT)) {
687687
journal_t *journal = EXT4_SB(sb)->s_journal;
688688

689-
EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
689+
ext4_set_mount_flag(sb, EXT4_MF_FS_ABORTED);
690690
if (journal)
691691
jbd2_journal_abort(journal, -EIO);
692692
}
@@ -904,7 +904,7 @@ void __ext4_abort(struct super_block *sb, const char *function,
904904
va_end(args);
905905

906906
if (sb_rdonly(sb) == 0) {
907-
EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
907+
ext4_set_mount_flag(sb, EXT4_MF_FS_ABORTED);
908908
if (EXT4_SB(sb)->s_journal)
909909
jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
910910

@@ -2153,7 +2153,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
21532153
ext4_msg(sb, KERN_WARNING, "Ignoring removed %s option", opt);
21542154
return 1;
21552155
case Opt_abort:
2156-
sbi->s_mount_flags |= EXT4_MF_FS_ABORTED;
2156+
ext4_set_mount_flag(sb, EXT4_MF_FS_ABORTED);
21572157
return 1;
21582158
case Opt_i_version:
21592159
sb->s_flags |= SB_I_VERSION;
@@ -4778,8 +4778,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
47784778
INIT_LIST_HEAD(&sbi->s_fc_dentry_q[FC_Q_MAIN]);
47794779
INIT_LIST_HEAD(&sbi->s_fc_dentry_q[FC_Q_STAGING]);
47804780
sbi->s_fc_bytes = 0;
4781-
sbi->s_mount_flags &= ~EXT4_MF_FC_INELIGIBLE;
4782-
sbi->s_mount_flags &= ~EXT4_MF_FC_COMMITTING;
4781+
ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE);
4782+
ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING);
47834783
spin_lock_init(&sbi->s_fc_lock);
47844784
memset(&sbi->s_fc_stats, 0, sizeof(sbi->s_fc_stats));
47854785
sbi->s_fc_replay_state.fc_regions = NULL;
@@ -5881,7 +5881,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
58815881
goto restore_opts;
58825882
}
58835883

5884-
if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
5884+
if (ext4_test_mount_flag(sb, EXT4_MF_FS_ABORTED))
58855885
ext4_abort(sb, EXT4_ERR_ESHUTDOWN, "Abort forced by user");
58865886

58875887
sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
@@ -5895,7 +5895,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
58955895
}
58965896

58975897
if ((bool)(*flags & SB_RDONLY) != sb_rdonly(sb)) {
5898-
if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) {
5898+
if (ext4_test_mount_flag(sb, EXT4_MF_FS_ABORTED)) {
58995899
err = -EROFS;
59005900
goto restore_opts;
59015901
}

0 commit comments

Comments
 (0)