Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 17c2f9f8 authored by Artem Bityutskiy's avatar Artem Bityutskiy
Browse files

UBIFS: separate debugging fields out



Introduce a new data structure which contains all debugging
stuff inside. This is cleaner than having debugging stuff
directly in 'c'.

Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
parent 5dd7cbc0
Loading
Loading
Loading
Loading
+13 −12
Original line number Diff line number Diff line
@@ -470,12 +470,12 @@ int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot)
{
	struct ubifs_idx_node *idx;
	int lnum, offs, len, err = 0;
	struct ubifs_debug_info *d = c->dbg;

	c->old_zroot = *zroot;

	lnum = c->old_zroot.lnum;
	offs = c->old_zroot.offs;
	len = c->old_zroot.len;
	d->old_zroot = *zroot;
	lnum = d->old_zroot.lnum;
	offs = d->old_zroot.offs;
	len = d->old_zroot.len;

	idx = kmalloc(c->max_idx_node_sz, GFP_NOFS);
	if (!idx)
@@ -485,8 +485,8 @@ int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot)
	if (err)
		goto out;

	c->old_zroot_level = le16_to_cpu(idx->level);
	c->old_zroot_sqnum = le64_to_cpu(idx->ch.sqnum);
	d->old_zroot_level = le16_to_cpu(idx->level);
	d->old_zroot_sqnum = le64_to_cpu(idx->ch.sqnum);
out:
	kfree(idx);
	return err;
@@ -509,6 +509,7 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
{
	int lnum, offs, len, err = 0, uninitialized_var(last_level), child_cnt;
	int first = 1, iip;
	struct ubifs_debug_info *d = c->dbg;
	union ubifs_key lower_key, upper_key, l_key, u_key;
	unsigned long long uninitialized_var(last_sqnum);
	struct ubifs_idx_node *idx;
@@ -525,9 +526,9 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
	     UBIFS_IDX_NODE_SZ;

	/* Start at the old zroot */
	lnum = c->old_zroot.lnum;
	offs = c->old_zroot.offs;
	len = c->old_zroot.len;
	lnum = d->old_zroot.lnum;
	offs = d->old_zroot.offs;
	len = d->old_zroot.len;
	iip = 0;

	/*
@@ -560,11 +561,11 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
		if (first) {
			first = 0;
			/* Check root level and sqnum */
			if (le16_to_cpu(idx->level) != c->old_zroot_level) {
			if (le16_to_cpu(idx->level) != d->old_zroot_level) {
				err = 2;
				goto out_dump;
			}
			if (le64_to_cpu(idx->ch.sqnum) != c->old_zroot_sqnum) {
			if (le64_to_cpu(idx->ch.sqnum) != d->old_zroot_sqnum) {
				err = 3;
				goto out_dump;
			}
+55 −16
Original line number Diff line number Diff line
@@ -705,7 +705,7 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum)

	printk(KERN_DEBUG "(pid %d) Dumping LEB %d\n", current->pid, lnum);

	sleb = ubifs_scan(c, lnum, 0, c->dbg_buf);
	sleb = ubifs_scan(c, lnum, 0, c->dbg->buf);
	if (IS_ERR(sleb)) {
		ubifs_err("scan error %d", (int)PTR_ERR(sleb));
		return;
@@ -2097,7 +2097,7 @@ static int simple_rand(void)
	return (next >> 16) & 32767;
}

void dbg_failure_mode_registration(struct ubifs_info *c)
static void failure_mode_init(struct ubifs_info *c)
{
	struct failure_mode_info *fmi;

@@ -2112,7 +2112,7 @@ void dbg_failure_mode_registration(struct ubifs_info *c)
	spin_unlock(&fmi_lock);
}

void dbg_failure_mode_deregistration(struct ubifs_info *c)
static void failure_mode_exit(struct ubifs_info *c)
{
	struct failure_mode_info *fmi, *tmp;

@@ -2146,42 +2146,44 @@ static int in_failure_mode(struct ubi_volume_desc *desc)
	struct ubifs_info *c = dbg_find_info(desc);

	if (c && dbg_failure_mode)
		return c->failure_mode;
		return c->dbg->failure_mode;
	return 0;
}

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_failure_mode)
		return 0;
	if (c->failure_mode)
	d = c->dbg;
	if (d->failure_mode)
		return 1;
	if (!c->fail_cnt) {
	if (!d->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 +
				d->fail_delay = 1;
				d->fail_timeout = jiffies +
						  msecs_to_jiffies(delay);
				dbg_rcvry("failing after %ums", delay);
			} else {
				c->fail_delay = 2;
				c->fail_cnt_max = delay;
				d->fail_delay = 2;
				d->fail_cnt_max = delay;
				dbg_rcvry("failing after %u calls", delay);
			}
		}
		c->fail_cnt += 1;
		d->fail_cnt += 1;
	}
	/* Determine if failure delay has expired */
	if (c->fail_delay == 1) {
		if (time_before(jiffies, c->fail_timeout))
	if (d->fail_delay == 1) {
		if (time_before(jiffies, d->fail_timeout))
			return 0;
	} else if (c->fail_delay == 2)
		if (c->fail_cnt++ < c->fail_cnt_max)
	} else if (d->fail_delay == 2)
		if (d->fail_cnt++ < d->fail_cnt_max)
			return 0;
	if (lnum == UBIFS_SB_LNUM) {
		if (write) {
@@ -2239,7 +2241,7 @@ static int do_fail(struct ubi_volume_desc *desc, int lnum, int write)
		dbg_rcvry("failing in bud LEB %d commit not running", lnum);
	}
	ubifs_err("*** SETTING FAILURE MODE ON (LEB %d) ***", lnum);
	c->failure_mode = 1;
	d->failure_mode = 1;
	dump_stack();
	return 1;
}
@@ -2344,4 +2346,41 @@ int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
	return 0;
}

