|
@@ -2539,16 +2539,7 @@ error_dump:
|
|
|
|
|
|
#define chance(n, d) (simple_rand() <= (n) * 32768LL / (d))
|
|
|
|
|
|
-struct failure_mode_info {
|
|
|
- struct list_head list;
|
|
|
- struct ubifs_info *c;
|
|
|
-};
|
|
|
-
|
|
|
-static LIST_HEAD(fmi_list);
|
|
|
-static DEFINE_SPINLOCK(fmi_lock);
|
|
|
-
|
|
|
static unsigned int next;
|
|
|
-
|
|
|
static int simple_rand(void)
|
|
|
{
|
|
|
if (next == 0)
|
|
@@ -2557,69 +2548,15 @@ static int simple_rand(void)
|
|
|
return (next >> 16) & 32767;
|
|
|
}
|
|
|
|
|
|
-static void failure_mode_init(struct ubifs_info *c)
|
|
|
-{
|
|
|
- struct failure_mode_info *fmi;
|
|
|
-
|
|
|
- fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS);
|
|
|
- if (!fmi) {
|
|
|
- ubifs_err("Failed to register failure mode - no memory");
|
|
|
- return;
|
|
|
- }
|
|
|
- fmi->c = c;
|
|
|
- spin_lock(&fmi_lock);
|
|
|
- list_add_tail(&fmi->list, &fmi_list);
|
|
|
- spin_unlock(&fmi_lock);
|
|
|
-}
|
|
|
-
|
|
|
-static void failure_mode_exit(struct ubifs_info *c)
|
|
|
-{
|
|
|
- struct failure_mode_info *fmi, *tmp;
|
|
|
-
|
|
|
- spin_lock(&fmi_lock);
|
|
|
- list_for_each_entry_safe(fmi, tmp, &fmi_list, list)
|
|
|
- if (fmi->c == c) {
|
|
|
- list_del(&fmi->list);
|
|
|
- kfree(fmi);
|
|
|
- }
|
|
|
- spin_unlock(&fmi_lock);
|
|
|
-}
|
|
|
-
|
|
|
-static struct ubifs_info *dbg_find_info(struct ubi_volume_desc *desc)
|
|
|
+static int do_fail(struct ubifs_info *c, int lnum, int write)
|
|
|
{
|
|
|
- struct failure_mode_info *fmi;
|
|
|
-
|
|
|
- spin_lock(&fmi_lock);
|
|
|
- list_for_each_entry(fmi, &fmi_list, list)
|
|
|
- if (fmi->c->ubi == desc) {
|
|
|
- struct ubifs_info *c = fmi->c;
|
|
|
-
|
|
|
- spin_unlock(&fmi_lock);
|
|
|
- return c;
|
|
|
- }
|
|
|
- spin_unlock(&fmi_lock);
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
-static int in_failure_mode(struct ubi_volume_desc *desc)
|
|
|
-{
|
|
|
- struct ubifs_info *c = dbg_find_info(desc);
|
|
|
+ struct ubifs_debug_info *d = c->dbg;
|
|
|
|
|
|
- if (c && dbg_is_tst_rcvry(c))
|
|
|
- return c->dbg->failure_mode;
|
|
|
- return 0;
|
|
|
-}
|
|
|
+ ubifs_assert(dbg_is_tst_rcvry(c));
|
|
|
|
|
|
-static int do_fail(struct ubi_volume_desc *desc, int lnum, int write)
|
|
|
-{
|
|
|
- struct ubifs_info *c = dbg_find_info(desc);
|
|
|
- struct ubifs_debug_info *d;
|
|
|
-
|
|
|
- if (!c || !dbg_is_tst_rcvry(c))
|
|
|
- return 0;
|
|
|
- d = c->dbg;
|
|
|
if (d->failure_mode)
|
|
|
return 1;
|
|
|
+
|
|
|
if (!d->fail_cnt) {
|
|
|
/* First call - decide delay to failure */
|
|
|
if (chance(1, 2)) {
|
|
@@ -2716,17 +2653,17 @@ static void cut_data(const void *buf, int len)
|
|
|
p[i] = 0xff;
|
|
|
}
|
|
|
|
|
|
-int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
|
|
|
+int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf,
|
|
|
int offs, int len, int dtype)
|
|
|
{
|
|
|
int err, failing;
|
|
|
|
|
|
- if (in_failure_mode(desc))
|
|
|
+ if (c->dbg->failure_mode)
|
|
|
return -EROFS;
|
|
|
- failing = do_fail(desc, lnum, 1);
|
|
|
+ failing = do_fail(c, lnum, 1);
|
|
|
if (failing)
|
|
|
cut_data(buf, len);
|
|
|
- err = ubi_leb_write(desc, lnum, buf, offs, len, dtype);
|
|
|
+ err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
|
|
|
if (err)
|
|
|
return err;
|
|
|
if (failing)
|
|
@@ -2734,45 +2671,45 @@ int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
|
|
|
+int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf,
|
|
|
int len, int dtype)
|
|
|
{
|
|
|
int err;
|
|
|
|
|
|
- if (do_fail(desc, lnum, 1))
|
|
|
+ if (do_fail(c, lnum, 1))
|
|
|
return -EROFS;
|
|
|
- err = ubi_leb_change(desc, lnum, buf, len, dtype);
|
|
|
+ err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
|
|
|
if (err)
|
|
|
return err;
|
|
|
- if (do_fail(desc, lnum, 1))
|
|
|
+ if (do_fail(c, lnum, 1))
|
|
|
return -EROFS;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum)
|
|
|
+int dbg_leb_unmap(struct ubifs_info *c, int lnum)
|
|
|
{
|
|
|
int err;
|
|
|
|
|
|
- if (do_fail(desc, lnum, 0))
|
|
|
+ if (do_fail(c, lnum, 0))
|
|
|
return -EROFS;
|
|
|
- err = ubi_leb_unmap(desc, lnum);
|
|
|
+ err = ubi_leb_unmap(c->ubi, lnum);
|
|
|
if (err)
|
|
|
return err;
|
|
|
- if (do_fail(desc, lnum, 0))
|
|
|
+ if (do_fail(c, lnum, 0))
|
|
|
return -EROFS;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
|
|
|
+int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype)
|
|
|
{
|
|
|
int err;
|
|
|
|
|
|
- if (do_fail(desc, lnum, 0))
|
|
|
+ if (do_fail(c, lnum, 0))
|
|
|
return -EROFS;
|
|
|
- err = ubi_leb_map(desc, lnum, dtype);
|
|
|
+ err = ubi_leb_map(c->ubi, lnum, dtype);
|
|
|
if (err)
|
|
|
return err;
|
|
|
- if (do_fail(desc, lnum, 0))
|
|
|
+ if (do_fail(c, lnum, 0))
|
|
|
return -EROFS;
|
|
|
return 0;
|
|
|
}
|
|
@@ -3210,7 +3147,6 @@ int ubifs_debugging_init(struct ubifs_info *c)
|
|
|
if (!c->dbg)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- failure_mode_init(c);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -3220,7 +3156,6 @@ int ubifs_debugging_init(struct ubifs_info *c)
|
|
|
*/
|
|
|
void ubifs_debugging_exit(struct ubifs_info *c)
|
|
|
{
|
|
|
- failure_mode_exit(c);
|
|
|
kfree(c->dbg);
|
|
|
}
|
|
|
|