aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2010-05-16 02:00:00 -0400
committerTheodore Ts'o <tytso@mit.edu>2010-05-16 02:00:00 -0400
commit6b0310fbf087ad6e9e3b8392adca97cd77184084 (patch)
tree6c15fad6ca442d92e8075578a9b04811ca093bda /fs
parent256a453546f1cf2c29a639c79fe0d603761a8e25 (diff)
ext4: don't return to userspace after freezing the fs with a mutex held
ext4_freeze() used jbd2_journal_lock_updates() which takes the j_barrier mutex, and then returns to userspace. The kernel does not like this: ================================================ [ BUG: lock held when returning to user space! ] ------------------------------------------------ lvcreate/1075 is leaving the kernel with locks still held! 1 lock held by lvcreate/1075: #0: (&journal->j_barrier){+.+...}, at: [<ffffffff811c6214>] jbd2_journal_lock_updates+0xe1/0xf0 Use vfs_check_frozen() added to ext4_journal_start_sb() and ext4_force_commit() instead. Addresses-Red-Hat-Bugzilla: #568503 Signed-off-by: Eric Sandeen <sandeen@redhat.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/super.c20
1 files changed, 10 insertions, 10 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index e14d22c170d5..00d09f58f188 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -241,6 +241,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
241 if (sb->s_flags & MS_RDONLY) 241 if (sb->s_flags & MS_RDONLY)
242 return ERR_PTR(-EROFS); 242 return ERR_PTR(-EROFS);
243 243
244 vfs_check_frozen(sb, SB_FREEZE_WRITE);
244 /* Special case here: if the journal has aborted behind our 245 /* Special case here: if the journal has aborted behind our
245 * backs (eg. EIO in the commit thread), then we still need to 246 * backs (eg. EIO in the commit thread), then we still need to
246 * take the FS itself readonly cleanly. */ 247 * take the FS itself readonly cleanly. */
@@ -3485,8 +3486,10 @@ int ext4_force_commit(struct super_block *sb)
3485 return 0; 3486 return 0;
3486 3487
3487 journal = EXT4_SB(sb)->s_journal; 3488 journal = EXT4_SB(sb)->s_journal;
3488 if (journal) 3489 if (journal) {
3490 vfs_check_frozen(sb, SB_FREEZE_WRITE);
3489 ret = ext4_journal_force_commit(journal); 3491 ret = ext4_journal_force_commit(journal);
3492 }
3490 3493
3491 return ret; 3494 return ret;
3492} 3495}
@@ -3535,18 +3538,16 @@ static int ext4_freeze(struct super_block *sb)
3535 * the journal. 3538 * the journal.
3536 */ 3539 */
3537 error = jbd2_journal_flush(journal); 3540 error = jbd2_journal_flush(journal);
3538 if (error < 0) { 3541 if (error < 0)
3539 out: 3542 goto out;
3540 jbd2_journal_unlock_updates(journal);
3541 return error;
3542 }
3543 3543
3544 /* Journal blocked and flushed, clear needs_recovery flag. */ 3544 /* Journal blocked and flushed, clear needs_recovery flag. */
3545 EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); 3545 EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
3546 error = ext4_commit_super(sb, 1); 3546 error = ext4_commit_super(sb, 1);
3547 if (error) 3547out:
3548 goto out; 3548 /* we rely on s_frozen to stop further updates */
3549 return 0; 3549 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
3550 return error;
3550} 3551}
3551 3552
3552/* 3553/*
@@ -3563,7 +3564,6 @@ static int ext4_unfreeze(struct super_block *sb)
3563 EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); 3564 EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
3564 ext4_commit_super(sb, 1); 3565 ext4_commit_super(sb, 1);
3565 unlock_super(sb); 3566 unlock_super(sb);
3566 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
3567 return 0; 3567 return 0;
3568} 3568}
3569 3569