diff options
author | Alexander Zarochentsev <zam@namesys.com> | 2006-03-25 06:06:59 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-25 11:22:51 -0500 |
commit | a44c94a7b82a425b73384c104d5cb3dd3caa075e (patch) | |
tree | da86b5245bea89942f2639fec2d6f7378a117836 | |
parent | 23f9e0f891c9b159a199629d4426f6ae0c383508 (diff) |
[PATCH] reiserfs: handle trans_id overflow
Reiserfs does not handle transaction ID overflow correctly. Transaction ID
== 0 causes reiserfs to crash. The patch fixes all places where the
transaction ID is incremented.
Signed-off-by: Alexander Zarochentsev <zam@namesys.com>
Signed-off-by: Hans Reiser <reiser@namesys.com>
Cc: Chris Mason <mason@suse.com>
Cc: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/reiserfs/journal.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 5a9d2722fa0a..1b73529b8099 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c | |||
@@ -2227,6 +2227,9 @@ static int journal_read_transaction(struct super_block *p_s_sb, | |||
2227 | journal->j_start = cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb); | 2227 | journal->j_start = cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb); |
2228 | journal->j_last_flush_trans_id = trans_id; | 2228 | journal->j_last_flush_trans_id = trans_id; |
2229 | journal->j_trans_id = trans_id + 1; | 2229 | journal->j_trans_id = trans_id + 1; |
2230 | /* check for trans_id overflow */ | ||
2231 | if (journal->j_trans_id == 0) | ||
2232 | journal->j_trans_id = 10; | ||
2230 | brelse(c_bh); | 2233 | brelse(c_bh); |
2231 | brelse(d_bh); | 2234 | brelse(d_bh); |
2232 | kfree(log_blocks); | 2235 | kfree(log_blocks); |
@@ -2450,6 +2453,9 @@ static int journal_read(struct super_block *p_s_sb) | |||
2450 | journal->j_start = le32_to_cpu(jh->j_first_unflushed_offset); | 2453 | journal->j_start = le32_to_cpu(jh->j_first_unflushed_offset); |
2451 | journal->j_trans_id = | 2454 | journal->j_trans_id = |
2452 | le32_to_cpu(jh->j_last_flush_trans_id) + 1; | 2455 | le32_to_cpu(jh->j_last_flush_trans_id) + 1; |
2456 | /* check for trans_id overflow */ | ||
2457 | if (journal->j_trans_id == 0) | ||
2458 | journal->j_trans_id = 10; | ||
2453 | journal->j_last_flush_trans_id = | 2459 | journal->j_last_flush_trans_id = |
2454 | le32_to_cpu(jh->j_last_flush_trans_id); | 2460 | le32_to_cpu(jh->j_last_flush_trans_id); |
2455 | journal->j_mount_id = le32_to_cpu(jh->j_mount_id) + 1; | 2461 | journal->j_mount_id = le32_to_cpu(jh->j_mount_id) + 1; |
@@ -3873,8 +3879,8 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, | |||
3873 | int cur_write_start = 0; /* start index of current log write */ | 3879 | int cur_write_start = 0; /* start index of current log write */ |
3874 | int old_start; | 3880 | int old_start; |
3875 | int i; | 3881 | int i; |
3876 | int flush = flags & FLUSH_ALL; | 3882 | int flush; |
3877 | int wait_on_commit = flags & WAIT; | 3883 | int wait_on_commit; |
3878 | struct reiserfs_journal_list *jl, *temp_jl; | 3884 | struct reiserfs_journal_list *jl, *temp_jl; |
3879 | struct list_head *entry, *safe; | 3885 | struct list_head *entry, *safe; |
3880 | unsigned long jindex; | 3886 | unsigned long jindex; |
@@ -3884,6 +3890,13 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, | |||
3884 | BUG_ON(th->t_refcount > 1); | 3890 | BUG_ON(th->t_refcount > 1); |
3885 | BUG_ON(!th->t_trans_id); | 3891 | BUG_ON(!th->t_trans_id); |
3886 | 3892 | ||
3893 | /* protect flush_older_commits from doing mistakes if the | ||
3894 | transaction ID counter gets overflowed. */ | ||
3895 | if (th->t_trans_id == ~0UL) | ||
3896 | flags |= FLUSH_ALL | COMMIT_NOW | WAIT; | ||
3897 | flush = flags & FLUSH_ALL; | ||
3898 | wait_on_commit = flags & WAIT; | ||
3899 | |||
3887 | put_fs_excl(); | 3900 | put_fs_excl(); |
3888 | current->journal_info = th->t_handle_save; | 3901 | current->journal_info = th->t_handle_save; |
3889 | reiserfs_check_lock_depth(p_s_sb, "journal end"); | 3902 | reiserfs_check_lock_depth(p_s_sb, "journal end"); |
@@ -4105,7 +4118,9 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, | |||
4105 | journal->j_first = NULL; | 4118 | journal->j_first = NULL; |
4106 | journal->j_len = 0; | 4119 | journal->j_len = 0; |
4107 | journal->j_trans_start_time = 0; | 4120 | journal->j_trans_start_time = 0; |
4108 | journal->j_trans_id++; | 4121 | /* check for trans_id overflow */ |
4122 | if (++journal->j_trans_id == 0) | ||
4123 | journal->j_trans_id = 10; | ||
4109 | journal->j_current_jl->j_trans_id = journal->j_trans_id; | 4124 | journal->j_current_jl->j_trans_id = journal->j_trans_id; |
4110 | journal->j_must_wait = 0; | 4125 | journal->j_must_wait = 0; |
4111 | journal->j_len_alloc = 0; | 4126 | journal->j_len_alloc = 0; |