diff options
author | Victor Leschuck <vleschuk@gmail.com> | 2013-08-23 10:26:32 -0400 |
---|---|---|
committer | Jeff Mahoney <jeffm@suse.de> | 2013-08-23 10:26:41 -0400 |
commit | 14e8805a0835776167cf435aaf91a56b74746d2f (patch) | |
tree | 0d8bdadbefce90f0f4d134ccf17fe1adf1a8d8ed | |
parent | d83a36e872d3409a0a1e3f3cc713674df97ba2f5 (diff) | |
download | reiserfsprogs-14e8805a0835776167cf435aaf91a56b74746d2f.tar.gz |
journal: fix division by 0 with one transaction in log
We have met a situation when reiserfsck segfaulted on one of our
partitions. I have performed a small research and the cause appeared
to be wrong detection of transaction count.
Our FS had only one journal transaction, however trans_count which was
passed to progbar_update() as maximum transaction value was detected
as (last_transaction - first_transaction) which in our case was 0.
Thus progbar_update() resulted in segmentation fault:
(gdb) bt
"Replaying journal", curr=1, max=0, dpynum=1) at progbar.c:80
Here is part of debugreiserfs -j output
Journal header (block #8210 of ./partition.bug):
j_last_flush_trans_id 0
j_first_unflushed_offset 0
j_mount_id 10
Device [0x0]
Magic [0x4f0a099e]
Size 8193 blocks (including 1 for journal header) (first block 18)
Max transaction length 1024 blocks
Max batch size 900 blocks
Max commit age 30
Mountid 10, transid 10, desc 18, length 2, commit 21
I successfully reproduced it on versions 3.6.21 (which we were using)
and 3.6.23 (which I believe is the latest).
Attaching patch. Let me know your opinion. If I am wrong, please
comment, if I am correct, feel free to include patch into sources.
Thanks.
Signed-off-by: Victor Leschuk <vleschuk@gmail.com>
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
-rw-r--r-- | lib/progbar.c | 3 | ||||
-rw-r--r-- | reiserfscore/journal.c | 5 |
2 files changed, 5 insertions, 3 deletions
diff --git a/lib/progbar.c b/lib/progbar.c index fde2e70..9ecc803 100644 --- a/lib/progbar.c +++ b/lib/progbar.c @@ -1,6 +1,7 @@ #include <stdio.h> #include <sys/time.h> #include <string.h> +#include <assert.h> #include "progbar.h" @@ -37,6 +38,8 @@ int progbar_update(struct progbar * ctx, const char *label, int curr, int max, struct timeval tv; int dpywidth; int fixed_percent; + assert (curr >= 0); + assert (max > 0); float percent = ((float) curr) / ((float) max) * 100; if (ctx->flags & E2F_FLAG_PROG_SUPPRESS) diff --git a/reiserfscore/journal.c b/reiserfscore/journal.c index a3ebcde..00e1939 100644 --- a/reiserfscore/journal.c +++ b/reiserfscore/journal.c @@ -818,13 +818,12 @@ int replay_journal (reiserfs_filsys_t * fs) control.trans_id = get_jh_last_flushed (j_head); control.desc_blocknr = get_jh_replay_start_offset (j_head); - if (!get_boundary_transactions (fs, &cur, &newest)) { + trans_count = get_boundary_transactions (fs, &cur, &newest); + if (!trans_count) { reiserfs_warning (stderr, "No transactions found\n"); return 0; } - trans_count = newest.trans_id - cur.trans_id; - /* Smth strange with journal header or journal. We cannot say for sure what was the last replaied transaction, but relying on JH data is preferable. */ |