summaryrefslogtreecommitdiff
path: root/include/linux/ext3_jbd.h
diff options
context:
space:
mode:
authorStephen C. Tweedie <sct@redhat.com>2005-01-04 05:27:36 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-04 05:27:36 -0800
commitc579b4e22af013e1c6745023a6bb37756d38fc52 (patch)
treee1ae592798ff66afbced4ac6b969bbbd9f2c56f6 /include/linux/ext3_jbd.h
parent046527de30b061a7d68e1bb72031473498847de9 (diff)
[PATCH] ext3: handle attempted delete of bitmap blocks.
This patch improves ext3's ability to deal with corruption on-disk. If we ever get a corrupt inode or indirect block, then an attempt to delete it can end up trying to remove any block on the fs, including bitmap blocks. This can cause ext3 to assert-fail as we end up trying to do an ext3_forget on a buffer with b_committed_data set. The fix is to downgrade this to an IO error and journal abort, so that we take the filesystem readonly but don't bring down the whole kernel. Make J_EXPECT_JH() return a value so it can be easily tested and yet still retained as an assert failure if we build ext3 with full internal debugging enabled. Make journal_forget() return an error code so that in this case the error can be passed up to the caller. This is easily reproduced with a sample ext3 fs image containing an inode whose direct and indirect blocks refer to a block bitmap block. Allocating new blocks and then deleting that inode will BUG() with: Assertion failure in journal_forget() at fs/jbd/transaction.c:1228: "!jh->b_committed_data" With the fix, ext3 recovers gracefully. Signed-off-by: Stephen Tweedie <sct@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include/linux/ext3_jbd.h')
-rw-r--r--include/linux/ext3_jbd.h11
1 files changed, 8 insertions, 3 deletions
diff --git a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h
index da1c91ef0821..0380c1fbdab0 100644
--- a/include/linux/ext3_jbd.h
+++ b/include/linux/ext3_jbd.h
@@ -138,10 +138,13 @@ ext3_journal_release_buffer(handle_t *handle, struct buffer_head *bh,
journal_release_buffer(handle, bh, credits);
}
-static inline void
-ext3_journal_forget(handle_t *handle, struct buffer_head *bh)
+static inline int
+__ext3_journal_forget(const char *where, handle_t *handle, struct buffer_head *bh)
{
- journal_forget(handle, bh);
+ int err = journal_forget(handle, bh);
+ if (err)
+ ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+ return err;
}
static inline int
@@ -187,6 +190,8 @@ __ext3_journal_dirty_metadata(const char *where,
__ext3_journal_get_create_access(__FUNCTION__, (handle), (bh))
#define ext3_journal_dirty_metadata(handle, bh) \
__ext3_journal_dirty_metadata(__FUNCTION__, (handle), (bh))
+#define ext3_journal_forget(handle, bh) \
+ __ext3_journal_forget(__FUNCTION__, (handle), (bh))
int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh);