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>
This commit is contained in:
1 parent
d83a36e872
commit
14e8805a08
2 files changed
+5
-3
No files matched your search
@@ -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)
|
||||
|
||||
@@ -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. */
|
||||
|
||||
|
||||
Reference in new issue
Block a user