Commit 2499604960fff307fe99ff4d4363c50eaa69235a

Authored by Jeff Mahoney
Committed by Linus Torvalds
1 parent 5d5e815618

[PATCH] reiserfs: close open transactions on error path

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@suse.com>

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 1 changed file with 18 additions and 8 deletions Side-by-side Diff

... ... @@ -32,6 +32,7 @@
32 32 JOURNAL_PER_BALANCE_CNT * 2 +
33 33 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
34 34 struct reiserfs_transaction_handle th;
  35 + int err;
35 36  
36 37 truncate_inode_pages(&inode->i_data, 0);
37 38  
38 39  
... ... @@ -49,15 +50,13 @@
49 50 }
50 51 reiserfs_update_inode_transaction(inode);
51 52  
52   - if (reiserfs_delete_object(&th, inode)) {
53   - up(&inode->i_sem);
54   - goto out;
55   - }
  53 + err = reiserfs_delete_object(&th, inode);
56 54  
57 55 /* Do quota update inside a transaction for journaled quotas. We must do that
58 56 * after delete_object so that quota updates go into the same transaction as
59 57 * stat data deletion */
60   - DQUOT_FREE_INODE(inode);
  58 + if (!err)
  59 + DQUOT_FREE_INODE(inode);
61 60  
62 61 if (journal_end(&th, inode->i_sb, jbegin_count)) {
63 62 up(&inode->i_sem);
... ... @@ -66,6 +65,12 @@
66 65  
67 66 up(&inode->i_sem);
68 67  
  68 + /* check return value from reiserfs_delete_object after
  69 + * ending the transaction
  70 + */
  71 + if (err)
  72 + goto out;
  73 +
69 74 /* all items of file are deleted, so we can remove "save" link */
70 75 remove_save_link(inode, 0 /* not truncate */ ); /* we can't do anything
71 76 * about an error here */
... ... @@ -2099,6 +2104,7 @@
2099 2104 struct page *page = NULL;
2100 2105 int error;
2101 2106 struct buffer_head *bh = NULL;
  2107 + int err2;
2102 2108  
2103 2109 reiserfs_write_lock(p_s_inode->i_sb);
2104 2110  
2105 2111  
... ... @@ -2136,14 +2142,18 @@
2136 2142 transaction of truncating gets committed - on reboot the file
2137 2143 either appears truncated properly or not truncated at all */
2138 2144 add_save_link(&th, p_s_inode, 1);
2139   - error = reiserfs_do_truncate(&th, p_s_inode, page, update_timestamps);
2140   - if (error)
2141   - goto out;
  2145 + err2 = reiserfs_do_truncate(&th, p_s_inode, page, update_timestamps);
2142 2146 error =
2143 2147 journal_end(&th, p_s_inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1);
2144 2148 if (error)
2145 2149 goto out;
2146 2150  
  2151 + /* check reiserfs_do_truncate after ending the transaction */
  2152 + if (err2) {
  2153 + error = err2;
  2154 + goto out;
  2155 + }
  2156 +
2147 2157 if (update_timestamps) {
2148 2158 error = remove_save_link(p_s_inode, 1 /* truncate */ );
2149 2159 if (error)