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 ++- fs/ubifs/file.c | 17 +++++++++-------- fs/ubifs/io.c | 4 ++-- fs/ubifs/lpt_commit.c | 2 +- fs/ubifs/orphan.c | 3 ++- fs/ubifs/super.c | 4 ++-- fs/ubifs/tnc.c | 10 +++++----- fs/ubifs/ubifs.h | 6 +++--- 8 files changed, 26 insertions(+), 23 deletions(-) (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; } } diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index b286db79c686..3f254e37b25b 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -971,11 +971,11 @@ static int do_writepage(struct page *page, int len) * the page locked, and it locks @ui_mutex. However, write-back does take inode * @i_mutex, which means other VFS operations may be run on this inode at the * same time. And the problematic one is truncation to smaller size, from where - * we have to call 'truncate_setsize()', which first changes @inode->i_size, then - * drops the truncated pages. And while dropping the pages, it takes the page - * lock. This means that 'do_truncation()' cannot call 'truncate_setsize()' with - * @ui_mutex locked, because it would deadlock with 'ubifs_writepage()'. This - * means that @inode->i_size is changed while @ui_mutex is unlocked. + * we have to call 'truncate_setsize()', which first changes @inode->i_size, + * then drops the truncated pages. And while dropping the pages, it takes the + * page lock. This means that 'do_truncation()' cannot call 'truncate_setsize()' + * with @ui_mutex locked, because it would deadlock with 'ubifs_writepage()'. + * This means that @inode->i_size is changed while @ui_mutex is unlocked. * * XXX(truncate): with the new truncate sequence this is not true anymore, * and the calls to truncate_setsize can be move around freely. They should @@ -1432,10 +1432,11 @@ static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags) } /* - * mmap()d file has taken write protection fault and is being made - * writable. UBIFS must ensure page is budgeted for. + * mmap()d file has taken write protection fault and is being made writable. + * UBIFS must ensure page is budgeted for. */ -static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) +static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, + struct vm_fault *vmf) { struct page *page = vmf->page; struct inode *inode = vma->vm_file->f_path.dentry->d_inode; diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index dfd168b7807e..6cc09311a632 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -393,7 +393,7 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf) ubifs_assert(wbuf->size % c->min_io_size == 0); ubifs_assert(!c->ro_media && !c->ro_mount); if (c->leb_size - wbuf->offs >= c->max_write_size) - ubifs_assert(!((wbuf->offs + wbuf->size) % c->max_write_size )); + ubifs_assert(!((wbuf->offs + wbuf->size) % c->max_write_size)); if (c->ro_error) return -EROFS; @@ -588,7 +588,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) ubifs_assert(mutex_is_locked(&wbuf->io_mutex)); ubifs_assert(!c->ro_media && !c->ro_mount); if (c->leb_size - wbuf->offs >= c->max_write_size) - ubifs_assert(!((wbuf->offs + wbuf->size) % c->max_write_size )); + ubifs_assert(!((wbuf->offs + wbuf->size) % c->max_write_size)); if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) { err = -ENOSPC; diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c index 0c9c69bd983a..9fe376a039cd 100644 --- a/fs/ubifs/lpt_commit.c +++ b/fs/ubifs/lpt_commit.c @@ -586,7 +586,7 @@ static struct ubifs_pnode *next_pnode_to_dirty(struct ubifs_info *c, if (nnode->nbranch[iip].lnum) break; } - } while (iip >= UBIFS_LPT_FANOUT); + } while (iip >= UBIFS_LPT_FANOUT); /* Go right */ nnode = ubifs_get_nnode(c, nnode, iip); diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c index 09df318e368f..bd644bf587a8 100644 --- a/fs/ubifs/orphan.c +++ b/fs/ubifs/orphan.c @@ -673,7 +673,8 @@ static int kill_orphans(struct ubifs_info *c) sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1); if (IS_ERR(sleb)) { if (PTR_ERR(sleb) == -EUCLEAN) - sleb = ubifs_recover_leb(c, lnum, 0, c->sbuf, 0); + sleb = ubifs_recover_leb(c, lnum, 0, + c->sbuf, 0); if (IS_ERR(sleb)) { err = PTR_ERR(sleb); break; diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 04ad07f4fcc3..a089cca63436 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1144,7 +1144,7 @@ static int check_free_space(struct ubifs_info *c) { ubifs_assert(c->dark_wm > 0); if (c->lst.total_free + c->lst.total_dirty < c->dark_wm) { - ubifs_err("insufficient free space to mount in read/write mode"); + ubifs_err("insufficient free space to mount in R/W mode"); dbg_dump_budg(c); dbg_dump_lprops(c); return -ENOSPC; @@ -1456,7 +1456,7 @@ static int mount_ubifs(struct ubifs_info *c) dbg_msg("node sizes: ref %zu, cmt. start %zu, orph %zu", UBIFS_REF_NODE_SZ, UBIFS_CS_NODE_SZ, UBIFS_ORPH_NODE_SZ); dbg_msg("max. node sizes: data %zu, inode %zu dentry %zu, idx %d", - UBIFS_MAX_DATA_NODE_SZ, UBIFS_MAX_INO_NODE_SZ, + UBIFS_MAX_DATA_NODE_SZ, UBIFS_MAX_INO_NODE_SZ, UBIFS_MAX_DENT_NODE_SZ, ubifs_idx_node_sz(c, c->fanout)); dbg_msg("dead watermark: %d", c->dead_wm); dbg_msg("dark watermark: %d", c->dark_wm); diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index de485979ca39..8119b1fd8d94 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -2557,11 +2557,11 @@ int ubifs_tnc_remove_nm(struct ubifs_info *c, const union ubifs_key *key, if (err) { /* Ensure the znode is dirtied */ if (znode->cnext || !ubifs_zn_dirty(znode)) { - znode = dirty_cow_bottom_up(c, znode); - if (IS_ERR(znode)) { - err = PTR_ERR(znode); - goto out_unlock; - } + znode = dirty_cow_bottom_up(c, znode); + if (IS_ERR(znode)) { + err = PTR_ERR(znode); + goto out_unlock; + } } err = tnc_delete(c, znode, n); } diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 8c40ad3c6721..d4c07a9b8211 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -389,9 +389,9 @@ struct ubifs_gced_idx_leb { * The @ui_size is a "shadow" variable for @inode->i_size and UBIFS uses * @ui_size instead of @inode->i_size. The reason for this is that UBIFS cannot * make sure @inode->i_size is always changed under @ui_mutex, because it - * cannot call 'truncate_setsize()' with @ui_mutex locked, because it would deadlock - * with 'ubifs_writepage()' (see file.c). All the other inode fields are - * changed under @ui_mutex, so they do not need "shadow" fields. Note, one + * cannot call 'truncate_setsize()' with @ui_mutex locked, because it would + * deadlock with 'ubifs_writepage()' (see file.c). All the other inode fields + * are changed under @ui_mutex, so they do not need "shadow" fields. Note, one * could consider to rework locking and base it on "shadow" fields. */ struct ubifs_inode { -- 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/budget.c | 104 +++++++++++++++++++++++++------------------------- fs/ubifs/commit.c | 2 +- fs/ubifs/debug.c | 14 +++---- fs/ubifs/dir.c | 4 +- fs/ubifs/file.c | 4 +- fs/ubifs/find.c | 10 ++--- fs/ubifs/master.c | 8 ++-- fs/ubifs/replay.c | 8 ++-- fs/ubifs/super.c | 26 ++++++------- fs/ubifs/tnc_commit.c | 10 ++--- fs/ubifs/ubifs.h | 75 +++++++++++++++++++----------------- 11 files changed, 135 insertions(+), 130 deletions(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 8b3a7da531eb..315de66e52b2 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -106,7 +106,7 @@ static long long get_liability(struct ubifs_info *c) long long liab; spin_lock(&c->space_lock); - liab = c->budg_idx_growth + c->budg_data_growth + c->budg_dd_growth; + liab = c->bi.idx_growth + c->bi.data_growth + c->bi.dd_growth; spin_unlock(&c->space_lock); return liab; } @@ -180,7 +180,7 @@ int ubifs_calc_min_idx_lebs(struct ubifs_info *c) int idx_lebs; long long idx_size; - idx_size = c->old_idx_sz + c->budg_idx_growth + c->budg_uncommitted_idx; + idx_size = c->bi.old_idx_sz + c->bi.idx_growth + c->bi.uncommitted_idx; /* And make sure we have thrice the index size of space reserved */ idx_size += idx_size << 1; /* @@ -292,13 +292,13 @@ static int can_use_rp(struct ubifs_info *c) * budgeted index space to the size of the current index, multiplies this by 3, * and makes sure this does not exceed the amount of free LEBs. * - * Notes about @c->min_idx_lebs and @c->lst.idx_lebs variables: + * Notes about @c->bi.min_idx_lebs and @c->lst.idx_lebs variables: * o @c->lst.idx_lebs is the number of LEBs the index currently uses. It might * be large, because UBIFS does not do any index consolidation as long as * there is free space. IOW, the index may take a lot of LEBs, but the LEBs * will contain a lot of dirt. - * o @c->min_idx_lebs is the number of LEBS the index presumably takes. IOW, - * the index may be consolidated to take up to @c->min_idx_lebs LEBs. + * o @c->bi.min_idx_lebs is the number of LEBS the index presumably takes. IOW, + * the index may be consolidated to take up to @c->bi.min_idx_lebs LEBs. * * This function returns zero in case of success, and %-ENOSPC in case of * failure. @@ -343,13 +343,13 @@ static int do_budget_space(struct ubifs_info *c) c->lst.taken_empty_lebs; if (unlikely(rsvd_idx_lebs > lebs)) { dbg_budg("out of indexing space: min_idx_lebs %d (old %d), " - "rsvd_idx_lebs %d", min_idx_lebs, c->min_idx_lebs, + "rsvd_idx_lebs %d", min_idx_lebs, c->bi.min_idx_lebs, rsvd_idx_lebs); return -ENOSPC; } available = ubifs_calc_available(c, min_idx_lebs); - outstanding = c->budg_data_growth + c->budg_dd_growth; + outstanding = c->bi.data_growth + c->bi.dd_growth; if (unlikely(available < outstanding)) { dbg_budg("out of data space: available %lld, outstanding %lld", @@ -360,7 +360,7 @@ static int do_budget_space(struct ubifs_info *c) if (available - outstanding <= c->rp_size && !can_use_rp(c)) return -ENOSPC; - c->min_idx_lebs = min_idx_lebs; + c->bi.min_idx_lebs = min_idx_lebs; return 0; } @@ -393,11 +393,11 @@ static int calc_data_growth(const struct ubifs_info *c, { int data_growth; - data_growth = req->new_ino ? c->inode_budget : 0; + data_growth = req->new_ino ? c->bi.inode_budget : 0; if (req->new_page) - data_growth += c->page_budget; + data_growth += c->bi.page_budget; if (req->new_dent) - data_growth += c->dent_budget; + data_growth += c->bi.dent_budget; data_growth += req->new_ino_d; return data_growth; } @@ -413,12 +413,12 @@ static int calc_dd_growth(const struct ubifs_info *c, { int dd_growth; - dd_growth = req->dirtied_page ? c->page_budget : 0; + dd_growth = req->dirtied_page ? c->bi.page_budget : 0; if (req->dirtied_ino) - dd_growth += c->inode_budget << (req->dirtied_ino - 1); + dd_growth += c->bi.inode_budget << (req->dirtied_ino - 1); if (req->mod_dent) - dd_growth += c->dent_budget; + dd_growth += c->bi.dent_budget; dd_growth += req->dirtied_ino_d; return dd_growth; } @@ -460,19 +460,19 @@ int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req) again: spin_lock(&c->space_lock); - ubifs_assert(c->budg_idx_growth >= 0); - ubifs_assert(c->budg_data_growth >= 0); - ubifs_assert(c->budg_dd_growth >= 0); + ubifs_assert(c->bi.idx_growth >= 0); + ubifs_assert(c->bi.data_growth >= 0); + ubifs_assert(c->bi.dd_growth >= 0); - if (unlikely(c->nospace) && (c->nospace_rp || !can_use_rp(c))) { + if (unlikely(c->bi.nospace) && (c->bi.nospace_rp || !can_use_rp(c))) { dbg_budg("no space"); spin_unlock(&c->space_lock); return -ENOSPC; } - c->budg_idx_growth += idx_growth; - c->budg_data_growth += data_growth; - c->budg_dd_growth += dd_growth; + c->bi.idx_growth += idx_growth; + c->bi.data_growth += data_growth; + c->bi.dd_growth += dd_growth; err = do_budget_space(c); if (likely(!err)) { @@ -484,9 +484,9 @@ again: } /* Restore the old values */ - c->budg_idx_growth -= idx_growth; - c->budg_data_growth -= data_growth; - c->budg_dd_growth -= dd_growth; + c->bi.idx_growth -= idx_growth; + c->bi.data_growth -= data_growth; + c->bi.dd_growth -= dd_growth; spin_unlock(&c->space_lock); if (req->fast) { @@ -506,9 +506,9 @@ again: goto again; } dbg_budg("FS is full, -ENOSPC"); - c->nospace = 1; + c->bi.nospace = 1; if (can_use_rp(c) || c->rp_size == 0) - c->nospace_rp = 1; + c->bi.nospace_rp = 1; smp_wmb(); } else ubifs_err("cannot budget space, error %d", err); @@ -523,8 +523,8 @@ again: * This function releases the space budgeted by 'ubifs_budget_space()'. Note, * since the index changes (which were budgeted for in @req->idx_growth) will * only be written to the media on commit, this function moves the index budget - * from @c->budg_idx_growth to @c->budg_uncommitted_idx. The latter will be - * zeroed by the commit operation. + * from @c->bi.idx_growth to @c->bi.uncommitted_idx. The latter will be zeroed + * by the commit operation. */ void ubifs_release_budget(struct ubifs_info *c, struct ubifs_budget_req *req) { @@ -553,23 +553,23 @@ void ubifs_release_budget(struct ubifs_info *c, struct ubifs_budget_req *req) if (!req->data_growth && !req->dd_growth) return; - c->nospace = c->nospace_rp = 0; + c->bi.nospace = c->bi.nospace_rp = 0; smp_wmb(); spin_lock(&c->space_lock); - c->budg_idx_growth -= req->idx_growth; - c->budg_uncommitted_idx += req->idx_growth; - c->budg_data_growth -= req->data_growth; - c->budg_dd_growth -= req->dd_growth; - c->min_idx_lebs = ubifs_calc_min_idx_lebs(c); - - ubifs_assert(c->budg_idx_growth >= 0); - ubifs_assert(c->budg_data_growth >= 0); - ubifs_assert(c->budg_dd_growth >= 0); - ubifs_assert(c->min_idx_lebs < c->main_lebs); - ubifs_assert(!(c->budg_idx_growth & 7)); - ubifs_assert(!(c->budg_data_growth & 7)); - ubifs_assert(!(c->budg_dd_growth & 7)); + c->bi.idx_growth -= req->idx_growth; + c->bi.uncommitted_idx += req->idx_growth; + c->bi.data_growth -= req->data_growth; + c->bi.dd_growth -= req->dd_growth; + c->bi.min_idx_lebs = ubifs_calc_min_idx_lebs(c); + + ubifs_assert(c->bi.idx_growth >= 0); + ubifs_assert(c->bi.data_growth >= 0); + ubifs_assert(c->bi.dd_growth >= 0); + ubifs_assert(c->bi.min_idx_lebs < c->main_lebs); + ubifs_assert(!(c->bi.idx_growth & 7)); + ubifs_assert(!(c->bi.data_growth & 7)); + ubifs_assert(!(c->bi.dd_growth & 7)); spin_unlock(&c->space_lock); } @@ -586,13 +586,13 @@ void ubifs_convert_page_budget(struct ubifs_info *c) { spin_lock(&c->space_lock); /* Release the index growth reservation */ - c->budg_idx_growth -= c->max_idx_node_sz << UBIFS_BLOCKS_PER_PAGE_SHIFT; + c->bi.idx_growth -= c->max_idx_node_sz << UBIFS_BLOCKS_PER_PAGE_SHIFT; /* Release the data growth reservation */ - c->budg_data_growth -= c->page_budget; + c->bi.data_growth -= c->bi.page_budget; /* Increase the dirty data growth reservation instead */ - c->budg_dd_growth += c->page_budget; + c->bi.dd_growth += c->bi.page_budget; /* And re-calculate the indexing space reservation */ - c->min_idx_lebs = ubifs_calc_min_idx_lebs(c); + c->bi.min_idx_lebs = ubifs_calc_min_idx_lebs(c); spin_unlock(&c->space_lock); } @@ -612,7 +612,7 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c, memset(&req, 0, sizeof(struct ubifs_budget_req)); /* The "no space" flags will be cleared because dd_growth is > 0 */ - req.dd_growth = c->inode_budget + ALIGN(ui->data_len, 8); + req.dd_growth = c->bi.inode_budget + ALIGN(ui->data_len, 8); ubifs_release_budget(c, &req); } @@ -682,9 +682,9 @@ long long ubifs_get_free_space_nolock(struct ubifs_info *c) int rsvd_idx_lebs, lebs; long long available, outstanding, free; - ubifs_assert(c->min_idx_lebs == ubifs_calc_min_idx_lebs(c)); - outstanding = c->budg_data_growth + c->budg_dd_growth; - available = ubifs_calc_available(c, c->min_idx_lebs); + ubifs_assert(c->bi.min_idx_lebs == ubifs_calc_min_idx_lebs(c)); + outstanding = c->bi.data_growth + c->bi.dd_growth; + available = ubifs_calc_available(c, c->bi.min_idx_lebs); /* * When reporting free space to user-space, UBIFS guarantees that it is @@ -697,8 +697,8 @@ long long ubifs_get_free_space_nolock(struct ubifs_info *c) * Note, the calculations below are similar to what we have in * 'do_budget_space()', so refer there for comments. */ - if (c->min_idx_lebs > c->lst.idx_lebs) - rsvd_idx_lebs = c->min_idx_lebs - c->lst.idx_lebs; + if (c->bi.min_idx_lebs > c->lst.idx_lebs) + rsvd_idx_lebs = c->bi.min_idx_lebs - c->lst.idx_lebs; else rsvd_idx_lebs = 0; lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c index 1bd01ded7123..87cd0ead8633 100644 --- a/fs/ubifs/commit.c +++ b/fs/ubifs/commit.c @@ -182,7 +182,7 @@ static int do_commit(struct ubifs_info *c) c->mst_node->root_len = cpu_to_le32(zroot.len); c->mst_node->ihead_lnum = cpu_to_le32(c->ihead_lnum); c->mst_node->ihead_offs = cpu_to_le32(c->ihead_offs); - c->mst_node->index_size = cpu_to_le64(c->old_idx_sz); + c->mst_node->index_size = cpu_to_le64(c->bi.old_idx_sz); c->mst_node->lpt_lnum = cpu_to_le32(c->lpt_lnum); c->mst_node->lpt_offs = cpu_to_le32(c->lpt_offs); c->mst_node->nhead_lnum = cpu_to_le32(c->nhead_lnum); 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", diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 7217d67a80a6..ef5abd38f0bf 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -603,7 +603,7 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry) ubifs_release_budget(c, &req); else { /* We've deleted something - clean the "no space" flags */ - c->nospace = c->nospace_rp = 0; + c->bi.nospace = c->bi.nospace_rp = 0; smp_wmb(); } return 0; @@ -693,7 +693,7 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry) ubifs_release_budget(c, &req); else { /* We've deleted something - clean the "no space" flags */ - c->nospace = c->nospace_rp = 0; + c->bi.nospace = c->bi.nospace_rp = 0; smp_wmb(); } return 0; diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 3f254e37b25b..3594aae12a88 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -212,7 +212,7 @@ static void release_new_page_budget(struct ubifs_info *c) */ static void release_existing_page_budget(struct ubifs_info *c) { - struct ubifs_budget_req req = { .dd_growth = c->page_budget}; + struct ubifs_budget_req req = { .dd_growth = c->bi.page_budget}; ubifs_release_budget(c, &req); } @@ -1189,7 +1189,7 @@ out_budg: if (budgeted) ubifs_release_budget(c, &req); else { - c->nospace = c->nospace_rp = 0; + c->bi.nospace = c->bi.nospace_rp = 0; smp_wmb(); } return err; diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c index 1d54383d1269..2559d174e004 100644 --- a/fs/ubifs/find.c +++ b/fs/ubifs/find.c @@ -252,8 +252,8 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp, * But if the index takes fewer LEBs than it is reserved for it, * this function must avoid picking those reserved LEBs. */ - if (c->min_idx_lebs >= c->lst.idx_lebs) { - rsvd_idx_lebs = c->min_idx_lebs - c->lst.idx_lebs; + if (c->bi.min_idx_lebs >= c->lst.idx_lebs) { + rsvd_idx_lebs = c->bi.min_idx_lebs - c->lst.idx_lebs; exclude_index = 1; } spin_unlock(&c->space_lock); @@ -276,7 +276,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp, pick_free = 0; } else { spin_lock(&c->space_lock); - exclude_index = (c->min_idx_lebs >= c->lst.idx_lebs); + exclude_index = (c->bi.min_idx_lebs >= c->lst.idx_lebs); spin_unlock(&c->space_lock); } @@ -501,8 +501,8 @@ int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *offs, /* Check if there are enough empty LEBs for commit */ spin_lock(&c->space_lock); - if (c->min_idx_lebs > c->lst.idx_lebs) - rsvd_idx_lebs = c->min_idx_lebs - c->lst.idx_lebs; + if (c->bi.min_idx_lebs > c->lst.idx_lebs) + rsvd_idx_lebs = c->bi.min_idx_lebs - c->lst.idx_lebs; else rsvd_idx_lebs = 0; lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c index 21f47afdacff..278c2382e8c2 100644 --- a/fs/ubifs/master.c +++ b/fs/ubifs/master.c @@ -148,7 +148,7 @@ static int validate_master(const struct ubifs_info *c) } main_sz = (long long)c->main_lebs * c->leb_size; - if (c->old_idx_sz & 7 || c->old_idx_sz >= main_sz) { + if (c->bi.old_idx_sz & 7 || c->bi.old_idx_sz >= main_sz) { err = 9; goto out; } @@ -218,7 +218,7 @@ static int validate_master(const struct ubifs_info *c) } if (c->lst.total_dead + c->lst.total_dark + - c->lst.total_used + c->old_idx_sz > main_sz) { + c->lst.total_used + c->bi.old_idx_sz > main_sz) { err = 21; goto out; } @@ -286,7 +286,7 @@ int ubifs_read_master(struct ubifs_info *c) c->gc_lnum = le32_to_cpu(c->mst_node->gc_lnum); c->ihead_lnum = le32_to_cpu(c->mst_node->ihead_lnum); c->ihead_offs = le32_to_cpu(c->mst_node->ihead_offs); - c->old_idx_sz = le64_to_cpu(c->mst_node->index_size); + c->bi.old_idx_sz = le64_to_cpu(c->mst_node->index_size); c->lpt_lnum = le32_to_cpu(c->mst_node->lpt_lnum); c->lpt_offs = le32_to_cpu(c->mst_node->lpt_offs); c->nhead_lnum = le32_to_cpu(c->mst_node->nhead_lnum); @@ -305,7 +305,7 @@ int ubifs_read_master(struct ubifs_info *c) c->lst.total_dead = le64_to_cpu(c->mst_node->total_dead); c->lst.total_dark = le64_to_cpu(c->mst_node->total_dark); - c->calc_idx_sz = c->old_idx_sz; + c->calc_idx_sz = c->bi.old_idx_sz; if (c->mst_node->flags & cpu_to_le32(UBIFS_MST_NO_ORPHS)) c->no_orphs = 1; diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c index d3d6d365bfc1..c29c4687cc52 100644 --- a/fs/ubifs/replay.c +++ b/fs/ubifs/replay.c @@ -1065,13 +1065,13 @@ int ubifs_replay_journal(struct ubifs_info *c) goto out; /* - * UBIFS budgeting calculations use @c->budg_uncommitted_idx variable - * to roughly estimate index growth. Things like @c->min_idx_lebs + * UBIFS budgeting calculations use @c->bi.uncommitted_idx variable + * to roughly estimate index growth. Things like @c->bi.min_idx_lebs * depend on it. This means we have to initialize it to make sure * budgeting works properly. */ - c->budg_uncommitted_idx = atomic_long_read(&c->dirty_zn_cnt); - c->budg_uncommitted_idx *= c->max_idx_node_sz; + c->bi.uncommitted_idx = atomic_long_read(&c->dirty_zn_cnt); + c->bi.uncommitted_idx *= c->max_idx_node_sz; ubifs_assert(c->bud_bytes <= c->max_bud_bytes || c->need_recovery); dbg_mnt("finished, log head LEB %d:%d, max_sqnum %llu, " diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index a089cca63436..a0aa95117ea1 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -375,7 +375,7 @@ out: ubifs_release_dirty_inode_budget(c, ui); else { /* We've deleted something - clean the "no space" flags */ - c->nospace = c->nospace_rp = 0; + c->bi.nospace = c->bi.nospace_rp = 0; smp_wmb(); } done: @@ -694,11 +694,11 @@ static int init_constants_sb(struct ubifs_info *c) * be compressed and direntries are of the maximum size. * * Note, data, which may be stored in inodes is budgeted separately, so - * it is not included into 'c->inode_budget'. + * it is not included into 'c->bi.inode_budget'. */ - c->page_budget = UBIFS_MAX_DATA_NODE_SZ * UBIFS_BLOCKS_PER_PAGE; - c->inode_budget = UBIFS_INO_NODE_SZ; - c->dent_budget = UBIFS_MAX_DENT_NODE_SZ; + c->bi.page_budget = UBIFS_MAX_DATA_NODE_SZ * UBIFS_BLOCKS_PER_PAGE; + c->bi.inode_budget = UBIFS_INO_NODE_SZ; + c->bi.dent_budget = UBIFS_MAX_DENT_NODE_SZ; /* * When the amount of flash space used by buds becomes @@ -742,7 +742,7 @@ static void init_constants_master(struct ubifs_info *c) { long long tmp64; - c->min_idx_lebs = ubifs_calc_min_idx_lebs(c); + c->bi.min_idx_lebs = ubifs_calc_min_idx_lebs(c); c->report_rp_size = ubifs_reported_space(c, c->rp_size); /* @@ -1304,7 +1304,7 @@ static int mount_ubifs(struct ubifs_info *c) if (err) goto out_lpt; - err = dbg_check_idx_size(c, c->old_idx_sz); + err = dbg_check_idx_size(c, c->bi.old_idx_sz); if (err) goto out_lpt; @@ -1313,7 +1313,7 @@ static int mount_ubifs(struct ubifs_info *c) goto out_journal; /* Calculate 'min_idx_lebs' after journal replay */ - c->min_idx_lebs = ubifs_calc_min_idx_lebs(c); + c->bi.min_idx_lebs = ubifs_calc_min_idx_lebs(c); err = ubifs_mount_orphans(c, c->need_recovery, c->ro_mount); if (err) @@ -1442,7 +1442,8 @@ static int mount_ubifs(struct ubifs_info *c) c->main_lebs, c->main_first, c->leb_cnt - 1); dbg_msg("index LEBs: %d", c->lst.idx_lebs); dbg_msg("total index bytes: %lld (%lld KiB, %lld MiB)", - c->old_idx_sz, c->old_idx_sz >> 10, c->old_idx_sz >> 20); + c->bi.old_idx_sz, c->bi.old_idx_sz >> 10, + c->bi.old_idx_sz >> 20); dbg_msg("key hash type: %d", c->key_hash_type); dbg_msg("tree fanout: %d", c->fanout); dbg_msg("reserved GC LEB: %d", c->gc_lnum); @@ -1766,10 +1767,9 @@ static void ubifs_put_super(struct super_block *sb) * to write them back because of I/O errors. */ if (!c->ro_error) { - ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0); - ubifs_assert(c->budg_idx_growth == 0); - ubifs_assert(c->budg_dd_growth == 0); - ubifs_assert(c->budg_data_growth == 0); + ubifs_assert(c->bi.idx_growth == 0); + ubifs_assert(c->bi.dd_growth == 0); + ubifs_assert(c->bi.data_growth == 0); } /* diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c index 53288e5d604e..9c376b9e74ff 100644 --- a/fs/ubifs/tnc_commit.c +++ b/fs/ubifs/tnc_commit.c @@ -796,16 +796,16 @@ int ubifs_tnc_start_commit(struct ubifs_info *c, struct ubifs_zbranch *zroot) spin_lock(&c->space_lock); /* * Although we have not finished committing yet, update size of the - * committed index ('c->old_idx_sz') and zero out the index growth + * committed index ('c->bi.old_idx_sz') and zero out the index growth * budget. It is OK to do this now, because we've reserved all the * space which is needed to commit the index, and it is save for the * budgeting subsystem to assume the index is already committed, * even though it is not. */ - ubifs_assert(c->min_idx_lebs == ubifs_calc_min_idx_lebs(c)); - c->old_idx_sz = c->calc_idx_sz; - c->budg_uncommitted_idx = 0; - c->min_idx_lebs = ubifs_calc_min_idx_lebs(c); + ubifs_assert(c->bi.min_idx_lebs == ubifs_calc_min_idx_lebs(c)); + c->bi.old_idx_sz = c->calc_idx_sz; + c->bi.uncommitted_idx = 0; + c->bi.min_idx_lebs = ubifs_calc_min_idx_lebs(c); spin_unlock(&c->space_lock); mutex_unlock(&c->tnc_mutex); diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index d4c07a9b8211..26a7ebe56d2e 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -937,6 +937,40 @@ struct ubifs_mount_opts { unsigned int compr_type:2; }; +/** + * struct ubifs_budg_info - UBIFS budgeting information. + * @idx_growth: amount of bytes budgeted for index growth + * @data_growth: amount of bytes budgeted for cached data + * @dd_growth: amount of bytes budgeted for cached data that will make + * other data dirty + * @uncommitted_idx: amount of bytes were budgeted for growth of the index, but + * which still have to be taken into account because the index + * has not been committed so far + * @old_idx_sz: size of index on flash + * @min_idx_lebs: minimum number of LEBs required for the index + * @nospace: non-zero if the file-system does not have flash space (used as + * optimization) + * @nospace_rp: the same as @nospace, but additionally means that even reserved + * pool is full + * @page_budget: budget for a page (constant, nenver changed after mount) + * @inode_budget: budget for an inode (constant, nenver changed after mount) + * @dent_budget: budget for a directory entry (constant, nenver changed after + * mount) + */ +struct ubifs_budg_info { + long long idx_growth; + long long data_growth; + long long dd_growth; + long long uncommitted_idx; + unsigned long long old_idx_sz; + int min_idx_lebs; + unsigned int nospace:1; + unsigned int nospace_rp:1; + int page_budget; + int inode_budget; + int dent_budget; +}; + struct ubifs_debug_info; /** @@ -1057,32 +1091,14 @@ struct ubifs_debug_info; * @dirty_zn_cnt: number of dirty znodes * @clean_zn_cnt: number of clean znodes * - * @budg_idx_growth: amount of bytes budgeted for index growth - * @budg_data_growth: amount of bytes budgeted for cached data - * @budg_dd_growth: amount of bytes budgeted for cached data that will make - * other data dirty - * @budg_uncommitted_idx: amount of bytes were budgeted for growth of the index, - * but which still have to be taken into account because - * the index has not been committed so far - * @space_lock: protects @budg_idx_growth, @budg_data_growth, @budg_dd_growth, - * @budg_uncommited_idx, @min_idx_lebs, @old_idx_sz, @lst, - * @nospace, and @nospace_rp; - * @min_idx_lebs: minimum number of LEBs required for the index - * @old_idx_sz: size of index on flash + * @space_lock: protects @bi and @lst + * @lst: lprops statistics + * @bi: budgeting information * @calc_idx_sz: temporary variable which is used to calculate new index size * (contains accurate new index size at end of TNC commit start) - * @lst: lprops statistics - * @nospace: non-zero if the file-system does not have flash space (used as - * optimization) - * @nospace_rp: the same as @nospace, but additionally means that even reserved - * pool is full - * - * @page_budget: budget for a page - * @inode_budget: budget for an inode - * @dent_budget: budget for a directory entry * * @ref_node_alsz: size of the LEB reference node aligned to the min. flash - * I/O unit + * I/O unit * @mst_node_alsz: master node aligned size * @min_idx_node_sz: minimum indexing node aligned on 8-bytes boundary * @max_idx_node_sz: maximum indexing node aligned on 8-bytes boundary @@ -1308,21 +1324,10 @@ struct ubifs_info { atomic_long_t dirty_zn_cnt; atomic_long_t clean_zn_cnt; - long long budg_idx_growth; - long long budg_data_growth; - long long budg_dd_growth; - long long budg_uncommitted_idx; spinlock_t space_lock; - int min_idx_lebs; - unsigned long long old_idx_sz; - unsigned long long calc_idx_sz; struct ubifs_lp_stats lst; - unsigned int nospace:1; - unsigned int nospace_rp:1; - - int page_budget; - int inode_budget; - int dent_budget; + struct ubifs_budg_info bi; + unsigned long long calc_idx_sz; int ref_node_alsz; int mst_node_alsz; -- 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 ++++-------- fs/ubifs/journal.c | 2 -- fs/ubifs/tnc_commit.c | 2 -- 3 files changed, 4 insertions(+), 12 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); diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index aed25e864227..65d485fc1eeb 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -380,10 +380,8 @@ out: if (err == -ENOSPC) { /* This are some budgeting problems, print useful information */ down_write(&c->commit_sem); - spin_lock(&c->space_lock); dbg_dump_stack(); dbg_dump_budg(c); - spin_unlock(&c->space_lock); dbg_dump_lprops(c); cmt_retries = dbg_check_lprops(c); up_write(&c->commit_sem); diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c index 9c376b9e74ff..66f066de2c57 100644 --- a/fs/ubifs/tnc_commit.c +++ b/fs/ubifs/tnc_commit.c @@ -383,9 +383,7 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt) * option which forces in-the-gaps is enabled. */ ubifs_err("out of space"); - spin_lock(&c->space_lock); dbg_dump_budg(c); - spin_unlock(&c->space_lock); dbg_dump_lprops(c); } /* Try to commit anyway */ -- 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 +++++++++++++++++++++++++++++------------- fs/ubifs/debug.h | 12 +++++++++--- fs/ubifs/journal.c | 2 +- fs/ubifs/super.c | 2 +- fs/ubifs/tnc_commit.c | 2 +- 5 files changed, 41 insertions(+), 19 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); diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index e6493cac193d..6b5fe7ba0296 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h @@ -50,7 +50,9 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c, * @new_ihead_offs: used by debugging to check @c->ihead_offs * * @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: direntry object of the file-system debugfs directory @@ -76,7 +78,9 @@ struct ubifs_debug_info { int new_ihead_offs; struct ubifs_lp_stats saved_lst; + struct ubifs_budg_info saved_bi; long long saved_free; + int saved_idx_gc_cnt; char dfs_dir_name[100]; struct dentry *dfs_dir; @@ -262,7 +266,7 @@ void dbg_dump_lpt_node(const struct ubifs_info *c, void *node, int lnum, int offs); void dbg_dump_budget_req(const struct ubifs_budget_req *req); 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_lprops(struct ubifs_info *c); void dbg_dump_lpt_info(struct ubifs_info *c); @@ -420,7 +424,9 @@ static inline void dbg_dump_budget_req(const struct ubifs_budget_req *req) { return; } static inline void 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, const struct ubifs_lprops *lp) { return; } static inline void dbg_dump_lprops(struct ubifs_info *c) { return; } diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 65d485fc1eeb..ce55a4807cdc 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -381,7 +381,7 @@ out: /* This are some budgeting problems, print useful information */ down_write(&c->commit_sem); dbg_dump_stack(); - dbg_dump_budg(c); + dbg_dump_budg(c, &c->bi); dbg_dump_lprops(c); cmt_retries = dbg_check_lprops(c); up_write(&c->commit_sem); diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index a0aa95117ea1..407c064fb1c1 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1145,7 +1145,7 @@ static int check_free_space(struct ubifs_info *c) ubifs_assert(c->dark_wm > 0); if (c->lst.total_free + c->lst.total_dirty < c->dark_wm) { 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); return -ENOSPC; } diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c index 66f066de2c57..c471b06798c8 100644 --- a/fs/ubifs/tnc_commit.c +++ b/fs/ubifs/tnc_commit.c @@ -383,7 +383,7 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt) * option which forces in-the-gaps is enabled. */ ubifs_err("out of space"); - dbg_dump_budg(c); + dbg_dump_budg(c, &c->bi); dbg_dump_lprops(c); } /* Try to commit anyway */ -- 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 --- Documentation/filesystems/ubifs.txt | 1 - fs/ubifs/debug.c | 9 +++------ fs/ubifs/debug.h | 19 ++++++++----------- fs/ubifs/tnc_commit.c | 4 ++-- 4 files changed, 13 insertions(+), 20 deletions(-) (limited to 'fs/ubifs/debug.c') diff --git a/Documentation/filesystems/ubifs.txt b/Documentation/filesystems/ubifs.txt index d7b13b01e980..7d17e5b91ff4 100644 --- a/Documentation/filesystems/ubifs.txt +++ b/Documentation/filesystems/ubifs.txt @@ -154,7 +154,6 @@ debug_tsts Selects a mode of testing, as follows: Test mode Flag value - Force in-the-gaps method 2 Failure mode for recovery testing 4 For example, set debug_msgs to 5 to display General messages and Mount 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 */ diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index 6b5fe7ba0296..8934c12f108e 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h @@ -31,6 +31,8 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c, #ifdef CONFIG_UBIFS_FS_DEBUG +#include + /** * ubifs_debug_info - per-FS debugging information. * @old_zroot: old index root - used by 'dbg_check_old_index()' @@ -237,11 +239,9 @@ enum { /* * Special testing flags. * - * UBIFS_TST_FORCE_IN_THE_GAPS: force the use of in-the-gaps method * UBIFS_TST_RCVRY: failure mode for recovery testing */ enum { - UBIFS_TST_FORCE_IN_THE_GAPS = 0x2, UBIFS_TST_RCVRY = 0x4, }; @@ -308,18 +308,16 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head); int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head); /* Force the use of in-the-gaps method for testing */ - -#define dbg_force_in_the_gaps_enabled \ - (ubifs_tst_flags & UBIFS_TST_FORCE_IN_THE_GAPS) - +static inline int dbg_force_in_the_gaps_enabled(void) +{ + return ubifs_chk_flags & UBIFS_CHK_GEN; +} int dbg_force_in_the_gaps(void); /* Failure mode for recovery testing */ - #define dbg_failure_mode (ubifs_tst_flags & UBIFS_TST_RCVRY) #ifndef UBIFS_DBG_PRESERVE_UBI - #define ubi_leb_read dbg_leb_read #define ubi_leb_write dbg_leb_write #define ubi_leb_change dbg_leb_change @@ -327,7 +325,6 @@ int dbg_force_in_the_gaps(void); #define ubi_leb_unmap dbg_leb_unmap #define ubi_is_mapped dbg_is_mapped #define ubi_leb_map dbg_leb_map - #endif int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, @@ -488,8 +485,8 @@ dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head) { return 0; } static inline int dbg_force_in_the_gaps(void) { return 0; } -#define dbg_force_in_the_gaps_enabled 0 -#define dbg_failure_mode 0 +#define dbg_force_in_the_gaps_enabled() 0 +#define dbg_failure_mode 0 static inline int dbg_debugfs_init(void) { return 0; } static inline void dbg_debugfs_exit(void) { return; } diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c index c471b06798c8..41920f357bbf 100644 --- a/fs/ubifs/tnc_commit.c +++ b/fs/ubifs/tnc_commit.c @@ -377,12 +377,12 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt) c->gap_lebs = NULL; return err; } - if (!dbg_force_in_the_gaps_enabled) { + if (dbg_force_in_the_gaps_enabled()) { /* * Do not print scary warnings if the debugging * option which forces in-the-gaps is enabled. */ - ubifs_err("out of space"); + ubifs_warn("out of space"); dbg_dump_budg(c, &c->bi); dbg_dump_lprops(c); } -- 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 ++ fs/ubifs/sb.c | 1 + fs/ubifs/ubifs-media.h | 2 ++ fs/ubifs/ubifs.h | 2 ++ 4 files changed, 7 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", diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index cad60b51f7c4..93d69289d6f4 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c @@ -617,6 +617,7 @@ int ubifs_read_superblock(struct ubifs_info *c) c->vfs_sb->s_time_gran = le32_to_cpu(sup->time_gran); memcpy(&c->uuid, &sup->uuid, 16); c->big_lpt = !!(sup_flags & UBIFS_FLG_BIGLPT); + c->space_fixup = !!(sup_flags & UBIFS_FLG_SPACE_FIXUP); /* Automatically increase file system size to the maximum size */ c->old_leb_cnt = c->leb_cnt; diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h index b922f03c31ae..e24380cf46ed 100644 --- a/fs/ubifs/ubifs-media.h +++ b/fs/ubifs/ubifs-media.h @@ -408,9 +408,11 @@ enum { * Superblock flags. * * UBIFS_FLG_BIGLPT: if "big" LPT model is used if set + * UBIFS_FLG_SPACE_FIXUP: first-mount "fixup" of free space within LEBs needed */ enum { UBIFS_FLG_BIGLPT = 0x02, + UBIFS_FLG_SPACE_FIXUP = 0x04, }; /** diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index a2f9d4e3519f..8e27553e9655 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1014,6 +1014,7 @@ struct ubifs_debug_info; * @cmt_wq: wait queue to sleep on if the log is full and a commit is running * * @big_lpt: flag that LPT is too big to write whole during commit + * @space_fixup: flag indicating that free space in LEBs needs to be cleaned up * @no_chk_data_crc: do not check CRCs when reading data nodes (except during * recovery) * @bulk_read: enable bulk-reads @@ -1253,6 +1254,7 @@ struct ubifs_info { wait_queue_head_t cmt_wq; unsigned int big_lpt:1; + unsigned int space_fixup:1; unsigned int no_chk_data_crc:1; unsigned int bulk_read:1; unsigned int default_compr:2; -- 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 --- Documentation/filesystems/ubifs.txt | 25 +------ fs/ubifs/debug.c | 3 - fs/ubifs/debug.h | 132 +++++++++++------------------------- 3 files changed, 43 insertions(+), 117 deletions(-) (limited to 'fs/ubifs/debug.c') diff --git a/Documentation/filesystems/ubifs.txt b/Documentation/filesystems/ubifs.txt index 7d17e5b91ff4..8e4fab639d9c 100644 --- a/Documentation/filesystems/ubifs.txt +++ b/Documentation/filesystems/ubifs.txt @@ -115,28 +115,8 @@ ubi.mtd=0 root=ubi0:rootfs rootfstype=ubifs Module Parameters for Debugging =============================== -When UBIFS has been compiled with debugging enabled, there are 3 module +When UBIFS has been compiled with debugging enabled, there are 2 module parameters that are available to control aspects of testing and debugging. -The parameters are unsigned integers where each bit controls an option. -The parameters are: - -debug_msgs Selects which debug messages to display, as follows: - - Message Type Flag value - - General messages 1 - Journal messages 2 - Mount messages 4 - Commit messages 8 - LEB search messages 16 - Budgeting messages 32 - Garbage collection messages 64 - Tree Node Cache (TNC) messages 128 - LEB properties (lprops) messages 256 - Input/output messages 512 - Log messages 1024 - Scan messages 2048 - Recovery messages 4096 debug_chks Selects extra checks that UBIFS can do while running: @@ -156,8 +136,7 @@ debug_tsts Selects a mode of testing, as follows: Failure mode for recovery testing 4 -For example, set debug_msgs to 5 to display General messages and Mount -messages. +For example, set debug_chks to 3 to enable general and TNC checks. References 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"); diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index 7538bf23c243..a811ac4a26bb 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h @@ -109,19 +109,6 @@ struct ubifs_debug_info { #define dbg_dump_stack() dump_stack() -/* Generic debugging messages */ -#define dbg_msg(fmt, ...) do { \ - spin_lock(&dbg_lock); \ - printk(KERN_DEBUG "UBIFS DBG (pid %d): %s: " fmt "\n", current->pid, \ - __func__, ##__VA_ARGS__); \ - spin_unlock(&dbg_lock); \ -} while (0) - -#define dbg_do_msg(typ, fmt, ...) do { \ - if (ubifs_msg_flags & typ) \ - dbg_msg(fmt, ##__VA_ARGS__); \ -} while (0) - #define dbg_err(fmt, ...) do { \ spin_lock(&dbg_lock); \ ubifs_err(fmt, ##__VA_ARGS__); \ @@ -140,77 +127,40 @@ const char *dbg_key_str1(const struct ubifs_info *c, #define DBGKEY(key) dbg_key_str0(c, (key)) #define DBGKEY1(key) dbg_key_str1(c, (key)) -/* General messages */ -#define dbg_gen(fmt, ...) dbg_do_msg(UBIFS_MSG_GEN, fmt, ##__VA_ARGS__) +#define ubifs_dbg_msg(type, fmt, ...) do { \ + spin_lock(&dbg_lock); \ + pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__); \ + spin_unlock(&dbg_lock); \ +} while (0) +/* Just a debugging messages not related to any specific UBIFS subsystem */ +#define dbg_msg(fmt, ...) ubifs_dbg_msg("msg", fmt, ##__VA_ARGS__) +/* General messages */ +#define dbg_gen(fmt, ...) ubifs_dbg_msg("gen", fmt, ##__VA_ARGS__) /* Additional journal messages */ -#define dbg_jnl(fmt, ...) dbg_do_msg(UBIFS_MSG_JNL, fmt, ##__VA_ARGS__) - +#define dbg_jnl(fmt, ...) ubifs_dbg_msg("jnl", fmt, ##__VA_ARGS__) /* Additional TNC messages */ -#define dbg_tnc(fmt, ...) dbg_do_msg(UBIFS_MSG_TNC, fmt, ##__VA_ARGS__) - +#define dbg_tnc(fmt, ...) ubifs_dbg_msg("tnc", fmt, ##__VA_ARGS__) /* Additional lprops messages */ -#define dbg_lp(fmt, ...) dbg_do_msg(UBIFS_MSG_LP, fmt, ##__VA_ARGS__) - +#define dbg_lp(fmt, ...) ubifs_dbg_msg("lp", fmt, ##__VA_ARGS__) /* Additional LEB find messages */ -#define dbg_find(fmt, ...) dbg_do_msg(UBIFS_MSG_FIND, fmt, ##__VA_ARGS__) - +#define dbg_find(fmt, ...) ubifs_dbg_msg("find", fmt, ##__VA_ARGS__) /* Additional mount messages */ -#define dbg_mnt(fmt, ...) dbg_do_msg(UBIFS_MSG_MNT, fmt, ##__VA_ARGS__) - +#define dbg_mnt(fmt, ...) ubifs_dbg_msg("mnt", fmt, ##__VA_ARGS__) /* Additional I/O messages */ -#define dbg_io(fmt, ...) dbg_do_msg(UBIFS_MSG_IO, fmt, ##__VA_ARGS__) - +#define dbg_io(fmt, ...) ubifs_dbg_msg("io", fmt, ##__VA_ARGS__) /* Additional commit messages */ -#define dbg_cmt(fmt, ...) dbg_do_msg(UBIFS_MSG_CMT, fmt, ##__VA_ARGS__) - +#define dbg_cmt(fmt, ...) ubifs_dbg_msg("cmt", fmt, ##__VA_ARGS__) /* Additional budgeting messages */ -#define dbg_budg(fmt, ...) dbg_do_msg(UBIFS_MSG_BUDG, fmt, ##__VA_ARGS__) - +#define dbg_budg(fmt, ...) ubifs_dbg_msg("budg", fmt, ##__VA_ARGS__) /* Additional log messages */ -#define dbg_log(fmt, ...) dbg_do_msg(UBIFS_MSG_LOG, fmt, ##__VA_ARGS__) - +#define dbg_log(fmt, ...) ubifs_dbg_msg("log", fmt, ##__VA_ARGS__) /* Additional gc messages */ -#define dbg_gc(fmt, ...) dbg_do_msg(UBIFS_MSG_GC, fmt, ##__VA_ARGS__) - +#define dbg_gc(fmt, ...) ubifs_dbg_msg("gc", fmt, ##__VA_ARGS__) /* Additional scan messages */ -#define dbg_scan(fmt, ...) dbg_do_msg(UBIFS_MSG_SCAN, fmt, ##__VA_ARGS__) - +#define dbg_scan(fmt, ...) ubifs_dbg_msg("scan", fmt, ##__VA_ARGS__) /* Additional recovery messages */ -#define dbg_rcvry(fmt, ...) dbg_do_msg(UBIFS_MSG_RCVRY, fmt, ##__VA_ARGS__) - -/* - * Debugging message type flags. - * - * UBIFS_MSG_GEN: general messages - * UBIFS_MSG_JNL: journal messages - * UBIFS_MSG_MNT: mount messages - * UBIFS_MSG_CMT: commit messages - * UBIFS_MSG_FIND: LEB find messages - * UBIFS_MSG_BUDG: budgeting messages - * UBIFS_MSG_GC: garbage collection messages - * UBIFS_MSG_TNC: TNC messages - * UBIFS_MSG_LP: lprops messages - * UBIFS_MSG_IO: I/O messages - * UBIFS_MSG_LOG: log messages - * UBIFS_MSG_SCAN: scan messages - * UBIFS_MSG_RCVRY: recovery messages - */ -enum { - UBIFS_MSG_GEN = 0x1, - UBIFS_MSG_JNL = 0x2, - UBIFS_MSG_MNT = 0x4, - UBIFS_MSG_CMT = 0x8, - UBIFS_MSG_FIND = 0x10, - UBIFS_MSG_BUDG = 0x20, - UBIFS_MSG_GC = 0x40, - UBIFS_MSG_TNC = 0x80, - UBIFS_MSG_LP = 0x100, - UBIFS_MSG_IO = 0x200, - UBIFS_MSG_LOG = 0x400, - UBIFS_MSG_SCAN = 0x800, - UBIFS_MSG_RCVRY = 0x1000, -}; +#define dbg_rcvry(fmt, ...) ubifs_dbg_msg("rcvry", fmt, ##__VA_ARGS__) /* * Debugging check flags. @@ -368,33 +318,33 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c); __func__, __LINE__, current->pid); \ } while (0) -#define dbg_err(fmt, ...) do { \ - if (0) \ - ubifs_err(fmt, ##__VA_ARGS__); \ +#define dbg_err(fmt, ...) do { \ + if (0) \ + ubifs_err(fmt, ##__VA_ARGS__); \ } while (0) -#define dbg_msg(fmt, ...) do { \ - if (0) \ - printk(KERN_DEBUG "UBIFS DBG (pid %d): %s: " fmt "\n", \ - current->pid, __func__, ##__VA_ARGS__); \ +#define ubifs_dbg_msg(fmt, ...) do { \ + if (0) \ + pr_debug(fmt "\n", ##__VA_ARGS__); \ } while (0) #define dbg_dump_stack() #define ubifs_assert_cmt_locked(c) -#define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_jnl(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_tnc(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_lp(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_find(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_mnt(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_io(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_cmt(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_budg(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_log(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_gc(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_scan(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_rcvry(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_msg(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_gen(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_jnl(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_tnc(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_lp(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_find(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_mnt(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_io(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_cmt(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_budg(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_log(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_gc(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_scan(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_rcvry(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__) #define DBGKEY(key) ((char *)(key)) #define DBGKEY1(key) ((char *)(key)) -- cgit v1.2.3