[PATCH] reiserfs: close open transactions on error path

From: Jeff Mahoney
Date: Wed Dec 14 2005 - 14:37:17 EST


The following patch fixes a bug where if the journal is aborted, it can
leave a transaction open. The result will be a BUG when another code path
attempts to start a transaction and will get a "nesting into different fs"
error, since current->journal_info will be left non-NULL.

Original fix against SUSE kernel by Chris Mason <mason@xxxxxxxx>

Signed-off-by: Jeff Mahoney <jeffm@xxxxxxxx>

diff -ruNpX dontdiff linux-2.6.14.orig/fs/reiserfs/inode.c linux-2.6.14.fixed/fs/reiserfs/inode.c
--- linux-2.6.14.orig/fs/reiserfs/inode.c 2005-10-27 20:02:08.000000000 -0400
+++ linux-2.6.14.fixed/fs/reiserfs/inode.c 2005-12-05 17:10:37.000000000 -0500
@@ -32,6 +32,7 @@ void reiserfs_delete_inode(struct inode
JOURNAL_PER_BALANCE_CNT * 2 +
2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
struct reiserfs_transaction_handle th;
+ int err;

truncate_inode_pages(&inode->i_data, 0);

@@ -49,15 +50,13 @@ void reiserfs_delete_inode(struct inode
}
reiserfs_update_inode_transaction(inode);

- if (reiserfs_delete_object(&th, inode)) {
- up(&inode->i_sem);
- goto out;
- }
+ err = reiserfs_delete_object(&th, inode);

/* Do quota update inside a transaction for journaled quotas. We must do that
* after delete_object so that quota updates go into the same transaction as
* stat data deletion */
- DQUOT_FREE_INODE(inode);
+ if (!err)
+ DQUOT_FREE_INODE(inode);

if (journal_end(&th, inode->i_sb, jbegin_count)) {
up(&inode->i_sem);
@@ -66,6 +65,12 @@ void reiserfs_delete_inode(struct inode

up(&inode->i_sem);

+ /* check return value from reiserfs_delete_object after
+ * ending the transaction
+ */
+ if (err)
+ goto out;
+
/* all items of file are deleted, so we can remove "save" link */
remove_save_link(inode, 0 /* not truncate */ ); /* we can't do anything
* about an error here */
@@ -2099,6 +2104,7 @@ int reiserfs_truncate_file(struct inode
struct page *page = NULL;
int error;
struct buffer_head *bh = NULL;
+ int err2;

reiserfs_write_lock(p_s_inode->i_sb);

@@ -2137,13 +2143,17 @@ int reiserfs_truncate_file(struct inode
either appears truncated properly or not truncated at all */
add_save_link(&th, p_s_inode, 1);
- error = reiserfs_do_truncate(&th, p_s_inode, page, update_timestamps);
+ err2 = reiserfs_do_truncate(&th, p_s_inode, page, update_timestamps);
- if (error)
- goto out;
error =
journal_end(&th, p_s_inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1);
if (error)
goto out;

+ /* check reiserfs_do_truncate after ending the transaction */
+ if (err2) {
+ error = err2;
+ goto out;
+ }
+
if (update_timestamps) {
error = remove_save_link(p_s_inode, 1 /* truncate */ );
if (error)
--
Jeff Mahoney
SuSE Labs
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/