/**
 * ubifs_debugging_init - initialize UBIFS debugging.
 * @c: UBIFS file-system description object
 *
 * This function initializes debugging-related data for the file system.
 * Returns zero in case of success and a negative error code in case of
 * failure.
 */
int ubifs_debugging_init(struct ubifs_info *c)
{
	c->dbg = kzalloc(sizeof(struct ubifs_debug_info), GFP_KERNEL);
	if (!c->dbg)
		return -ENOMEM;

	c->dbg->buf = vmalloc(c->leb_size);
	if (!c->dbg->buf)
		goto out;

	failure_mode_init(c);
	return 0;

out:
	kfree(c->dbg);
	return -ENOMEM;
}

/**
 * ubifs_debugging_exit - free debugging data.
 * @c: UBIFS file-system description object
 */
void ubifs_debugging_exit(struct ubifs_info *c)
{
	failure_mode_exit(c);
	vfree(c->dbg->buf);
	kfree(c->dbg);
}

#endif /* CONFIG_UBIFS_FS_DEBUG */
+43 −8
Original line number Diff line number Diff line
@@ -25,7 +25,43 @@

#ifdef CONFIG_UBIFS_FS_DEBUG

#define UBIFS_DBG(op) op
/**
 * ubifs_debug_info - per-FS debugging information.
 * @buf: a buffer of LEB size, used for various purposes
 * @old_zroot: old index root - used by 'dbg_check_old_index()'
 * @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
 * @chk_lpt_sz: used by LPT tree size checker
 * @chk_lpt_sz2: used by LPT tree size checker
 * @chk_lpt_wastage: used by LPT tree size checker
 * @chk_lpt_lebs: used by LPT tree size checker
 * @new_nhead_offs: used by LPT tree size checker
 * @new_ihead_lnum: used by debugging to check ihead_lnum
 * @new_ihead_offs: used by debugging to check ihead_offs
 */
struct ubifs_debug_info {
	void *buf;
	struct ubifs_zbranch old_zroot;
	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;
	long long chk_lpt_sz;
	long long chk_lpt_sz2;
	long long chk_lpt_wastage;
	int chk_lpt_lebs;
	int new_nhead_offs;
	int new_ihead_lnum;
	int new_ihead_offs;
};

