diff options
author | Adrian Hunter <ext-adrian.hunter@nokia.com> | 2008-05-27 09:42:04 +0300 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2008-06-06 18:50:34 +0300 |
commit | 3cba725ac8b791171d4e958e118dadd0a5172308 (patch) | |
tree | a4638ad14f6addba5162ef16d44c64f6f31689db /fs/ubifs | |
parent | 33aef343b2093af29c1781eaa003c5337351aa7c (diff) |
UBIFS: tweak asserts and gc_lnum fix
Signed-off-by: Adrian Hunter <ext-adrian.hunter@nokia.com>
Diffstat (limited to 'fs/ubifs')
-rw-r--r-- | fs/ubifs/debug.c | 37 | ||||
-rw-r--r-- | fs/ubifs/gc.c | 3 | ||||
-rw-r--r-- | fs/ubifs/recovery.c | 13 | ||||
-rw-r--r-- | fs/ubifs/super.c | 7 | ||||
-rw-r--r-- | fs/ubifs/ubifs.h | 8 |
5 files changed, 57 insertions, 11 deletions
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 69f1f7f16135..2698b10f4aa2 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -1337,9 +1337,34 @@ static int do_fail(struct ubi_volume_desc *desc, int lnum, int write) return 0; if (c->failure_mode) return 1; + if (!c->fail_cnt) { + /* First call - decide delay to failure */ + if (chance(1, 2)) { + unsigned int delay = 1 << (simple_rand() >> 11); + + if (chance(1, 2)) { + c->fail_delay = 1; + c->fail_timeout = jiffies + + msecs_to_jiffies(delay); + dbg_rcvry("failing after %ums", delay); + } else { + c->fail_delay = 2; + c->fail_cnt_max = delay; + dbg_rcvry("failing after %u calls", delay); + } + } + c->fail_cnt += 1; + } + /* Determine if failure delay has expired */ + if (c->fail_delay == 1) { + if (time_before(jiffies, c->fail_timeout)) + return 0; + } else if (c->fail_delay == 2) + if (c->fail_cnt++ < c->fail_cnt_max) + return 0; if (lnum == UBIFS_SB_LNUM) { if (write) { - if (chance(10, 20)) + if (chance(1, 2)) return 0; } else if (chance(19, 20)) return 0; @@ -1357,16 +1382,16 @@ static int do_fail(struct ubi_volume_desc *desc, int lnum, int write) dbg_rcvry("failing in log LEB %d", lnum); } else if (lnum >= c->lpt_first && lnum <= c->lpt_last) { if (write) { - if (chance(99, 100)) + if (chance(7, 8)) return 0; - } else if (chance(399, 400)) + } else if (chance(19, 20)) return 0; dbg_rcvry("failing in LPT LEB %d", lnum); } else if (lnum >= c->orph_first && lnum <= c->orph_last) { if (write) { - if (chance(9, 10)) + if (chance(1, 2)) return 0; - } else if (chance(39, 40)) + } else if (chance(9, 10)) return 0; dbg_rcvry("failing in orphan LEB %d", lnum); } else if (lnum == c->ihead_lnum) { @@ -1374,7 +1399,7 @@ static int do_fail(struct ubi_volume_desc *desc, int lnum, int write) return 0; dbg_rcvry("failing in index head LEB %d", lnum); } else if (c->jheads && lnum == c->jheads[GCHD].wbuf.lnum) { - if (chance(99, 100)) + if (chance(9, 10)) return 0; dbg_rcvry("failing in GC head LEB %d", lnum); } else if (write && !RB_EMPTY_ROOT(&c->buds) && diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 1e8a940908ea..6d238aa10da3 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -273,7 +273,8 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf; int err = 0, lnum = lp->lnum; - ubifs_assert(c->gc_lnum != -1 || wbuf->offs + wbuf->used == 0); + ubifs_assert(c->gc_lnum != -1 || wbuf->offs + wbuf->used == 0 || + c->need_recovery); ubifs_assert(c->gc_lnum != lnum); ubifs_assert(wbuf->lnum != lnum); diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 6ee0e07bf3e3..0fdd560b8ca9 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c @@ -1125,9 +1125,17 @@ int ubifs_recover_gc_lnum(struct ubifs_info *c) return err; goto find_free; } - /* It fits, so GC it */ + /* It fits, so GC it - use locking to keep 'ubifs_assert()' happy */ dbg_rcvry("GC'ing LEB %d", lnum); + mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); err = ubifs_garbage_collect_leb(c, &lp); + if (err >= 0) { + int err2 = ubifs_wbuf_sync_nolock(wbuf); + + if (err2) + err = err2; + } + mutex_unlock(&wbuf->io_mutex); if (err < 0) { dbg_err("GC failed, error %d", err); if (err == -EAGAIN) @@ -1138,6 +1146,9 @@ int ubifs_recover_gc_lnum(struct ubifs_info *c) dbg_err("GC returned %d", err); return -EINVAL; } + err = ubifs_leb_unmap(c, c->gc_lnum); + if (err) + return err; dbg_rcvry("allocated LEB %d for GC", lnum); return 0; diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index c84656fa611d..56be98f05d7b 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1345,6 +1345,10 @@ static int ubifs_remount_rw(struct ubifs_info *c) } wake_up_process(c->bgt); + err = ubifs_mount_orphans(c, c->need_recovery); + if (err) + goto out; + if (c->need_recovery) err = ubifs_recover_gc_lnum(c); else @@ -1352,9 +1356,6 @@ static int ubifs_remount_rw(struct ubifs_info *c) if (err) goto out; - err = ubifs_mount_orphans(c, c->need_recovery); - if (err) - goto out; /* Check for enough log space */ lnum = c->lhead_lnum + 1; if (lnum >= UBIFS_LOG_LNUM + c->log_lebs) diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 9bb05b9ffdc1..1d80991bbc2d 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1033,6 +1033,10 @@ struct ubifs_mount_opts { * @old_zroot_level: old index root level - used by 'dbg_check_old_index()' * @old_zroot_sqnum: old index root sqnum - used by 'dbg_check_old_index()' * @failure_mode: failure mode for recovery testing + * @fail_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls + * @fail_timeout: time in jiffies when delay of failure mode expires + * @fail_cnt: current number of calls to failure mode I/O functions + * @fail_cnt_max: number of calls by which to delay failure mode */ struct ubifs_info { struct super_block *vfs_sb; @@ -1257,6 +1261,10 @@ struct ubifs_info { int old_zroot_level; unsigned long long old_zroot_sqnum; int failure_mode; + int fail_delay; + unsigned long fail_timeout; + unsigned int fail_cnt; + unsigned int fail_cnt_max; #endif }; |