|
@@ -332,33 +332,17 @@ static void ext4_put_nojournal(handle_t *handle)
|
|
|
* journal_end calls result in the superblock being marked dirty, so
|
|
|
* that sync() will call the filesystem's write_super callback if
|
|
|
* appropriate.
|
|
|
- *
|
|
|
- * To avoid j_barrier hold in userspace when a user calls freeze(),
|
|
|
- * ext4 prevents a new handle from being started by s_frozen, which
|
|
|
- * is in an upper layer.
|
|
|
*/
|
|
|
handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
|
|
|
{
|
|
|
journal_t *journal;
|
|
|
- handle_t *handle;
|
|
|
|
|
|
trace_ext4_journal_start(sb, nblocks, _RET_IP_);
|
|
|
if (sb->s_flags & MS_RDONLY)
|
|
|
return ERR_PTR(-EROFS);
|
|
|
|
|
|
+ WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
|
|
|
journal = EXT4_SB(sb)->s_journal;
|
|
|
- handle = ext4_journal_current_handle();
|
|
|
-
|
|
|
- /*
|
|
|
- * If a handle has been started, it should be allowed to
|
|
|
- * finish, otherwise deadlock could happen between freeze
|
|
|
- * and others(e.g. truncate) due to the restart of the
|
|
|
- * journal handle if the filesystem is forzen and active
|
|
|
- * handles are not stopped.
|
|
|
- */
|
|
|
- if (!handle)
|
|
|
- vfs_check_frozen(sb, SB_FREEZE_TRANS);
|
|
|
-
|
|
|
if (!journal)
|
|
|
return ext4_get_nojournal();
|
|
|
/*
|
|
@@ -2723,6 +2707,7 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
|
|
|
sb = elr->lr_super;
|
|
|
ngroups = EXT4_SB(sb)->s_groups_count;
|
|
|
|
|
|
+ sb_start_write(sb);
|
|
|
for (group = elr->lr_next_group; group < ngroups; group++) {
|
|
|
gdp = ext4_get_group_desc(sb, group, NULL);
|
|
|
if (!gdp) {
|
|
@@ -2749,6 +2734,7 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
|
|
|
elr->lr_next_sched = jiffies + elr->lr_timeout;
|
|
|
elr->lr_next_group = group + 1;
|
|
|
}
|
|
|
+ sb_end_write(sb);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
@@ -4302,10 +4288,8 @@ int ext4_force_commit(struct super_block *sb)
|
|
|
return 0;
|
|
|
|
|
|
journal = EXT4_SB(sb)->s_journal;
|
|
|
- if (journal) {
|
|
|
- vfs_check_frozen(sb, SB_FREEZE_TRANS);
|
|
|
+ if (journal)
|
|
|
ret = ext4_journal_force_commit(journal);
|
|
|
- }
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
@@ -4342,9 +4326,8 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
|
|
|
* gives us a chance to flush the journal completely and mark the fs clean.
|
|
|
*
|
|
|
* Note that only this function cannot bring a filesystem to be in a clean
|
|
|
- * state independently, because ext4 prevents a new handle from being started
|
|
|
- * by @sb->s_frozen, which stays in an upper layer. It thus needs help from
|
|
|
- * the upper layer.
|
|
|
+ * state independently. It relies on upper layer to stop all data & metadata
|
|
|
+ * modifications.
|
|
|
*/
|
|
|
static int ext4_freeze(struct super_block *sb)
|
|
|
{
|
|
@@ -4371,7 +4354,7 @@ static int ext4_freeze(struct super_block *sb)
|
|
|
EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
|
|
|
error = ext4_commit_super(sb, 1);
|
|
|
out:
|
|
|
- /* we rely on s_frozen to stop further updates */
|
|
|
+ /* we rely on upper layer to stop further updates */
|
|
|
jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
|
|
|
return error;
|
|
|
}
|