Commit f1bd66af authored by Artem Bityutskiy's avatar Artem Bityutskiy

UBIFS: improve space checking debugging feature

This patch improves the 'dbg_check_space_info()' function which checks
whether the amount of space before re-mounting and after re-mounting
is the same (remounting from R/O to R/W modes and vice-versa).

The problem is that 'dbg_check_space_info()' does not save the budgeting
information before re-mounting, so when an error is reported, we do not
know why the amount of free space changed.

This patches makes the following changes:

1. Teaches 'dbg_dump_budg()' function to accept a 'struct ubifs_budg_info'
   argument and print out the this argument. This way we may ask it to
   print any saved budgeting info, no only the current one.
2. Accordingly changes all the callers of 'dbg_dump_budg()' to comply with
   the changed interface.
3. Introduce a 'saved_bi' (saved budgeting info) field to
   'struct ubifs_debug_info' and save the budgeting info before re-mounting
   there.
4. Change 'dbg_check_space_info()' and make it print both old and new
   budgeting information.
5. Additionally, save 'c->igx_gc_cnt' and print it if and error happens. This
   value contributes to the amount of free space, so we have to print it.
Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
parent 8c3067e4
...@@ -602,7 +602,7 @@ void dbg_dump_lstats(const struct ubifs_lp_stats *lst) ...@@ -602,7 +602,7 @@ void dbg_dump_lstats(const struct ubifs_lp_stats *lst)
spin_unlock(&dbg_lock); spin_unlock(&dbg_lock);
} }
void dbg_dump_budg(struct ubifs_info *c) void dbg_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi)
{ {
int i; int i;
struct rb_node *rb; struct rb_node *rb;
...@@ -614,20 +614,29 @@ void dbg_dump_budg(struct ubifs_info *c) ...@@ -614,20 +614,29 @@ void dbg_dump_budg(struct ubifs_info *c)
spin_lock(&dbg_lock); spin_lock(&dbg_lock);
printk(KERN_DEBUG "(pid %d) Budgeting info: data budget sum %lld, " printk(KERN_DEBUG "(pid %d) Budgeting info: data budget sum %lld, "
"total budget sum %lld\n", current->pid, "total budget sum %lld\n", current->pid,
c->bi.data_growth + c->bi.dd_growth, bi->data_growth + bi->dd_growth,
c->bi.data_growth + c->bi.dd_growth + c->bi.idx_growth); bi->data_growth + bi->dd_growth + bi->idx_growth);
printk(KERN_DEBUG "\tbudg_data_growth %lld, budg_dd_growth %lld, " printk(KERN_DEBUG "\tbudg_data_growth %lld, budg_dd_growth %lld, "
"budg_idx_growth %lld\n", c->bi.data_growth, c->bi.dd_growth, "budg_idx_growth %lld\n", bi->data_growth, bi->dd_growth,
c->bi.idx_growth); bi->idx_growth);
printk(KERN_DEBUG "\tmin_idx_lebs %d, old_idx_sz %llu, " printk(KERN_DEBUG "\tmin_idx_lebs %d, old_idx_sz %llu, "
"uncommitted_idx %lld\n", c->bi.min_idx_lebs, c->bi.old_idx_sz, "uncommitted_idx %lld\n", bi->min_idx_lebs, bi->old_idx_sz,
c->bi.uncommitted_idx); bi->uncommitted_idx);
printk(KERN_DEBUG "\tpage_budget %d, inode_budget %d, dent_budget %d\n", printk(KERN_DEBUG "\tpage_budget %d, inode_budget %d, dent_budget %d\n",
c->bi.page_budget, c->bi.inode_budget, c->bi.dent_budget); bi->page_budget, bi->inode_budget, bi->dent_budget);
printk(KERN_DEBUG "\tnospace %u, nospace_rp %u\n", printk(KERN_DEBUG "\tnospace %u, nospace_rp %u\n",
c->bi.nospace, c->bi.nospace_rp); bi->nospace, bi->nospace_rp);
printk(KERN_DEBUG "\tdark_wm %d, dead_wm %d, max_idx_node_sz %d\n", printk(KERN_DEBUG "\tdark_wm %d, dead_wm %d, max_idx_node_sz %d\n",
c->dark_wm, c->dead_wm, c->max_idx_node_sz); c->dark_wm, c->dead_wm, c->max_idx_node_sz);
if (bi != &c->bi)
/*
* If we are dumping saved budgeting data, do not print
* additional information which is about the current state, not
* the old one which corresponded to the saved budgeting data.
*/
goto out_unlock;
printk(KERN_DEBUG "\tfreeable_cnt %d, calc_idx_sz %lld, idx_gc_cnt %d\n", printk(KERN_DEBUG "\tfreeable_cnt %d, calc_idx_sz %lld, idx_gc_cnt %d\n",
c->freeable_cnt, c->calc_idx_sz, c->idx_gc_cnt); c->freeable_cnt, c->calc_idx_sz, c->idx_gc_cnt);
printk(KERN_DEBUG "\tdirty_pg_cnt %ld, dirty_zn_cnt %ld, " printk(KERN_DEBUG "\tdirty_pg_cnt %ld, dirty_zn_cnt %ld, "
...@@ -636,6 +645,7 @@ void dbg_dump_budg(struct ubifs_info *c) ...@@ -636,6 +645,7 @@ void dbg_dump_budg(struct ubifs_info *c)
atomic_long_read(&c->clean_zn_cnt)); atomic_long_read(&c->clean_zn_cnt));
printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n", printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n",
c->gc_lnum, c->ihead_lnum); c->gc_lnum, c->ihead_lnum);
/* If we are in R/O mode, journal heads do not exist */ /* If we are in R/O mode, journal heads do not exist */
if (c->jheads) if (c->jheads)
for (i = 0; i < c->jhead_cnt; i++) for (i = 0; i < c->jhead_cnt; i++)
...@@ -660,6 +670,7 @@ void dbg_dump_budg(struct ubifs_info *c) ...@@ -660,6 +670,7 @@ void dbg_dump_budg(struct ubifs_info *c)
printk(KERN_DEBUG "Budgeting predictions:\n"); printk(KERN_DEBUG "Budgeting predictions:\n");
printk(KERN_DEBUG "\tavailable: %lld, outstanding %lld, free %lld\n", printk(KERN_DEBUG "\tavailable: %lld, outstanding %lld, free %lld\n",
available, outstanding, free); available, outstanding, free);
out_unlock:
spin_unlock(&dbg_lock); spin_unlock(&dbg_lock);
spin_unlock(&c->space_lock); spin_unlock(&c->space_lock);
} }
...@@ -983,6 +994,8 @@ void dbg_save_space_info(struct ubifs_info *c) ...@@ -983,6 +994,8 @@ void dbg_save_space_info(struct ubifs_info *c)
spin_lock(&c->space_lock); spin_lock(&c->space_lock);
memcpy(&d->saved_lst, &c->lst, sizeof(struct ubifs_lp_stats)); memcpy(&d->saved_lst, &c->lst, sizeof(struct ubifs_lp_stats));
memcpy(&d->saved_bi, &c->bi, sizeof(struct ubifs_budg_info));
d->saved_idx_gc_cnt = c->idx_gc_cnt;
/* /*
* We use a dirty hack here and zero out @c->freeable_cnt, because it * We use a dirty hack here and zero out @c->freeable_cnt, because it
...@@ -1049,11 +1062,14 @@ int dbg_check_space_info(struct ubifs_info *c) ...@@ -1049,11 +1062,14 @@ int dbg_check_space_info(struct ubifs_info *c)
out: out:
ubifs_msg("saved lprops statistics dump"); ubifs_msg("saved lprops statistics dump");
dbg_dump_lstats(&d->saved_lst); dbg_dump_lstats(&d->saved_lst);
ubifs_get_lp_stats(c, &lst); ubifs_msg("saved budgeting info dump");
dbg_dump_budg(c, &d->saved_bi);
ubifs_msg("saved idx_gc_cnt %d", d->saved_idx_gc_cnt);
ubifs_msg("current lprops statistics dump"); ubifs_msg("current lprops statistics dump");
ubifs_get_lp_stats(c, &lst);
dbg_dump_lstats(&lst); dbg_dump_lstats(&lst);
dbg_dump_budg(c); ubifs_msg("current budgeting info dump");
dbg_dump_budg(c, &c->bi);
dump_stack(); dump_stack();
return -EINVAL; return -EINVAL;
} }
...@@ -2801,7 +2817,7 @@ static ssize_t write_debugfs_file(struct file *file, const char __user *buf, ...@@ -2801,7 +2817,7 @@ static ssize_t write_debugfs_file(struct file *file, const char __user *buf,
if (file->f_path.dentry == d->dfs_dump_lprops) if (file->f_path.dentry == d->dfs_dump_lprops)
dbg_dump_lprops(c); dbg_dump_lprops(c);
else if (file->f_path.dentry == d->dfs_dump_budg) else if (file->f_path.dentry == d->dfs_dump_budg)
dbg_dump_budg(c); dbg_dump_budg(c, &c->bi);
else if (file->f_path.dentry == d->dfs_dump_tnc) { else if (file->f_path.dentry == d->dfs_dump_tnc) {
mutex_lock(&c->tnc_mutex); mutex_lock(&c->tnc_mutex);
dbg_dump_tnc(c); dbg_dump_tnc(c);
......
...@@ -50,7 +50,9 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c, ...@@ -50,7 +50,9 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c,
* @new_ihead_offs: used by debugging to check @c->ihead_offs * @new_ihead_offs: used by debugging to check @c->ihead_offs
* *
* @saved_lst: saved lprops statistics (used by 'dbg_save_space_info()') * @saved_lst: saved lprops statistics (used by 'dbg_save_space_info()')
* @saved_free: saved free space (used by 'dbg_save_space_info()') * @saved_bi: saved budgeting information
* @saved_free: saved amount of free space
* @saved_idx_gc_cnt: saved value of @c->idx_gc_cnt
* *
* dfs_dir_name: name of debugfs directory containing this file-system's files * dfs_dir_name: name of debugfs directory containing this file-system's files
* dfs_dir: direntry object of the file-system debugfs directory * dfs_dir: direntry object of the file-system debugfs directory
...@@ -76,7 +78,9 @@ struct ubifs_debug_info { ...@@ -76,7 +78,9 @@ struct ubifs_debug_info {
int new_ihead_offs; int new_ihead_offs;
struct ubifs_lp_stats saved_lst; struct ubifs_lp_stats saved_lst;
struct ubifs_budg_info saved_bi;
long long saved_free; long long saved_free;
int saved_idx_gc_cnt;
char dfs_dir_name[100]; char dfs_dir_name[100];
struct dentry *dfs_dir; struct dentry *dfs_dir;
...@@ -262,7 +266,7 @@ void dbg_dump_lpt_node(const struct ubifs_info *c, void *node, int lnum, ...@@ -262,7 +266,7 @@ void dbg_dump_lpt_node(const struct ubifs_info *c, void *node, int lnum,
int offs); int offs);
void dbg_dump_budget_req(const struct ubifs_budget_req *req); void dbg_dump_budget_req(const struct ubifs_budget_req *req);
void dbg_dump_lstats(const struct ubifs_lp_stats *lst); void dbg_dump_lstats(const struct ubifs_lp_stats *lst);
void dbg_dump_budg(struct ubifs_info *c); void dbg_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi);
void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp); void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp);
void dbg_dump_lprops(struct ubifs_info *c); void dbg_dump_lprops(struct ubifs_info *c);
void dbg_dump_lpt_info(struct ubifs_info *c); void dbg_dump_lpt_info(struct ubifs_info *c);
...@@ -420,7 +424,9 @@ static inline void ...@@ -420,7 +424,9 @@ static inline void
dbg_dump_budget_req(const struct ubifs_budget_req *req) { return; } dbg_dump_budget_req(const struct ubifs_budget_req *req) { return; }
static inline void static inline void
dbg_dump_lstats(const struct ubifs_lp_stats *lst) { return; } dbg_dump_lstats(const struct ubifs_lp_stats *lst) { return; }
static inline void dbg_dump_budg(struct ubifs_info *c) { return; } static inline void
dbg_dump_budg(struct ubifs_info *c,
const struct ubifs_budg_info *bi) { return; }
static inline void dbg_dump_lprop(const struct ubifs_info *c, static inline void dbg_dump_lprop(const struct ubifs_info *c,
const struct ubifs_lprops *lp) { return; } const struct ubifs_lprops *lp) { return; }
static inline void dbg_dump_lprops(struct ubifs_info *c) { return; } static inline void dbg_dump_lprops(struct ubifs_info *c) { return; }
......
...@@ -381,7 +381,7 @@ static int make_reservation(struct ubifs_info *c, int jhead, int len) ...@@ -381,7 +381,7 @@ static int make_reservation(struct ubifs_info *c, int jhead, int len)
/* This are some budgeting problems, print useful information */ /* This are some budgeting problems, print useful information */
down_write(&c->commit_sem); down_write(&c->commit_sem);
dbg_dump_stack(); dbg_dump_stack();
dbg_dump_budg(c); dbg_dump_budg(c, &c->bi);
dbg_dump_lprops(c); dbg_dump_lprops(c);
cmt_retries = dbg_check_lprops(c); cmt_retries = dbg_check_lprops(c);
up_write(&c->commit_sem); up_write(&c->commit_sem);
......
...@@ -1145,7 +1145,7 @@ static int check_free_space(struct ubifs_info *c) ...@@ -1145,7 +1145,7 @@ static int check_free_space(struct ubifs_info *c)
ubifs_assert(c->dark_wm > 0); ubifs_assert(c->dark_wm > 0);
if (c->lst.total_free + c->lst.total_dirty < c->dark_wm) { if (c->lst.total_free + c->lst.total_dirty < c->dark_wm) {
ubifs_err("insufficient free space to mount in R/W mode"); ubifs_err("insufficient free space to mount in R/W mode");
dbg_dump_budg(c); dbg_dump_budg(c, &c->bi);
dbg_dump_lprops(c); dbg_dump_lprops(c);
return -ENOSPC; return -ENOSPC;
} }
......
...@@ -383,7 +383,7 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt) ...@@ -383,7 +383,7 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt)
* option which forces in-the-gaps is enabled. * option which forces in-the-gaps is enabled.
*/ */
ubifs_err("out of space"); ubifs_err("out of space");
dbg_dump_budg(c); dbg_dump_budg(c, &c->bi);
dbg_dump_lprops(c); dbg_dump_lprops(c);
} }
/* Try to commit anyway */ /* Try to commit anyway */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment