From 1bbfc848a915081237660d898bbcf50e4a8fc59f Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 21 Mar 2011 16:26:42 +0200 Subject: UBIFS: make debugfs files non-seekable Turn the debufs files UBIFS maintains into non-seekable. Indeed, none of them is supposed to be seek'ed. Do this by making the '.lseek()' handler to be 'no_llseek()' and by using 'nonseekable_open()' in the '.open()' operation. This does mean an API break but this debugging API is only used by a couple of test scripts which do not rely in the 'llseek()' operation. Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 004d3745dc45..da9ecddf028a 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -2784,7 +2784,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, @@ -2814,7 +2814,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, }; /** -- cgit v1.2.3 From c43615702f9c5957981693a4d966ed81d8fc1ecc Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 25 Mar 2011 15:27:40 +0200 Subject: UBIFS: fix minor stylistic issues Fix several minor stylistic issues: * lines longer than 80 characters * space before closing parenthesis ')' * spaces in the indentations Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index da9ecddf028a..fa65b2931034 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -2421,7 +2421,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; } } -- cgit v1.2.3 From b137545c44fc0c80fb778abb0c582bda5601e8f8 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 29 Mar 2011 18:04:05 +0300 Subject: UBIFS: introduce a separate structure for budgeting info This patch separates out all the budgeting-related information from 'struct ubifs_info' to 'struct ubifs_budg_info'. This way the code looks a bit cleaner. However, the main driver for this is that we want to save budgeting information and print it later, so a separate data structure for this is helpful. This patch is a preparation for the further debugging output improvements. Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index fa65b2931034..c58867cbd019 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -614,14 +614,14 @@ void dbg_dump_budg(struct ubifs_info *c) 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,8 +648,8 @@ 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", -- cgit v1.2.3 From 8ff83089f8bcbd9a2e898b68f1a46487c8b6e38c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 29 Mar 2011 18:19:50 +0300 Subject: UBIFS: simplify dbg_dump_budg calling conventions The current 'dbg_dump_budg()' calling convention is that the 'c->space_lock' spinlock is held. However, none of the callers actually use it from contects which have 'c->space_lock' locked, so all callers have to explicitely lock and unlock the spinlock. This is not very sensible convention. This patch changes it and makes 'dbg_dump_budg()' lock the spinlock instead of imposing this to the callers. This simplifies the code a little. Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index c58867cbd019..aad4fb80d187 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -610,7 +610,7 @@ 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, @@ -655,6 +655,7 @@ void dbg_dump_budg(struct ubifs_info *c) 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) @@ -1046,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; } @@ -2796,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); -- cgit v1.2.3 From 8c3067e445fb25119761356c88abc39dacfb9524 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 30 Mar 2011 13:18:58 +0300 Subject: UBIFS: rearrange the budget dump Re-arrange the budget dump and make sure we first dump all the 'struct ubifs_budg_info' fields, and then the other information. Additionally, print the 'uncommitted_idx' variable. This change is required for to the following dumping function enhancement where it will be possible to dump saved 'struct ubifs_budg_info' objects, not only the current one. Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index aad4fb80d187..8e8bba937331 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -612,22 +612,28 @@ void dbg_dump_budg(struct ubifs_info *c) 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->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->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->bi.min_idx_lebs, - c->bi.old_idx_sz, c->calc_idx_sz, c->idx_gc_cnt); + printk(KERN_DEBUG "(pid %d) Budgeting info: data budget sum %lld, " + "total budget sum %lld\n", current->pid, + c->bi.data_growth + c->bi.dd_growth, + c->bi.data_growth + c->bi.dd_growth + c->bi.idx_growth); + printk(KERN_DEBUG "\tbudg_data_growth %lld, budg_dd_growth %lld, " + "budg_idx_growth %lld\n", c->bi.data_growth, c->bi.dd_growth, + c->bi.idx_growth); + 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, + c->bi.uncommitted_idx); + 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); + printk(KERN_DEBUG "\tnospace %u, nospace_rp %u\n", + c->bi.nospace, c->bi.nospace_rp); + 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); + 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); 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), atomic_long_read(&c->clean_zn_cnt)); - 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); printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n", c->gc_lnum, c->ihead_lnum); /* If we are in R/O mode, journal heads do not exist */ -- cgit v1.2.3 From f1bd66afb14c25095cf6ff499c1388db423acc9e Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 29 Mar 2011 18:36:21 +0300 Subject: 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: Artem Bityutskiy --- fs/ubifs/debug.c | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 8e8bba937331..546ad575b660 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -602,7 +602,7 @@ void dbg_dump_lstats(const struct ubifs_lp_stats *lst) 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; struct rb_node *rb; @@ -614,20 +614,29 @@ void dbg_dump_budg(struct ubifs_info *c) spin_lock(&dbg_lock); printk(KERN_DEBUG "(pid %d) Budgeting info: data budget sum %lld, " "total budget sum %lld\n", current->pid, - c->bi.data_growth + c->bi.dd_growth, - c->bi.data_growth + c->bi.dd_growth + c->bi.idx_growth); + bi->data_growth + bi->dd_growth, + bi->data_growth + bi->dd_growth + bi->idx_growth); printk(KERN_DEBUG "\tbudg_data_growth %lld, budg_dd_growth %lld, " - "budg_idx_growth %lld\n", c->bi.data_growth, c->bi.dd_growth, - c->bi.idx_growth); + "budg_idx_growth %lld\n", bi->data_growth, bi->dd_growth, + bi->idx_growth); 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, - c->bi.uncommitted_idx); + "uncommitted_idx %lld\n", bi->min_idx_lebs, bi->old_idx_sz, + bi->uncommitted_idx); 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", - 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", 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", c->freeable_cnt, c->calc_idx_sz, c->idx_gc_cnt); printk(KERN_DEBUG "\tdirty_pg_cnt %ld, dirty_zn_cnt %ld, " @@ -636,6 +645,7 @@ void dbg_dump_budg(struct ubifs_info *c) atomic_long_read(&c->clean_zn_cnt)); printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n", c->gc_lnum, c->ihead_lnum); + /* If we are in R/O mode, journal heads do not exist */ if (c->jheads) for (i = 0; i < c->jhead_cnt; i++) @@ -660,6 +670,7 @@ void dbg_dump_budg(struct ubifs_info *c) printk(KERN_DEBUG "Budgeting predictions:\n"); printk(KERN_DEBUG "\tavailable: %lld, outstanding %lld, free %lld\n", available, outstanding, free); +out_unlock: spin_unlock(&dbg_lock); spin_unlock(&c->space_lock); } @@ -983,6 +994,8 @@ void dbg_save_space_info(struct ubifs_info *c) spin_lock(&c->space_lock); 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 @@ -1049,11 +1062,14 @@ int dbg_check_space_info(struct ubifs_info *c) out: ubifs_msg("saved lprops statistics dump"); 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_get_lp_stats(c, &lst); dbg_dump_lstats(&lst); - dbg_dump_budg(c); + ubifs_msg("current budgeting info dump"); + dbg_dump_budg(c, &c->bi); dump_stack(); return -EINVAL; } @@ -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) dbg_dump_lprops(c); 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) { mutex_lock(&c->tnc_mutex); dbg_dump_tnc(c); -- cgit v1.2.3 From bc3f07f0906e867270fdc2006b0bbcb130a722c1 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 5 Apr 2011 13:52:20 +0300 Subject: UBIFS: make force in-the-gaps to be a general self-check UBIFS can force itself to use the 'in-the-gaps' commit method - the last resort method which is normally invoced very very rarely. Currently this "force int-the-gaps" debugging feature is a separate test mode. But it is a bit saner to make it to be the "general" self-test check instead. This patch is just a clean-up which should make the debugging code look a bit nicer and easier to use - we have way too many debugging options. Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 546ad575b660..06d171cefe45 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -34,7 +34,6 @@ #include #include #include -#include #ifdef CONFIG_UBIFS_FS_DEBUG @@ -2458,14 +2457,12 @@ error_dump: return 0; } -static int invocation_cnt; - int dbg_force_in_the_gaps(void) { - if (!dbg_force_in_the_gaps_enabled) + if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) return 0; - /* Force in-the-gaps every 8th commit */ - return !((invocation_cnt++) & 0x7); + + return !(random32() & 7); } /* Failure mode for recovery testing */ -- cgit v1.2.3 From 1a29af8bd740b2720caeafbffece1c0be6a9d06d Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 20 Apr 2011 17:06:17 +0300 Subject: UBIFS: use EROFS when emulating failures When the debugging failure emulation is enabled and UBIFS decides to emulate an I/O error, it uses EIO error code. In which case UBIFS switches into R/O mode later on. The for the user-space is that when a failure is emulated, the file-system sometimes returns EIO and sometimes EROFS. This makes it more difficult to implement user-space tests for the failure mode. Let's be consistent and return EROFS in all the cases. This patch is an improvement for the debugging code and does not affect the functionality at all. Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 06d171cefe45..ba4d795d63a3 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -2650,7 +2650,7 @@ int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, int len, int check) { if (in_failure_mode(desc)) - return -EIO; + return -EROFS; return ubi_leb_read(desc, lnum, buf, offset, len, check); } @@ -2660,7 +2660,7 @@ int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, int err, failing; if (in_failure_mode(desc)) - return -EIO; + return -EROFS; failing = do_fail(desc, lnum, 1); if (failing) cut_data(buf, len); @@ -2668,7 +2668,7 @@ int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, if (err) return err; if (failing) - return -EIO; + return -EROFS; return 0; } @@ -2678,12 +2678,12 @@ int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, int err; if (do_fail(desc, lnum, 1)) - return -EIO; + return -EROFS; err = ubi_leb_change(desc, lnum, buf, len, dtype); if (err) return err; if (do_fail(desc, lnum, 1)) - return -EIO; + return -EROFS; return 0; } @@ -2692,12 +2692,12 @@ int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum) int err; if (do_fail(desc, lnum, 0)) - return -EIO; + return -EROFS; err = ubi_leb_erase(desc, lnum); if (err) return err; if (do_fail(desc, lnum, 0)) - return -EIO; + return -EROFS; return 0; } @@ -2706,19 +2706,19 @@ int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum) int err; if (do_fail(desc, lnum, 0)) - return -EIO; + return -EROFS; err = ubi_leb_unmap(desc, lnum); if (err) return err; if (do_fail(desc, lnum, 0)) - return -EIO; + return -EROFS; return 0; } int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum) { if (in_failure_mode(desc)) - return -EIO; + return -EROFS; return ubi_is_mapped(desc, lnum); } @@ -2727,12 +2727,12 @@ int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype) int err; if (do_fail(desc, lnum, 0)) - return -EIO; + return -EROFS; err = ubi_leb_map(desc, lnum, dtype); if (err) return err; if (do_fail(desc, lnum, 0)) - return -EIO; + return -EROFS; return 0; } -- cgit v1.2.3 From 1321657d8f843641529eff26e25722158cc29349 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 24 Apr 2011 10:53:17 +0300 Subject: UBIFS: fix oops in lprops dump function The 'dbg_dump_lprop()' is trying to detect journal head LEBs when printing, so it looks at the write-buffers. However, if we are in R/O mode, we de-allocate the write-buffers, so 'dbg_dump_lprop()' oopses. This patch fixes the issue. Note, this patch is not critical, it is only about the debugging code path, and it is unlikely that anyone but UBIFS developers would ever hit this issue. Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index ba4d795d63a3..4062ec602632 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -746,7 +746,13 @@ void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp) if (bud->lnum == lp->lnum) { int head = 0; for (i = 0; i < c->jhead_cnt; i++) { - if (lp->lnum == c->jheads[i].wbuf.lnum) { + /* + * Note, if we are in R/O mode or in the middle + * of mounting/re-mounting, the write-buffers do + * not exist. + */ + if (c->jheads && + lp->lnum == c->jheads[i].wbuf.lnum) { printk(KERN_CONT ", jhead %s", dbg_jhead(i)); head = 1; -- cgit v1.2.3 From 341e262f903afbb8c23133ed6e193ea6254f73c4 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 22 Apr 2011 12:11:12 +0300 Subject: UBIFS: do not change debugfs file position This patch is a tiny improvement which removes few bytes of code. UBIFS debugfs files are non-seekable and the file position is ignored, so do not increase it in the write handler. Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 4062ec602632..f7515bd38b4f 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -2828,7 +2828,6 @@ static ssize_t write_debugfs_file(struct file *file, const char __user *buf, } else return -EINVAL; - *ppos += count; return count; } -- cgit v1.2.3 From 45cd5cddbfbdf0993dbc76d06ed77d0bf547b421 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 2 May 2011 22:34:39 +0300 Subject: UBIFS: fix debugging FS checking failure When the debugging self-checks are enabled, we go trough whole file-system after mount and check/validate every single node referred to by the index. This is implemented by the 'dbg_check_filesystem()' function. However, this function fails if we mount "unclean" file-system, i.e., if we mount the file-system after a power cut. It fails with the following symptoms: UBIFS DBG (pid 8171): ubifs_recover_size: ino 937 size 3309925 -> 3317760 UBIFS: recovery deferred UBIFS error (pid 8171): check_leaf: data node at LEB 1000:0 is not within inode size 3309925 The reason of failure is that recovery fixed up the inode size in memory, but not on the flash so far. So the value on the flash is incorrect so far, and would be corrected when we re-mount R/W. But 'check_leaf()' ignores this fact and tries to validate the size of the on-flash inode, which is incorrect, so it fails. This patch teaches the checking code to look at the VFS inode cache first, and if there is the inode in question, use that inode instead of the inode on the flash media. This fixes the issue. Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index f7515bd38b4f..b5ba2ea5b626 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -1818,6 +1818,8 @@ static struct fsck_inode *add_inode(struct ubifs_info *c, struct rb_node **p, *parent = NULL; struct fsck_inode *fscki; ino_t inum = key_inum_flash(c, &ino->key); + struct inode *inode; + struct ubifs_inode *ui; p = &fsckd->inodes.rb_node; while (*p) { @@ -1841,19 +1843,46 @@ static struct fsck_inode *add_inode(struct ubifs_info *c, if (!fscki) return ERR_PTR(-ENOMEM); + inode = ilookup(c->vfs_sb, inum); + fscki->inum = inum; - fscki->nlink = le32_to_cpu(ino->nlink); - fscki->size = le64_to_cpu(ino->size); - fscki->xattr_cnt = le32_to_cpu(ino->xattr_cnt); - fscki->xattr_sz = le32_to_cpu(ino->xattr_size); - fscki->xattr_nms = le32_to_cpu(ino->xattr_names); - fscki->mode = le32_to_cpu(ino->mode); + /* + * If the inode is present in the VFS inode cache, use it instead of + * the on-flash inode which might be out-of-date. E.g., the size might + * be out-of-date. If we do not do this, the following may happen, for + * example: + * 1. A power cut happens + * 2. We mount the file-system R/O, the replay process fixes up the + * inode size in the VFS cache, but on on-flash. + * 3. 'check_leaf()' fails because it hits a data node beyond inode + * size. + */ + if (!inode) { + fscki->nlink = le32_to_cpu(ino->nlink); + fscki->size = le64_to_cpu(ino->size); + fscki->xattr_cnt = le32_to_cpu(ino->xattr_cnt); + fscki->xattr_sz = le32_to_cpu(ino->xattr_size); + fscki->xattr_nms = le32_to_cpu(ino->xattr_names); + fscki->mode = le32_to_cpu(ino->mode); + } else { + ui = ubifs_inode(inode); + fscki->nlink = inode->i_nlink; + fscki->size = inode->i_size; + fscki->xattr_cnt = ui->xattr_cnt; + fscki->xattr_sz = ui->xattr_size; + fscki->xattr_nms = ui->xattr_names; + fscki->mode = inode->i_mode; + iput(inode); + } + if (S_ISDIR(fscki->mode)) { fscki->calc_sz = UBIFS_INO_NODE_SZ; fscki->calc_cnt = 2; } + rb_link_node(&fscki->rb, parent, p); rb_insert_color(&fscki->rb, &fsckd->inodes); + return fscki; } -- cgit v1.2.3 From 9f58d3503a1368673609db1962e4a584261b62eb Mon Sep 17 00:00:00 2001 From: "Matthew L. Creech" Date: Thu, 5 May 2011 16:33:20 -0400 Subject: UBIFS: add a superblock flag for free space fix-up The 'space_fixup' flag can be set in the superblock of a new filesystem by mkfs.ubifs to indicate that any eraseblocks with free space remaining should be fixed-up the first time it's mounted (after which the flag is un-set). This means that the UBIFS image has been flashed by a "dumb" flasher and the free space has been actually programmed (writing all 0xFFs), so this free space cannot be used. UBIFS fixes the free space up by re-writing the contents of all LEBs with free space using the atomic LEB change UBI operation. Artem: improved commit message, add some more commentaries to the code. Signed-off-by: Matthew L. Creech Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index b5ba2ea5b626..f46d77e9f031 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -316,6 +316,8 @@ void dbg_dump_node(const struct ubifs_info *c, const void *node) printk(KERN_DEBUG "\tflags %#x\n", sup_flags); printk(KERN_DEBUG "\t big_lpt %u\n", !!(sup_flags & UBIFS_FLG_BIGLPT)); + printk(KERN_DEBUG "\t space_fixup %u\n", + !!(sup_flags & UBIFS_FLG_SPACE_FIXUP)); printk(KERN_DEBUG "\tmin_io_size %u\n", le32_to_cpu(sup->min_io_size)); printk(KERN_DEBUG "\tleb_size %u\n", -- cgit v1.2.3 From 56e46742e846e4de167dde0e1e1071ace1c882a5 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 17 May 2011 15:15:30 +0300 Subject: UBIFS: switch to dynamic printks Switch to debugging using dynamic printk (pr_debug()). There is no good reason to carry custom debugging prints if there is so cool and powerful generic dynamic printk infrastructure, see Documentation/dynamic-debug-howto.txt. With dynamic printks we can switch on/of individual prints, per-file, per-function and per format messages. This means that instead of doing old-fashioned echo 1 > /sys/module/ubifs/parameters/debug_msgs to enable general messages, we can do: echo 'format "UBIFS DBG gen" +ptlf' > control to enable general messages and additionally ask the dynamic printk infrastructure to print process ID, line number and function name. So there is no reason to keep UBIFS-specific crud if there is more powerful generic thing. Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index f46d77e9f031..0bb2bcef0de9 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -42,15 +42,12 @@ DEFINE_SPINLOCK(dbg_lock); static char dbg_key_buf0[128]; static char dbg_key_buf1[128]; -unsigned int ubifs_msg_flags; unsigned int ubifs_chk_flags; unsigned int ubifs_tst_flags; -module_param_named(debug_msgs, ubifs_msg_flags, uint, S_IRUGO | S_IWUSR); module_param_named(debug_chks, ubifs_chk_flags, uint, S_IRUGO | S_IWUSR); module_param_named(debug_tsts, ubifs_tst_flags, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug_msgs, "Debug message type flags"); MODULE_PARM_DESC(debug_chks, "Debug check flags"); MODULE_PARM_DESC(debug_tsts, "Debug special test flags"); -- cgit v1.2.3