aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r--fs/ext4/super.c31
1 files changed, 7 insertions, 24 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 2d51cd9af225..d76ec8277d3f 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -331,33 +331,17 @@ static void ext4_put_nojournal(handle_t *handle)
331 * journal_end calls result in the superblock being marked dirty, so 331 * journal_end calls result in the superblock being marked dirty, so
332 * that sync() will call the filesystem's write_super callback if 332 * that sync() will call the filesystem's write_super callback if
333 * appropriate. 333 * appropriate.
334 *
335 * To avoid j_barrier hold in userspace when a user calls freeze(),
336 * ext4 prevents a new handle from being started by s_frozen, which
337 * is in an upper layer.
338 */ 334 */
339handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) 335handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
340{ 336{
341 journal_t *journal; 337 journal_t *journal;
342 handle_t *handle;
343 338
344 trace_ext4_journal_start(sb, nblocks, _RET_IP_); 339 trace_ext4_journal_start(sb, nblocks, _RET_IP_);
345 if (sb->s_flags & MS_RDONLY) 340 if (sb->s_flags & MS_RDONLY)
346 return ERR_PTR(-EROFS); 341 return ERR_PTR(-EROFS);
347 342
343 WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
348 journal = EXT4_SB(sb)->s_journal; 344 journal = EXT4_SB(sb)->s_journal;
349 handle = ext4_journal_current_handle();
350
351 /*
352 * If a handle has been started, it should be allowed to
353 * finish, otherwise deadlock could happen between freeze
354 * and others(e.g. truncate) due to the restart of the
355 * journal handle if the filesystem is forzen and active
356 * handles are not stopped.
357 */
358 if (!handle)
359 vfs_check_frozen(sb, SB_FREEZE_TRANS);
360
361 if (!journal) 345 if (!journal)
362 return ext4_get_nojournal(); 346 return ext4_get_nojournal();
363 /* 347 /*
@@ -2747,6 +2731,7 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
2747 sb = elr->lr_super; 2731 sb = elr->lr_super;
2748 ngroups = EXT4_SB(sb)->s_groups_count; 2732 ngroups = EXT4_SB(sb)->s_groups_count;
2749 2733
2734 sb_start_write(sb);
2750 for (group = elr->lr_next_group; group < ngroups; group++) { 2735 for (group = elr->lr_next_group; group < ngroups; group++) {
2751 gdp = ext4_get_group_desc(sb, group, NULL); 2736 gdp = ext4_get_group_desc(sb, group, NULL);
2752 if (!gdp) { 2737 if (!gdp) {
@@ -2773,6 +2758,7 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
2773 elr->lr_next_sched = jiffies + elr->lr_timeout; 2758 elr->lr_next_sched = jiffies + elr->lr_timeout;
2774 elr->lr_next_group = group + 1; 2759 elr->lr_next_group = group + 1;
2775 } 2760 }
2761 sb_end_write(sb);
2776 2762
2777 return ret; 2763 return ret;
2778} 2764}
@@ -4460,10 +4446,8 @@ int ext4_force_commit(struct super_block *sb)
4460 return 0; 4446 return 0;
4461 4447
4462 journal = EXT4_SB(sb)->s_journal; 4448 journal = EXT4_SB(sb)->s_journal;
4463 if (journal) { 4449 if (journal)
4464 vfs_check_frozen(sb, SB_FREEZE_TRANS);
4465 ret = ext4_journal_force_commit(journal); 4450 ret = ext4_journal_force_commit(journal);
4466 }
4467 4451
4468 return ret; 4452 return ret;
4469} 4453}
@@ -4493,9 +4477,8 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
4493 * gives us a chance to flush the journal completely and mark the fs clean. 4477 * gives us a chance to flush the journal completely and mark the fs clean.
4494 * 4478 *
4495 * Note that only this function cannot bring a filesystem to be in a clean 4479 * Note that only this function cannot bring a filesystem to be in a clean
4496 * state independently, because ext4 prevents a new handle from being started 4480 * state independently. It relies on upper layer to stop all data & metadata
4497 * by @sb->s_frozen, which stays in an upper layer. It thus needs help from 4481 * modifications.
4498 * the upper layer.
4499 */ 4482 */
4500static int ext4_freeze(struct super_block *sb) 4483static int ext4_freeze(struct super_block *sb)
4501{ 4484{
@@ -4522,7 +4505,7 @@ static int ext4_freeze(struct super_block *sb)
4522 EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); 4505 EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
4523 error = ext4_commit_super(sb, 1); 4506 error = ext4_commit_super(sb, 1);
4524out: 4507out:
4525 /* we rely on s_frozen to stop further updates */ 4508 /* we rely on upper layer to stop further updates */
4526 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 4509 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
4527 return error; 4510 return error;
4528} 4511}