2008-07-29 06:57:48

by Andrew Morton

[permalink] [raw]
Subject: + ext3-abort-ext3-if-the-journal-has-aborted.patch added to -mm tree


The patch titled
ext3: abort ext3 if the journal has aborted
has been added to the -mm tree. Its filename is
ext3-abort-ext3-if-the-journal-has-aborted.patch

Before you just go and hit "reply", please:
a) Consider who else should be cc'ed
b) Prefer to cc a suitable mailing list as well
c) Ideally: find the original patch on the mailing list and do a
reply-to-all to that, adding suitable additional cc's

*** Remember to use Documentation/SubmitChecklist when testing your code ***

See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find
out what to do about this

The current -mm tree may be found at http://userweb.kernel.org/~akpm/mmotm/

------------------------------------------------------
Subject: ext3: abort ext3 if the journal has aborted
From: Hidehiro Kawai <[email protected]>

If the journal has aborted due to a checkpointing failure, we have to keep
the contents of the journal space. ext3_put_super() detects the journal
abort, then it invokes ext3_abort() to make the filesystem read only and
keep needs_recovery flag.

Signed-off-by: Hidehiro Kawai <[email protected]>
Acked-by: Jan Kara <[email protected]>
Cc: <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
---

fs/ext3/ioctl.c | 12 ++++++++----
fs/ext3/super.c | 11 +++++++++--
2 files changed, 17 insertions(+), 6 deletions(-)

diff -puN fs/ext3/ioctl.c~ext3-abort-ext3-if-the-journal-has-aborted fs/ext3/ioctl.c
--- a/fs/ext3/ioctl.c~ext3-abort-ext3-if-the-journal-has-aborted
+++ a/fs/ext3/ioctl.c
@@ -239,7 +239,7 @@ setrsvsz_out:
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;
@@ -254,8 +254,10 @@ setrsvsz_out:
}
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;
@@ -263,7 +265,7 @@ group_extend_out:
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;
@@ -280,8 +282,10 @@ group_extend_out:

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;
diff -puN fs/ext3/super.c~ext3-abort-ext3-if-the-journal-has-aborted fs/ext3/super.c
--- a/fs/ext3/super.c~ext3-abort-ext3-if-the-journal-has-aborted
+++ a/fs/ext3/super.c
@@ -393,7 +393,8 @@ static void ext3_put_super (struct super
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);
@@ -2388,7 +2389,13 @@ static void ext3_write_super_lockfs(stru

/* 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);
_

Patches currently in -mm which might be from [email protected] are

origin.patch
linux-next.patch
jbd-abort-when-failed-to-log-metadata-buffers.patch
jbd-fix-error-handling-for-checkpoint-io.patch
ext3-abort-ext3-if-the-journal-has-aborted.patch
jbd-dont-dirty-original-metadata-buffer-on-abort.patch



2008-07-30 02:44:43

by Hidehiro Kawai

[permalink] [raw]
Subject: Re: + ext3-abort-ext3-if-the-journal-has-aborted.patch added to -mm tree

Hi Andrew,

[email protected] wrote:

> The patch titled
> ext3: abort ext3 if the journal has aborted
> has been added to the -mm tree. Its filename is
> ext3-abort-ext3-if-the-journal-has-aborted.patch

A problem was found in this patch:

http://lkml.org/lkml/2008/7/28/15
> 4. when checkpointing fails, notify this error to the ext3 layer so
>> that ext3 don't clear the needs_recovery flag, otherwise the
>> journaled contents are ignored and cleaned in the recovery phase
>
> Mike Snitzer noticed that ext3_mark_recovery_complete() doesn't
> check checkpointing failure and it clears needs_recovery flag
> (thanks, Mike!). I need an additional fix.
>
> I also found ext3_quota_on() forces checkpointing by journal_flush()
> but it doesn't check the error. This will appear in 2.6.27-rc1,
> so I'll send the revised patch set for 2.6.27-rc1 (it may be
> a separate patch).

I attached the revised version below. Could you replace the patch
titled `ext3: abort ext3 if the journal has aborted' with this
new one? Please note that the patch's title also changed.


Subject: [PATCH 3/4] ext3: add checks for errors from jbd

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]>
---
fs/ext3/ioctl.c | 12 ++++++++----
fs/ext3/super.c | 23 +++++++++++++++++++----
2 files changed, 27 insertions(+), 8 deletions(-)

Index: linux-2.6.27-rc1/fs/ext3/ioctl.c
===================================================================
--- linux-2.6.27-rc1.orig/fs/ext3/ioctl.c
+++ linux-2.6.27-rc1/fs/ext3/ioctl.c
@@ -239,7 +239,7 @@ setrsvsz_out:
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;
@@ -254,8 +254,10 @@ setrsvsz_out:
}
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;
@@ -263,7 +265,7 @@ group_extend_out:
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;
@@ -280,8 +282,10 @@ group_extend_out:

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;
Index: linux-2.6.27-rc1/fs/ext3/super.c
===================================================================
--- linux-2.6.27-rc1.orig/fs/ext3/super.c
+++ linux-2.6.27-rc1/fs/ext3/super.c
@@ -393,7 +393,8 @@ static void ext3_put_super (struct super
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);
@@ -2280,7 +2281,9 @@ static void ext3_mark_recovery_complete(
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) {
@@ -2289,6 +2292,8 @@ static void ext3_mark_recovery_complete(
ext3_commit_super(sb, es, 1);
}
unlock_super(sb);
+
+out:
journal_unlock_updates(journal);
}

@@ -2388,7 +2393,13 @@ static void ext3_write_super_lockfs(stru

/* 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);
@@ -2806,8 +2817,12 @@ static int ext3_quota_on(struct super_bl
* 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;
+ }
}

path_put(&nd.path);