#define ubifs_assert(expr) do {                                                \
	if (unlikely(!(expr))) {                                               \
@@ -211,6 +247,9 @@ extern unsigned int ubifs_msg_flags;
extern unsigned int ubifs_chk_flags;
extern unsigned int ubifs_tst_flags;

int ubifs_debugging_init(struct ubifs_info *c);
void ubifs_debugging_exit(struct ubifs_info *c);

/* Dump functions */

const char *dbg_ntype(int type);
@@ -274,9 +313,6 @@ int dbg_force_in_the_gaps(void);

#define dbg_failure_mode (ubifs_tst_flags & UBIFS_TST_RCVRY)

void dbg_failure_mode_registration(struct ubifs_info *c);
void dbg_failure_mode_deregistration(struct ubifs_info *c);

#ifndef UBIFS_DBG_PRESERVE_UBI

#define ubi_leb_read   dbg_leb_read
@@ -320,8 +356,6 @@ static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,

#else /* !CONFIG_UBIFS_FS_DEBUG */

#define UBIFS_DBG(op)

/* Use "if (0)" to make compiler check arguments even if debugging is off */
#define ubifs_assert(expr)  do {                                               \
	if (0 && (expr))                                                       \
@@ -360,6 +394,9 @@ static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
#define DBGKEY(key)  ((char *)(key))
#define DBGKEY1(key) ((char *)(key))

#define ubifs_debugging_init(c)               0
#define ubifs_debugging_exit(c)               ({})

#define dbg_ntype(type)                       ""
#define dbg_cstate(cmt_state)                 ""
#define dbg_get_key_dump(c, key)              ({})
@@ -396,8 +433,6 @@ static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
#define dbg_force_in_the_gaps_enabled              0
#define dbg_force_in_the_gaps()                    0
#define dbg_failure_mode                           0
#define dbg_failure_mode_registration(c)           ({})
#define dbg_failure_mode_deregistration(c)         ({})

#endif /* !CONFIG_UBIFS_FS_DEBUG */

+1 −1
Original line number Diff line number Diff line
@@ -1088,7 +1088,7 @@ static int scan_check_cb(struct ubifs_info *c,
		}
	}

	sleb = ubifs_scan(c, lnum, 0, c->dbg_buf);
	sleb = ubifs_scan(c, lnum, 0, c->dbg->buf);
	if (IS_ERR(sleb)) {
		/*
		 * After an unclean unmount, empty and freeable LEBs
+28 −27
Original line number Diff line number Diff line
@@ -1602,7 +1602,7 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum)
{
	int err, len = c->leb_size, dirty = 0, node_type, node_num, node_len;
	int ret;
	void *buf = c->dbg_buf;
	void *buf = c->dbg->buf;

	dbg_lp("LEB %d", lnum);
	err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
@@ -1731,15 +1731,16 @@ int dbg_chk_lpt_free_spc(struct ubifs_info *c)
 */
int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
{
	struct ubifs_debug_info *d = c->dbg;
	long long chk_lpt_sz, lpt_sz;
	int err = 0;

	switch (action) {
	case 0:
		c->chk_lpt_sz = 0;
		c->chk_lpt_sz2 = 0;
		c->chk_lpt_lebs = 0;
		c->chk_lpt_wastage = 0;
		d->chk_lpt_sz = 0;
		d->chk_lpt_sz2 = 0;
		d->chk_lpt_lebs = 0;
		d->chk_lpt_wastage = 0;
		if (c->dirty_pn_cnt > c->pnode_cnt) {
			dbg_err("dirty pnodes %d exceed max %d",
				c->dirty_pn_cnt, c->pnode_cnt);
@@ -1752,35 +1753,35 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
		}
		return err;
	case 1:
		c->chk_lpt_sz += len;
		d->chk_lpt_sz += len;
		return 0;
	case 2:
		c->chk_lpt_sz += len;
		c->chk_lpt_wastage += len;
		c->chk_lpt_lebs += 1;
		d->chk_lpt_sz += len;
		d->chk_lpt_wastage += len;
		d->chk_lpt_lebs += 1;
		return 0;
	case 3:
		chk_lpt_sz = c->leb_size;
		chk_lpt_sz *= c->chk_lpt_lebs;
		chk_lpt_sz *= d->chk_lpt_lebs;
		chk_lpt_sz += len - c->nhead_offs;
		if (c->chk_lpt_sz != chk_lpt_sz) {
		if (d->chk_lpt_sz != chk_lpt_sz) {
			dbg_err("LPT wrote %lld but space used was %lld",
				c->chk_lpt_sz, chk_lpt_sz);
				d->chk_lpt_sz, chk_lpt_sz);
			err = -EINVAL;
		}
		if (c->chk_lpt_sz > c->lpt_sz) {
		if (d->chk_lpt_sz > c->lpt_sz) {
			dbg_err("LPT wrote %lld but lpt_sz is %lld",
				c->chk_lpt_sz, c->lpt_sz);
				d->chk_lpt_sz, c->lpt_sz);
			err = -EINVAL;
		}
		if (c->chk_lpt_sz2 && c->chk_lpt_sz != c->chk_lpt_sz2) {
		if (d->chk_lpt_sz2 && d->chk_lpt_sz != d->chk_lpt_sz2) {
			dbg_err("LPT layout size %lld but wrote %lld",
				c->chk_lpt_sz, c->chk_lpt_sz2);
				d->chk_lpt_sz, d->chk_lpt_sz2);
			err = -EINVAL;
		}
		if (c->chk_lpt_sz2 && c->new_nhead_offs != len) {
		if (d->chk_lpt_sz2 && d->new_nhead_offs != len) {
			dbg_err("LPT new nhead offs: expected %d was %d",
				c->new_nhead_offs, len);
				d->new_nhead_offs, len);
			err = -EINVAL;
		}
		lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
@@ -1788,22 +1789,22 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
		lpt_sz += c->ltab_sz;
		if (c->big_lpt)
			lpt_sz += c->lsave_sz;
		if (c->chk_lpt_sz - c->chk_lpt_wastage > lpt_sz) {
		if (d->chk_lpt_sz - d->chk_lpt_wastage > lpt_sz) {
			dbg_err("LPT chk_lpt_sz %lld + waste %lld exceeds %lld",
				c->chk_lpt_sz, c->chk_lpt_wastage, lpt_sz);
				d->chk_lpt_sz, d->chk_lpt_wastage, lpt_sz);
			err = -EINVAL;
		}
		if (err)
			dbg_dump_lpt_info(c);
		c->chk_lpt_sz2 = c->chk_lpt_sz;
		c->chk_lpt_sz = 0;
		c->chk_lpt_wastage = 0;
		c->chk_lpt_lebs = 0;
		c->new_nhead_offs = len;
		d->chk_lpt_sz2 = d->chk_lpt_sz;
		d->chk_lpt_sz = 0;
		d->chk_lpt_wastage = 0;
		d->chk_lpt_lebs = 0;
		d->new_nhead_offs = len;
		return err;
	case 4:
		c->chk_lpt_sz += len;
		c->chk_lpt_wastage += len;
		d->chk_lpt_sz += len;
		d->chk_lpt_wastage += len;
		return 0;
	default:
		return -EINVAL;
Loading