UBIFS: simplify dbg_dump_budg calling conventions
[pandora-kernel.git] / fs / ubifs / debug.c
index 304cc6e..aad4fb8 100644 (file)
@@ -610,18 +610,18 @@ void dbg_dump_budg(struct ubifs_info *c)
        struct ubifs_gced_idx_leb *idx_gc;
        long long available, outstanding, free;
 
-       ubifs_assert(spin_is_locked(&c->space_lock));
+       spin_lock(&c->space_lock);
        spin_lock(&dbg_lock);
        printk(KERN_DEBUG "(pid %d) Budgeting info: budg_data_growth %lld, "
               "budg_dd_growth %lld, budg_idx_growth %lld\n", current->pid,
-              c->budg_data_growth, c->budg_dd_growth, c->budg_idx_growth);
+              c->bi.data_growth, c->bi.dd_growth, c->bi.idx_growth);
        printk(KERN_DEBUG "\tdata budget sum %lld, total budget sum %lld, "
-              "freeable_cnt %d\n", c->budg_data_growth + c->budg_dd_growth,
-              c->budg_data_growth + c->budg_dd_growth + c->budg_idx_growth,
+              "freeable_cnt %d\n", c->bi.data_growth + c->bi.dd_growth,
+              c->bi.data_growth + c->bi.dd_growth + c->bi.idx_growth,
               c->freeable_cnt);
        printk(KERN_DEBUG "\tmin_idx_lebs %d, old_idx_sz %lld, "
-              "calc_idx_sz %lld, idx_gc_cnt %d\n", c->min_idx_lebs,
-              c->old_idx_sz, c->calc_idx_sz, c->idx_gc_cnt);
+              "calc_idx_sz %lld, idx_gc_cnt %d\n", c->bi.min_idx_lebs,
+              c->bi.old_idx_sz, c->calc_idx_sz, c->idx_gc_cnt);
        printk(KERN_DEBUG "\tdirty_pg_cnt %ld, dirty_zn_cnt %ld, "
               "clean_zn_cnt %ld\n", atomic_long_read(&c->dirty_pg_cnt),
               atomic_long_read(&c->dirty_zn_cnt),
@@ -648,13 +648,14 @@ void dbg_dump_budg(struct ubifs_info *c)
        printk(KERN_DEBUG "\tcommit state %d\n", c->cmt_state);
 
        /* Print budgeting predictions */
-       available = ubifs_calc_available(c, c->min_idx_lebs);
-       outstanding = c->budg_data_growth + c->budg_dd_growth;
+       available = ubifs_calc_available(c, c->bi.min_idx_lebs);
+       outstanding = c->bi.data_growth + c->bi.dd_growth;
        free = ubifs_get_free_space_nolock(c);
        printk(KERN_DEBUG "Budgeting predictions:\n");
        printk(KERN_DEBUG "\tavailable: %lld, outstanding %lld, free %lld\n",
               available, outstanding, free);
        spin_unlock(&dbg_lock);
+       spin_unlock(&c->space_lock);
 }
 
 void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp)
@@ -972,11 +973,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 +1022,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",
@@ -1015,10 +1047,7 @@ out:
 
        ubifs_msg("current lprops statistics dump");
        dbg_dump_lstats(&lst);
-
-       spin_lock(&c->space_lock);
        dbg_dump_budg(c);
-       spin_unlock(&c->space_lock);
        dump_stack();
        return -EINVAL;
 }
@@ -2390,7 +2419,8 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
                hashb = key_block(c, &sb->key);
 
                if (hasha > hashb) {
-                       ubifs_err("larger hash %u goes before %u", hasha, hashb);
+                       ubifs_err("larger hash %u goes before %u",
+                                 hasha, hashb);
                        goto error_dump;
                }
        }
@@ -2753,7 +2783,7 @@ void dbg_debugfs_exit(void)
 static int open_debugfs_file(struct inode *inode, struct file *file)
 {
        file->private_data = inode->i_private;
-       return 0;
+       return nonseekable_open(inode, file);
 }
 
 static ssize_t write_debugfs_file(struct file *file, const char __user *buf,
@@ -2764,11 +2794,9 @@ static ssize_t write_debugfs_file(struct file *file, const char __user *buf,
 
        if (file->f_path.dentry == d->dfs_dump_lprops)
                dbg_dump_lprops(c);
-       else if (file->f_path.dentry == d->dfs_dump_budg) {
-               spin_lock(&c->space_lock);
+       else if (file->f_path.dentry == d->dfs_dump_budg)
                dbg_dump_budg(c);
-               spin_unlock(&c->space_lock);
-       } 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);
                dbg_dump_tnc(c);
                mutex_unlock(&c->tnc_mutex);
@@ -2783,7 +2811,7 @@ static const struct file_operations dfs_fops = {
        .open = open_debugfs_file,
        .write = write_debugfs_file,
        .owner = THIS_MODULE,
-       .llseek = default_llseek,
+       .llseek = no_llseek,
 };
 
 /**
@@ -2808,25 +2836,25 @@ int dbg_debugfs_init_fs(struct ubifs_info *c)
        sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
        fname = d->dfs_dir_name;
        dent = debugfs_create_dir(fname, dfs_rootdir);
-       if (IS_ERR(dent))
+       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;
 
@@ -2835,7 +2863,7 @@ int dbg_debugfs_init_fs(struct ubifs_info *c)
 out_remove:
        debugfs_remove_recursive(d->dfs_dir);
 out:
-       err = PTR_ERR(dent);
+       err = dent ? PTR_ERR(dent) : -ENODEV;
        ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
                  fname, err);
        return err;