Message ID | 1307621434.7374.78.camel@localhost |
---|---|
State | New, archived |
Headers | show |
On Thu, Jun 9, 2011 at 8:10 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote: > > With my latest code-base, I am able to inject a hack into > ubifs_leb_change() - but this function does not exist in your code-base. > Anyway, I'm currently running power cut emulation testing with the > following hack: > Hi Artem, just wanted to post an update to this: I hacked this change into my kernel last week, and enabled the in-kernel debugging options you suggested, then set up a power-cut test: - the device in question is powered by a UPS with controllable outlets - its firmware boots and immediately starts writing large amounts of data to flash (so we'll have a dirty FS) - a separate script controlling the UPS waits for the device to boot, then sleeps some random time between 0 and 10 minutes - it then cuts power to the outlet and later restores it The test has been running for the better part of a week with no issues - it has now power-cycled the device over 1500 times, but I've gotten no errors, and the filesystem is functioning fine. FYI this is way more stress than was placed on the "bad" units we've gotten back from the field - most of those rarely lose power, and when they do, they're less likely to be in the middle of a write operation. I'll continue testing, but based on this it seems like UBIFS handles power cuts very well!
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index 9228950..9f7dbbf 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -153,6 +153,30 @@ int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len, ubifs_ro_mode(c, err); dbg_dump_stack(); } + + /* Temporary hack to catch incorrect recovery, if we have such */ + if (!err && (lnum < c->lpt_first || lnum > c->lpt_last)) { + void *buf = vmalloc(c->leb_size); + struct ubifs_scan_leb *sleb; + + if (!buf) + return 0; + + sleb = ubifs_scan(c, lnum, 0, buf, 0); + if (!IS_ERR(sleb)) { + /* Scan succeeded */ + vfree(buf); + return 0; + } + + ubifs_err("scanning after LEB %d change failed, error %d!", lnum, err); + print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 32, 1, + buf, c->leb_size, 1); + dump_stack(); + vfree(buf); + return -EINVAL; + } + return err; }