|
@@ -972,11 +972,39 @@ void dbg_dump_index(struct ubifs_info *c)
|
|
|
void dbg_save_space_info(struct ubifs_info *c)
|
|
|
{
|
|
|
struct ubifs_debug_info *d = c->dbg;
|
|
|
-
|
|
|
- ubifs_get_lp_stats(c, &d->saved_lst);
|
|
|
+ int freeable_cnt;
|
|
|
|
|
|
spin_lock(&c->space_lock);
|
|
|
+ memcpy(&d->saved_lst, &c->lst, sizeof(struct ubifs_lp_stats));
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We use a dirty hack here and zero out @c->freeable_cnt, because it
|
|
|
+ * affects the free space calculations, and UBIFS might not know about
|
|
|
+ * all freeable eraseblocks. Indeed, we know about freeable eraseblocks
|
|
|
+ * only when we read their lprops, and we do this only lazily, upon the
|
|
|
+ * need. So at any given point of time @c->freeable_cnt might be not
|
|
|
+ * exactly accurate.
|
|
|
+ *
|
|
|
+ * Just one example about the issue we hit when we did not zero
|
|
|
+ * @c->freeable_cnt.
|
|
|
+ * 1. The file-system is mounted R/O, c->freeable_cnt is %0. We save the
|
|
|
+ * amount of free space in @d->saved_free
|
|
|
+ * 2. We re-mount R/W, which makes UBIFS to read the "lsave"
|
|
|
+ * information from flash, where we cache LEBs from various
|
|
|
+ * categories ('ubifs_remount_fs()' -> 'ubifs_lpt_init()'
|
|
|
+ * -> 'lpt_init_wr()' -> 'read_lsave()' -> 'ubifs_lpt_lookup()'
|
|
|
+ * -> 'ubifs_get_pnode()' -> 'update_cats()'
|
|
|
+ * -> 'ubifs_add_to_cat()').
|
|
|
+ * 3. Lsave contains a freeable eraseblock, and @c->freeable_cnt
|
|
|
+ * becomes %1.
|
|
|
+ * 4. We calculate the amount of free space when the re-mount is
|
|
|
+ * finished in 'dbg_check_space_info()' and it does not match
|
|
|
+ * @d->saved_free.
|
|
|
+ */
|
|
|
+ freeable_cnt = c->freeable_cnt;
|
|
|
+ c->freeable_cnt = 0;
|
|
|
d->saved_free = ubifs_get_free_space_nolock(c);
|
|
|
+ c->freeable_cnt = freeable_cnt;
|
|
|
spin_unlock(&c->space_lock);
|
|
|
}
|
|
|
|
|
@@ -993,12 +1021,15 @@ int dbg_check_space_info(struct ubifs_info *c)
|
|
|
{
|
|
|
struct ubifs_debug_info *d = c->dbg;
|
|
|
struct ubifs_lp_stats lst;
|
|
|
- long long avail, free;
|
|
|
+ long long free;
|
|
|
+ int freeable_cnt;
|
|
|
|
|
|
spin_lock(&c->space_lock);
|
|
|
- avail = ubifs_calc_available(c, c->min_idx_lebs);
|
|
|
+ freeable_cnt = c->freeable_cnt;
|
|
|
+ c->freeable_cnt = 0;
|
|
|
+ free = ubifs_get_free_space_nolock(c);
|
|
|
+ c->freeable_cnt = freeable_cnt;
|
|
|
spin_unlock(&c->space_lock);
|
|
|
- free = ubifs_get_free_space(c);
|
|
|
|
|
|
if (free != d->saved_free) {
|
|
|
ubifs_err("free space changed from %lld to %lld",
|
|
@@ -2806,40 +2837,38 @@ int dbg_debugfs_init_fs(struct ubifs_info *c)
|
|
|
struct ubifs_debug_info *d = c->dbg;
|
|
|
|
|
|
sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
|
|
|
- d->dfs_dir = debugfs_create_dir(d->dfs_dir_name, dfs_rootdir);
|
|
|
- if (IS_ERR(d->dfs_dir)) {
|
|
|
- err = PTR_ERR(d->dfs_dir);
|
|
|
- ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
|
|
|
- d->dfs_dir_name, err);
|
|
|
+ fname = d->dfs_dir_name;
|
|
|
+ dent = debugfs_create_dir(fname, dfs_rootdir);
|
|
|
+ if (IS_ERR_OR_NULL(dent))
|
|
|
goto out;
|
|
|
- }
|
|
|
+ d->dfs_dir = dent;
|
|
|
|
|
|
fname = "dump_lprops";
|
|
|
dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops);
|
|
|
- if (IS_ERR(dent))
|
|
|
+ if (IS_ERR_OR_NULL(dent))
|
|
|
goto out_remove;
|
|
|
d->dfs_dump_lprops = dent;
|
|
|
|
|
|
fname = "dump_budg";
|
|
|
dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops);
|
|
|
- if (IS_ERR(dent))
|
|
|
+ if (IS_ERR_OR_NULL(dent))
|
|
|
goto out_remove;
|
|
|
d->dfs_dump_budg = dent;
|
|
|
|
|
|
fname = "dump_tnc";
|
|
|
dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops);
|
|
|
- if (IS_ERR(dent))
|
|
|
+ if (IS_ERR_OR_NULL(dent))
|
|
|
goto out_remove;
|
|
|
d->dfs_dump_tnc = dent;
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
out_remove:
|
|
|
- err = PTR_ERR(dent);
|
|
|
- ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
|
|
|
- fname, err);
|
|
|
debugfs_remove_recursive(d->dfs_dir);
|
|
|
out:
|
|
|
+ err = dent ? PTR_ERR(dent) : -ENODEV;
|
|
|
+ ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
|
|
|
+ fname, err);
|
|
|
return err;
|
|
|
}
|
|
|
|