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 <[EMAIL PROTECTED]>

Signed-off-by: Jeff Mahoney <[EMAIL PROTECTED]>

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

Reply via email to