Commit 24996049 authored by Jeff Mahoney's avatar Jeff Mahoney Committed by Linus Torvalds

[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: default avatarJeff Mahoney <jeffm@suse.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5d5e8156
...@@ -32,6 +32,7 @@ void reiserfs_delete_inode(struct inode *inode) ...@@ -32,6 +32,7 @@ void reiserfs_delete_inode(struct inode *inode)
JOURNAL_PER_BALANCE_CNT * 2 + JOURNAL_PER_BALANCE_CNT * 2 +
2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb); 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
int err;
truncate_inode_pages(&inode->i_data, 0); truncate_inode_pages(&inode->i_data, 0);
...@@ -49,15 +50,13 @@ void reiserfs_delete_inode(struct inode *inode) ...@@ -49,15 +50,13 @@ void reiserfs_delete_inode(struct inode *inode)
} }
reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(inode);
if (reiserfs_delete_object(&th, inode)) { err = reiserfs_delete_object(&th, inode);
up(&inode->i_sem);
goto out;
}
/* Do quota update inside a transaction for journaled quotas. We must do that /* 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 * after delete_object so that quota updates go into the same transaction as
* stat data deletion */ * stat data deletion */
DQUOT_FREE_INODE(inode); if (!err)
DQUOT_FREE_INODE(inode);
if (journal_end(&th, inode->i_sb, jbegin_count)) { if (journal_end(&th, inode->i_sb, jbegin_count)) {
up(&inode->i_sem); up(&inode->i_sem);
...@@ -66,6 +65,12 @@ void reiserfs_delete_inode(struct inode *inode) ...@@ -66,6 +65,12 @@ void reiserfs_delete_inode(struct inode *inode)
up(&inode->i_sem); 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 */ /* all items of file are deleted, so we can remove "save" link */
remove_save_link(inode, 0 /* not truncate */ ); /* we can't do anything remove_save_link(inode, 0 /* not truncate */ ); /* we can't do anything
* about an error here */ * about an error here */
...@@ -2099,6 +2104,7 @@ int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) ...@@ -2099,6 +2104,7 @@ int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps)
struct page *page = NULL; struct page *page = NULL;
int error; int error;
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
int err2;
reiserfs_write_lock(p_s_inode->i_sb); reiserfs_write_lock(p_s_inode->i_sb);
...@@ -2136,14 +2142,18 @@ int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) ...@@ -2136,14 +2142,18 @@ int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps)
transaction of truncating gets committed - on reboot the file transaction of truncating gets committed - on reboot the file
either appears truncated properly or not truncated at all */ either appears truncated properly or not truncated at all */
add_save_link(&th, p_s_inode, 1); 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 = error =
journal_end(&th, p_s_inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1); journal_end(&th, p_s_inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1);
if (error) if (error)
goto out; goto out;
/* check reiserfs_do_truncate after ending the transaction */
if (err2) {
error = err2;
goto out;
}
if (update_timestamps) { if (update_timestamps) {
error = remove_save_link(p_s_inode, 1 /* truncate */ ); error = remove_save_link(p_s_inode, 1 /* truncate */ );
if (error) if (error)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment