Skip to content

Commit

Permalink
ext3: add checks for errors from jbd
Browse files Browse the repository at this point in the history
If the journal has aborted due to a checkpointing failure, we have to
keep the contents of the journal space.  Otherwise, the filesystem will
lose uncheckpointed metadata completely and become inconsistent.  To
avoid this, we need to keep needs_recovery flag if checkpoint has
failed.

With this patch, ext3_put_super() detects a checkpointing failure from
the return value of journal_destroy(), then it invokes ext3_abort() to
make the filesystem read only and keep needs_recovery flag.  Errors
from journal_flush() are also handled by this patch in some places.

Signed-off-by: Hidehiro Kawai <[email protected]>
Cc: Jan Kara <[email protected]>
Cc: Stephen Rothwell <[email protected]>
Cc: Al Viro <[email protected]>
Cc: <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Hidehiro Kawai authored and torvalds committed Oct 23, 2008
1 parent 4afe978 commit 2d7c820
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 8 deletions.
12 changes: 8 additions & 4 deletions fs/ext3/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
case EXT3_IOC_GROUP_EXTEND: {
ext3_fsblk_t n_blocks_count;
struct super_block *sb = inode->i_sb;
int err;
int err, err2;

if (!capable(CAP_SYS_RESOURCE))
return -EPERM;
Expand All @@ -254,16 +254,18 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
}
err = ext3_group_extend(sb, EXT3_SB(sb)->s_es, n_blocks_count);
journal_lock_updates(EXT3_SB(sb)->s_journal);
journal_flush(EXT3_SB(sb)->s_journal);
err2 = journal_flush(EXT3_SB(sb)->s_journal);
journal_unlock_updates(EXT3_SB(sb)->s_journal);
if (err == 0)
err = err2;
group_extend_out:
mnt_drop_write(filp->f_path.mnt);
return err;
}
case EXT3_IOC_GROUP_ADD: {
struct ext3_new_group_data input;
struct super_block *sb = inode->i_sb;
int err;
int err, err2;

if (!capable(CAP_SYS_RESOURCE))
return -EPERM;
Expand All @@ -280,8 +282,10 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,

err = ext3_group_add(sb, &input);
journal_lock_updates(EXT3_SB(sb)->s_journal);
journal_flush(EXT3_SB(sb)->s_journal);
err2 = journal_flush(EXT3_SB(sb)->s_journal);
journal_unlock_updates(EXT3_SB(sb)->s_journal);
if (err == 0)
err = err2;
group_add_out:
mnt_drop_write(filp->f_path.mnt);
return err;
Expand Down
23 changes: 19 additions & 4 deletions fs/ext3/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@ static void ext3_put_super (struct super_block * sb)
int i;

ext3_xattr_put_super(sb);
journal_destroy(sbi->s_journal);
if (journal_destroy(sbi->s_journal) < 0)
ext3_abort(sb, __func__, "Couldn't clean up the journal");
if (!(sb->s_flags & MS_RDONLY)) {
EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
es->s_state = cpu_to_le16(sbi->s_mount_state);
Expand Down Expand Up @@ -2296,7 +2297,9 @@ static void ext3_mark_recovery_complete(struct super_block * sb,
journal_t *journal = EXT3_SB(sb)->s_journal;

journal_lock_updates(journal);
journal_flush(journal);
if (journal_flush(journal) < 0)
goto out;

lock_super(sb);
if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) &&
sb->s_flags & MS_RDONLY) {
Expand All @@ -2305,6 +2308,8 @@ static void ext3_mark_recovery_complete(struct super_block * sb,
ext3_commit_super(sb, es, 1);
}
unlock_super(sb);

out:
journal_unlock_updates(journal);
}

Expand Down Expand Up @@ -2404,7 +2409,13 @@ static void ext3_write_super_lockfs(struct super_block *sb)

/* Now we set up the journal barrier. */
journal_lock_updates(journal);
journal_flush(journal);

/*
* We don't want to clear needs_recovery flag when we failed
* to flush the journal.
*/
if (journal_flush(journal) < 0)
return;

/* Journal blocked and flushed, clear needs_recovery flag. */
EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
Expand Down Expand Up @@ -2822,8 +2833,12 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
* otherwise be livelocked...
*/
journal_lock_updates(EXT3_SB(sb)->s_journal);
journal_flush(EXT3_SB(sb)->s_journal);
err = journal_flush(EXT3_SB(sb)->s_journal);
journal_unlock_updates(EXT3_SB(sb)->s_journal);
if (err) {
path_put(&nd.path);
return err;
}
}

err = vfs_quota_on_path(sb, type, format_id, &nd.path);
Expand Down

0 comments on commit 2d7c820

Please sign in to comment.