From 9401a795c6478953e10226471ba5990db5000e05 Mon Sep 17 00:00:00 2001 From: Taesoo Kim Date: Wed, 25 Mar 2015 09:53:37 +0100 Subject: UBIFS: fix incorrect unlocking handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When ubifs_init_security() fails, 'ui_mutex' is incorrectly unlocked and incorrectly restores 'i_size'. Fix this. Signed-off-by: Taesoo Kim Fixes: d7f0b70d30ff ("UBIFS: Add security.* XATTR support for the UBIFS") Reviewed-by: Ben Shelton Signed-off-by: Uwe Kleine-König Signed-off-by: Artem Bityutskiy --- fs/ubifs/dir.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 0fa6c803992e..5b24bc42cad9 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -272,7 +272,7 @@ static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode, err = ubifs_init_security(dir, inode, &dentry->d_name); if (err) - goto out_cancel; + goto out_inode; mutex_lock(&dir_ui->ui_mutex); dir->i_size += sz_change; @@ -292,6 +292,7 @@ out_cancel: dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; mutex_unlock(&dir_ui->ui_mutex); +out_inode: make_bad_inode(inode); iput(inode); out_budg: @@ -732,7 +733,7 @@ static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) err = ubifs_init_security(dir, inode, &dentry->d_name); if (err) - goto out_cancel; + goto out_inode; mutex_lock(&dir_ui->ui_mutex); insert_inode_hash(inode); @@ -757,6 +758,7 @@ out_cancel: dir_ui->ui_size = dir->i_size; drop_nlink(dir); mutex_unlock(&dir_ui->ui_mutex); +out_inode: make_bad_inode(inode); iput(inode); out_budg: @@ -816,7 +818,7 @@ static int ubifs_mknod(struct inode *dir, struct dentry *dentry, err = ubifs_init_security(dir, inode, &dentry->d_name); if (err) - goto out_cancel; + goto out_inode; mutex_lock(&dir_ui->ui_mutex); dir->i_size += sz_change; @@ -836,6 +838,7 @@ out_cancel: dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; mutex_unlock(&dir_ui->ui_mutex); +out_inode: make_bad_inode(inode); iput(inode); out_budg: @@ -896,7 +899,7 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry, err = ubifs_init_security(dir, inode, &dentry->d_name); if (err) - goto out_cancel; + goto out_inode; mutex_lock(&dir_ui->ui_mutex); dir->i_size += sz_change; -- cgit v1.2.3-59-g8ed1b From 2c84599ca4c2ffd81301f23eabc69c5180ff2f64 Mon Sep 17 00:00:00 2001 From: Sheng Yong Date: Wed, 4 Mar 2015 10:46:16 +0000 Subject: UBIFS: do not write master node if need recovery The commits 781c571 ("UBIFS: intialize LPT earlier") and 0980119 ("UBIFS: fix-up free space earlier") move some initialization before marking the master node dirty. But the modification changes the conditions of writing master. If unclean umount happens, ubifs may fail when mounting. But trying to mount it will write new master nodes on the flash. This is useless but increasing sqnum. So check need_recovery before writing master node, and don't create new master node if filesystem needs recovery. The behavour of the bug shows at: http://lists.infradead.org/pipermail/linux-mtd/2015-February/057712.html Signed-off-by: Sheng Yong Reviewed-by: Ben Gardiner Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 93e946561c5c..0b7378a7ee04 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1284,7 +1284,7 @@ static int mount_ubifs(struct ubifs_info *c) goto out_lpt; } - if (!c->ro_mount) { + if (!c->ro_mount && !c->need_recovery) { /* * Set the "dirty" flag so that if we reboot uncleanly we * will notice this immediately on the next mount. -- cgit v1.2.3-59-g8ed1b From d3f9db00d04ef1388d7ff24130b9a95099ce1542 Mon Sep 17 00:00:00 2001 From: Yannick Guerrini Date: Fri, 6 Mar 2015 23:14:39 +0100 Subject: UBIFS: Fix trivial typos in comments Change 'comress' to 'compress' Change 'inteval' to 'interval' Change 'disabe' to 'disable' Change 'nenver' to 'never' Signed-off-by: Yannick Guerrini Signed-off-by: Artem Bityutskiy --- fs/ubifs/ubifs.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index bc04b9c69891..2911d2d23456 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -158,7 +158,7 @@ #define WORST_COMPR_FACTOR 2 /* - * How much memory is needed for a buffer where we comress a data node. + * How much memory is needed for a buffer where we compress a data node. */ #define COMPRESSED_DATA_NODE_BUF_SZ \ (UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR) @@ -664,7 +664,7 @@ typedef int (*ubifs_lpt_scan_callback)(struct ubifs_info *c, * @lock: serializes @buf, @lnum, @offs, @avail, @used, @next_ino and @inodes * fields * @softlimit: soft write-buffer timeout interval - * @delta: hard and soft timeouts delta (the timer expire inteval is @softlimit + * @delta: hard and soft timeouts delta (the timer expire interval is @softlimit * and @softlimit + @delta) * @timer: write-buffer timer * @no_timer: non-zero if this write-buffer does not have a timer @@ -930,9 +930,9 @@ struct ubifs_orphan { /** * struct ubifs_mount_opts - UBIFS-specific mount options information. * @unmount_mode: selected unmount mode (%0 default, %1 normal, %2 fast) - * @bulk_read: enable/disable bulk-reads (%0 default, %1 disabe, %2 enable) + * @bulk_read: enable/disable bulk-reads (%0 default, %1 disable, %2 enable) * @chk_data_crc: enable/disable CRC data checking when reading data nodes - * (%0 default, %1 disabe, %2 enable) + * (%0 default, %1 disable, %2 enable) * @override_compr: override default compressor (%0 - do not override and use * superblock compressor, %1 - override and use compressor * specified in @compr_type) @@ -962,9 +962,9 @@ struct ubifs_mount_opts { * 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 + * @page_budget: budget for a page (constant, never changed after mount) + * @inode_budget: budget for an inode (constant, never changed after mount) + * @dent_budget: budget for a directory entry (constant, never changed after * mount) */ struct ubifs_budg_info { -- cgit v1.2.3-59-g8ed1b From 8a87dc55f75f19ffdbb52066afea1b633577c79f Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Thu, 12 Mar 2015 21:34:21 +0100 Subject: UBIFS: simplify returns Directly return recover_head() and ubifs_leb_unmap() instead of storing value in err and testing it. Signed-off-by: Fabian Frederick Acked-by: Geert Uytterhoeven Signed-off-by: Artem Bityutskiy --- fs/ubifs/recovery.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index c640938f62f0..13ca4dbc4d19 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c @@ -975,11 +975,8 @@ int ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf) return err; dbg_rcvry("checking LPT head at %d:%d", c->nhead_lnum, c->nhead_offs); - err = recover_head(c, c->nhead_lnum, c->nhead_offs, sbuf); - if (err) - return err; - return 0; + return recover_head(c, c->nhead_lnum, c->nhead_offs, sbuf); } /** @@ -1004,10 +1001,7 @@ static int clean_an_unclean_leb(struct ubifs_info *c, if (len == 0) { /* Nothing to read, just unmap it */ - err = ubifs_leb_unmap(c, lnum); - if (err) - return err; - return 0; + return ubifs_leb_unmap(c, lnum); } err = ubifs_leb_read(c, lnum, buf, offs, len, 0); -- cgit v1.2.3-59-g8ed1b From 235c362bd0f6afcf767bc72aa0c647e1434cc631 Mon Sep 17 00:00:00 2001 From: Sheng Yong Date: Fri, 20 Mar 2015 10:39:42 +0000 Subject: UBIFS: extend debug/message capabilities In the case where we have more than one volumes on different UBI devices, it may be not that easy to tell which volume prints the messages. Add ubi number and volume id in ubifs_msg/warn/error to help debug. These two values are passed by struct ubifs_info. For those where ubifs_info is not initialized yet, ubifs_* is replaced by pr_*. For those where ubifs_info is not avaliable, ubifs_info is passed to the calling function as a const parameter. The output looks like, [ 95.444879] UBIFS (ubi0:1): background thread "ubifs_bgt0_1" started, PID 696 [ 95.484688] UBIFS (ubi0:1): UBIFS: mounted UBI device 0, volume 1, name "test1" [ 95.484694] UBIFS (ubi0:1): LEB size: 126976 bytes (124 KiB), min./max. I/O unit sizes: 2048 bytes/2048 bytes [ 95.484699] UBIFS (ubi0:1): FS size: 30220288 bytes (28 MiB, 238 LEBs), journal size 1523712 bytes (1 MiB, 12 LEBs) [ 95.484703] UBIFS (ubi0:1): reserved for root: 1427378 bytes (1393 KiB) [ 95.484709] UBIFS (ubi0:1): media format: w4/r0 (latest is w4/r0), UUID 40DFFC0E-70BE-4193-8905-F7D6DFE60B17, small LPT model [ 95.489875] UBIFS (ubi1:0): background thread "ubifs_bgt1_0" started, PID 699 [ 95.529713] UBIFS (ubi1:0): UBIFS: mounted UBI device 1, volume 0, name "test2" [ 95.529718] UBIFS (ubi1:0): LEB size: 126976 bytes (124 KiB), min./max. I/O unit sizes: 2048 bytes/2048 bytes [ 95.529724] UBIFS (ubi1:0): FS size: 19808256 bytes (18 MiB, 156 LEBs), journal size 1015809 bytes (0 MiB, 8 LEBs) [ 95.529727] UBIFS (ubi1:0): reserved for root: 935592 bytes (913 KiB) [ 95.529733] UBIFS (ubi1:0): media format: w4/r0 (latest is w4/r0), UUID EEB7779D-F419-4CA9-811B-831CAC7233D4, small LPT model [ 954.264767] UBIFS error (ubi1:0 pid 756): ubifs_read_node: bad node type (255 but expected 6) [ 954.367030] UBIFS error (ubi1:0 pid 756): ubifs_read_node: bad node at LEB 0:0, LEB mapping status 1 Signed-off-by: Sheng Yong Signed-off-by: Artem Bityutskiy --- fs/ubifs/budget.c | 2 +- fs/ubifs/commit.c | 12 ++-- fs/ubifs/compress.c | 22 +++--- fs/ubifs/debug.c | 186 +++++++++++++++++++++++++------------------------- fs/ubifs/dir.c | 12 ++-- fs/ubifs/file.c | 17 ++--- fs/ubifs/io.c | 40 +++++------ fs/ubifs/ioctl.c | 2 +- fs/ubifs/journal.c | 17 ++--- fs/ubifs/log.c | 4 +- fs/ubifs/lprops.c | 62 ++++++++--------- fs/ubifs/lpt.c | 59 ++++++++-------- fs/ubifs/lpt_commit.c | 34 ++++----- fs/ubifs/master.c | 6 +- fs/ubifs/orphan.c | 26 +++---- fs/ubifs/recovery.c | 34 ++++----- fs/ubifs/replay.c | 34 ++++----- fs/ubifs/sb.c | 30 ++++---- fs/ubifs/scan.c | 24 +++---- fs/ubifs/super.c | 105 ++++++++++++++-------------- fs/ubifs/tnc.c | 20 +++--- fs/ubifs/tnc_commit.c | 12 ++-- fs/ubifs/tnc_misc.c | 24 +++---- fs/ubifs/ubifs.h | 26 ++++--- fs/ubifs/xattr.c | 18 ++--- 25 files changed, 419 insertions(+), 409 deletions(-) diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index eb997e9c4ab0..11a11b32a2a9 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -509,7 +509,7 @@ again: c->bi.nospace_rp = 1; smp_wmb(); } else - ubifs_err("cannot budget space, error %d", err); + ubifs_err(c, "cannot budget space, error %d", err); return err; } diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c index 26b69b2d4a45..63f56619991d 100644 --- a/fs/ubifs/commit.c +++ b/fs/ubifs/commit.c @@ -225,7 +225,7 @@ out_cancel: out_up: up_write(&c->commit_sem); out: - ubifs_err("commit failed, error %d", err); + ubifs_err(c, "commit failed, error %d", err); spin_lock(&c->cs_lock); c->cmt_state = COMMIT_BROKEN; wake_up(&c->cmt_wq); @@ -289,7 +289,7 @@ int ubifs_bg_thread(void *info) int err; struct ubifs_info *c = info; - ubifs_msg("background thread \"%s\" started, PID %d", + ubifs_msg(c, "background thread \"%s\" started, PID %d", c->bgt_name, current->pid); set_freezable(); @@ -324,7 +324,7 @@ int ubifs_bg_thread(void *info) cond_resched(); } - ubifs_msg("background thread \"%s\" stops", c->bgt_name); + ubifs_msg(c, "background thread \"%s\" stops", c->bgt_name); return 0; } @@ -712,13 +712,13 @@ out: return 0; out_dump: - ubifs_err("dumping index node (iip=%d)", i->iip); + ubifs_err(c, "dumping index node (iip=%d)", i->iip); ubifs_dump_node(c, idx); list_del(&i->list); kfree(i); if (!list_empty(&list)) { i = list_entry(list.prev, struct idx_node, list); - ubifs_err("dumping parent index node"); + ubifs_err(c, "dumping parent index node"); ubifs_dump_node(c, &i->idx); } out_free: @@ -727,7 +727,7 @@ out_free: list_del(&i->list); kfree(i); } - ubifs_err("failed, error %d", err); + ubifs_err(c, "failed, error %d", err); if (err > 0) err = -EINVAL; return err; diff --git a/fs/ubifs/compress.c b/fs/ubifs/compress.c index 2bfa0953335d..565cb56d7225 100644 --- a/fs/ubifs/compress.c +++ b/fs/ubifs/compress.c @@ -92,8 +92,8 @@ struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; * Note, if the input buffer was not compressed, it is copied to the output * buffer and %UBIFS_COMPR_NONE is returned in @compr_type. */ -void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len, - int *compr_type) +void ubifs_compress(const struct ubifs_info *c, const void *in_buf, + int in_len, void *out_buf, int *out_len, int *compr_type) { int err; struct ubifs_compressor *compr = ubifs_compressors[*compr_type]; @@ -112,9 +112,9 @@ void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len, if (compr->comp_mutex) mutex_unlock(compr->comp_mutex); if (unlikely(err)) { - ubifs_warn("cannot compress %d bytes, compressor %s, error %d, leave data uncompressed", + ubifs_warn(c, "cannot compress %d bytes, compressor %s, error %d, leave data uncompressed", in_len, compr->name, err); - goto no_compr; + goto no_compr; } /* @@ -144,21 +144,21 @@ no_compr: * The length of the uncompressed data is returned in @out_len. This functions * returns %0 on success or a negative error code on failure. */ -int ubifs_decompress(const void *in_buf, int in_len, void *out_buf, - int *out_len, int compr_type) +int ubifs_decompress(const struct ubifs_info *c, const void *in_buf, + int in_len, void *out_buf, int *out_len, int compr_type) { int err; struct ubifs_compressor *compr; if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) { - ubifs_err("invalid compression type %d", compr_type); + ubifs_err(c, "invalid compression type %d", compr_type); return -EINVAL; } compr = ubifs_compressors[compr_type]; if (unlikely(!compr->capi_name)) { - ubifs_err("%s compression is not compiled in", compr->name); + ubifs_err(c, "%s compression is not compiled in", compr->name); return -EINVAL; } @@ -175,7 +175,7 @@ int ubifs_decompress(const void *in_buf, int in_len, void *out_buf, if (compr->decomp_mutex) mutex_unlock(compr->decomp_mutex); if (err) - ubifs_err("cannot decompress %d bytes, compressor %s, error %d", + ubifs_err(c, "cannot decompress %d bytes, compressor %s, error %d", in_len, compr->name, err); return err; @@ -193,8 +193,8 @@ static int __init compr_init(struct ubifs_compressor *compr) if (compr->capi_name) { compr->cc = crypto_alloc_comp(compr->capi_name, 0, 0); if (IS_ERR(compr->cc)) { - ubifs_err("cannot initialize compressor %s, error %ld", - compr->name, PTR_ERR(compr->cc)); + pr_err("UBIFS error (pid %d): cannot initialize compressor %s, error %ld", + current->pid, compr->name, PTR_ERR(compr->cc)); return PTR_ERR(compr->cc); } } diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 4cfb3e82c56f..4c46a9865fa7 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -746,7 +746,7 @@ void ubifs_dump_lprops(struct ubifs_info *c) for (lnum = c->main_first; lnum < c->leb_cnt; lnum++) { err = ubifs_read_one_lp(c, lnum, &lp); if (err) { - ubifs_err("cannot read lprops for LEB %d", lnum); + ubifs_err(c, "cannot read lprops for LEB %d", lnum); continue; } @@ -819,13 +819,13 @@ void ubifs_dump_leb(const struct ubifs_info *c, int lnum) buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); if (!buf) { - ubifs_err("cannot allocate memory for dumping LEB %d", lnum); + ubifs_err(c, "cannot allocate memory for dumping LEB %d", lnum); return; } sleb = ubifs_scan(c, lnum, 0, buf, 0); if (IS_ERR(sleb)) { - ubifs_err("scan error %d", (int)PTR_ERR(sleb)); + ubifs_err(c, "scan error %d", (int)PTR_ERR(sleb)); goto out; } @@ -1032,7 +1032,7 @@ int dbg_check_space_info(struct ubifs_info *c) spin_unlock(&c->space_lock); if (free != d->saved_free) { - ubifs_err("free space changed from %lld to %lld", + ubifs_err(c, "free space changed from %lld to %lld", d->saved_free, free); goto out; } @@ -1040,15 +1040,15 @@ int dbg_check_space_info(struct ubifs_info *c) return 0; out: - ubifs_msg("saved lprops statistics dump"); + ubifs_msg(c, "saved lprops statistics dump"); ubifs_dump_lstats(&d->saved_lst); - ubifs_msg("saved budgeting info dump"); + ubifs_msg(c, "saved budgeting info dump"); ubifs_dump_budg(c, &d->saved_bi); - ubifs_msg("saved idx_gc_cnt %d", d->saved_idx_gc_cnt); - ubifs_msg("current lprops statistics dump"); + ubifs_msg(c, "saved idx_gc_cnt %d", d->saved_idx_gc_cnt); + ubifs_msg(c, "current lprops statistics dump"); ubifs_get_lp_stats(c, &lst); ubifs_dump_lstats(&lst); - ubifs_msg("current budgeting info dump"); + ubifs_msg(c, "current budgeting info dump"); ubifs_dump_budg(c, &c->bi); dump_stack(); return -EINVAL; @@ -1077,9 +1077,9 @@ int dbg_check_synced_i_size(const struct ubifs_info *c, struct inode *inode) mutex_lock(&ui->ui_mutex); spin_lock(&ui->ui_lock); if (ui->ui_size != ui->synced_i_size && !ui->dirty) { - ubifs_err("ui_size is %lld, synced_i_size is %lld, but inode is clean", + ubifs_err(c, "ui_size is %lld, synced_i_size is %lld, but inode is clean", ui->ui_size, ui->synced_i_size); - ubifs_err("i_ino %lu, i_mode %#x, i_size %lld", inode->i_ino, + ubifs_err(c, "i_ino %lu, i_mode %#x, i_size %lld", inode->i_ino, inode->i_mode, i_size_read(inode)); dump_stack(); err = -EINVAL; @@ -1140,7 +1140,7 @@ int dbg_check_dir(struct ubifs_info *c, const struct inode *dir) kfree(pdent); if (i_size_read(dir) != size) { - ubifs_err("directory inode %lu has size %llu, but calculated size is %llu", + ubifs_err(c, "directory inode %lu has size %llu, but calculated size is %llu", dir->i_ino, (unsigned long long)i_size_read(dir), (unsigned long long)size); ubifs_dump_inode(c, dir); @@ -1148,7 +1148,7 @@ int dbg_check_dir(struct ubifs_info *c, const struct inode *dir) return -EINVAL; } if (dir->i_nlink != nlink) { - ubifs_err("directory inode %lu has nlink %u, but calculated nlink is %u", + ubifs_err(c, "directory inode %lu has nlink %u, but calculated nlink is %u", dir->i_ino, dir->i_nlink, nlink); ubifs_dump_inode(c, dir); dump_stack(); @@ -1207,10 +1207,10 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1, err = 1; key_read(c, &dent1->key, &key); if (keys_cmp(c, &zbr1->key, &key)) { - ubifs_err("1st entry at %d:%d has key %s", zbr1->lnum, + ubifs_err(c, "1st entry at %d:%d has key %s", zbr1->lnum, zbr1->offs, dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN)); - ubifs_err("but it should have key %s according to tnc", + ubifs_err(c, "but it should have key %s according to tnc", dbg_snprintf_key(c, &zbr1->key, key_buf, DBG_KEY_BUF_LEN)); ubifs_dump_node(c, dent1); @@ -1219,10 +1219,10 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1, key_read(c, &dent2->key, &key); if (keys_cmp(c, &zbr2->key, &key)) { - ubifs_err("2nd entry at %d:%d has key %s", zbr1->lnum, + ubifs_err(c, "2nd entry at %d:%d has key %s", zbr1->lnum, zbr1->offs, dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN)); - ubifs_err("but it should have key %s according to tnc", + ubifs_err(c, "but it should have key %s according to tnc", dbg_snprintf_key(c, &zbr2->key, key_buf, DBG_KEY_BUF_LEN)); ubifs_dump_node(c, dent2); @@ -1238,14 +1238,14 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1, goto out_free; } if (cmp == 0 && nlen1 == nlen2) - ubifs_err("2 xent/dent nodes with the same name"); + ubifs_err(c, "2 xent/dent nodes with the same name"); else - ubifs_err("bad order of colliding key %s", + ubifs_err(c, "bad order of colliding key %s", dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN)); - ubifs_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs); + ubifs_msg(c, "first node at %d:%d\n", zbr1->lnum, zbr1->offs); ubifs_dump_node(c, dent1); - ubifs_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs); + ubifs_msg(c, "second node at %d:%d\n", zbr2->lnum, zbr2->offs); ubifs_dump_node(c, dent2); out_free: @@ -1447,11 +1447,11 @@ static int dbg_check_znode(struct ubifs_info *c, struct ubifs_zbranch *zbr) return 0; out: - ubifs_err("failed, error %d", err); - ubifs_msg("dump of the znode"); + ubifs_err(c, "failed, error %d", err); + ubifs_msg(c, "dump of the znode"); ubifs_dump_znode(c, znode); if (zp) { - ubifs_msg("dump of the parent znode"); + ubifs_msg(c, "dump of the parent znode"); ubifs_dump_znode(c, zp); } dump_stack(); @@ -1518,9 +1518,9 @@ int dbg_check_tnc(struct ubifs_info *c, int extra) if (err < 0) return err; if (err) { - ubifs_msg("first znode"); + ubifs_msg(c, "first znode"); ubifs_dump_znode(c, prev); - ubifs_msg("second znode"); + ubifs_msg(c, "second znode"); ubifs_dump_znode(c, znode); return -EINVAL; } @@ -1529,13 +1529,13 @@ int dbg_check_tnc(struct ubifs_info *c, int extra) if (extra) { if (clean_cnt != atomic_long_read(&c->clean_zn_cnt)) { - ubifs_err("incorrect clean_zn_cnt %ld, calculated %ld", + ubifs_err(c, "incorrect clean_zn_cnt %ld, calculated %ld", atomic_long_read(&c->clean_zn_cnt), clean_cnt); return -EINVAL; } if (dirty_cnt != atomic_long_read(&c->dirty_zn_cnt)) { - ubifs_err("incorrect dirty_zn_cnt %ld, calculated %ld", + ubifs_err(c, "incorrect dirty_zn_cnt %ld, calculated %ld", atomic_long_read(&c->dirty_zn_cnt), dirty_cnt); return -EINVAL; @@ -1608,7 +1608,7 @@ int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb, if (znode_cb) { err = znode_cb(c, znode, priv); if (err) { - ubifs_err("znode checking function returned error %d", + ubifs_err(c, "znode checking function returned error %d", err); ubifs_dump_znode(c, znode); goto out_dump; @@ -1619,7 +1619,7 @@ int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb, zbr = &znode->zbranch[idx]; err = leaf_cb(c, zbr, priv); if (err) { - ubifs_err("leaf checking function returned error %d, for leaf at LEB %d:%d", + ubifs_err(c, "leaf checking function returned error %d, for leaf at LEB %d:%d", err, zbr->lnum, zbr->offs); goto out_dump; } @@ -1675,7 +1675,7 @@ out_dump: zbr = &znode->parent->zbranch[znode->iip]; else zbr = &c->zroot; - ubifs_msg("dump of znode at LEB %d:%d", zbr->lnum, zbr->offs); + ubifs_msg(c, "dump of znode at LEB %d:%d", zbr->lnum, zbr->offs); ubifs_dump_znode(c, znode); out_unlock: mutex_unlock(&c->tnc_mutex); @@ -1722,12 +1722,12 @@ int dbg_check_idx_size(struct ubifs_info *c, long long idx_size) err = dbg_walk_index(c, NULL, add_size, &calc); if (err) { - ubifs_err("error %d while walking the index", err); + ubifs_err(c, "error %d while walking the index", err); return err; } if (calc != idx_size) { - ubifs_err("index size check failed: calculated size is %lld, should be %lld", + ubifs_err(c, "index size check failed: calculated size is %lld, should be %lld", calc, idx_size); dump_stack(); return -EINVAL; @@ -1814,7 +1814,7 @@ static struct fsck_inode *add_inode(struct ubifs_info *c, } if (inum > c->highest_inum) { - ubifs_err("too high inode number, max. is %lu", + ubifs_err(c, "too high inode number, max. is %lu", (unsigned long)c->highest_inum); return ERR_PTR(-EINVAL); } @@ -1921,17 +1921,17 @@ static struct fsck_inode *read_add_inode(struct ubifs_info *c, ino_key_init(c, &key, inum); err = ubifs_lookup_level0(c, &key, &znode, &n); if (!err) { - ubifs_err("inode %lu not found in index", (unsigned long)inum); + ubifs_err(c, "inode %lu not found in index", (unsigned long)inum); return ERR_PTR(-ENOENT); } else if (err < 0) { - ubifs_err("error %d while looking up inode %lu", + ubifs_err(c, "error %d while looking up inode %lu", err, (unsigned long)inum); return ERR_PTR(err); } zbr = &znode->zbranch[n]; if (zbr->len < UBIFS_INO_NODE_SZ) { - ubifs_err("bad node %lu node length %d", + ubifs_err(c, "bad node %lu node length %d", (unsigned long)inum, zbr->len); return ERR_PTR(-EINVAL); } @@ -1942,7 +1942,7 @@ static struct fsck_inode *read_add_inode(struct ubifs_info *c, err = ubifs_tnc_read_node(c, zbr, ino); if (err) { - ubifs_err("cannot read inode node at LEB %d:%d, error %d", + ubifs_err(c, "cannot read inode node at LEB %d:%d, error %d", zbr->lnum, zbr->offs, err); kfree(ino); return ERR_PTR(err); @@ -1951,7 +1951,7 @@ static struct fsck_inode *read_add_inode(struct ubifs_info *c, fscki = add_inode(c, fsckd, ino); kfree(ino); if (IS_ERR(fscki)) { - ubifs_err("error %ld while adding inode %lu node", + ubifs_err(c, "error %ld while adding inode %lu node", PTR_ERR(fscki), (unsigned long)inum); return fscki; } @@ -1985,7 +1985,7 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr, struct fsck_inode *fscki; if (zbr->len < UBIFS_CH_SZ) { - ubifs_err("bad leaf length %d (LEB %d:%d)", + ubifs_err(c, "bad leaf length %d (LEB %d:%d)", zbr->len, zbr->lnum, zbr->offs); return -EINVAL; } @@ -1996,7 +1996,7 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr, err = ubifs_tnc_read_node(c, zbr, node); if (err) { - ubifs_err("cannot read leaf node at LEB %d:%d, error %d", + ubifs_err(c, "cannot read leaf node at LEB %d:%d, error %d", zbr->lnum, zbr->offs, err); goto out_free; } @@ -2006,7 +2006,7 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr, fscki = add_inode(c, priv, node); if (IS_ERR(fscki)) { err = PTR_ERR(fscki); - ubifs_err("error %d while adding inode node", err); + ubifs_err(c, "error %d while adding inode node", err); goto out_dump; } goto out; @@ -2014,7 +2014,7 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr, if (type != UBIFS_DENT_KEY && type != UBIFS_XENT_KEY && type != UBIFS_DATA_KEY) { - ubifs_err("unexpected node type %d at LEB %d:%d", + ubifs_err(c, "unexpected node type %d at LEB %d:%d", type, zbr->lnum, zbr->offs); err = -EINVAL; goto out_free; @@ -2022,7 +2022,7 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr, ch = node; if (le64_to_cpu(ch->sqnum) > c->max_sqnum) { - ubifs_err("too high sequence number, max. is %llu", + ubifs_err(c, "too high sequence number, max. is %llu", c->max_sqnum); err = -EINVAL; goto out_dump; @@ -2042,7 +2042,7 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr, fscki = read_add_inode(c, priv, inum); if (IS_ERR(fscki)) { err = PTR_ERR(fscki); - ubifs_err("error %d while processing data node and trying to find inode node %lu", + ubifs_err(c, "error %d while processing data node and trying to find inode node %lu", err, (unsigned long)inum); goto out_dump; } @@ -2052,7 +2052,7 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr, blk_offs <<= UBIFS_BLOCK_SHIFT; blk_offs += le32_to_cpu(dn->size); if (blk_offs > fscki->size) { - ubifs_err("data node at LEB %d:%d is not within inode size %lld", + ubifs_err(c, "data node at LEB %d:%d is not within inode size %lld", zbr->lnum, zbr->offs, fscki->size); err = -EINVAL; goto out_dump; @@ -2076,7 +2076,7 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr, fscki = read_add_inode(c, priv, inum); if (IS_ERR(fscki)) { err = PTR_ERR(fscki); - ubifs_err("error %d while processing entry node and trying to find inode node %lu", + ubifs_err(c, "error %d while processing entry node and trying to find inode node %lu", err, (unsigned long)inum); goto out_dump; } @@ -2088,7 +2088,7 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr, fscki1 = read_add_inode(c, priv, inum); if (IS_ERR(fscki1)) { err = PTR_ERR(fscki1); - ubifs_err("error %d while processing entry node and trying to find parent inode node %lu", + ubifs_err(c, "error %d while processing entry node and trying to find parent inode node %lu", err, (unsigned long)inum); goto out_dump; } @@ -2111,7 +2111,7 @@ out: return 0; out_dump: - ubifs_msg("dump of node at LEB %d:%d", zbr->lnum, zbr->offs); + ubifs_msg(c, "dump of node at LEB %d:%d", zbr->lnum, zbr->offs); ubifs_dump_node(c, node); out_free: kfree(node); @@ -2162,52 +2162,52 @@ static int check_inodes(struct ubifs_info *c, struct fsck_data *fsckd) */ if (fscki->inum != UBIFS_ROOT_INO && fscki->references != 1) { - ubifs_err("directory inode %lu has %d direntries which refer it, but should be 1", + ubifs_err(c, "directory inode %lu has %d direntries which refer it, but should be 1", (unsigned long)fscki->inum, fscki->references); goto out_dump; } if (fscki->inum == UBIFS_ROOT_INO && fscki->references != 0) { - ubifs_err("root inode %lu has non-zero (%d) direntries which refer it", + ubifs_err(c, "root inode %lu has non-zero (%d) direntries which refer it", (unsigned long)fscki->inum, fscki->references); goto out_dump; } if (fscki->calc_sz != fscki->size) { - ubifs_err("directory inode %lu size is %lld, but calculated size is %lld", + ubifs_err(c, "directory inode %lu size is %lld, but calculated size is %lld", (unsigned long)fscki->inum, fscki->size, fscki->calc_sz); goto out_dump; } if (fscki->calc_cnt != fscki->nlink) { - ubifs_err("directory inode %lu nlink is %d, but calculated nlink is %d", + ubifs_err(c, "directory inode %lu nlink is %d, but calculated nlink is %d", (unsigned long)fscki->inum, fscki->nlink, fscki->calc_cnt); goto out_dump; } } else { if (fscki->references != fscki->nlink) { - ubifs_err("inode %lu nlink is %d, but calculated nlink is %d", + ubifs_err(c, "inode %lu nlink is %d, but calculated nlink is %d", (unsigned long)fscki->inum, fscki->nlink, fscki->references); goto out_dump; } } if (fscki->xattr_sz != fscki->calc_xsz) { - ubifs_err("inode %lu has xattr size %u, but calculated size is %lld", + ubifs_err(c, "inode %lu has xattr size %u, but calculated size is %lld", (unsigned long)fscki->inum, fscki->xattr_sz, fscki->calc_xsz); goto out_dump; } if (fscki->xattr_cnt != fscki->calc_xcnt) { - ubifs_err("inode %lu has %u xattrs, but calculated count is %lld", + ubifs_err(c, "inode %lu has %u xattrs, but calculated count is %lld", (unsigned long)fscki->inum, fscki->xattr_cnt, fscki->calc_xcnt); goto out_dump; } if (fscki->xattr_nms != fscki->calc_xnms) { - ubifs_err("inode %lu has xattr names' size %u, but calculated names' size is %lld", + ubifs_err(c, "inode %lu has xattr names' size %u, but calculated names' size is %lld", (unsigned long)fscki->inum, fscki->xattr_nms, fscki->calc_xnms); goto out_dump; @@ -2221,11 +2221,11 @@ out_dump: ino_key_init(c, &key, fscki->inum); err = ubifs_lookup_level0(c, &key, &znode, &n); if (!err) { - ubifs_err("inode %lu not found in index", + ubifs_err(c, "inode %lu not found in index", (unsigned long)fscki->inum); return -ENOENT; } else if (err < 0) { - ubifs_err("error %d while looking up inode %lu", + ubifs_err(c, "error %d while looking up inode %lu", err, (unsigned long)fscki->inum); return err; } @@ -2237,13 +2237,13 @@ out_dump: err = ubifs_tnc_read_node(c, zbr, ino); if (err) { - ubifs_err("cannot read inode node at LEB %d:%d, error %d", + ubifs_err(c, "cannot read inode node at LEB %d:%d, error %d", zbr->lnum, zbr->offs, err); kfree(ino); return err; } - ubifs_msg("dump of the inode %lu sitting in LEB %d:%d", + ubifs_msg(c, "dump of the inode %lu sitting in LEB %d:%d", (unsigned long)fscki->inum, zbr->lnum, zbr->offs); ubifs_dump_node(c, ino); kfree(ino); @@ -2284,7 +2284,7 @@ int dbg_check_filesystem(struct ubifs_info *c) return 0; out_free: - ubifs_err("file-system check failed with error %d", err); + ubifs_err(c, "file-system check failed with error %d", err); dump_stack(); free_inodes(&fsckd); return err; @@ -2315,12 +2315,12 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head) sb = container_of(cur->next, struct ubifs_scan_node, list); if (sa->type != UBIFS_DATA_NODE) { - ubifs_err("bad node type %d", sa->type); + ubifs_err(c, "bad node type %d", sa->type); ubifs_dump_node(c, sa->node); return -EINVAL; } if (sb->type != UBIFS_DATA_NODE) { - ubifs_err("bad node type %d", sb->type); + ubifs_err(c, "bad node type %d", sb->type); ubifs_dump_node(c, sb->node); return -EINVAL; } @@ -2331,7 +2331,7 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head) if (inuma < inumb) continue; if (inuma > inumb) { - ubifs_err("larger inum %lu goes before inum %lu", + ubifs_err(c, "larger inum %lu goes before inum %lu", (unsigned long)inuma, (unsigned long)inumb); goto error_dump; } @@ -2340,11 +2340,11 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head) blkb = key_block(c, &sb->key); if (blka > blkb) { - ubifs_err("larger block %u goes before %u", blka, blkb); + ubifs_err(c, "larger block %u goes before %u", blka, blkb); goto error_dump; } if (blka == blkb) { - ubifs_err("two data nodes for the same block"); + ubifs_err(c, "two data nodes for the same block"); goto error_dump; } } @@ -2383,19 +2383,19 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head) if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE && sa->type != UBIFS_XENT_NODE) { - ubifs_err("bad node type %d", sa->type); + ubifs_err(c, "bad node type %d", sa->type); ubifs_dump_node(c, sa->node); return -EINVAL; } if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE && sa->type != UBIFS_XENT_NODE) { - ubifs_err("bad node type %d", sb->type); + ubifs_err(c, "bad node type %d", sb->type); ubifs_dump_node(c, sb->node); return -EINVAL; } if (sa->type != UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) { - ubifs_err("non-inode node goes before inode node"); + ubifs_err(c, "non-inode node goes before inode node"); goto error_dump; } @@ -2405,7 +2405,7 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head) if (sa->type == UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) { /* Inode nodes are sorted in descending size order */ if (sa->len < sb->len) { - ubifs_err("smaller inode node goes first"); + ubifs_err(c, "smaller inode node goes first"); goto error_dump; } continue; @@ -2421,7 +2421,7 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head) if (inuma < inumb) continue; if (inuma > inumb) { - ubifs_err("larger inum %lu goes before inum %lu", + ubifs_err(c, "larger inum %lu goes before inum %lu", (unsigned long)inuma, (unsigned long)inumb); goto error_dump; } @@ -2430,7 +2430,7 @@ 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", + ubifs_err(c, "larger hash %u goes before %u", hasha, hashb); goto error_dump; } @@ -2439,9 +2439,9 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head) return 0; error_dump: - ubifs_msg("dumping first node"); + ubifs_msg(c, "dumping first node"); ubifs_dump_node(c, sa->node); - ubifs_msg("dumping second node"); + ubifs_msg(c, "dumping second node"); ubifs_dump_node(c, sb->node); return -EINVAL; return 0; @@ -2470,13 +2470,13 @@ static int power_cut_emulated(struct ubifs_info *c, int lnum, int write) delay = prandom_u32() % 60000; d->pc_timeout = jiffies; d->pc_timeout += msecs_to_jiffies(delay); - ubifs_warn("failing after %lums", delay); + ubifs_warn(c, "failing after %lums", delay); } else { d->pc_delay = 2; delay = prandom_u32() % 10000; /* Fail within 10000 operations */ d->pc_cnt_max = delay; - ubifs_warn("failing after %lu calls", delay); + ubifs_warn(c, "failing after %lu calls", delay); } } @@ -2494,55 +2494,55 @@ static int power_cut_emulated(struct ubifs_info *c, int lnum, int write) return 0; if (chance(19, 20)) return 0; - ubifs_warn("failing in super block LEB %d", lnum); + ubifs_warn(c, "failing in super block LEB %d", lnum); } else if (lnum == UBIFS_MST_LNUM || lnum == UBIFS_MST_LNUM + 1) { if (chance(19, 20)) return 0; - ubifs_warn("failing in master LEB %d", lnum); + ubifs_warn(c, "failing in master LEB %d", lnum); } else if (lnum >= UBIFS_LOG_LNUM && lnum <= c->log_last) { if (write && chance(99, 100)) return 0; if (chance(399, 400)) return 0; - ubifs_warn("failing in log LEB %d", lnum); + ubifs_warn(c, "failing in log LEB %d", lnum); } else if (lnum >= c->lpt_first && lnum <= c->lpt_last) { if (write && chance(7, 8)) return 0; if (chance(19, 20)) return 0; - ubifs_warn("failing in LPT LEB %d", lnum); + ubifs_warn(c, "failing in LPT LEB %d", lnum); } else if (lnum >= c->orph_first && lnum <= c->orph_last) { if (write && chance(1, 2)) return 0; if (chance(9, 10)) return 0; - ubifs_warn("failing in orphan LEB %d", lnum); + ubifs_warn(c, "failing in orphan LEB %d", lnum); } else if (lnum == c->ihead_lnum) { if (chance(99, 100)) return 0; - ubifs_warn("failing in index head LEB %d", lnum); + ubifs_warn(c, "failing in index head LEB %d", lnum); } else if (c->jheads && lnum == c->jheads[GCHD].wbuf.lnum) { if (chance(9, 10)) return 0; - ubifs_warn("failing in GC head LEB %d", lnum); + ubifs_warn(c, "failing in GC head LEB %d", lnum); } else if (write && !RB_EMPTY_ROOT(&c->buds) && !ubifs_search_bud(c, lnum)) { if (chance(19, 20)) return 0; - ubifs_warn("failing in non-bud LEB %d", lnum); + ubifs_warn(c, "failing in non-bud LEB %d", lnum); } else if (c->cmt_state == COMMIT_RUNNING_BACKGROUND || c->cmt_state == COMMIT_RUNNING_REQUIRED) { if (chance(999, 1000)) return 0; - ubifs_warn("failing in bud LEB %d commit running", lnum); + ubifs_warn(c, "failing in bud LEB %d commit running", lnum); } else { if (chance(9999, 10000)) return 0; - ubifs_warn("failing in bud LEB %d commit not running", lnum); + ubifs_warn(c, "failing in bud LEB %d commit not running", lnum); } d->pc_happened = 1; - ubifs_warn("========== Power cut emulated =========="); + ubifs_warn(c, "========== Power cut emulated =========="); dump_stack(); return 1; } @@ -2557,7 +2557,7 @@ static int corrupt_data(const struct ubifs_info *c, const void *buf, /* Corruption span max to end of write unit */ to = min(len, ALIGN(from + 1, c->max_write_size)); - ubifs_warn("filled bytes %u-%u with %s", from, to - 1, + ubifs_warn(c, "filled bytes %u-%u with %s", from, to - 1, ffs ? "0xFFs" : "random data"); if (ffs) @@ -2579,7 +2579,7 @@ int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf, failing = power_cut_emulated(c, lnum, 1); if (failing) { len = corrupt_data(c, buf, len); - ubifs_warn("actually write %d bytes to LEB %d:%d (the buffer was corrupted)", + ubifs_warn(c, "actually write %d bytes to LEB %d:%d (the buffer was corrupted)", len, lnum, offs); } err = ubi_leb_write(c->ubi, lnum, buf, offs, len); @@ -2909,7 +2909,7 @@ out_remove: debugfs_remove_recursive(d->dfs_dir); out: err = dent ? PTR_ERR(dent) : -ENODEV; - ubifs_err("cannot create \"%s\" debugfs file or directory, error %d\n", + ubifs_err(c, "cannot create \"%s\" debugfs file or directory, error %d\n", fname, err); return err; } @@ -3063,8 +3063,8 @@ out_remove: debugfs_remove_recursive(dfs_rootdir); out: err = dent ? PTR_ERR(dent) : -ENODEV; - ubifs_err("cannot create \"%s\" debugfs file or directory, error %d\n", - fname, err); + pr_err("UBIFS error (pid %d): cannot create \"%s\" debugfs file or directory, error %d\n", + current->pid, fname, err); return err; } diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 5b24bc42cad9..90fe60c2f112 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -146,12 +146,12 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir, if (c->highest_inum >= INUM_WARN_WATERMARK) { if (c->highest_inum >= INUM_WATERMARK) { spin_unlock(&c->cnt_lock); - ubifs_err("out of inode numbers"); + ubifs_err(c, "out of inode numbers"); make_bad_inode(inode); iput(inode); return ERR_PTR(-EINVAL); } - ubifs_warn("running out of inode numbers (current %lu, max %d)", + ubifs_warn(c, "running out of inode numbers (current %lu, max %d)", (unsigned long)c->highest_inum, INUM_WATERMARK); } @@ -222,7 +222,7 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, * checking. */ err = PTR_ERR(inode); - ubifs_err("dead directory entry '%pd', error %d", + ubifs_err(c, "dead directory entry '%pd', error %d", dentry, err); ubifs_ro_mode(c, err); goto out; @@ -297,7 +297,7 @@ out_inode: iput(inode); out_budg: ubifs_release_budget(c, &req); - ubifs_err("cannot create regular file, error %d", err); + ubifs_err(c, "cannot create regular file, error %d", err); return err; } @@ -450,7 +450,7 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx) out: if (err != -ENOENT) { - ubifs_err("cannot find next direntry, error %d", err); + ubifs_err(c, "cannot find next direntry, error %d", err); return err; } @@ -744,7 +744,7 @@ static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) dir->i_mtime = dir->i_ctime = inode->i_ctime; err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0); if (err) { - ubifs_err("cannot create directory, error %d", err); + ubifs_err(c, "cannot create directory, error %d", err); goto out_cancel; } mutex_unlock(&dir_ui->ui_mutex); diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index e627c0acf626..9cd12976ed1b 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -80,7 +80,7 @@ static int read_block(struct inode *inode, void *addr, unsigned int block, dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ; out_len = UBIFS_BLOCK_SIZE; - err = ubifs_decompress(&dn->data, dlen, addr, &out_len, + err = ubifs_decompress(c, &dn->data, dlen, addr, &out_len, le16_to_cpu(dn->compr_type)); if (err || len != out_len) goto dump; @@ -96,7 +96,7 @@ static int read_block(struct inode *inode, void *addr, unsigned int block, return 0; dump: - ubifs_err("bad data node (block %u, inode %lu)", + ubifs_err(c, "bad data node (block %u, inode %lu)", block, inode->i_ino); ubifs_dump_node(c, dn); return -EINVAL; @@ -161,13 +161,14 @@ static int do_readpage(struct page *page) addr += UBIFS_BLOCK_SIZE; } if (err) { + struct ubifs_info *c = inode->i_sb->s_fs_info; if (err == -ENOENT) { /* Not found, so it must be a hole */ SetPageChecked(page); dbg_gen("hole"); goto out_free; } - ubifs_err("cannot read page %lu of inode %lu, error %d", + ubifs_err(c, "cannot read page %lu of inode %lu, error %d", page->index, inode->i_ino, err); goto error; } @@ -650,7 +651,7 @@ static int populate_page(struct ubifs_info *c, struct page *page, dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ; out_len = UBIFS_BLOCK_SIZE; - err = ubifs_decompress(&dn->data, dlen, addr, &out_len, + err = ubifs_decompress(c, &dn->data, dlen, addr, &out_len, le16_to_cpu(dn->compr_type)); if (err || len != out_len) goto out_err; @@ -698,7 +699,7 @@ out_err: SetPageError(page); flush_dcache_page(page); kunmap(page); - ubifs_err("bad data node (block %u, inode %lu)", + ubifs_err(c, "bad data node (block %u, inode %lu)", page_block, inode->i_ino); return -EINVAL; } @@ -802,7 +803,7 @@ out_free: return ret; out_warn: - ubifs_warn("ignoring error %d and skipping bulk-read", err); + ubifs_warn(c, "ignoring error %d and skipping bulk-read", err); goto out_free; out_bu_off: @@ -930,7 +931,7 @@ static int do_writepage(struct page *page, int len) } if (err) { SetPageError(page); - ubifs_err("cannot write page %lu of inode %lu, error %d", + ubifs_err(c, "cannot write page %lu of inode %lu, error %d", page->index, inode->i_ino, err); ubifs_ro_mode(c, err); } @@ -1485,7 +1486,7 @@ static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, err = ubifs_budget_space(c, &req); if (unlikely(err)) { if (err == -ENOSPC) - ubifs_warn("out of space for mmapped file (inode number %lu)", + ubifs_warn(c, "out of space for mmapped file (inode number %lu)", inode->i_ino); return VM_FAULT_SIGBUS; } diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index fb08b0c514b6..97be41215332 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -85,7 +85,7 @@ void ubifs_ro_mode(struct ubifs_info *c, int err) c->ro_error = 1; c->no_chk_data_crc = 0; c->vfs_sb->s_flags |= MS_RDONLY; - ubifs_warn("switched to read-only mode, error %d", err); + ubifs_warn(c, "switched to read-only mode, error %d", err); dump_stack(); } } @@ -107,7 +107,7 @@ int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs, * @even_ebadmsg is true. */ if (err && (err != -EBADMSG || even_ebadmsg)) { - ubifs_err("reading %d bytes from LEB %d:%d failed, error %d", + ubifs_err(c, "reading %d bytes from LEB %d:%d failed, error %d", len, lnum, offs, err); dump_stack(); } @@ -127,7 +127,7 @@ int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs, else err = dbg_leb_write(c, lnum, buf, offs, len); if (err) { - ubifs_err("writing %d bytes to LEB %d:%d failed, error %d", + ubifs_err(c, "writing %d bytes to LEB %d:%d failed, error %d", len, lnum, offs, err); ubifs_ro_mode(c, err); dump_stack(); @@ -147,7 +147,7 @@ int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len) else err = dbg_leb_change(c, lnum, buf, len); if (err) { - ubifs_err("changing %d bytes in LEB %d failed, error %d", + ubifs_err(c, "changing %d bytes in LEB %d failed, error %d", len, lnum, err); ubifs_ro_mode(c, err); dump_stack(); @@ -167,7 +167,7 @@ int ubifs_leb_unmap(struct ubifs_info *c, int lnum) else err = dbg_leb_unmap(c, lnum); if (err) { - ubifs_err("unmap LEB %d failed, error %d", lnum, err); + ubifs_err(c, "unmap LEB %d failed, error %d", lnum, err); ubifs_ro_mode(c, err); dump_stack(); } @@ -186,7 +186,7 @@ int ubifs_leb_map(struct ubifs_info *c, int lnum) else err = dbg_leb_map(c, lnum); if (err) { - ubifs_err("mapping LEB %d failed, error %d", lnum, err); + ubifs_err(c, "mapping LEB %d failed, error %d", lnum, err); ubifs_ro_mode(c, err); dump_stack(); } @@ -199,7 +199,7 @@ int ubifs_is_mapped(const struct ubifs_info *c, int lnum) err = ubi_is_mapped(c->ubi, lnum); if (err < 0) { - ubifs_err("ubi_is_mapped failed for LEB %d, error %d", + ubifs_err(c, "ubi_is_mapped failed for LEB %d, error %d", lnum, err); dump_stack(); } @@ -247,7 +247,7 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, magic = le32_to_cpu(ch->magic); if (magic != UBIFS_NODE_MAGIC) { if (!quiet) - ubifs_err("bad magic %#08x, expected %#08x", + ubifs_err(c, "bad magic %#08x, expected %#08x", magic, UBIFS_NODE_MAGIC); err = -EUCLEAN; goto out; @@ -256,7 +256,7 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, type = ch->node_type; if (type < 0 || type >= UBIFS_NODE_TYPES_CNT) { if (!quiet) - ubifs_err("bad node type %d", type); + ubifs_err(c, "bad node type %d", type); goto out; } @@ -279,7 +279,7 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, node_crc = le32_to_cpu(ch->crc); if (crc != node_crc) { if (!quiet) - ubifs_err("bad CRC: calculated %#08x, read %#08x", + ubifs_err(c, "bad CRC: calculated %#08x, read %#08x", crc, node_crc); err = -EUCLEAN; goto out; @@ -289,10 +289,10 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, out_len: if (!quiet) - ubifs_err("bad node length %d", node_len); + ubifs_err(c, "bad node length %d", node_len); out: if (!quiet) { - ubifs_err("bad node at LEB %d:%d", lnum, offs); + ubifs_err(c, "bad node at LEB %d:%d", lnum, offs); ubifs_dump_node(c, buf); dump_stack(); } @@ -355,11 +355,11 @@ static unsigned long long next_sqnum(struct ubifs_info *c) if (unlikely(sqnum >= SQNUM_WARN_WATERMARK)) { if (sqnum >= SQNUM_WATERMARK) { - ubifs_err("sequence number overflow %llu, end of life", + ubifs_err(c, "sequence number overflow %llu, end of life", sqnum); ubifs_ro_mode(c, -EINVAL); } - ubifs_warn("running out of sequence numbers, end of life soon"); + ubifs_warn(c, "running out of sequence numbers, end of life soon"); } return sqnum; @@ -636,7 +636,7 @@ int ubifs_bg_wbufs_sync(struct ubifs_info *c) err = ubifs_wbuf_sync_nolock(wbuf); mutex_unlock(&wbuf->io_mutex); if (err) { - ubifs_err("cannot sync write-buffer, error %d", err); + ubifs_err(c, "cannot sync write-buffer, error %d", err); ubifs_ro_mode(c, err); goto out_timers; } @@ -833,7 +833,7 @@ exit: return 0; out: - ubifs_err("cannot write %d bytes to LEB %d:%d, error %d", + ubifs_err(c, "cannot write %d bytes to LEB %d:%d, error %d", len, wbuf->lnum, wbuf->offs, err); ubifs_dump_node(c, buf); dump_stack(); @@ -932,27 +932,27 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len, } if (type != ch->node_type) { - ubifs_err("bad node type (%d but expected %d)", + ubifs_err(c, "bad node type (%d but expected %d)", ch->node_type, type); goto out; } err = ubifs_check_node(c, buf, lnum, offs, 0, 0); if (err) { - ubifs_err("expected node type %d", type); + ubifs_err(c, "expected node type %d", type); return err; } rlen = le32_to_cpu(ch->len); if (rlen != len) { - ubifs_err("bad node length %d, expected %d", rlen, len); + ubifs_err(c, "bad node length %d, expected %d", rlen, len); goto out; } return 0; out: - ubifs_err("bad node at LEB %d:%d", lnum, offs); + ubifs_err(c, "bad node at LEB %d:%d", lnum, offs); ubifs_dump_node(c, buf); dump_stack(); return -EINVAL; diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c index 648b143606cc..3c7b29de0ca7 100644 --- a/fs/ubifs/ioctl.c +++ b/fs/ubifs/ioctl.c @@ -138,7 +138,7 @@ static int setflags(struct inode *inode, int flags) return err; out_unlock: - ubifs_err("can't modify inode %lu attributes", inode->i_ino); + ubifs_err(c, "can't modify inode %lu attributes", inode->i_ino); mutex_unlock(&ui->ui_mutex); ubifs_release_budget(c, &req); return err; diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index f6ac3f29323c..90ae1a8439d9 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -363,11 +363,11 @@ again: * This should not happen unless the journal size limitations * are too tough. */ - ubifs_err("stuck in space allocation"); + ubifs_err(c, "stuck in space allocation"); err = -ENOSPC; goto out; } else if (cmt_retries > 32) - ubifs_warn("too many space allocation re-tries (%d)", + ubifs_warn(c, "too many space allocation re-tries (%d)", cmt_retries); dbg_jnl("-EAGAIN, commit and retry (retried %d times)", @@ -380,7 +380,7 @@ again: goto again; out: - ubifs_err("cannot reserve %d bytes in jhead %d, error %d", + ubifs_err(c, "cannot reserve %d bytes in jhead %d, error %d", len, jhead, err); if (err == -ENOSPC) { /* This are some budgeting problems, print useful information */ @@ -731,7 +731,7 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode, compr_type = ui->compr_type; out_len = dlen - UBIFS_DATA_NODE_SZ; - ubifs_compress(buf, len, &data->data, &out_len, &compr_type); + ubifs_compress(c, buf, len, &data->data, &out_len, &compr_type); ubifs_assert(out_len <= UBIFS_BLOCK_SIZE); dlen = UBIFS_DATA_NODE_SZ + out_len; @@ -1100,7 +1100,8 @@ out_free: * This function is used when an inode is truncated and the last data node of * the inode has to be re-compressed and re-written. */ -static int recomp_data_node(struct ubifs_data_node *dn, int *new_len) +static int recomp_data_node(const struct ubifs_info *c, + struct ubifs_data_node *dn, int *new_len) { void *buf; int err, len, compr_type, out_len; @@ -1112,11 +1113,11 @@ static int recomp_data_node(struct ubifs_data_node *dn, int *new_len) len = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ; compr_type = le16_to_cpu(dn->compr_type); - err = ubifs_decompress(&dn->data, len, buf, &out_len, compr_type); + err = ubifs_decompress(c, &dn->data, len, buf, &out_len, compr_type); if (err) goto out; - ubifs_compress(buf, *new_len, &dn->data, &out_len, &compr_type); + ubifs_compress(c, buf, *new_len, &dn->data, &out_len, &compr_type); ubifs_assert(out_len <= UBIFS_BLOCK_SIZE); dn->compr_type = cpu_to_le16(compr_type); dn->size = cpu_to_le32(*new_len); @@ -1191,7 +1192,7 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode, int compr_type = le16_to_cpu(dn->compr_type); if (compr_type != UBIFS_COMPR_NONE) { - err = recomp_data_node(dn, &dlen); + err = recomp_data_node(c, dn, &dlen); if (err) goto out_free; } else { diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c index c14628fbeee2..8c795e6392b1 100644 --- a/fs/ubifs/log.c +++ b/fs/ubifs/log.c @@ -696,7 +696,7 @@ int ubifs_consolidate_log(struct ubifs_info *c) destroy_done_tree(&done_tree); vfree(buf); if (write_lnum == c->lhead_lnum) { - ubifs_err("log is too full"); + ubifs_err(c, "log is too full"); return -EINVAL; } /* Unmap remaining LEBs */ @@ -743,7 +743,7 @@ static int dbg_check_bud_bytes(struct ubifs_info *c) bud_bytes += c->leb_size - bud->start; if (c->bud_bytes != bud_bytes) { - ubifs_err("bad bud_bytes %lld, calculated %lld", + ubifs_err(c, "bad bud_bytes %lld, calculated %lld", c->bud_bytes, bud_bytes); err = -EINVAL; } diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c index 46190a7c42a6..a0011aa3a779 100644 --- a/fs/ubifs/lprops.c +++ b/fs/ubifs/lprops.c @@ -682,7 +682,7 @@ int ubifs_change_one_lp(struct ubifs_info *c, int lnum, int free, int dirty, out: ubifs_release_lprops(c); if (err) - ubifs_err("cannot change properties of LEB %d, error %d", + ubifs_err(c, "cannot change properties of LEB %d, error %d", lnum, err); return err; } @@ -721,7 +721,7 @@ int ubifs_update_one_lp(struct ubifs_info *c, int lnum, int free, int dirty, out: ubifs_release_lprops(c); if (err) - ubifs_err("cannot update properties of LEB %d, error %d", + ubifs_err(c, "cannot update properties of LEB %d, error %d", lnum, err); return err; } @@ -746,7 +746,7 @@ int ubifs_read_one_lp(struct ubifs_info *c, int lnum, struct ubifs_lprops *lp) lpp = ubifs_lpt_lookup(c, lnum); if (IS_ERR(lpp)) { err = PTR_ERR(lpp); - ubifs_err("cannot read properties of LEB %d, error %d", + ubifs_err(c, "cannot read properties of LEB %d, error %d", lnum, err); goto out; } @@ -873,13 +873,13 @@ int dbg_check_cats(struct ubifs_info *c) list_for_each_entry(lprops, &c->empty_list, list) { if (lprops->free != c->leb_size) { - ubifs_err("non-empty LEB %d on empty list (free %d dirty %d flags %d)", + ubifs_err(c, "non-empty LEB %d on empty list (free %d dirty %d flags %d)", lprops->lnum, lprops->free, lprops->dirty, lprops->flags); return -EINVAL; } if (lprops->flags & LPROPS_TAKEN) { - ubifs_err("taken LEB %d on empty list (free %d dirty %d flags %d)", + ubifs_err(c, "taken LEB %d on empty list (free %d dirty %d flags %d)", lprops->lnum, lprops->free, lprops->dirty, lprops->flags); return -EINVAL; @@ -889,13 +889,13 @@ int dbg_check_cats(struct ubifs_info *c) i = 0; list_for_each_entry(lprops, &c->freeable_list, list) { if (lprops->free + lprops->dirty != c->leb_size) { - ubifs_err("non-freeable LEB %d on freeable list (free %d dirty %d flags %d)", + ubifs_err(c, "non-freeable LEB %d on freeable list (free %d dirty %d flags %d)", lprops->lnum, lprops->free, lprops->dirty, lprops->flags); return -EINVAL; } if (lprops->flags & LPROPS_TAKEN) { - ubifs_err("taken LEB %d on freeable list (free %d dirty %d flags %d)", + ubifs_err(c, "taken LEB %d on freeable list (free %d dirty %d flags %d)", lprops->lnum, lprops->free, lprops->dirty, lprops->flags); return -EINVAL; @@ -903,7 +903,7 @@ int dbg_check_cats(struct ubifs_info *c) i += 1; } if (i != c->freeable_cnt) { - ubifs_err("freeable list count %d expected %d", i, + ubifs_err(c, "freeable list count %d expected %d", i, c->freeable_cnt); return -EINVAL; } @@ -912,26 +912,26 @@ int dbg_check_cats(struct ubifs_info *c) list_for_each(pos, &c->idx_gc) i += 1; if (i != c->idx_gc_cnt) { - ubifs_err("idx_gc list count %d expected %d", i, + ubifs_err(c, "idx_gc list count %d expected %d", i, c->idx_gc_cnt); return -EINVAL; } list_for_each_entry(lprops, &c->frdi_idx_list, list) { if (lprops->free + lprops->dirty != c->leb_size) { - ubifs_err("non-freeable LEB %d on frdi_idx list (free %d dirty %d flags %d)", + ubifs_err(c, "non-freeable LEB %d on frdi_idx list (free %d dirty %d flags %d)", lprops->lnum, lprops->free, lprops->dirty, lprops->flags); return -EINVAL; } if (lprops->flags & LPROPS_TAKEN) { - ubifs_err("taken LEB %d on frdi_idx list (free %d dirty %d flags %d)", + ubifs_err(c, "taken LEB %d on frdi_idx list (free %d dirty %d flags %d)", lprops->lnum, lprops->free, lprops->dirty, lprops->flags); return -EINVAL; } if (!(lprops->flags & LPROPS_INDEX)) { - ubifs_err("non-index LEB %d on frdi_idx list (free %d dirty %d flags %d)", + ubifs_err(c, "non-index LEB %d on frdi_idx list (free %d dirty %d flags %d)", lprops->lnum, lprops->free, lprops->dirty, lprops->flags); return -EINVAL; @@ -944,15 +944,15 @@ int dbg_check_cats(struct ubifs_info *c) for (i = 0; i < heap->cnt; i++) { lprops = heap->arr[i]; if (!lprops) { - ubifs_err("null ptr in LPT heap cat %d", cat); + ubifs_err(c, "null ptr in LPT heap cat %d", cat); return -EINVAL; } if (lprops->hpos != i) { - ubifs_err("bad ptr in LPT heap cat %d", cat); + ubifs_err(c, "bad ptr in LPT heap cat %d", cat); return -EINVAL; } if (lprops->flags & LPROPS_TAKEN) { - ubifs_err("taken LEB in LPT heap cat %d", cat); + ubifs_err(c, "taken LEB in LPT heap cat %d", cat); return -EINVAL; } } @@ -988,7 +988,7 @@ void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat, goto out; } if (lprops != lp) { - ubifs_err("lprops %zx lp %zx lprops->lnum %d lp->lnum %d", + ubifs_err(c, "lprops %zx lp %zx lprops->lnum %d lp->lnum %d", (size_t)lprops, (size_t)lp, lprops->lnum, lp->lnum); err = 4; @@ -1008,7 +1008,7 @@ void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat, } out: if (err) { - ubifs_err("failed cat %d hpos %d err %d", cat, i, err); + ubifs_err(c, "failed cat %d hpos %d err %d", cat, i, err); dump_stack(); ubifs_dump_heap(c, heap, cat); } @@ -1039,7 +1039,7 @@ static int scan_check_cb(struct ubifs_info *c, if (cat != LPROPS_UNCAT) { cat = ubifs_categorize_lprops(c, lp); if (cat != (lp->flags & LPROPS_CAT_MASK)) { - ubifs_err("bad LEB category %d expected %d", + ubifs_err(c, "bad LEB category %d expected %d", (lp->flags & LPROPS_CAT_MASK), cat); return -EINVAL; } @@ -1074,7 +1074,7 @@ static int scan_check_cb(struct ubifs_info *c, } } if (!found) { - ubifs_err("bad LPT list (category %d)", cat); + ubifs_err(c, "bad LPT list (category %d)", cat); return -EINVAL; } } @@ -1086,7 +1086,7 @@ static int scan_check_cb(struct ubifs_info *c, if ((lp->hpos != -1 && heap->arr[lp->hpos]->lnum != lnum) || lp != heap->arr[lp->hpos]) { - ubifs_err("bad LPT heap (category %d)", cat); + ubifs_err(c, "bad LPT heap (category %d)", cat); return -EINVAL; } } @@ -1133,7 +1133,7 @@ static int scan_check_cb(struct ubifs_info *c, is_idx = (snod->type == UBIFS_IDX_NODE) ? 1 : 0; if (is_idx && snod->type != UBIFS_IDX_NODE) { - ubifs_err("indexing node in data LEB %d:%d", + ubifs_err(c, "indexing node in data LEB %d:%d", lnum, snod->offs); goto out_destroy; } @@ -1159,7 +1159,7 @@ static int scan_check_cb(struct ubifs_info *c, if (free > c->leb_size || free < 0 || dirty > c->leb_size || dirty < 0) { - ubifs_err("bad calculated accounting for LEB %d: free %d, dirty %d", + ubifs_err(c, "bad calculated accounting for LEB %d: free %d, dirty %d", lnum, free, dirty); goto out_destroy; } @@ -1206,13 +1206,13 @@ static int scan_check_cb(struct ubifs_info *c, /* Free but not unmapped LEB, it's fine */ is_idx = 0; else { - ubifs_err("indexing node without indexing flag"); + ubifs_err(c, "indexing node without indexing flag"); goto out_print; } } if (!is_idx && (lp->flags & LPROPS_INDEX)) { - ubifs_err("data node with indexing flag"); + ubifs_err(c, "data node with indexing flag"); goto out_print; } @@ -1241,7 +1241,7 @@ static int scan_check_cb(struct ubifs_info *c, return LPT_SCAN_CONTINUE; out_print: - ubifs_err("bad accounting of LEB %d: free %d, dirty %d flags %#x, should be free %d, dirty %d", + ubifs_err(c, "bad accounting of LEB %d: free %d, dirty %d flags %#x, should be free %d, dirty %d", lnum, lp->free, lp->dirty, lp->flags, free, dirty); ubifs_dump_leb(c, lnum); out_destroy: @@ -1293,11 +1293,11 @@ int dbg_check_lprops(struct ubifs_info *c) lst.total_free != c->lst.total_free || lst.total_dirty != c->lst.total_dirty || lst.total_used != c->lst.total_used) { - ubifs_err("bad overall accounting"); - ubifs_err("calculated: empty_lebs %d, idx_lebs %d, total_free %lld, total_dirty %lld, total_used %lld", + ubifs_err(c, "bad overall accounting"); + ubifs_err(c, "calculated: empty_lebs %d, idx_lebs %d, total_free %lld, total_dirty %lld, total_used %lld", lst.empty_lebs, lst.idx_lebs, lst.total_free, lst.total_dirty, lst.total_used); - ubifs_err("read from lprops: empty_lebs %d, idx_lebs %d, total_free %lld, total_dirty %lld, total_used %lld", + ubifs_err(c, "read from lprops: empty_lebs %d, idx_lebs %d, total_free %lld, total_dirty %lld, total_used %lld", c->lst.empty_lebs, c->lst.idx_lebs, c->lst.total_free, c->lst.total_dirty, c->lst.total_used); err = -EINVAL; @@ -1306,10 +1306,10 @@ int dbg_check_lprops(struct ubifs_info *c) if (lst.total_dead != c->lst.total_dead || lst.total_dark != c->lst.total_dark) { - ubifs_err("bad dead/dark space accounting"); - ubifs_err("calculated: total_dead %lld, total_dark %lld", + ubifs_err(c, "bad dead/dark space accounting"); + ubifs_err(c, "calculated: total_dead %lld, total_dark %lld", lst.total_dead, lst.total_dark); - ubifs_err("read from lprops: total_dead %lld, total_dark %lld", + ubifs_err(c, "read from lprops: total_dead %lld, total_dark %lld", c->lst.total_dead, c->lst.total_dark); err = -EINVAL; goto out; diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c index 421bd0a80424..dc9f27e9d61b 100644 --- a/fs/ubifs/lpt.c +++ b/fs/ubifs/lpt.c @@ -145,13 +145,13 @@ int ubifs_calc_lpt_geom(struct ubifs_info *c) sz = c->lpt_sz * 2; /* Must have at least 2 times the size */ lebs_needed = div_u64(sz + c->leb_size - 1, c->leb_size); if (lebs_needed > c->lpt_lebs) { - ubifs_err("too few LPT LEBs"); + ubifs_err(c, "too few LPT LEBs"); return -EINVAL; } /* Verify that ltab fits in a single LEB (since ltab is a single node */ if (c->ltab_sz > c->leb_size) { - ubifs_err("LPT ltab too big"); + ubifs_err(c, "LPT ltab too big"); return -EINVAL; } @@ -213,7 +213,7 @@ static int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs, continue; } if (c->ltab_sz > c->leb_size) { - ubifs_err("LPT ltab too big"); + ubifs_err(c, "LPT ltab too big"); return -EINVAL; } *main_lebs = c->main_lebs; @@ -911,7 +911,7 @@ static void replace_cats(struct ubifs_info *c, struct ubifs_pnode *old_pnode, * * This function returns %0 on success and a negative error code on failure. */ -static int check_lpt_crc(void *buf, int len) +static int check_lpt_crc(const struct ubifs_info *c, void *buf, int len) { int pos = 0; uint8_t *addr = buf; @@ -921,8 +921,8 @@ static int check_lpt_crc(void *buf, int len) calc_crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES, len - UBIFS_LPT_CRC_BYTES); if (crc != calc_crc) { - ubifs_err("invalid crc in LPT node: crc %hx calc %hx", crc, - calc_crc); + ubifs_err(c, "invalid crc in LPT node: crc %hx calc %hx", + crc, calc_crc); dump_stack(); return -EINVAL; } @@ -938,14 +938,15 @@ static int check_lpt_crc(void *buf, int len) * * This function returns %0 on success and a negative error code on failure. */ -static int check_lpt_type(uint8_t **addr, int *pos, int type) +static int check_lpt_type(const struct ubifs_info *c, uint8_t **addr, + int *pos, int type) { int node_type; node_type = ubifs_unpack_bits(addr, pos, UBIFS_LPT_TYPE_BITS); if (node_type != type) { - ubifs_err("invalid type (%d) in LPT node type %d", node_type, - type); + ubifs_err(c, "invalid type (%d) in LPT node type %d", + node_type, type); dump_stack(); return -EINVAL; } @@ -966,7 +967,7 @@ static int unpack_pnode(const struct ubifs_info *c, void *buf, uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; int i, pos = 0, err; - err = check_lpt_type(&addr, &pos, UBIFS_LPT_PNODE); + err = check_lpt_type(c, &addr, &pos, UBIFS_LPT_PNODE); if (err) return err; if (c->big_lpt) @@ -985,7 +986,7 @@ static int unpack_pnode(const struct ubifs_info *c, void *buf, lprops->flags = 0; lprops->flags |= ubifs_categorize_lprops(c, lprops); } - err = check_lpt_crc(buf, c->pnode_sz); + err = check_lpt_crc(c, buf, c->pnode_sz); return err; } @@ -1003,7 +1004,7 @@ int ubifs_unpack_nnode(const struct ubifs_info *c, void *buf, uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; int i, pos = 0, err; - err = check_lpt_type(&addr, &pos, UBIFS_LPT_NNODE); + err = check_lpt_type(c, &addr, &pos, UBIFS_LPT_NNODE); if (err) return err; if (c->big_lpt) @@ -1019,7 +1020,7 @@ int ubifs_unpack_nnode(const struct ubifs_info *c, void *buf, nnode->nbranch[i].offs = ubifs_unpack_bits(&addr, &pos, c->lpt_offs_bits); } - err = check_lpt_crc(buf, c->nnode_sz); + err = check_lpt_crc(c, buf, c->nnode_sz); return err; } @@ -1035,7 +1036,7 @@ static int unpack_ltab(const struct ubifs_info *c, void *buf) uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; int i, pos = 0, err; - err = check_lpt_type(&addr, &pos, UBIFS_LPT_LTAB); + err = check_lpt_type(c, &addr, &pos, UBIFS_LPT_LTAB); if (err) return err; for (i = 0; i < c->lpt_lebs; i++) { @@ -1051,7 +1052,7 @@ static int unpack_ltab(const struct ubifs_info *c, void *buf) c->ltab[i].tgc = 0; c->ltab[i].cmt = 0; } - err = check_lpt_crc(buf, c->ltab_sz); + err = check_lpt_crc(c, buf, c->ltab_sz); return err; } @@ -1067,7 +1068,7 @@ static int unpack_lsave(const struct ubifs_info *c, void *buf) uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; int i, pos = 0, err; - err = check_lpt_type(&addr, &pos, UBIFS_LPT_LSAVE); + err = check_lpt_type(c, &addr, &pos, UBIFS_LPT_LSAVE); if (err) return err; for (i = 0; i < c->lsave_cnt; i++) { @@ -1077,7 +1078,7 @@ static int unpack_lsave(const struct ubifs_info *c, void *buf) return -EINVAL; c->lsave[i] = lnum; } - err = check_lpt_crc(buf, c->lsave_sz); + err = check_lpt_crc(c, buf, c->lsave_sz); return err; } @@ -1243,7 +1244,7 @@ int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip) return 0; out: - ubifs_err("error %d reading nnode at %d:%d", err, lnum, offs); + ubifs_err(c, "error %d reading nnode at %d:%d", err, lnum, offs); dump_stack(); kfree(nnode); return err; @@ -1308,10 +1309,10 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip) return 0; out: - ubifs_err("error %d reading pnode at %d:%d", err, lnum, offs); + ubifs_err(c, "error %d reading pnode at %d:%d", err, lnum, offs); ubifs_dump_pnode(c, pnode, parent, iip); dump_stack(); - ubifs_err("calc num: %d", calc_pnode_num_from_parent(c, parent, iip)); + ubifs_err(c, "calc num: %d", calc_pnode_num_from_parent(c, parent, iip)); kfree(pnode); return err; } @@ -2095,7 +2096,7 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, int i; if (pnode->num != col) { - ubifs_err("pnode num %d expected %d parent num %d iip %d", + ubifs_err(c, "pnode num %d expected %d parent num %d iip %d", pnode->num, col, pnode->parent->num, pnode->iip); return -EINVAL; } @@ -2110,13 +2111,13 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, if (lnum >= c->leb_cnt) continue; if (lprops->lnum != lnum) { - ubifs_err("bad LEB number %d expected %d", + ubifs_err(c, "bad LEB number %d expected %d", lprops->lnum, lnum); return -EINVAL; } if (lprops->flags & LPROPS_TAKEN) { if (cat != LPROPS_UNCAT) { - ubifs_err("LEB %d taken but not uncat %d", + ubifs_err(c, "LEB %d taken but not uncat %d", lprops->lnum, cat); return -EINVAL; } @@ -2129,7 +2130,7 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, case LPROPS_FRDI_IDX: break; default: - ubifs_err("LEB %d index but cat %d", + ubifs_err(c, "LEB %d index but cat %d", lprops->lnum, cat); return -EINVAL; } @@ -2142,7 +2143,7 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, case LPROPS_FREEABLE: break; default: - ubifs_err("LEB %d not index but cat %d", + ubifs_err(c, "LEB %d not index but cat %d", lprops->lnum, cat); return -EINVAL; } @@ -2183,14 +2184,14 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, break; } if (!found) { - ubifs_err("LEB %d cat %d not found in cat heap/list", + ubifs_err(c, "LEB %d cat %d not found in cat heap/list", lprops->lnum, cat); return -EINVAL; } switch (cat) { case LPROPS_EMPTY: if (lprops->free != c->leb_size) { - ubifs_err("LEB %d cat %d free %d dirty %d", + ubifs_err(c, "LEB %d cat %d free %d dirty %d", lprops->lnum, cat, lprops->free, lprops->dirty); return -EINVAL; @@ -2199,7 +2200,7 @@ static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, case LPROPS_FREEABLE: case LPROPS_FRDI_IDX: if (lprops->free + lprops->dirty != c->leb_size) { - ubifs_err("LEB %d cat %d free %d dirty %d", + ubifs_err(c, "LEB %d cat %d free %d dirty %d", lprops->lnum, cat, lprops->free, lprops->dirty); return -EINVAL; @@ -2236,7 +2237,7 @@ int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode, /* cnode is a nnode */ num = calc_nnode_num(row, col); if (cnode->num != num) { - ubifs_err("nnode num %d expected %d parent num %d iip %d", + ubifs_err(c, "nnode num %d expected %d parent num %d iip %d", cnode->num, num, (nnode ? nnode->num : 0), cnode->iip); return -EINVAL; diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c index d9c02928e992..ce89bdc3eb02 100644 --- a/fs/ubifs/lpt_commit.c +++ b/fs/ubifs/lpt_commit.c @@ -319,7 +319,7 @@ static int layout_cnodes(struct ubifs_info *c) return 0; no_space: - ubifs_err("LPT out of space at LEB %d:%d needing %d, done_ltab %d, done_lsave %d", + ubifs_err(c, "LPT out of space at LEB %d:%d needing %d, done_ltab %d, done_lsave %d", lnum, offs, len, done_ltab, done_lsave); ubifs_dump_lpt_info(c); ubifs_dump_lpt_lebs(c); @@ -543,7 +543,7 @@ static int write_cnodes(struct ubifs_info *c) return 0; no_space: - ubifs_err("LPT out of space mismatch at LEB %d:%d needing %d, done_ltab %d, done_lsave %d", + ubifs_err(c, "LPT out of space mismatch at LEB %d:%d needing %d, done_ltab %d, done_lsave %d", lnum, offs, len, done_ltab, done_lsave); ubifs_dump_lpt_info(c); ubifs_dump_lpt_lebs(c); @@ -1638,7 +1638,7 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum) buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); if (!buf) { - ubifs_err("cannot allocate memory for ltab checking"); + ubifs_err(c, "cannot allocate memory for ltab checking"); return 0; } @@ -1660,18 +1660,18 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum) continue; } if (!dbg_is_all_ff(p, len)) { - ubifs_err("invalid empty space in LEB %d at %d", + ubifs_err(c, "invalid empty space in LEB %d at %d", lnum, c->leb_size - len); err = -EINVAL; } i = lnum - c->lpt_first; if (len != c->ltab[i].free) { - ubifs_err("invalid free space in LEB %d (free %d, expected %d)", + ubifs_err(c, "invalid free space in LEB %d (free %d, expected %d)", lnum, len, c->ltab[i].free); err = -EINVAL; } if (dirty != c->ltab[i].dirty) { - ubifs_err("invalid dirty space in LEB %d (dirty %d, expected %d)", + ubifs_err(c, "invalid dirty space in LEB %d (dirty %d, expected %d)", lnum, dirty, c->ltab[i].dirty); err = -EINVAL; } @@ -1725,7 +1725,7 @@ int dbg_check_ltab(struct ubifs_info *c) for (lnum = c->lpt_first; lnum <= c->lpt_last; lnum++) { err = dbg_check_ltab_lnum(c, lnum); if (err) { - ubifs_err("failed at LEB %d", lnum); + ubifs_err(c, "failed at LEB %d", lnum); return err; } } @@ -1757,7 +1757,7 @@ int dbg_chk_lpt_free_spc(struct ubifs_info *c) free += c->leb_size; } if (free < c->lpt_sz) { - ubifs_err("LPT space error: free %lld lpt_sz %lld", + ubifs_err(c, "LPT space error: free %lld lpt_sz %lld", free, c->lpt_sz); ubifs_dump_lpt_info(c); ubifs_dump_lpt_lebs(c); @@ -1797,12 +1797,12 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len) d->chk_lpt_lebs = 0; d->chk_lpt_wastage = 0; if (c->dirty_pn_cnt > c->pnode_cnt) { - ubifs_err("dirty pnodes %d exceed max %d", + ubifs_err(c, "dirty pnodes %d exceed max %d", c->dirty_pn_cnt, c->pnode_cnt); err = -EINVAL; } if (c->dirty_nn_cnt > c->nnode_cnt) { - ubifs_err("dirty nnodes %d exceed max %d", + ubifs_err(c, "dirty nnodes %d exceed max %d", c->dirty_nn_cnt, c->nnode_cnt); err = -EINVAL; } @@ -1820,22 +1820,22 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len) chk_lpt_sz *= d->chk_lpt_lebs; chk_lpt_sz += len - c->nhead_offs; if (d->chk_lpt_sz != chk_lpt_sz) { - ubifs_err("LPT wrote %lld but space used was %lld", + ubifs_err(c, "LPT wrote %lld but space used was %lld", d->chk_lpt_sz, chk_lpt_sz); err = -EINVAL; } if (d->chk_lpt_sz > c->lpt_sz) { - ubifs_err("LPT wrote %lld but lpt_sz is %lld", + ubifs_err(c, "LPT wrote %lld but lpt_sz is %lld", d->chk_lpt_sz, c->lpt_sz); err = -EINVAL; } if (d->chk_lpt_sz2 && d->chk_lpt_sz != d->chk_lpt_sz2) { - ubifs_err("LPT layout size %lld but wrote %lld", + ubifs_err(c, "LPT layout size %lld but wrote %lld", d->chk_lpt_sz, d->chk_lpt_sz2); err = -EINVAL; } if (d->chk_lpt_sz2 && d->new_nhead_offs != len) { - ubifs_err("LPT new nhead offs: expected %d was %d", + ubifs_err(c, "LPT new nhead offs: expected %d was %d", d->new_nhead_offs, len); err = -EINVAL; } @@ -1845,7 +1845,7 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len) if (c->big_lpt) lpt_sz += c->lsave_sz; if (d->chk_lpt_sz - d->chk_lpt_wastage > lpt_sz) { - ubifs_err("LPT chk_lpt_sz %lld + waste %lld exceeds %lld", + ubifs_err(c, "LPT chk_lpt_sz %lld + waste %lld exceeds %lld", d->chk_lpt_sz, d->chk_lpt_wastage, lpt_sz); err = -EINVAL; } @@ -1887,7 +1887,7 @@ static void dump_lpt_leb(const struct ubifs_info *c, int lnum) pr_err("(pid %d) start dumping LEB %d\n", current->pid, lnum); buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); if (!buf) { - ubifs_err("cannot allocate memory to dump LPT"); + ubifs_err(c, "cannot allocate memory to dump LPT"); return; } @@ -1962,7 +1962,7 @@ static void dump_lpt_leb(const struct ubifs_info *c, int lnum) pr_err("LEB %d:%d, lsave len\n", lnum, offs); break; default: - ubifs_err("LPT node type %d not recognized", node_type); + ubifs_err(c, "LPT node type %d not recognized", node_type); goto out; } diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c index 1a4bb9e8b3b8..c6a5e39e2ba5 100644 --- a/fs/ubifs/master.c +++ b/fs/ubifs/master.c @@ -82,7 +82,7 @@ out: return -EUCLEAN; out_dump: - ubifs_err("unexpected node type %d master LEB %d:%d", + ubifs_err(c, "unexpected node type %d master LEB %d:%d", snod->type, lnum, snod->offs); ubifs_scan_destroy(sleb); return -EINVAL; @@ -240,7 +240,7 @@ static int validate_master(const struct ubifs_info *c) return 0; out: - ubifs_err("bad master node at offset %d error %d", c->mst_offs, err); + ubifs_err(c, "bad master node at offset %d error %d", c->mst_offs, err); ubifs_dump_node(c, c->mst_node); return -EINVAL; } @@ -316,7 +316,7 @@ int ubifs_read_master(struct ubifs_info *c) if (c->leb_cnt < old_leb_cnt || c->leb_cnt < UBIFS_MIN_LEB_CNT) { - ubifs_err("bad leb_cnt on master node"); + ubifs_err(c, "bad leb_cnt on master node"); ubifs_dump_node(c, c->mst_node); return -EINVAL; } diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c index 4409f486ecef..caf2d123e9ee 100644 --- a/fs/ubifs/orphan.c +++ b/fs/ubifs/orphan.c @@ -88,7 +88,7 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum) else if (inum > o->inum) p = &(*p)->rb_right; else { - ubifs_err("orphaned twice"); + ubifs_err(c, "orphaned twice"); spin_unlock(&c->orphan_lock); kfree(orphan); return 0; @@ -155,7 +155,7 @@ void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum) } } spin_unlock(&c->orphan_lock); - ubifs_err("missing orphan ino %lu", (unsigned long)inum); + ubifs_err(c, "missing orphan ino %lu", (unsigned long)inum); dump_stack(); } @@ -287,7 +287,7 @@ static int write_orph_node(struct ubifs_info *c, int atomic) * We limit the number of orphans so that this should * never happen. */ - ubifs_err("out of space in orphan area"); + ubifs_err(c, "out of space in orphan area"); return -EINVAL; } } @@ -397,7 +397,7 @@ static int consolidate(struct ubifs_info *c) * We limit the number of orphans so that this should * never happen. */ - ubifs_err("out of space in orphan area"); + ubifs_err(c, "out of space in orphan area"); err = -EINVAL; } spin_unlock(&c->orphan_lock); @@ -569,7 +569,7 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb, list_for_each_entry(snod, &sleb->nodes, list) { if (snod->type != UBIFS_ORPH_NODE) { - ubifs_err("invalid node type %d in orphan area at %d:%d", + ubifs_err(c, "invalid node type %d in orphan area at %d:%d", snod->type, sleb->lnum, snod->offs); ubifs_dump_node(c, snod->node); return -EINVAL; @@ -596,7 +596,7 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb, * number. That makes this orphan node, out of date. */ if (!first) { - ubifs_err("out of order commit number %llu in orphan node at %d:%d", + ubifs_err(c, "out of order commit number %llu in orphan node at %d:%d", cmt_no, sleb->lnum, snod->offs); ubifs_dump_node(c, snod->node); return -EINVAL; @@ -831,20 +831,20 @@ static int dbg_orphan_check(struct ubifs_info *c, struct ubifs_zbranch *zbr, if (inum != ci->last_ino) { /* Lowest node type is the inode node, so it comes first */ if (key_type(c, &zbr->key) != UBIFS_INO_KEY) - ubifs_err("found orphan node ino %lu, type %d", + ubifs_err(c, "found orphan node ino %lu, type %d", (unsigned long)inum, key_type(c, &zbr->key)); ci->last_ino = inum; ci->tot_inos += 1; err = ubifs_tnc_read_node(c, zbr, ci->node); if (err) { - ubifs_err("node read failed, error %d", err); + ubifs_err(c, "node read failed, error %d", err); return err; } if (ci->node->nlink == 0) /* Must be recorded as an orphan */ if (!dbg_find_check_orphan(&ci->root, inum) && !dbg_find_orphan(c, inum)) { - ubifs_err("missing orphan, ino %lu", + ubifs_err(c, "missing orphan, ino %lu", (unsigned long)inum); ci->missing += 1; } @@ -887,7 +887,7 @@ static int dbg_scan_orphans(struct ubifs_info *c, struct check_info *ci) buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); if (!buf) { - ubifs_err("cannot allocate memory to check orphans"); + ubifs_err(c, "cannot allocate memory to check orphans"); return 0; } @@ -925,7 +925,7 @@ static int dbg_check_orphans(struct ubifs_info *c) ci.root = RB_ROOT; ci.node = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS); if (!ci.node) { - ubifs_err("out of memory"); + ubifs_err(c, "out of memory"); return -ENOMEM; } @@ -935,12 +935,12 @@ static int dbg_check_orphans(struct ubifs_info *c) err = dbg_walk_index(c, &dbg_orphan_check, NULL, &ci); if (err) { - ubifs_err("cannot scan TNC, error %d", err); + ubifs_err(c, "cannot scan TNC, error %d", err); goto out; } if (ci.missing) { - ubifs_err("%lu missing orphan(s)", ci.missing); + ubifs_err(c, "%lu missing orphan(s)", ci.missing); err = -EINVAL; goto out; } diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 13ca4dbc4d19..695fc71d5244 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c @@ -305,7 +305,7 @@ int ubifs_recover_master_node(struct ubifs_info *c) mst = mst2; } - ubifs_msg("recovered master node from LEB %d", + ubifs_msg(c, "recovered master node from LEB %d", (mst == mst1 ? UBIFS_MST_LNUM : UBIFS_MST_LNUM + 1)); memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ); @@ -360,13 +360,13 @@ int ubifs_recover_master_node(struct ubifs_info *c) out_err: err = -EINVAL; out_free: - ubifs_err("failed to recover master node"); + ubifs_err(c, "failed to recover master node"); if (mst1) { - ubifs_err("dumping first master node"); + ubifs_err(c, "dumping first master node"); ubifs_dump_node(c, mst1); } if (mst2) { - ubifs_err("dumping second master node"); + ubifs_err(c, "dumping second master node"); ubifs_dump_node(c, mst2); } vfree(buf2); @@ -682,7 +682,7 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, ret, lnum, offs); break; } else { - ubifs_err("unexpected return value %d", ret); + ubifs_err(c, "unexpected return value %d", ret); err = -EINVAL; goto error; } @@ -702,7 +702,7 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, * See header comment for this file for more * explanations about the reasons we have this check. */ - ubifs_err("corrupt empty space LEB %d:%d, corruption starts at %d", + ubifs_err(c, "corrupt empty space LEB %d:%d, corruption starts at %d", lnum, offs, corruption); /* Make sure we dump interesting non-0xFF data */ offs += corruption; @@ -788,13 +788,13 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, corrupted_rescan: /* Re-scan the corrupted data with verbose messages */ - ubifs_err("corruption %d", ret); + ubifs_err(c, "corruption %d", ret); ubifs_scan_a_node(c, buf, len, lnum, offs, 1); corrupted: ubifs_scanned_corruption(c, lnum, offs, buf); err = -EUCLEAN; error: - ubifs_err("LEB %d scanning failed", lnum); + ubifs_err(c, "LEB %d scanning failed", lnum); ubifs_scan_destroy(sleb); return ERR_PTR(err); } @@ -826,15 +826,15 @@ static int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs, goto out_free; ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0); if (ret != SCANNED_A_NODE) { - ubifs_err("Not a valid node"); + ubifs_err(c, "Not a valid node"); goto out_err; } if (cs_node->ch.node_type != UBIFS_CS_NODE) { - ubifs_err("Node a CS node, type is %d", cs_node->ch.node_type); + ubifs_err(c, "Node a CS node, type is %d", cs_node->ch.node_type); goto out_err; } if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) { - ubifs_err("CS node cmt_no %llu != current cmt_no %llu", + ubifs_err(c, "CS node cmt_no %llu != current cmt_no %llu", (unsigned long long)le64_to_cpu(cs_node->cmt_no), c->cmt_no); goto out_err; @@ -847,7 +847,7 @@ static int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs, out_err: err = -EINVAL; out_free: - ubifs_err("failed to get CS sqnum"); + ubifs_err(c, "failed to get CS sqnum"); kfree(cs_node); return err; } @@ -899,7 +899,7 @@ struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum, } } if (snod->sqnum > cs_sqnum) { - ubifs_err("unrecoverable log corruption in LEB %d", + ubifs_err(c, "unrecoverable log corruption in LEB %d", lnum); ubifs_scan_destroy(sleb); return ERR_PTR(-EUCLEAN); @@ -1037,7 +1037,7 @@ static int clean_an_unclean_leb(struct ubifs_info *c, } if (ret == SCANNED_EMPTY_SPACE) { - ubifs_err("unexpected empty space at %d:%d", + ubifs_err(c, "unexpected empty space at %d:%d", lnum, offs); return -EUCLEAN; } @@ -1131,7 +1131,7 @@ static int grab_empty_leb(struct ubifs_info *c) */ lnum = ubifs_find_free_leb_for_idx(c); if (lnum < 0) { - ubifs_err("could not find an empty LEB"); + ubifs_err(c, "could not find an empty LEB"); ubifs_dump_lprops(c); ubifs_dump_budg(c, &c->bi); return lnum; @@ -1211,7 +1211,7 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c) } mutex_unlock(&wbuf->io_mutex); if (err < 0) { - ubifs_err("GC failed, error %d", err); + ubifs_err(c, "GC failed, error %d", err); if (err == -EAGAIN) err = -EINVAL; return err; @@ -1458,7 +1458,7 @@ static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e) return 0; out: - ubifs_warn("inode %lu failed to fix size %lld -> %lld error %d", + ubifs_warn(c, "inode %lu failed to fix size %lld -> %lld error %d", (unsigned long)e->inum, e->i_size, e->d_size, err); return err; } diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c index 9b40a1c5e160..3ca4540130b5 100644 --- a/fs/ubifs/replay.c +++ b/fs/ubifs/replay.c @@ -458,13 +458,13 @@ int ubifs_validate_entry(struct ubifs_info *c, nlen > UBIFS_MAX_NLEN || dent->name[nlen] != 0 || strnlen(dent->name, nlen) != nlen || le64_to_cpu(dent->inum) > MAX_INUM) { - ubifs_err("bad %s node", key_type == UBIFS_DENT_KEY ? + ubifs_err(c, "bad %s node", key_type == UBIFS_DENT_KEY ? "directory entry" : "extended attribute entry"); return -EINVAL; } if (key_type != UBIFS_DENT_KEY && key_type != UBIFS_XENT_KEY) { - ubifs_err("bad key type %d", key_type); + ubifs_err(c, "bad key type %d", key_type); return -EINVAL; } @@ -589,7 +589,7 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b) cond_resched(); if (snod->sqnum >= SQNUM_WATERMARK) { - ubifs_err("file system's life ended"); + ubifs_err(c, "file system's life ended"); goto out_dump; } @@ -647,7 +647,7 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b) if (old_size < 0 || old_size > c->max_inode_sz || new_size < 0 || new_size > c->max_inode_sz || old_size <= new_size) { - ubifs_err("bad truncation node"); + ubifs_err(c, "bad truncation node"); goto out_dump; } @@ -662,7 +662,7 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b) break; } default: - ubifs_err("unexpected node type %d in bud LEB %d:%d", + ubifs_err(c, "unexpected node type %d in bud LEB %d:%d", snod->type, lnum, snod->offs); err = -EINVAL; goto out_dump; @@ -685,7 +685,7 @@ out: return err; out_dump: - ubifs_err("bad node is at LEB %d:%d", lnum, snod->offs); + ubifs_err(c, "bad node is at LEB %d:%d", lnum, snod->offs); ubifs_dump_node(c, snod->node); ubifs_scan_destroy(sleb); return -EINVAL; @@ -805,7 +805,7 @@ static int validate_ref(struct ubifs_info *c, const struct ubifs_ref_node *ref) if (bud) { if (bud->jhead == jhead && bud->start <= offs) return 1; - ubifs_err("bud at LEB %d:%d was already referred", lnum, offs); + ubifs_err(c, "bud at LEB %d:%d was already referred", lnum, offs); return -EINVAL; } @@ -861,12 +861,12 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf) * numbers. */ if (snod->type != UBIFS_CS_NODE) { - ubifs_err("first log node at LEB %d:%d is not CS node", + ubifs_err(c, "first log node at LEB %d:%d is not CS node", lnum, offs); goto out_dump; } if (le64_to_cpu(node->cmt_no) != c->cmt_no) { - ubifs_err("first CS node at LEB %d:%d has wrong commit number %llu expected %llu", + ubifs_err(c, "first CS node at LEB %d:%d has wrong commit number %llu expected %llu", lnum, offs, (unsigned long long)le64_to_cpu(node->cmt_no), c->cmt_no); @@ -891,7 +891,7 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf) /* Make sure the first node sits at offset zero of the LEB */ if (snod->offs != 0) { - ubifs_err("first node is not at zero offset"); + ubifs_err(c, "first node is not at zero offset"); goto out_dump; } @@ -899,12 +899,12 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf) cond_resched(); if (snod->sqnum >= SQNUM_WATERMARK) { - ubifs_err("file system's life ended"); + ubifs_err(c, "file system's life ended"); goto out_dump; } if (snod->sqnum < c->cs_sqnum) { - ubifs_err("bad sqnum %llu, commit sqnum %llu", + ubifs_err(c, "bad sqnum %llu, commit sqnum %llu", snod->sqnum, c->cs_sqnum); goto out_dump; } @@ -934,12 +934,12 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf) case UBIFS_CS_NODE: /* Make sure it sits at the beginning of LEB */ if (snod->offs != 0) { - ubifs_err("unexpected node in log"); + ubifs_err(c, "unexpected node in log"); goto out_dump; } break; default: - ubifs_err("unexpected node in log"); + ubifs_err(c, "unexpected node in log"); goto out_dump; } } @@ -955,7 +955,7 @@ out: return err; out_dump: - ubifs_err("log error detected while replaying the log at LEB %d:%d", + ubifs_err(c, "log error detected while replaying the log at LEB %d:%d", lnum, offs + snod->offs); ubifs_dump_node(c, snod->node); ubifs_scan_destroy(sleb); @@ -1017,7 +1017,7 @@ int ubifs_replay_journal(struct ubifs_info *c) return free; /* Error code */ if (c->ihead_offs != c->leb_size - free) { - ubifs_err("bad index head LEB %d:%d", c->ihead_lnum, + ubifs_err(c, "bad index head LEB %d:%d", c->ihead_lnum, c->ihead_offs); return -EINVAL; } @@ -1040,7 +1040,7 @@ int ubifs_replay_journal(struct ubifs_info *c) * someting went wrong and we cannot proceed mounting * the file-system. */ - ubifs_err("no UBIFS nodes found at the log head LEB %d:%d, possibly corrupted", + ubifs_err(c, "no UBIFS nodes found at the log head LEB %d:%d, possibly corrupted", lnum, 0); err = -EINVAL; } diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index 79c6dbbc0e04..f4fbc7b6b794 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c @@ -335,7 +335,7 @@ static int create_default_filesystem(struct ubifs_info *c) if (err) return err; - ubifs_msg("default file-system created"); + ubifs_msg(c, "default file-system created"); return 0; } @@ -365,13 +365,13 @@ static int validate_sb(struct ubifs_info *c, struct ubifs_sb_node *sup) } if (le32_to_cpu(sup->min_io_size) != c->min_io_size) { - ubifs_err("min. I/O unit mismatch: %d in superblock, %d real", + ubifs_err(c, "min. I/O unit mismatch: %d in superblock, %d real", le32_to_cpu(sup->min_io_size), c->min_io_size); goto failed; } if (le32_to_cpu(sup->leb_size) != c->leb_size) { - ubifs_err("LEB size mismatch: %d in superblock, %d real", + ubifs_err(c, "LEB size mismatch: %d in superblock, %d real", le32_to_cpu(sup->leb_size), c->leb_size); goto failed; } @@ -393,33 +393,33 @@ static int validate_sb(struct ubifs_info *c, struct ubifs_sb_node *sup) min_leb_cnt += c->lpt_lebs + c->orph_lebs + c->jhead_cnt + 6; if (c->leb_cnt < min_leb_cnt || c->leb_cnt > c->vi.size) { - ubifs_err("bad LEB count: %d in superblock, %d on UBI volume, %d minimum required", + ubifs_err(c, "bad LEB count: %d in superblock, %d on UBI volume, %d minimum required", c->leb_cnt, c->vi.size, min_leb_cnt); goto failed; } if (c->max_leb_cnt < c->leb_cnt) { - ubifs_err("max. LEB count %d less than LEB count %d", + ubifs_err(c, "max. LEB count %d less than LEB count %d", c->max_leb_cnt, c->leb_cnt); goto failed; } if (c->main_lebs < UBIFS_MIN_MAIN_LEBS) { - ubifs_err("too few main LEBs count %d, must be at least %d", + ubifs_err(c, "too few main LEBs count %d, must be at least %d", c->main_lebs, UBIFS_MIN_MAIN_LEBS); goto failed; } max_bytes = (long long)c->leb_size * UBIFS_MIN_BUD_LEBS; if (c->max_bud_bytes < max_bytes) { - ubifs_err("too small journal (%lld bytes), must be at least %lld bytes", + ubifs_err(c, "too small journal (%lld bytes), must be at least %lld bytes", c->max_bud_bytes, max_bytes); goto failed; } max_bytes = (long long)c->leb_size * c->main_lebs; if (c->max_bud_bytes > max_bytes) { - ubifs_err("too large journal size (%lld bytes), only %lld bytes available in the main area", + ubifs_err(c, "too large journal size (%lld bytes), only %lld bytes available in the main area", c->max_bud_bytes, max_bytes); goto failed; } @@ -468,7 +468,7 @@ static int validate_sb(struct ubifs_info *c, struct ubifs_sb_node *sup) return 0; failed: - ubifs_err("bad superblock, error %d", err); + ubifs_err(c, "bad superblock, error %d", err); ubifs_dump_node(c, sup); return -EINVAL; } @@ -549,12 +549,12 @@ int ubifs_read_superblock(struct ubifs_info *c) ubifs_assert(!c->ro_media || c->ro_mount); if (!c->ro_mount || c->ro_compat_version > UBIFS_RO_COMPAT_VERSION) { - ubifs_err("on-flash format version is w%d/r%d, but software only supports up to version w%d/r%d", + ubifs_err(c, "on-flash format version is w%d/r%d, but software only supports up to version w%d/r%d", c->fmt_version, c->ro_compat_version, UBIFS_FORMAT_VERSION, UBIFS_RO_COMPAT_VERSION); if (c->ro_compat_version <= UBIFS_RO_COMPAT_VERSION) { - ubifs_msg("only R/O mounting is possible"); + ubifs_msg(c, "only R/O mounting is possible"); err = -EROFS; } else err = -EINVAL; @@ -570,7 +570,7 @@ int ubifs_read_superblock(struct ubifs_info *c) } if (c->fmt_version < 3) { - ubifs_err("on-flash format version %d is not supported", + ubifs_err(c, "on-flash format version %d is not supported", c->fmt_version); err = -EINVAL; goto out; @@ -595,7 +595,7 @@ int ubifs_read_superblock(struct ubifs_info *c) c->key_len = UBIFS_SK_LEN; break; default: - ubifs_err("unsupported key format"); + ubifs_err(c, "unsupported key format"); err = -EINVAL; goto out; } @@ -785,7 +785,7 @@ int ubifs_fixup_free_space(struct ubifs_info *c) ubifs_assert(c->space_fixup); ubifs_assert(!c->ro_mount); - ubifs_msg("start fixing up free space"); + ubifs_msg(c, "start fixing up free space"); err = fixup_free_space(c); if (err) @@ -804,6 +804,6 @@ int ubifs_fixup_free_space(struct ubifs_info *c) if (err) return err; - ubifs_msg("free space fixup complete"); + ubifs_msg(c, "free space fixup complete"); return err; } diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c index 89adbc4d08ac..aab87340d3de 100644 --- a/fs/ubifs/scan.c +++ b/fs/ubifs/scan.c @@ -100,7 +100,7 @@ int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum, if (pad_len < 0 || offs + node_len + pad_len > c->leb_size) { if (!quiet) { - ubifs_err("bad pad node at LEB %d:%d", + ubifs_err(c, "bad pad node at LEB %d:%d", lnum, offs); ubifs_dump_node(c, pad); } @@ -110,7 +110,7 @@ int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum, /* Make the node pads to 8-byte boundary */ if ((node_len + pad_len) & 7) { if (!quiet) - ubifs_err("bad padding length %d - %d", + ubifs_err(c, "bad padding length %d - %d", offs, offs + node_len + pad_len); return SCANNED_A_BAD_PAD_NODE; } @@ -152,7 +152,7 @@ struct ubifs_scan_leb *ubifs_start_scan(const struct ubifs_info *c, int lnum, err = ubifs_leb_read(c, lnum, sbuf + offs, offs, c->leb_size - offs, 0); if (err && err != -EBADMSG) { - ubifs_err("cannot read %d bytes from LEB %d:%d, error %d", + ubifs_err(c, "cannot read %d bytes from LEB %d:%d, error %d", c->leb_size - offs, lnum, offs, err); kfree(sleb); return ERR_PTR(err); @@ -240,11 +240,11 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs, { int len; - ubifs_err("corruption at LEB %d:%d", lnum, offs); + ubifs_err(c, "corruption at LEB %d:%d", lnum, offs); len = c->leb_size - offs; if (len > 8192) len = 8192; - ubifs_err("first %d bytes from LEB %d:%d", len, lnum, offs); + ubifs_err(c, "first %d bytes from LEB %d:%d", len, lnum, offs); print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1); } @@ -299,16 +299,16 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum, switch (ret) { case SCANNED_GARBAGE: - ubifs_err("garbage"); + ubifs_err(c, "garbage"); goto corrupted; case SCANNED_A_NODE: break; case SCANNED_A_CORRUPT_NODE: case SCANNED_A_BAD_PAD_NODE: - ubifs_err("bad node"); + ubifs_err(c, "bad node"); goto corrupted; default: - ubifs_err("unknown"); + ubifs_err(c, "unknown"); err = -EINVAL; goto error; } @@ -325,7 +325,7 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum, if (offs % c->min_io_size) { if (!quiet) - ubifs_err("empty space starts at non-aligned offset %d", + ubifs_err(c, "empty space starts at non-aligned offset %d", offs); goto corrupted; } @@ -338,7 +338,7 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum, for (; len; offs++, buf++, len--) if (*(uint8_t *)buf != 0xff) { if (!quiet) - ubifs_err("corrupt empty space at LEB %d:%d", + ubifs_err(c, "corrupt empty space at LEB %d:%d", lnum, offs); goto corrupted; } @@ -348,14 +348,14 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum, corrupted: if (!quiet) { ubifs_scanned_corruption(c, lnum, offs, buf); - ubifs_err("LEB %d scanning failed", lnum); + ubifs_err(c, "LEB %d scanning failed", lnum); } err = -EUCLEAN; ubifs_scan_destroy(sleb); return ERR_PTR(err); error: - ubifs_err("LEB %d scanning failed, error %d", lnum, err); + ubifs_err(c, "LEB %d scanning failed, error %d", lnum, err); ubifs_scan_destroy(sleb); return ERR_PTR(err); } diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 0b7378a7ee04..75e6f04bb795 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -70,13 +70,13 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode) const struct ubifs_inode *ui = ubifs_inode(inode); if (inode->i_size > c->max_inode_sz) { - ubifs_err("inode is too large (%lld)", + ubifs_err(c, "inode is too large (%lld)", (long long)inode->i_size); return 1; } if (ui->compr_type >= UBIFS_COMPR_TYPES_CNT) { - ubifs_err("unknown compression type %d", ui->compr_type); + ubifs_err(c, "unknown compression type %d", ui->compr_type); return 2; } @@ -90,7 +90,7 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode) return 5; if (!ubifs_compr_present(ui->compr_type)) { - ubifs_warn("inode %lu uses '%s' compression, but it was not compiled in", + ubifs_warn(c, "inode %lu uses '%s' compression, but it was not compiled in", inode->i_ino, ubifs_compr_name(ui->compr_type)); } @@ -242,14 +242,14 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum) return inode; out_invalid: - ubifs_err("inode %lu validation failed, error %d", inode->i_ino, err); + ubifs_err(c, "inode %lu validation failed, error %d", inode->i_ino, err); ubifs_dump_node(c, ino); ubifs_dump_inode(c, inode); err = -EINVAL; out_ino: kfree(ino); out: - ubifs_err("failed to read inode %lu, error %d", inode->i_ino, err); + ubifs_err(c, "failed to read inode %lu, error %d", inode->i_ino, err); iget_failed(inode); return ERR_PTR(err); } @@ -319,7 +319,7 @@ static int ubifs_write_inode(struct inode *inode, struct writeback_control *wbc) if (inode->i_nlink) { err = ubifs_jnl_write_inode(c, inode); if (err) - ubifs_err("can't write inode %lu, error %d", + ubifs_err(c, "can't write inode %lu, error %d", inode->i_ino, err); else err = dbg_check_inode_size(c, inode, ui->ui_size); @@ -363,7 +363,7 @@ static void ubifs_evict_inode(struct inode *inode) * Worst case we have a lost orphan inode wasting space, so a * simple error message is OK here. */ - ubifs_err("can't delete inode %lu, error %d", + ubifs_err(c, "can't delete inode %lu, error %d", inode->i_ino, err); out: @@ -492,17 +492,17 @@ static int ubifs_sync_fs(struct super_block *sb, int wait) static int init_constants_early(struct ubifs_info *c) { if (c->vi.corrupted) { - ubifs_warn("UBI volume is corrupted - read-only mode"); + ubifs_warn(c, "UBI volume is corrupted - read-only mode"); c->ro_media = 1; } if (c->di.ro_mode) { - ubifs_msg("read-only UBI device"); + ubifs_msg(c, "read-only UBI device"); c->ro_media = 1; } if (c->vi.vol_type == UBI_STATIC_VOLUME) { - ubifs_msg("static UBI volume - read-only mode"); + ubifs_msg(c, "static UBI volume - read-only mode"); c->ro_media = 1; } @@ -516,19 +516,19 @@ static int init_constants_early(struct ubifs_info *c) c->max_write_shift = fls(c->max_write_size) - 1; if (c->leb_size < UBIFS_MIN_LEB_SZ) { - ubifs_err("too small LEBs (%d bytes), min. is %d bytes", + ubifs_err(c, "too small LEBs (%d bytes), min. is %d bytes", c->leb_size, UBIFS_MIN_LEB_SZ); return -EINVAL; } if (c->leb_cnt < UBIFS_MIN_LEB_CNT) { - ubifs_err("too few LEBs (%d), min. is %d", + ubifs_err(c, "too few LEBs (%d), min. is %d", c->leb_cnt, UBIFS_MIN_LEB_CNT); return -EINVAL; } if (!is_power_of_2(c->min_io_size)) { - ubifs_err("bad min. I/O size %d", c->min_io_size); + ubifs_err(c, "bad min. I/O size %d", c->min_io_size); return -EINVAL; } @@ -539,7 +539,7 @@ static int init_constants_early(struct ubifs_info *c) if (c->max_write_size < c->min_io_size || c->max_write_size % c->min_io_size || !is_power_of_2(c->max_write_size)) { - ubifs_err("bad write buffer size %d for %d min. I/O unit", + ubifs_err(c, "bad write buffer size %d for %d min. I/O unit", c->max_write_size, c->min_io_size); return -EINVAL; } @@ -665,7 +665,7 @@ static int init_constants_sb(struct ubifs_info *c) tmp = UBIFS_CS_NODE_SZ + UBIFS_REF_NODE_SZ * c->jhead_cnt; tmp = ALIGN(tmp, c->min_io_size); if (tmp > c->leb_size) { - ubifs_err("too small LEB size %d, at least %d needed", + ubifs_err(c, "too small LEB size %d, at least %d needed", c->leb_size, tmp); return -EINVAL; } @@ -680,7 +680,7 @@ static int init_constants_sb(struct ubifs_info *c) tmp /= c->leb_size; tmp += 1; if (c->log_lebs < tmp) { - ubifs_err("too small log %d LEBs, required min. %d LEBs", + ubifs_err(c, "too small log %d LEBs, required min. %d LEBs", c->log_lebs, tmp); return -EINVAL; } @@ -772,7 +772,7 @@ static int take_gc_lnum(struct ubifs_info *c) int err; if (c->gc_lnum == -1) { - ubifs_err("no LEB for GC"); + ubifs_err(c, "no LEB for GC"); return -EINVAL; } @@ -857,7 +857,7 @@ static void free_orphans(struct ubifs_info *c) orph = list_entry(c->orph_list.next, struct ubifs_orphan, list); list_del(&orph->list); kfree(orph); - ubifs_err("orphan list not empty at unmount"); + ubifs_err(c, "orphan list not empty at unmount"); } vfree(c->orph_buf); @@ -954,7 +954,8 @@ static const match_table_t tokens = { */ static int parse_standard_option(const char *option) { - ubifs_msg("parse %s", option); + + pr_notice("UBIFS: parse %s\n", option); if (!strcmp(option, "sync")) return MS_SYNCHRONOUS; return 0; @@ -1026,7 +1027,7 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options, else if (!strcmp(name, "zlib")) c->mount_opts.compr_type = UBIFS_COMPR_ZLIB; else { - ubifs_err("unknown compressor \"%s\"", name); + ubifs_err(c, "unknown compressor \"%s\"", name); //FIXME: is c ready? kfree(name); return -EINVAL; } @@ -1042,7 +1043,7 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options, flag = parse_standard_option(p); if (!flag) { - ubifs_err("unrecognized mount option \"%s\" or missing value", + ubifs_err(c, "unrecognized mount option \"%s\" or missing value", p); return -EINVAL; } @@ -1105,7 +1106,7 @@ again: } /* Just disable bulk-read */ - ubifs_warn("cannot allocate %d bytes of memory for bulk-read, disabling it", + ubifs_warn(c, "cannot allocate %d bytes of memory for bulk-read, disabling it", c->max_bu_buf_len); c->mount_opts.bulk_read = 1; c->bulk_read = 0; @@ -1124,7 +1125,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"); + ubifs_err(c, "insufficient free space to mount in R/W mode"); ubifs_dump_budg(c, &c->bi); ubifs_dump_lprops(c); return -ENOSPC; @@ -1166,14 +1167,14 @@ static int mount_ubifs(struct ubifs_info *c) * This UBI volume is empty, and read-only, or the file system * is mounted read-only - we cannot format it. */ - ubifs_err("can't format empty UBI volume: read-only %s", + ubifs_err(c, "can't format empty UBI volume: read-only %s", c->ro_media ? "UBI volume" : "mount"); err = -EROFS; goto out_free; } if (c->ro_media && !c->ro_mount) { - ubifs_err("cannot mount read-write - read-only media"); + ubifs_err(c, "cannot mount read-write - read-only media"); err = -EROFS; goto out_free; } @@ -1221,7 +1222,7 @@ static int mount_ubifs(struct ubifs_info *c) * or overridden by mount options is actually compiled in. */ if (!ubifs_compr_present(c->default_compr)) { - ubifs_err("'compressor \"%s\" is not compiled in", + ubifs_err(c, "'compressor \"%s\" is not compiled in", ubifs_compr_name(c->default_compr)); err = -ENOTSUPP; goto out_free; @@ -1250,7 +1251,7 @@ static int mount_ubifs(struct ubifs_info *c) if (IS_ERR(c->bgt)) { err = PTR_ERR(c->bgt); c->bgt = NULL; - ubifs_err("cannot spawn \"%s\", error %d", + ubifs_err(c, "cannot spawn \"%s\", error %d", c->bgt_name, err); goto out_wbufs; } @@ -1264,7 +1265,7 @@ static int mount_ubifs(struct ubifs_info *c) init_constants_master(c); if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) { - ubifs_msg("recovery needed"); + ubifs_msg(c, "recovery needed"); c->need_recovery = 1; } @@ -1373,10 +1374,10 @@ static int mount_ubifs(struct ubifs_info *c) if (c->need_recovery) { if (c->ro_mount) - ubifs_msg("recovery deferred"); + ubifs_msg(c, "recovery deferred"); else { c->need_recovery = 0; - ubifs_msg("recovery completed"); + ubifs_msg(c, "recovery completed"); /* * GC LEB has to be empty and taken at this point. But * the journal head LEBs may also be accounted as @@ -1397,20 +1398,20 @@ static int mount_ubifs(struct ubifs_info *c) c->mounting = 0; - ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"%s", + ubifs_msg(c, "UBIFS: mounted UBI device %d, volume %d, name \"%s\"%s", c->vi.ubi_num, c->vi.vol_id, c->vi.name, c->ro_mount ? ", R/O mode" : ""); x = (long long)c->main_lebs * c->leb_size; y = (long long)c->log_lebs * c->leb_size + c->max_bud_bytes; - ubifs_msg("LEB size: %d bytes (%d KiB), min./max. I/O unit sizes: %d bytes/%d bytes", + ubifs_msg(c, "LEB size: %d bytes (%d KiB), min./max. I/O unit sizes: %d bytes/%d bytes", c->leb_size, c->leb_size >> 10, c->min_io_size, c->max_write_size); - ubifs_msg("FS size: %lld bytes (%lld MiB, %d LEBs), journal size %lld bytes (%lld MiB, %d LEBs)", + ubifs_msg(c, "FS size: %lld bytes (%lld MiB, %d LEBs), journal size %lld bytes (%lld MiB, %d LEBs)", x, x >> 20, c->main_lebs, y, y >> 20, c->log_lebs + c->max_bud_cnt); - ubifs_msg("reserved for root: %llu bytes (%llu KiB)", + ubifs_msg(c, "reserved for root: %llu bytes (%llu KiB)", c->report_rp_size, c->report_rp_size >> 10); - ubifs_msg("media format: w%d/r%d (latest is w%d/r%d), UUID %pUB%s", + ubifs_msg(c, "media format: w%d/r%d (latest is w%d/r%d), UUID %pUB%s", c->fmt_version, c->ro_compat_version, UBIFS_FORMAT_VERSION, UBIFS_RO_COMPAT_VERSION, c->uuid, c->big_lpt ? ", big LPT model" : ", small LPT model"); @@ -1543,8 +1544,8 @@ static int ubifs_remount_rw(struct ubifs_info *c) int err, lnum; if (c->rw_incompat) { - ubifs_err("the file-system is not R/W-compatible"); - ubifs_msg("on-flash format version is w%d/r%d, but software only supports up to version w%d/r%d", + ubifs_err(c, "the file-system is not R/W-compatible"); + ubifs_msg(c, "on-flash format version is w%d/r%d, but software only supports up to version w%d/r%d", c->fmt_version, c->ro_compat_version, UBIFS_FORMAT_VERSION, UBIFS_RO_COMPAT_VERSION); return -EROFS; @@ -1581,7 +1582,7 @@ static int ubifs_remount_rw(struct ubifs_info *c) } if (c->need_recovery) { - ubifs_msg("completing deferred recovery"); + ubifs_msg(c, "completing deferred recovery"); err = ubifs_write_rcvrd_mst_node(c); if (err) goto out; @@ -1630,7 +1631,7 @@ static int ubifs_remount_rw(struct ubifs_info *c) if (IS_ERR(c->bgt)) { err = PTR_ERR(c->bgt); c->bgt = NULL; - ubifs_err("cannot spawn \"%s\", error %d", + ubifs_err(c, "cannot spawn \"%s\", error %d", c->bgt_name, err); goto out; } @@ -1664,7 +1665,7 @@ static int ubifs_remount_rw(struct ubifs_info *c) if (c->need_recovery) { c->need_recovery = 0; - ubifs_msg("deferred recovery completed"); + ubifs_msg(c, "deferred recovery completed"); } else { /* * Do not run the debugging space check if the were doing @@ -1752,8 +1753,7 @@ static void ubifs_put_super(struct super_block *sb) int i; struct ubifs_info *c = sb->s_fs_info; - ubifs_msg("un-mount UBI device %d, volume %d", c->vi.ubi_num, - c->vi.vol_id); + ubifs_msg(c, "un-mount UBI device %d", c->vi.ubi_num); /* * The following asserts are only valid if there has not been a failure @@ -1809,7 +1809,7 @@ static void ubifs_put_super(struct super_block *sb) * next mount, so we just print a message and * continue to unmount normally. */ - ubifs_err("failed to write master node, error %d", + ubifs_err(c, "failed to write master node, error %d", err); } else { for (i = 0; i < c->jhead_cnt; i++) @@ -1834,17 +1834,17 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) err = ubifs_parse_options(c, data, 1); if (err) { - ubifs_err("invalid or unknown remount parameter"); + ubifs_err(c, "invalid or unknown remount parameter"); return err; } if (c->ro_mount && !(*flags & MS_RDONLY)) { if (c->ro_error) { - ubifs_msg("cannot re-mount R/W due to prior errors"); + ubifs_msg(c, "cannot re-mount R/W due to prior errors"); return -EROFS; } if (c->ro_media) { - ubifs_msg("cannot re-mount R/W - UBI volume is R/O"); + ubifs_msg(c, "cannot re-mount R/W - UBI volume is R/O"); return -EROFS; } err = ubifs_remount_rw(c); @@ -1852,7 +1852,7 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) return err; } else if (!c->ro_mount && (*flags & MS_RDONLY)) { if (c->ro_error) { - ubifs_msg("cannot re-mount R/O due to prior errors"); + ubifs_msg(c, "cannot re-mount R/O due to prior errors"); return -EROFS; } ubifs_remount_ro(c); @@ -2104,8 +2104,8 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, */ ubi = open_ubi(name, UBI_READONLY); if (IS_ERR(ubi)) { - ubifs_err("cannot open \"%s\", error %d", - name, (int)PTR_ERR(ubi)); + pr_err("UBIFS error (pid: %d): cannot open \"%s\", error %d", + current->pid, name, (int)PTR_ERR(ubi)); return ERR_CAST(ubi); } @@ -2233,8 +2233,8 @@ static int __init ubifs_init(void) * UBIFS_BLOCK_SIZE. It is assumed that both are powers of 2. */ if (PAGE_CACHE_SIZE < UBIFS_BLOCK_SIZE) { - ubifs_err("VFS page cache size is %u bytes, but UBIFS requires at least 4096 bytes", - (unsigned int)PAGE_CACHE_SIZE); + pr_err("UBIFS error (pid %d): VFS page cache size is %u bytes, but UBIFS requires at least 4096 bytes", + current->pid, (unsigned int)PAGE_CACHE_SIZE); return -EINVAL; } @@ -2257,7 +2257,8 @@ static int __init ubifs_init(void) err = register_filesystem(&ubifs_fs_type); if (err) { - ubifs_err("cannot register file system, error %d", err); + pr_err("UBIFS error (pid %d): cannot register file system, error %d", + current->pid, err); goto out_dbg; } return 0; diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index 6793db0754f6..957f5757f374 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -98,7 +98,7 @@ static int insert_old_idx(struct ubifs_info *c, int lnum, int offs) else if (offs > o->offs) p = &(*p)->rb_right; else { - ubifs_err("old idx added twice!"); + ubifs_err(c, "old idx added twice!"); kfree(old_idx); return 0; } @@ -447,7 +447,7 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type, err = ubifs_leb_read(c, lnum, buf, offs, len, 1); if (err) { - ubifs_err("cannot read node type %d from LEB %d:%d, error %d", + ubifs_err(c, "cannot read node type %d from LEB %d:%d, error %d", type, lnum, offs, err); return err; } @@ -1684,27 +1684,27 @@ static int validate_data_node(struct ubifs_info *c, void *buf, int err, len; if (ch->node_type != UBIFS_DATA_NODE) { - ubifs_err("bad node type (%d but expected %d)", + ubifs_err(c, "bad node type (%d but expected %d)", ch->node_type, UBIFS_DATA_NODE); goto out_err; } err = ubifs_check_node(c, buf, zbr->lnum, zbr->offs, 0, 0); if (err) { - ubifs_err("expected node type %d", UBIFS_DATA_NODE); + ubifs_err(c, "expected node type %d", UBIFS_DATA_NODE); goto out; } len = le32_to_cpu(ch->len); if (len != zbr->len) { - ubifs_err("bad node length %d, expected %d", len, zbr->len); + ubifs_err(c, "bad node length %d, expected %d", len, zbr->len); goto out_err; } /* Make sure the key of the read node is correct */ key_read(c, buf + UBIFS_KEY_OFFSET, &key1); if (!keys_eq(c, &zbr->key, &key1)) { - ubifs_err("bad key in node at LEB %d:%d", + ubifs_err(c, "bad key in node at LEB %d:%d", zbr->lnum, zbr->offs); dbg_tnck(&zbr->key, "looked for key "); dbg_tnck(&key1, "found node's key "); @@ -1716,7 +1716,7 @@ static int validate_data_node(struct ubifs_info *c, void *buf, out_err: err = -EINVAL; out: - ubifs_err("bad node at LEB %d:%d", zbr->lnum, zbr->offs); + ubifs_err(c, "bad node at LEB %d:%d", zbr->lnum, zbr->offs); ubifs_dump_node(c, buf); dump_stack(); return err; @@ -1741,7 +1741,7 @@ int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu) len = bu->zbranch[bu->cnt - 1].offs; len += bu->zbranch[bu->cnt - 1].len - offs; if (len > bu->buf_len) { - ubifs_err("buffer too small %d vs %d", bu->buf_len, len); + ubifs_err(c, "buffer too small %d vs %d", bu->buf_len, len); return -EINVAL; } @@ -1757,7 +1757,7 @@ int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu) return -EAGAIN; if (err && err != -EBADMSG) { - ubifs_err("failed to read from LEB %d:%d, error %d", + ubifs_err(c, "failed to read from LEB %d:%d, error %d", lnum, offs, err); dump_stack(); dbg_tnck(&bu->key, "key "); @@ -3313,7 +3313,7 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode, out_dump: block = key_block(c, key); - ubifs_err("inode %lu has size %lld, but there are data at offset %lld", + ubifs_err(c, "inode %lu has size %lld, but there are data at offset %lld", (unsigned long)inode->i_ino, size, ((loff_t)block) << UBIFS_BLOCK_SHIFT); mutex_unlock(&c->tnc_mutex); diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c index 7a205e046776..b45345d701e7 100644 --- a/fs/ubifs/tnc_commit.c +++ b/fs/ubifs/tnc_commit.c @@ -53,7 +53,7 @@ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx, br->offs = cpu_to_le32(zbr->offs); br->len = cpu_to_le32(zbr->len); if (!zbr->lnum || !zbr->len) { - ubifs_err("bad ref in znode"); + ubifs_err(c, "bad ref in znode"); ubifs_dump_znode(c, znode); if (zbr->znode) ubifs_dump_znode(c, zbr->znode); @@ -384,7 +384,7 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt) * Do not print scary warnings if the debugging * option which forces in-the-gaps is enabled. */ - ubifs_warn("out of space"); + ubifs_warn(c, "out of space"); ubifs_dump_budg(c, &c->bi); ubifs_dump_lprops(c); } @@ -441,7 +441,7 @@ static int layout_in_empty_space(struct ubifs_info *c) /* Determine the index node position */ if (lnum == -1) { if (c->ileb_nxt >= c->ileb_cnt) { - ubifs_err("out of space"); + ubifs_err(c, "out of space"); return -ENOSPC; } lnum = c->ilebs[c->ileb_nxt++]; @@ -855,7 +855,7 @@ static int write_index(struct ubifs_info *c) br->offs = cpu_to_le32(zbr->offs); br->len = cpu_to_le32(zbr->len); if (!zbr->lnum || !zbr->len) { - ubifs_err("bad ref in znode"); + ubifs_err(c, "bad ref in znode"); ubifs_dump_znode(c, znode); if (zbr->znode) ubifs_dump_znode(c, zbr->znode); @@ -875,7 +875,7 @@ static int write_index(struct ubifs_info *c) if (lnum != znode->lnum || offs != znode->offs || len != znode->len) { - ubifs_err("inconsistent znode posn"); + ubifs_err(c, "inconsistent znode posn"); return -EINVAL; } @@ -973,7 +973,7 @@ static int write_index(struct ubifs_info *c) if (lnum != c->dbg->new_ihead_lnum || buf_offs != c->dbg->new_ihead_offs) { - ubifs_err("inconsistent ihead"); + ubifs_err(c, "inconsistent ihead"); return -EINVAL; } diff --git a/fs/ubifs/tnc_misc.c b/fs/ubifs/tnc_misc.c index f6bf8995c7b1..93f5b7859e6f 100644 --- a/fs/ubifs/tnc_misc.c +++ b/fs/ubifs/tnc_misc.c @@ -293,9 +293,9 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len, lnum, offs, znode->level, znode->child_cnt); if (znode->child_cnt > c->fanout || znode->level > UBIFS_MAX_LEVELS) { - ubifs_err("current fanout %d, branch count %d", + ubifs_err(c, "current fanout %d, branch count %d", c->fanout, znode->child_cnt); - ubifs_err("max levels %d, znode level %d", + ubifs_err(c, "max levels %d, znode level %d", UBIFS_MAX_LEVELS, znode->level); err = 1; goto out_dump; @@ -316,7 +316,7 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len, if (zbr->lnum < c->main_first || zbr->lnum >= c->leb_cnt || zbr->offs < 0 || zbr->offs + zbr->len > c->leb_size || zbr->offs & 7) { - ubifs_err("bad branch %d", i); + ubifs_err(c, "bad branch %d", i); err = 2; goto out_dump; } @@ -328,7 +328,7 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len, case UBIFS_XENT_KEY: break; default: - ubifs_err("bad key type at slot %d: %d", + ubifs_err(c, "bad key type at slot %d: %d", i, key_type(c, &zbr->key)); err = 3; goto out_dump; @@ -340,17 +340,17 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len, type = key_type(c, &zbr->key); if (c->ranges[type].max_len == 0) { if (zbr->len != c->ranges[type].len) { - ubifs_err("bad target node (type %d) length (%d)", + ubifs_err(c, "bad target node (type %d) length (%d)", type, zbr->len); - ubifs_err("have to be %d", c->ranges[type].len); + ubifs_err(c, "have to be %d", c->ranges[type].len); err = 4; goto out_dump; } } else if (zbr->len < c->ranges[type].min_len || zbr->len > c->ranges[type].max_len) { - ubifs_err("bad target node (type %d) length (%d)", + ubifs_err(c, "bad target node (type %d) length (%d)", type, zbr->len); - ubifs_err("have to be in range of %d-%d", + ubifs_err(c, "have to be in range of %d-%d", c->ranges[type].min_len, c->ranges[type].max_len); err = 5; @@ -370,12 +370,12 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len, cmp = keys_cmp(c, key1, key2); if (cmp > 0) { - ubifs_err("bad key order (keys %d and %d)", i, i + 1); + ubifs_err(c, "bad key order (keys %d and %d)", i, i + 1); err = 6; goto out_dump; } else if (cmp == 0 && !is_hash_key(c, key1)) { /* These can only be keys with colliding hash */ - ubifs_err("keys %d and %d are not hashed but equivalent", + ubifs_err(c, "keys %d and %d are not hashed but equivalent", i, i + 1); err = 7; goto out_dump; @@ -386,7 +386,7 @@ static int read_znode(struct ubifs_info *c, int lnum, int offs, int len, return 0; out_dump: - ubifs_err("bad indexing node at LEB %d:%d, error %d", lnum, offs, err); + ubifs_err(c, "bad indexing node at LEB %d:%d, error %d", lnum, offs, err); ubifs_dump_node(c, idx); kfree(idx); return -EINVAL; @@ -482,7 +482,7 @@ int ubifs_tnc_read_node(struct ubifs_info *c, struct ubifs_zbranch *zbr, /* Make sure the key of the read node is correct */ key_read(c, node + UBIFS_KEY_OFFSET, &key1); if (!keys_eq(c, key, &key1)) { - ubifs_err("bad key in node at LEB %d:%d", + ubifs_err(c, "bad key in node at LEB %d:%d", zbr->lnum, zbr->offs); dbg_tnck(key, "looked for key "); dbg_tnck(&key1, "but found node's key "); diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 2911d2d23456..de759022f3d6 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -43,15 +43,19 @@ #define UBIFS_VERSION 1 /* Normal UBIFS messages */ -#define ubifs_msg(fmt, ...) pr_notice("UBIFS: " fmt "\n", ##__VA_ARGS__) +#define ubifs_msg(c, fmt, ...) \ + pr_notice("UBIFS (ubi%d:%d): " fmt "\n", \ + (c)->vi.ubi_num, (c)->vi.vol_id, ##__VA_ARGS__) /* UBIFS error messages */ -#define ubifs_err(fmt, ...) \ - pr_err("UBIFS error (pid %d): %s: " fmt "\n", current->pid, \ +#define ubifs_err(c, fmt, ...) \ + pr_err("UBIFS error (ubi%d:%d pid %d): %s: " fmt "\n", \ + (c)->vi.ubi_num, (c)->vi.vol_id, current->pid, \ __func__, ##__VA_ARGS__) /* UBIFS warning messages */ -#define ubifs_warn(fmt, ...) \ - pr_warn("UBIFS warning (pid %d): %s: " fmt "\n", \ - current->pid, __func__, ##__VA_ARGS__) +#define ubifs_warn(c, fmt, ...) \ + pr_warn("UBIFS warning (ubi%d:%d pid %d): %s: " fmt "\n", \ + (c)->vi.ubi_num, (c)->vi.vol_id, current->pid, \ + __func__, ##__VA_ARGS__) /* * A variant of 'ubifs_err()' which takes the UBIFS file-sytem description * object as an argument. @@ -59,7 +63,7 @@ #define ubifs_errc(c, fmt, ...) \ do { \ if (!(c)->probing) \ - ubifs_err(fmt, ##__VA_ARGS__); \ + ubifs_err(c, fmt, ##__VA_ARGS__); \ } while (0) /* UBIFS file system VFS magic number */ @@ -1787,10 +1791,10 @@ long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); /* compressor.c */ int __init ubifs_compressors_init(void); void ubifs_compressors_exit(void); -void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len, - int *compr_type); -int ubifs_decompress(const void *buf, int len, void *out, int *out_len, - int compr_type); +void ubifs_compress(const struct ubifs_info *c, const void *in_buf, int in_len, + void *out_buf, int *out_len, int *compr_type); +int ubifs_decompress(const struct ubifs_info *c, const void *buf, int len, + void *out, int *out_len, int compr_type); #include "debug.h" #include "misc.h" diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c index a92be244a6fb..3659b1934500 100644 --- a/fs/ubifs/xattr.c +++ b/fs/ubifs/xattr.c @@ -108,7 +108,7 @@ static int create_xattr(struct ubifs_info *c, struct inode *host, .dirtied_ino_d = ALIGN(host_ui->data_len, 8) }; if (host_ui->xattr_cnt >= MAX_XATTRS_PER_INODE) { - ubifs_err("inode %lu already has too many xattrs (%d), cannot create more", + ubifs_err(c, "inode %lu already has too many xattrs (%d), cannot create more", host->i_ino, host_ui->xattr_cnt); return -ENOSPC; } @@ -120,7 +120,7 @@ static int create_xattr(struct ubifs_info *c, struct inode *host, */ names_len = host_ui->xattr_names + host_ui->xattr_cnt + nm->len + 1; if (names_len > XATTR_LIST_MAX) { - ubifs_err("cannot add one more xattr name to inode %lu, total names length would become %d, max. is %d", + ubifs_err(c, "cannot add one more xattr name to inode %lu, total names length would become %d, max. is %d", host->i_ino, names_len, XATTR_LIST_MAX); return -ENOSPC; } @@ -288,13 +288,13 @@ static struct inode *iget_xattr(struct ubifs_info *c, ino_t inum) inode = ubifs_iget(c->vfs_sb, inum); if (IS_ERR(inode)) { - ubifs_err("dead extended attribute entry, error %d", + ubifs_err(c, "dead extended attribute entry, error %d", (int)PTR_ERR(inode)); return inode; } if (ubifs_inode(inode)->xattr) return inode; - ubifs_err("corrupt extended attribute entry"); + ubifs_err(c, "corrupt extended attribute entry"); iput(inode); return ERR_PTR(-EINVAL); } @@ -412,7 +412,7 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf, if (buf) { /* If @buf is %NULL we are supposed to return the length */ if (ui->data_len > size) { - ubifs_err("buffer size %zd, xattr len %d", + ubifs_err(c, "buffer size %zd, xattr len %d", size, ui->data_len); err = -ERANGE; goto out_iput; @@ -485,7 +485,7 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size) kfree(pxent); if (err != -ENOENT) { - ubifs_err("cannot find next direntry, error %d", err); + ubifs_err(c, "cannot find next direntry, error %d", err); return err; } @@ -657,8 +657,10 @@ int ubifs_init_security(struct inode *dentry, struct inode *inode, &init_xattrs, 0); mutex_unlock(&inode->i_mutex); - if (err) - ubifs_err("cannot initialize security for inode %lu, error %d", + if (err) { + struct ubifs_info *c = dentry->i_sb->s_fs_info; + ubifs_err(c, "cannot initialize security for inode %lu, error %d", inode->i_ino, err); + } return err; } -- cgit v1.2.3-59-g8ed1b From 8eef7d70f7c6772c3490f410ee2bceab3b543fa1 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Sat, 28 Feb 2015 02:23:25 -0800 Subject: UBI: account for bitflips in both the VID header and data We are completely discarding the earlier value of 'bitflips', which could reflect a bitflip found in ubi_io_read_vid_hdr(). Let's use the bitwise OR of header and data 'bitflip' statuses instead. Coverity CID #1226856 Cc: stable Signed-off-by: Brian Norris Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/attach.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index 9d2e16f3150a..b5e154856994 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c @@ -410,7 +410,7 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, second_is_newer = !second_is_newer; } else { dbg_bld("PEB %d CRC is OK", pnum); - bitflips = !!err; + bitflips |= !!err; } mutex_unlock(&ubi->buf_mutex); -- cgit v1.2.3-59-g8ed1b From d74adbdb9abf0d2506a6c4afa534d894f28b763f Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Sat, 28 Feb 2015 02:23:26 -0800 Subject: UBI: fix out of bounds write If aeb->len >= vol->reserved_pebs, we should not be writing aeb into the PEB->LEB mapping. Caught by Coverity, CID #711212. Cc: stable Signed-off-by: Brian Norris Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/eba.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 16e34b37d134..8c9a710def99 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -1419,7 +1419,8 @@ int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai) * during re-size. */ ubi_move_aeb_to_list(av, aeb, &ai->erase); - vol->eba_tbl[aeb->lnum] = aeb->pnum; + else + vol->eba_tbl[aeb->lnum] = aeb->pnum; } } -- cgit v1.2.3-59-g8ed1b From f16db8071ce18819fbd705ddcc91c6f392fb61f8 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Sat, 28 Feb 2015 02:23:27 -0800 Subject: UBI: initialize LEB number variable In some of the 'out_not_moved' error paths, lnum may be used uninitialized. Don't ignore the warning; let's fix it. This uninitialized variable doesn't have much visible effect in the end, since we just schedule the PEB for erasure, and its LEB number doesn't really matter (it just gets printed in debug messages). But let's get it straight anyway. Coverity CID #113449 Cc: stable Signed-off-by: Brian Norris Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/wl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 8f7bde6a85d6..0bd92d816391 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1002,7 +1002,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, int shutdown) { int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0; - int vol_id = -1, uninitialized_var(lnum); + int vol_id = -1, lnum = -1; #ifdef CONFIG_MTD_UBI_FASTMAP int anchor = wrk->anchor; #endif -- cgit v1.2.3-59-g8ed1b From 299d0c5b27346a77a0777c993372bf8777d4f2e5 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Sat, 28 Feb 2015 02:23:28 -0800 Subject: UBI: fix check for "too many bytes" The comparison from the previous line seems to have been erroneously (partially) copied-and-pasted onto the next. The second line should be checking req.bytes, not req.lnum. Coverity CID #139400 Cc: stable Signed-off-by: Brian Norris [rw: Fixed comparison] Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/cdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index d647e504f9b1..d16fccf79179 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -455,7 +455,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd, /* Validate the request */ err = -EINVAL; if (req.lnum < 0 || req.lnum >= vol->reserved_pebs || - req.bytes < 0 || req.lnum >= vol->usable_leb_size) + req.bytes < 0 || req.bytes > vol->usable_leb_size) break; err = get_exclusive(desc); -- cgit v1.2.3-59-g8ed1b From ab6de685221a95392e46d75d0651ac08b8a57689 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Sat, 28 Feb 2015 02:23:29 -0800 Subject: UBI: align comment for readability The kerneldoc for @vid_hdr_aloffset continues onto a second line, but this is not obvious, because the second line isn't indented, and it begins with '@'. Signed-off-by: Brian Norris Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/ubi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index c5be82d9d345..2251a6c4c8fa 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -479,7 +479,7 @@ struct ubi_debug_info { * @vid_hdr_offset: starting offset of the volume identifier header (might be * unaligned) * @vid_hdr_aloffset: starting offset of the VID header aligned to - * @hdrs_min_io_size + * @hdrs_min_io_size * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or * not -- cgit v1.2.3-59-g8ed1b From 19371d73c9bd31a8e634ec5a80fc19fcd7714481 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 23 Sep 2014 19:29:05 +0200 Subject: UBI: Fastmap: Ensure that only one fastmap work is scheduled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the WL pool runs out of PEBs we schedule a fastmap write to refill it as soon as possible. Ensure that only one at a time is scheduled otherwise we might end in a fastmap write storm because writing the fastmap can schedule another write if bitflips are detected. Signed-off-by: Richard Weinberger Reviewed-by: Tanya Brokhman Reviewed-by: Guido Martínez --- drivers/mtd/ubi/ubi.h | 4 +++- drivers/mtd/ubi/wl.c | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 2251a6c4c8fa..7a33470c0416 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -431,6 +431,7 @@ struct ubi_debug_info { * @fm_size: fastmap size in bytes * @fm_sem: allows ubi_update_fastmap() to block EBA table changes * @fm_work: fastmap work queue + * @fm_work_scheduled: non-zero if fastmap work was scheduled * * @used: RB-tree of used physical eraseblocks * @erroneous: RB-tree of erroneous used physical eraseblocks @@ -442,7 +443,7 @@ struct ubi_debug_info { * @pq_head: protection queue head * @wl_lock: protects the @used, @free, @pq, @pq_head, @lookuptbl, @move_from, * @move_to, @move_to_put @erase_pending, @wl_scheduled, @works, - * @erroneous, and @erroneous_peb_count fields + * @erroneous, @erroneous_peb_count, and @fm_work_scheduled fields * @move_mutex: serializes eraseblock moves * @work_sem: used to wait for all the scheduled works to finish and prevent * new works from being submitted @@ -537,6 +538,7 @@ struct ubi_device { void *fm_buf; size_t fm_size; struct work_struct fm_work; + int fm_work_scheduled; /* Wear-leveling sub-system's stuff */ struct rb_root used; diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 0bd92d816391..ae174f4ed674 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -149,6 +149,9 @@ static void update_fastmap_work_fn(struct work_struct *wrk) { struct ubi_device *ubi = container_of(wrk, struct ubi_device, fm_work); ubi_update_fastmap(ubi); + spin_lock(&ubi->wl_lock); + ubi->fm_work_scheduled = 0; + spin_unlock(&ubi->wl_lock); } /** @@ -657,7 +660,10 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi) /* We cannot update the fastmap here because this * function is called in atomic context. * Let's fail here and refill/update it as soon as possible. */ - schedule_work(&ubi->fm_work); + if (!ubi->fm_work_scheduled) { + ubi->fm_work_scheduled = 1; + schedule_work(&ubi->fm_work); + } return NULL; } else { pnum = pool->pebs[pool->used++]; -- cgit v1.2.3-59-g8ed1b From 399a9feeac83c2f64138c438e41222a12dd71766 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 26 Sep 2014 23:08:15 +0200 Subject: UBI: Fastmap: Ensure that all fastmap work is done upon WL shutdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ...otherwise the deferred work might run after datastructures got freed and corrupt memory. Signed-off-by: Richard Weinberger Reviewed-by: Guido Martínez --- drivers/mtd/ubi/wl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index ae174f4ed674..bf66890fefad 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1856,6 +1856,9 @@ int ubi_thread(void *u) */ static void shutdown_work(struct ubi_device *ubi) { +#ifdef CONFIG_MTD_UBI_FASTMAP + flush_work(&ubi->fm_work); +#endif while (!list_empty(&ubi->works)) { struct ubi_work *wrk; -- cgit v1.2.3-59-g8ed1b From d59f21bebe9d0fda34027ff1afda4f2b0d5f1869 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Thu, 2 Oct 2014 15:00:35 +0200 Subject: UBI: Fastmap: Fix races in ubi_wl_get_peb() ubi_wl_get_peb() has two problems, it reads the pool size and usage counters without any protection. While reading one value would be perfectly fine it reads multiple values and compares them. This is racy and can lead to incorrect pool handling. Furthermore ubi_update_fastmap() is called without wl_lock held, before incrementing the used counter it needs to be checked again. It could happen that another thread consumed all PEBs from the pool and the counter goes beyond ->size. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/ubi.h | 3 ++- drivers/mtd/ubi/wl.c | 34 +++++++++++++++++++++++----------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 7a33470c0416..bc13d14e02c4 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -443,7 +443,8 @@ struct ubi_debug_info { * @pq_head: protection queue head * @wl_lock: protects the @used, @free, @pq, @pq_head, @lookuptbl, @move_from, * @move_to, @move_to_put @erase_pending, @wl_scheduled, @works, - * @erroneous, @erroneous_peb_count, and @fm_work_scheduled fields + * @erroneous, @erroneous_peb_count, @fm_work_scheduled, @fm_pool, + * and @fm_wl_pool fields * @move_mutex: serializes eraseblock moves * @work_sem: used to wait for all the scheduled works to finish and prevent * new works from being submitted diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index bf66890fefad..2539a12140e7 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -626,24 +626,36 @@ void ubi_refill_pools(struct ubi_device *ubi) */ int ubi_wl_get_peb(struct ubi_device *ubi) { - int ret; + int ret, retried = 0; struct ubi_fm_pool *pool = &ubi->fm_pool; struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool; - if (!pool->size || !wl_pool->size || pool->used == pool->size || - wl_pool->used == wl_pool->size) +again: + spin_lock(&ubi->wl_lock); + /* We check here also for the WL pool because at this point we can + * refill the WL pool synchronous. */ + if (pool->used == pool->size || wl_pool->used == wl_pool->size) { + spin_unlock(&ubi->wl_lock); ubi_update_fastmap(ubi); - - /* we got not a single free PEB */ - if (!pool->size) - ret = -ENOSPC; - else { spin_lock(&ubi->wl_lock); - ret = pool->pebs[pool->used++]; - prot_queue_add(ubi, ubi->lookuptbl[ret]); + } + + if (pool->used == pool->size) { spin_unlock(&ubi->wl_lock); + if (retried) { + ubi_err(ubi, "Unable to get a free PEB from user WL pool"); + ret = -ENOSPC; + goto out; + } + retried = 1; + goto again; } + ubi_assert(pool->used < pool->size); + ret = pool->pebs[pool->used++]; + prot_queue_add(ubi, ubi->lookuptbl[ret]); + spin_unlock(&ubi->wl_lock); +out: return ret; } @@ -656,7 +668,7 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi) struct ubi_fm_pool *pool = &ubi->fm_wl_pool; int pnum; - if (pool->used == pool->size || !pool->size) { + if (pool->used == pool->size) { /* We cannot update the fastmap here because this * function is called in atomic context. * Let's fail here and refill/update it as soon as possible. */ -- cgit v1.2.3-59-g8ed1b From 691a870563b4fe9e014a309477fb8f9fe41b36bb Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 7 Nov 2014 23:40:27 +0100 Subject: UBI: Split __wl_get_peb() Make it two functions, wl_get_wle() and wl_get_peb(). wl_get_peb() works exactly like __wl_get_peb() but wl_get_wle() does not call produce_free_peb(). While refilling the fastmap user pool we cannot release ubi->wl_lock as produce_free_peb() does. Hence the fastmap logic uses now wl_get_wle(). Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/wl.c | 61 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 2539a12140e7..9f57d6b7579b 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -496,13 +496,46 @@ out: #endif /** - * __wl_get_peb - get a physical eraseblock. + * wl_get_wle - get a mean wl entry to be used by wl_get_peb() or + * refill_wl_user_pool(). + * @ubi: UBI device description object + * + * This function returns a a wear leveling entry in case of success and + * NULL in case of failure. + */ +static struct ubi_wl_entry *wl_get_wle(struct ubi_device *ubi) +{ + struct ubi_wl_entry *e; + + e = find_mean_wl_entry(ubi, &ubi->free); + if (!e) { + ubi_err(ubi, "no free eraseblocks"); + return NULL; + } + + self_check_in_wl_tree(ubi, e, &ubi->free); + + /* + * Move the physical eraseblock to the protection queue where it will + * be protected from being moved for some time. + */ + rb_erase(&e->u.rb, &ubi->free); + ubi->free_count--; + dbg_wl("PEB %d EC %d", e->pnum, e->ec); + + return e; +} + +/** + * wl_get_peb - get a physical eraseblock. * @ubi: UBI device description object * * This function returns a physical eraseblock in case of success and a * negative error code in case of failure. + * It is the low level component of ubi_wl_get_peb() in the non-fastmap + * case. */ -static int __wl_get_peb(struct ubi_device *ubi) +static int wl_get_peb(struct ubi_device *ubi) { int err; struct ubi_wl_entry *e; @@ -521,27 +554,9 @@ retry: goto retry; } - e = find_mean_wl_entry(ubi, &ubi->free); - if (!e) { - ubi_err(ubi, "no free eraseblocks"); - return -ENOSPC; - } - - self_check_in_wl_tree(ubi, e, &ubi->free); - - /* - * Move the physical eraseblock to the protection queue where it will - * be protected from being moved for some time. - */ - rb_erase(&e->u.rb, &ubi->free); - ubi->free_count--; - dbg_wl("PEB %d EC %d", e->pnum, e->ec); -#ifndef CONFIG_MTD_UBI_FASTMAP - /* We have to enqueue e only if fastmap is disabled, - * is fastmap enabled prot_queue_add() will be called by - * ubi_wl_get_peb() after removing e from the pool. */ + e = wl_get_wle(ubi); prot_queue_add(ubi, e); -#endif + return e->pnum; } @@ -701,7 +716,7 @@ int ubi_wl_get_peb(struct ubi_device *ubi) int peb, err; spin_lock(&ubi->wl_lock); - peb = __wl_get_peb(ubi); + peb = wl_get_peb(ubi); spin_unlock(&ubi->wl_lock); if (peb < 0) -- cgit v1.2.3-59-g8ed1b From 6830356466a57db21c7bc31bf3be4e61189e145b Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 10 Nov 2014 15:39:17 +0100 Subject: UBI: Fastmap: Make ubi_refill_pools() fair MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently ubi_refill_pools() first fills the first and then the second one. If only very few free PEBs are available the second pool can get zero PEBs. Change ubi_refill_pools() to distribute free PEBs fair between all pools. Signed-off-by: Richard Weinberger Reviewed-by: Guido Martínez --- drivers/mtd/ubi/wl.c | 85 +++++++++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 9f57d6b7579b..227ca641f700 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -580,59 +580,62 @@ static void return_unused_pool_pebs(struct ubi_device *ubi, } /** - * refill_wl_pool - refills all the fastmap pool used by the - * WL sub-system. + * ubi_refill_pools - refills all fastmap PEB pools. * @ubi: UBI device description object */ -static void refill_wl_pool(struct ubi_device *ubi) +void ubi_refill_pools(struct ubi_device *ubi) { + struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool; + struct ubi_fm_pool *pool = &ubi->fm_pool; struct ubi_wl_entry *e; - struct ubi_fm_pool *pool = &ubi->fm_wl_pool; + int enough; + spin_lock(&ubi->wl_lock); + + return_unused_pool_pebs(ubi, wl_pool); return_unused_pool_pebs(ubi, pool); - for (pool->size = 0; pool->size < pool->max_size; pool->size++) { - if (!ubi->free.rb_node || - (ubi->free_count - ubi->beb_rsvd_pebs < 5)) - break; + wl_pool->size = 0; + pool->size = 0; - e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF); - self_check_in_wl_tree(ubi, e, &ubi->free); - rb_erase(&e->u.rb, &ubi->free); - ubi->free_count--; + for (;;) { + enough = 0; + if (pool->size < pool->max_size) { + if (!ubi->free.rb_node || + (ubi->free_count - ubi->beb_rsvd_pebs < 5)) + break; - pool->pebs[pool->size] = e->pnum; - } - pool->used = 0; -} + e = wl_get_wle(ubi); + if (!e) + break; -/** - * refill_wl_user_pool - refills all the fastmap pool used by ubi_wl_get_peb. - * @ubi: UBI device description object - */ -static void refill_wl_user_pool(struct ubi_device *ubi) -{ - struct ubi_fm_pool *pool = &ubi->fm_pool; + pool->pebs[pool->size] = e->pnum; + pool->size++; + } else + enough++; - return_unused_pool_pebs(ubi, pool); + if (wl_pool->size < wl_pool->max_size) { + if (!ubi->free.rb_node || + (ubi->free_count - ubi->beb_rsvd_pebs < 5)) + break; + + e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF); + self_check_in_wl_tree(ubi, e, &ubi->free); + rb_erase(&e->u.rb, &ubi->free); + ubi->free_count--; + + wl_pool->pebs[wl_pool->size] = e->pnum; + wl_pool->size++; + } else + enough++; - for (pool->size = 0; pool->size < pool->max_size; pool->size++) { - pool->pebs[pool->size] = __wl_get_peb(ubi); - if (pool->pebs[pool->size] < 0) + if (enough == 2) break; } + + wl_pool->used = 0; pool->used = 0; -} -/** - * ubi_refill_pools - refills all fastmap PEB pools. - * @ubi: UBI device description object - */ -void ubi_refill_pools(struct ubi_device *ubi) -{ - spin_lock(&ubi->wl_lock); - refill_wl_pool(ubi); - refill_wl_user_pool(ubi); spin_unlock(&ubi->wl_lock); } @@ -2002,9 +2005,15 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) dbg_wl("found %i PEBs", found_pebs); - if (ubi->fm) + if (ubi->fm) { ubi_assert(ubi->good_peb_count == \ found_pebs + ubi->fm->used_blocks); + + for (i = 0; i < ubi->fm->used_blocks; i++) { + e = ubi->fm->e[i]; + ubi->lookuptbl[e->pnum] = e; + } + } else ubi_assert(ubi->good_peb_count == found_pebs); -- cgit v1.2.3-59-g8ed1b From c4ca6be9d67eaf5a53054903530c8f422b4b88bd Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 6 Oct 2014 14:47:51 +0200 Subject: UBI: Fastmap: Don't allocate new ubi_wl_entry objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to allocate new ones every time, we can reuse the existing ones. This makes the code cleaner and more easy to follow. Signed-off-by: Richard Weinberger Reviewed-by: Tanya Brokhman Reviewed-by: Guido Martínez --- drivers/mtd/ubi/fastmap.c | 31 +++++-------------------------- drivers/mtd/ubi/wl.c | 3 --- 2 files changed, 5 insertions(+), 29 deletions(-) diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index db3defdfc3c0..95077026ad53 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -1446,19 +1446,6 @@ int ubi_update_fastmap(struct ubi_device *ubi) } new_fm->used_blocks = ubi->fm_size / ubi->leb_size; - - for (i = 0; i < new_fm->used_blocks; i++) { - new_fm->e[i] = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); - if (!new_fm->e[i]) { - while (i--) - kfree(new_fm->e[i]); - - kfree(new_fm); - mutex_unlock(&ubi->fm_mutex); - return -ENOMEM; - } - } - old_fm = ubi->fm; ubi->fm = NULL; @@ -1494,12 +1481,9 @@ int ubi_update_fastmap(struct ubi_device *ubi) ubi_err(ubi, "could not erase old fastmap PEB"); goto err; } - - new_fm->e[i]->pnum = old_fm->e[i]->pnum; - new_fm->e[i]->ec = old_fm->e[i]->ec; + new_fm->e[i] = old_fm->e[i]; } else { - new_fm->e[i]->pnum = tmp_e->pnum; - new_fm->e[i]->ec = tmp_e->ec; + new_fm->e[i] = tmp_e; if (old_fm) ubi_wl_put_fm_peb(ubi, old_fm->e[i], i, @@ -1524,16 +1508,13 @@ int ubi_update_fastmap(struct ubi_device *ubi) i, 0); goto err; } - - new_fm->e[0]->pnum = old_fm->e[0]->pnum; + new_fm->e[0] = old_fm->e[0]; new_fm->e[0]->ec = ret; } else { /* we've got a new anchor PEB, return the old one */ ubi_wl_put_fm_peb(ubi, old_fm->e[0], 0, old_fm->to_be_tortured[0]); - - new_fm->e[0]->pnum = tmp_e->pnum; - new_fm->e[0]->ec = tmp_e->ec; + new_fm->e[0] = tmp_e; } } else { if (!tmp_e) { @@ -1546,9 +1527,7 @@ int ubi_update_fastmap(struct ubi_device *ubi) ret = -ENOSPC; goto err; } - - new_fm->e[0]->pnum = tmp_e->pnum; - new_fm->e[0]->ec = tmp_e->ec; + new_fm->e[0] = tmp_e; } down_write(&ubi->work_sem); diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 227ca641f700..34a8ec44cc59 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1011,9 +1011,6 @@ int ubi_wl_put_fm_peb(struct ubi_device *ubi, struct ubi_wl_entry *fm_e, e = fm_e; ubi_assert(e->ec >= 0); ubi->lookuptbl[pnum] = e; - } else { - e->ec = fm_e->ec; - kfree(fm_e); } spin_unlock(&ubi->wl_lock); -- cgit v1.2.3-59-g8ed1b From 74cdaf24004aea8de350f58979548b3eddc11e9a Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 6 Oct 2014 14:42:01 +0200 Subject: UBI: Fastmap: Fix memory leaks while closing the WL sub-system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a ubi_fastmap_close() to free all resources used by fastmap at WL shutdown. Signed-off-by: Richard Weinberger Tested-by: Guido Martínez Reviewed-by: Guido Martínez --- drivers/mtd/ubi/wl.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 34a8ec44cc59..11e0d7523d14 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -2064,6 +2064,23 @@ static void protection_queue_destroy(struct ubi_device *ubi) } } +static void ubi_fastmap_close(struct ubi_device *ubi) +{ +#ifdef CONFIG_MTD_UBI_FASTMAP + int i; + + flush_work(&ubi->fm_work); + return_unused_pool_pebs(ubi, &ubi->fm_pool); + return_unused_pool_pebs(ubi, &ubi->fm_wl_pool); + + if (ubi->fm) { + for (i = 0; i < ubi->fm->used_blocks; i++) + kfree(ubi->fm->e[i]); + } + kfree(ubi->fm); +#endif +} + /** * ubi_wl_close - close the wear-leveling sub-system. * @ubi: UBI device description object @@ -2071,6 +2088,7 @@ static void protection_queue_destroy(struct ubi_device *ubi) void ubi_wl_close(struct ubi_device *ubi) { dbg_wl("close the WL sub-system"); + ubi_fastmap_close(ubi); shutdown_work(ubi); protection_queue_destroy(ubi); tree_destroy(&ubi->used); -- cgit v1.2.3-59-g8ed1b From 943b33564e78130014ca91b575181becc828179e Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 6 Oct 2014 14:57:18 +0200 Subject: UBI: Fastmap: Notify user in case of an ubi_update_fastmap() failure If ubi_update_fastmap() fails notify the user. This is not a hard error as ubi_update_fastmap() makes sure that upon failure the current on-flash fastmap will no be used upon next UBI attach. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/wl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 11e0d7523d14..b9b7f97db837 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -654,7 +654,11 @@ again: * refill the WL pool synchronous. */ if (pool->used == pool->size || wl_pool->used == wl_pool->size) { spin_unlock(&ubi->wl_lock); - ubi_update_fastmap(ubi); + ret = ubi_update_fastmap(ubi); + if (ret) { + ubi_msg(ubi, "Unable to write a new fastmap: %i", ret); + return -ENOSPC; + } spin_lock(&ubi->wl_lock); } -- cgit v1.2.3-59-g8ed1b From 5e0246e332349751d39d186ea0b7ec1e371ab2f8 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 6 Oct 2014 15:12:16 +0200 Subject: UBI: Fastmap: Wrap fastmap specific function in a ifdef ...such that we can implement NOP variants of some functions. This will help to reduce fastmap specific ifdefs in other c files. Signed-off-by: Richard Weinberger Reviewed-by: Tanya Brokhman --- drivers/mtd/ubi/ubi.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index bc13d14e02c4..3ea9480bd055 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -871,10 +871,14 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, int pnum, const struct ubi_vid_hdr *vid_hdr); /* fastmap.c */ +#ifdef CONFIG_MTD_UBI_FASTMAP size_t ubi_calc_fm_size(struct ubi_device *ubi); int ubi_update_fastmap(struct ubi_device *ubi); int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, int fm_anchor); +#else +static inline int ubi_update_fastmap(struct ubi_device *ubi) { return 0; } +#endif /* block.c */ #ifdef CONFIG_MTD_UBI_BLOCK -- cgit v1.2.3-59-g8ed1b From 84b678f497c6eda650f0640bd7cf165e2c1acb49 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 6 Oct 2014 15:14:16 +0200 Subject: UBI: Fastmap: Fix fastmap usage in ubi_volume_notify() There is no need to switch to ro mode if ubi_update_fastmap() fails. Also get rid of the ifdef. Signed-off-by: Richard Weinberger Reviewed-by: Tanya Brokhman --- drivers/mtd/ubi/build.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index ba01a8d22d28..112a66c65966 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -154,23 +154,22 @@ static struct device_attribute dev_mtd_num = */ int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol, int ntype) { + int ret; struct ubi_notification nt; ubi_do_get_device_info(ubi, &nt.di); ubi_do_get_volume_info(ubi, vol, &nt.vi); -#ifdef CONFIG_MTD_UBI_FASTMAP switch (ntype) { case UBI_VOLUME_ADDED: case UBI_VOLUME_REMOVED: case UBI_VOLUME_RESIZED: case UBI_VOLUME_RENAMED: - if (ubi_update_fastmap(ubi)) { - ubi_err(ubi, "Unable to update fastmap!"); - ubi_ro_mode(ubi); - } + ret = ubi_update_fastmap(ubi); + if (ret) + ubi_msg(ubi, "Unable to write a new fastmap: %i", ret); } -#endif + return blocking_notifier_call_chain(&ubi_notifiers, ntype, &nt); } -- cgit v1.2.3-59-g8ed1b From 98105d0819daf569e741ddfba73cedcac371b9d8 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 6 Oct 2014 15:39:01 +0200 Subject: UBI: Fastmap: Fix memory leak while attaching Currently we leak a few ubi_ainf_pebs while attaching. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/attach.c | 61 +++++++++++++++++++++++++---------------------- drivers/mtd/ubi/fastmap.c | 13 ---------- 2 files changed, 33 insertions(+), 41 deletions(-) diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index b5e154856994..ef619c3a75d3 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c @@ -1301,6 +1301,30 @@ out_ech: return err; } +static struct ubi_attach_info *alloc_ai(const char *slab_name) +{ + struct ubi_attach_info *ai; + + ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL); + if (!ai) + return ai; + + INIT_LIST_HEAD(&ai->corr); + INIT_LIST_HEAD(&ai->free); + INIT_LIST_HEAD(&ai->erase); + INIT_LIST_HEAD(&ai->alien); + ai->volumes = RB_ROOT; + ai->aeb_slab_cache = kmem_cache_create(slab_name, + sizeof(struct ubi_ainf_peb), + 0, 0, NULL); + if (!ai->aeb_slab_cache) { + kfree(ai); + ai = NULL; + } + + return ai; +} + #ifdef CONFIG_MTD_UBI_FASTMAP /** @@ -1313,7 +1337,7 @@ out_ech: * UBI_NO_FASTMAP denotes that no fastmap was found. * UBI_BAD_FASTMAP denotes that the found fastmap was invalid. */ -static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info *ai) +static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai) { int err, pnum, fm_anchor = -1; unsigned long long max_sqnum = 0; @@ -1334,7 +1358,7 @@ static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info *ai) cond_resched(); dbg_gen("process PEB %d", pnum); - err = scan_peb(ubi, ai, pnum, &vol_id, &sqnum); + err = scan_peb(ubi, *ai, pnum, &vol_id, &sqnum); if (err < 0) goto out_vidh; @@ -1350,7 +1374,12 @@ static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info *ai) if (fm_anchor < 0) return UBI_NO_FASTMAP; - return ubi_scan_fastmap(ubi, ai, fm_anchor); + destroy_ai(*ai); + *ai = alloc_ai("ubi_aeb_slab_cache"); + if (!*ai) + return -ENOMEM; + + return ubi_scan_fastmap(ubi, *ai, fm_anchor); out_vidh: ubi_free_vid_hdr(ubi, vidh); @@ -1362,30 +1391,6 @@ out: #endif -static struct ubi_attach_info *alloc_ai(const char *slab_name) -{ - struct ubi_attach_info *ai; - - ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL); - if (!ai) - return ai; - - INIT_LIST_HEAD(&ai->corr); - INIT_LIST_HEAD(&ai->free); - INIT_LIST_HEAD(&ai->erase); - INIT_LIST_HEAD(&ai->alien); - ai->volumes = RB_ROOT; - ai->aeb_slab_cache = kmem_cache_create(slab_name, - sizeof(struct ubi_ainf_peb), - 0, 0, NULL); - if (!ai->aeb_slab_cache) { - kfree(ai); - ai = NULL; - } - - return ai; -} - /** * ubi_attach - attach an MTD device. * @ubi: UBI device descriptor @@ -1413,7 +1418,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) if (force_scan) err = scan_all(ubi, ai, 0); else { - err = scan_fast(ubi, ai); + err = scan_fast(ubi, &ai); if (err > 0) { if (err != UBI_NO_FASTMAP) { destroy_ai(ai); diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 95077026ad53..600c4f9683e9 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -561,21 +561,8 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, INIT_LIST_HEAD(&used); INIT_LIST_HEAD(&free); INIT_LIST_HEAD(&eba_orphans); - INIT_LIST_HEAD(&ai->corr); - INIT_LIST_HEAD(&ai->free); - INIT_LIST_HEAD(&ai->erase); - INIT_LIST_HEAD(&ai->alien); - ai->volumes = RB_ROOT; ai->min_ec = UBI_MAX_ERASECOUNTER; - ai->aeb_slab_cache = kmem_cache_create("ubi_ainf_peb_slab", - sizeof(struct ubi_ainf_peb), - 0, 0, NULL); - if (!ai->aeb_slab_cache) { - ret = -ENOMEM; - goto fail; - } - fmsb = (struct ubi_fm_sb *)(fm_raw); ai->max_sqnum = fmsb->sqnum; fm_pos += sizeof(struct ubi_fm_sb); -- cgit v1.2.3-59-g8ed1b From d2158f69a7d469c21c37f7028c18aa8c54707de3 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 6 Oct 2014 15:58:07 +0200 Subject: UBI: Remove alloc_ai() slab name from parameter list There is always exactly one ubi_attach_info object allocated, therefore we don't have to care about the name. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/attach.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index ef619c3a75d3..5d89b3fb1d3c 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c @@ -1301,7 +1301,7 @@ out_ech: return err; } -static struct ubi_attach_info *alloc_ai(const char *slab_name) +static struct ubi_attach_info *alloc_ai(void) { struct ubi_attach_info *ai; @@ -1314,7 +1314,7 @@ static struct ubi_attach_info *alloc_ai(const char *slab_name) INIT_LIST_HEAD(&ai->erase); INIT_LIST_HEAD(&ai->alien); ai->volumes = RB_ROOT; - ai->aeb_slab_cache = kmem_cache_create(slab_name, + ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache", sizeof(struct ubi_ainf_peb), 0, 0, NULL); if (!ai->aeb_slab_cache) { @@ -1375,7 +1375,7 @@ static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai) return UBI_NO_FASTMAP; destroy_ai(*ai); - *ai = alloc_ai("ubi_aeb_slab_cache"); + *ai = alloc_ai(); if (!*ai) return -ENOMEM; @@ -1404,7 +1404,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) int err; struct ubi_attach_info *ai; - ai = alloc_ai("ubi_aeb_slab_cache"); + ai = alloc_ai(); if (!ai) return -ENOMEM; @@ -1422,7 +1422,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) if (err > 0) { if (err != UBI_NO_FASTMAP) { destroy_ai(ai); - ai = alloc_ai("ubi_aeb_slab_cache2"); + ai = alloc_ai(); if (!ai) return -ENOMEM; @@ -1461,7 +1461,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) if (ubi->fm && ubi_dbg_chk_gen(ubi)) { struct ubi_attach_info *scan_ai; - scan_ai = alloc_ai("ubi_ckh_aeb_slab_cache"); + scan_ai = alloc_ai(); if (!scan_ai) { err = -ENOMEM; goto out_wl; -- cgit v1.2.3-59-g8ed1b From 36a87e44f642966442fd0d23f2ec536851e00236 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 7 Oct 2014 16:31:22 +0200 Subject: UBI: Fastmap: Fix race in ubi_eba_atomic_leb_change() This function a) requests a new PEB, b) writes data to it, c) returns the old PEB and d) registers the new PEB in the EBA table. For the non-fastmap case this works perfectly fine and is powercut safe. Is fastmap enabled this can lead to issues. If a new fastmap is written between a) and c) the freshly requested PEB is no longer in a pool and will not be scanned upon attaching. If now a powercut happens between c) and d) the freshly requested PEB will not be scanned and the old one got already scheduled for erase. After attaching the EBA table will point to a erased PEB. Fix this issue by swapping steps c) and d). Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/eba.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 8c9a710def99..e0a06e4b95a4 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -900,7 +900,7 @@ write_error: int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, const void *buf, int len) { - int err, pnum, tries = 0, vol_id = vol->vol_id; + int err, pnum, old_pnum, tries = 0, vol_id = vol->vol_id; struct ubi_vid_hdr *vid_hdr; uint32_t crc; @@ -963,16 +963,17 @@ retry: goto write_error; } - if (vol->eba_tbl[lnum] >= 0) { - err = ubi_wl_put_peb(ubi, vol_id, lnum, vol->eba_tbl[lnum], 0); - if (err) - goto out_leb_unlock; - } - down_read(&ubi->fm_sem); + old_pnum = vol->eba_tbl[lnum]; vol->eba_tbl[lnum] = pnum; up_read(&ubi->fm_sem); + if (old_pnum >= 0) { + err = ubi_wl_put_peb(ubi, vol_id, lnum, old_pnum, 0); + if (err) + goto out_leb_unlock; + } + out_leb_unlock: leb_write_unlock(ubi, vol_id, lnum); out_mutex: -- cgit v1.2.3-59-g8ed1b From a83832a7c8d023f446ec865926190951bd18a4b1 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 7 Oct 2014 18:51:07 +0200 Subject: UBI: Fastmap: Remove bogus ubi_assert() It is legal to have PEBs left in the used list. This can happen if UBI copies a PEB and a powercut happens between writing a new fastmap and adding this PEB into the EBA table. In this case the old PEB will be used. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 600c4f9683e9..9858bfb22314 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -814,7 +814,9 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) list_move_tail(&tmp_aeb->u.list, &ai->free); - ubi_assert(list_empty(&used)); + list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &used, u.list) + list_move_tail(&tmp_aeb->u.list, &ai->erase); + ubi_assert(list_empty(&eba_orphans)); ubi_assert(list_empty(&free)); -- cgit v1.2.3-59-g8ed1b From d141a8ef21ab496ab6f8d188dfe7ca33e16fe798 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 7 Oct 2014 21:39:20 +0200 Subject: UBI: Fastmap: Remove eba_orphans logic This logic is in vain as we treat protected PEBs also as used, so this case must not happen. If a PEB is found which is in the EBA table but not known as used has to be issued as fatal error. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap.c | 91 +++++------------------------------------------ 1 file changed, 8 insertions(+), 83 deletions(-) diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 9858bfb22314..8b95c48a002d 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -376,7 +376,6 @@ static void unmap_peb(struct ubi_attach_info *ai, int pnum) * @pebs: an array of all PEB numbers in the to be scanned pool * @pool_size: size of the pool (number of entries in @pebs) * @max_sqnum: pointer to the maximal sequence number - * @eba_orphans: list of PEBs which need to be scanned * @free: list of PEBs which are most likely free (and go into @ai->free) * * Returns 0 on success, if the pool is unusable UBI_BAD_FASTMAP is returned. @@ -384,12 +383,12 @@ static void unmap_peb(struct ubi_attach_info *ai, int pnum) */ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, int *pebs, int pool_size, unsigned long long *max_sqnum, - struct list_head *eba_orphans, struct list_head *free) + struct list_head *free) { struct ubi_vid_hdr *vh; struct ubi_ec_hdr *ech; - struct ubi_ainf_peb *new_aeb, *tmp_aeb; - int i, pnum, err, found_orphan, ret = 0; + struct ubi_ainf_peb *new_aeb; + int i, pnum, err, ret = 0; ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); if (!ech) @@ -457,18 +456,6 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, if (err == UBI_IO_BITFLIPS) scrub = 1; - found_orphan = 0; - list_for_each_entry(tmp_aeb, eba_orphans, u.list) { - if (tmp_aeb->pnum == pnum) { - found_orphan = 1; - break; - } - } - if (found_orphan) { - list_del(&tmp_aeb->u.list); - kmem_cache_free(ai->aeb_slab_cache, tmp_aeb); - } - new_aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL); if (!new_aeb) { @@ -543,10 +530,9 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, struct ubi_fastmap_layout *fm) { - struct list_head used, eba_orphans, free; + struct list_head used, free; struct ubi_ainf_volume *av; struct ubi_ainf_peb *aeb, *tmp_aeb, *_tmp_aeb; - struct ubi_ec_hdr *ech; struct ubi_fm_sb *fmsb; struct ubi_fm_hdr *fmhdr; struct ubi_fm_scan_pool *fmpl1, *fmpl2; @@ -560,7 +546,6 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, INIT_LIST_HEAD(&used); INIT_LIST_HEAD(&free); - INIT_LIST_HEAD(&eba_orphans); ai->min_ec = UBI_MAX_ERASECOUNTER; fmsb = (struct ubi_fm_sb *)(fm_raw); @@ -728,28 +713,9 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, } } - /* This can happen if a PEB is already in an EBA known - * by this fastmap but the PEB itself is not in the used - * list. - * In this case the PEB can be within the fastmap pool - * or while writing the fastmap it was in the protection - * queue. - */ if (!aeb) { - aeb = kmem_cache_alloc(ai->aeb_slab_cache, - GFP_KERNEL); - if (!aeb) { - ret = -ENOMEM; - - goto fail; - } - - aeb->lnum = j; - aeb->pnum = be32_to_cpu(fm_eba->pnum[j]); - aeb->ec = -1; - aeb->scrub = aeb->copy_flag = aeb->sqnum = 0; - list_add_tail(&aeb->u.list, &eba_orphans); - continue; + ubi_err(ubi, "PEB %i is in EBA but not in used list", pnum); + goto fail_bad; } aeb->lnum = j; @@ -762,49 +728,13 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, dbg_bld("inserting PEB:%i (LEB %i) to vol %i", aeb->pnum, aeb->lnum, av->vol_id); } - - ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); - if (!ech) { - ret = -ENOMEM; - goto fail; - } - - list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &eba_orphans, - u.list) { - int err; - - if (ubi_io_is_bad(ubi, tmp_aeb->pnum)) { - ubi_err(ubi, "bad PEB in fastmap EBA orphan list"); - ret = UBI_BAD_FASTMAP; - kfree(ech); - goto fail; - } - - err = ubi_io_read_ec_hdr(ubi, tmp_aeb->pnum, ech, 0); - if (err && err != UBI_IO_BITFLIPS) { - ubi_err(ubi, "unable to read EC header! PEB:%i err:%i", - tmp_aeb->pnum, err); - ret = err > 0 ? UBI_BAD_FASTMAP : err; - kfree(ech); - - goto fail; - } else if (err == UBI_IO_BITFLIPS) - tmp_aeb->scrub = 1; - - tmp_aeb->ec = be64_to_cpu(ech->ec); - assign_aeb_to_av(ai, tmp_aeb, av); - } - - kfree(ech); } - ret = scan_pool(ubi, ai, fmpl1->pebs, pool_size, &max_sqnum, - &eba_orphans, &free); + ret = scan_pool(ubi, ai, fmpl1->pebs, pool_size, &max_sqnum, &free); if (ret) goto fail; - ret = scan_pool(ubi, ai, fmpl2->pebs, wl_pool_size, &max_sqnum, - &eba_orphans, &free); + ret = scan_pool(ubi, ai, fmpl2->pebs, wl_pool_size, &max_sqnum, &free); if (ret) goto fail; @@ -817,7 +747,6 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &used, u.list) list_move_tail(&tmp_aeb->u.list, &ai->erase); - ubi_assert(list_empty(&eba_orphans)); ubi_assert(list_empty(&free)); /* @@ -839,10 +768,6 @@ fail: list_del(&tmp_aeb->u.list); kmem_cache_free(ai->aeb_slab_cache, tmp_aeb); } - list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &eba_orphans, u.list) { - list_del(&tmp_aeb->u.list); - kmem_cache_free(ai->aeb_slab_cache, tmp_aeb); - } list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) { list_del(&tmp_aeb->u.list); kmem_cache_free(ai->aeb_slab_cache, tmp_aeb); -- cgit v1.2.3-59-g8ed1b From 2d93fb3632755c170bc684989709e28ef3d22a80 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 7 Oct 2014 21:45:19 +0200 Subject: UBI: Fastmap: Switch to ro mode if invalidate_fastmap() fails We have to switch to ro mode to guarantee that upon next UBI attach all data is consistent. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 8b95c48a002d..3d913f53fd06 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -1466,8 +1466,10 @@ err: ret = 0; if (old_fm) { ret = invalidate_fastmap(ubi, old_fm); - if (ret < 0) + if (ret < 0) { ubi_err(ubi, "Unable to invalidiate current fastmap!"); + ubi_ro_mode(ubi); + } else if (ret) ret = 0; } -- cgit v1.2.3-59-g8ed1b From 68e3226bd4e05c4be1f6286e4e708e1163ffa092 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 8 Oct 2014 14:55:58 +0200 Subject: UBI: Fastmap: Make WL pool size 50% of user pool size Don't use a fixed size for the WL pool. Make it instead 50% of the user pool. We don't make it 100% as it is not as heavily used as the user pool. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/build.c | 2 +- drivers/mtd/ubi/ubi-media.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 112a66c65966..59af91b41f9a 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -949,7 +949,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, if (ubi->fm_pool.max_size < UBI_FM_MIN_POOL_SIZE) ubi->fm_pool.max_size = UBI_FM_MIN_POOL_SIZE; - ubi->fm_wl_pool.max_size = UBI_FM_WL_POOL_SIZE; + ubi->fm_wl_pool.max_size = ubi->fm_pool.max_size / 2; ubi->fm_disabled = !fm_autoconvert; if (!ubi->fm_disabled && (int)mtd_div_by_eb(ubi->mtd->size, ubi->mtd) diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h index ac2b24d1783d..d0d072e7ccd2 100644 --- a/drivers/mtd/ubi/ubi-media.h +++ b/drivers/mtd/ubi/ubi-media.h @@ -403,8 +403,6 @@ struct ubi_vtbl_record { #define UBI_FM_MIN_POOL_SIZE 8 #define UBI_FM_MAX_POOL_SIZE 256 -#define UBI_FM_WL_POOL_SIZE 25 - /** * struct ubi_fm_sb - UBI fastmap super block * @magic: fastmap super block magic number (%UBI_FM_SB_MAGIC) -- cgit v1.2.3-59-g8ed1b From ad3d6a05ee45eebf68ff08da0d3f86251b530a27 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 24 Oct 2014 15:22:05 +0200 Subject: UBI: Fastmap: Fix leb_count unbalance If a LEB is unmapped we have to decrement leb_count as well. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 3d913f53fd06..5db41a5fdd7a 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -362,6 +362,7 @@ static void unmap_peb(struct ubi_attach_info *ai, int pnum) aeb = rb_entry(node2, struct ubi_ainf_peb, u.rb); if (aeb->pnum == pnum) { rb_erase(&aeb->u.rb, &av->root); + av->leb_count--; kmem_cache_free(ai->aeb_slab_cache, aeb); return; } -- cgit v1.2.3-59-g8ed1b From 8fb2a514780eee48602424a86e3cd72d3f1bdfb2 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 10 Nov 2014 16:27:10 +0100 Subject: UBI: Fastmap: Fix race after ubi_wl_get_peb() ubi_wl_get_peb() returns a fresh PEB which can be used by user of UBI. Due to the pool logic fastmap will correctly map this PEB upon attach time because it will be scanned. If a new fastmap is written (due to heavy parallel io) while the before the fresh PEB is assigned to the EBA table it will not be scanned as it is no longer in the pool. So, the race window exists between ubi_wl_get_peb() and the EBA table assignment. We have to make sure that no new fastmap can be written while that. To ensure that ubi_wl_get_peb() will grab ubi->fm_sem in read mode and the user of ubi_wl_get_peb() has to release it after the PEB got assigned. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/eba.c | 24 ++++++++++++++++++------ drivers/mtd/ubi/wl.c | 7 +++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index e0a06e4b95a4..4757cef756f7 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -567,6 +567,7 @@ retry: new_pnum = ubi_wl_get_peb(ubi); if (new_pnum < 0) { ubi_free_vid_hdr(ubi, vid_hdr); + up_read(&ubi->fm_sem); return new_pnum; } @@ -577,13 +578,16 @@ retry: if (err && err != UBI_IO_BITFLIPS) { if (err > 0) err = -EIO; + up_read(&ubi->fm_sem); goto out_put; } vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi)); err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr); - if (err) + if (err) { + up_read(&ubi->fm_sem); goto write_error; + } data_size = offset + len; mutex_lock(&ubi->buf_mutex); @@ -592,8 +596,10 @@ retry: /* Read everything before the area where the write failure happened */ if (offset > 0) { err = ubi_io_read_data(ubi, ubi->peb_buf, pnum, 0, offset); - if (err && err != UBI_IO_BITFLIPS) + if (err && err != UBI_IO_BITFLIPS) { + up_read(&ubi->fm_sem); goto out_unlock; + } } memcpy(ubi->peb_buf + offset, buf, len); @@ -601,13 +607,13 @@ retry: err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size); if (err) { mutex_unlock(&ubi->buf_mutex); + up_read(&ubi->fm_sem); goto write_error; } mutex_unlock(&ubi->buf_mutex); ubi_free_vid_hdr(ubi, vid_hdr); - down_read(&ubi->fm_sem); vol->eba_tbl[lnum] = new_pnum; up_read(&ubi->fm_sem); ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1); @@ -704,6 +710,7 @@ retry: if (pnum < 0) { ubi_free_vid_hdr(ubi, vid_hdr); leb_write_unlock(ubi, vol_id, lnum); + up_read(&ubi->fm_sem); return pnum; } @@ -714,6 +721,7 @@ retry: if (err) { ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d", vol_id, lnum, pnum); + up_read(&ubi->fm_sem); goto write_error; } @@ -722,11 +730,11 @@ retry: if (err) { ubi_warn(ubi, "failed to write %d bytes at offset %d of LEB %d:%d, PEB %d", len, offset, vol_id, lnum, pnum); + up_read(&ubi->fm_sem); goto write_error; } } - down_read(&ubi->fm_sem); vol->eba_tbl[lnum] = pnum; up_read(&ubi->fm_sem); @@ -825,6 +833,7 @@ retry: if (pnum < 0) { ubi_free_vid_hdr(ubi, vid_hdr); leb_write_unlock(ubi, vol_id, lnum); + up_read(&ubi->fm_sem); return pnum; } @@ -835,6 +844,7 @@ retry: if (err) { ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d", vol_id, lnum, pnum); + up_read(&ubi->fm_sem); goto write_error; } @@ -842,11 +852,11 @@ retry: if (err) { ubi_warn(ubi, "failed to write %d bytes of data to PEB %d", len, pnum); + up_read(&ubi->fm_sem); goto write_error; } ubi_assert(vol->eba_tbl[lnum] < 0); - down_read(&ubi->fm_sem); vol->eba_tbl[lnum] = pnum; up_read(&ubi->fm_sem); @@ -943,6 +953,7 @@ retry: pnum = ubi_wl_get_peb(ubi); if (pnum < 0) { err = pnum; + up_read(&ubi->fm_sem); goto out_leb_unlock; } @@ -953,6 +964,7 @@ retry: if (err) { ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d", vol_id, lnum, pnum); + up_read(&ubi->fm_sem); goto write_error; } @@ -960,10 +972,10 @@ retry: if (err) { ubi_warn(ubi, "failed to write %d bytes of data to PEB %d", len, pnum); + up_read(&ubi->fm_sem); goto write_error; } - down_read(&ubi->fm_sem); old_pnum = vol->eba_tbl[lnum]; vol->eba_tbl[lnum] = pnum; up_read(&ubi->fm_sem); diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index b9b7f97db837..b8ad5e005cdc 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -641,6 +641,7 @@ void ubi_refill_pools(struct ubi_device *ubi) /* ubi_wl_get_peb - works exaclty like __wl_get_peb but keeps track of * the fastmap pool. + * Returns with ubi->fm_sem held in read mode! */ int ubi_wl_get_peb(struct ubi_device *ubi) { @@ -649,16 +650,20 @@ int ubi_wl_get_peb(struct ubi_device *ubi) struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool; again: + down_read(&ubi->fm_sem); spin_lock(&ubi->wl_lock); /* We check here also for the WL pool because at this point we can * refill the WL pool synchronous. */ if (pool->used == pool->size || wl_pool->used == wl_pool->size) { spin_unlock(&ubi->wl_lock); + up_read(&ubi->fm_sem); ret = ubi_update_fastmap(ubi); if (ret) { ubi_msg(ubi, "Unable to write a new fastmap: %i", ret); + down_read(&ubi->fm_sem); return -ENOSPC; } + down_read(&ubi->fm_sem); spin_lock(&ubi->wl_lock); } @@ -670,6 +675,7 @@ again: goto out; } retried = 1; + up_read(&ubi->fm_sem); goto again; } @@ -725,6 +731,7 @@ int ubi_wl_get_peb(struct ubi_device *ubi) spin_lock(&ubi->wl_lock); peb = wl_get_peb(ubi); spin_unlock(&ubi->wl_lock); + down_read(&ubi->fm_sem); if (peb < 0) return peb; -- cgit v1.2.3-59-g8ed1b From 42dd3cdcd6b5671ebedc3df76ca8dcc3473bcc67 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sat, 25 Oct 2014 13:26:49 +0200 Subject: UBI: Fastmap: Set used_ebs only for static volumes If we set it for dynamic ones we might confuse various self checks. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 5db41a5fdd7a..749e2e4738fc 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -136,14 +136,15 @@ static struct ubi_ainf_volume *add_vol(struct ubi_attach_info *ai, int vol_id, if (!av) goto out; - av->highest_lnum = av->leb_count = 0; + av->highest_lnum = av->leb_count = av->used_ebs = 0; av->vol_id = vol_id; - av->used_ebs = used_ebs; av->data_pad = data_pad; av->last_data_size = last_eb_bytes; av->compat = 0; av->vol_type = vol_type; av->root = RB_ROOT; + if (av->vol_type == UBI_STATIC_VOLUME) + av->used_ebs = used_ebs; dbg_bld("found volume (ID %i)", vol_id); -- cgit v1.2.3-59-g8ed1b From 111ab0b26fc1bfad575d1e376e146d194d261e22 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 10 Nov 2014 16:28:08 +0100 Subject: UBI: Fastmap: Locking updates a) Rename ubi->fm_sem to ubi->fm_eba_sem as this semaphore protects EBA changes. b) Turn ubi->fm_mutex into a rw semaphore. It will still serialize fastmap writes but also ensures that ubi_wl_put_peb() is not interrupted by a fastmap write. We use a rw semaphore to allow ubi_wl_put_peb() still to be executed in parallel if no fastmap write is happening. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/build.c | 4 ++-- drivers/mtd/ubi/eba.c | 44 ++++++++++++++++++++++---------------------- drivers/mtd/ubi/fastmap.c | 18 +++++++++--------- drivers/mtd/ubi/ubi.h | 9 +++++---- drivers/mtd/ubi/wl.c | 19 ++++++++++++------- 5 files changed, 50 insertions(+), 44 deletions(-) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 59af91b41f9a..a7571508fdab 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -969,8 +969,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, mutex_init(&ubi->ckvol_mutex); mutex_init(&ubi->device_mutex); spin_lock_init(&ubi->volumes_lock); - mutex_init(&ubi->fm_mutex); - init_rwsem(&ubi->fm_sem); + init_rwsem(&ubi->fm_protect); + init_rwsem(&ubi->fm_eba_sem); ubi_msg(ubi, "attaching mtd%d", mtd->index); diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 4757cef756f7..51bca035cd83 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -340,9 +340,9 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol, dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum); - down_read(&ubi->fm_sem); + down_read(&ubi->fm_eba_sem); vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED; - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 0); out_unlock: @@ -567,7 +567,7 @@ retry: new_pnum = ubi_wl_get_peb(ubi); if (new_pnum < 0) { ubi_free_vid_hdr(ubi, vid_hdr); - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); return new_pnum; } @@ -578,14 +578,14 @@ retry: if (err && err != UBI_IO_BITFLIPS) { if (err > 0) err = -EIO; - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); goto out_put; } vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi)); err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr); if (err) { - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); goto write_error; } @@ -597,7 +597,7 @@ retry: if (offset > 0) { err = ubi_io_read_data(ubi, ubi->peb_buf, pnum, 0, offset); if (err && err != UBI_IO_BITFLIPS) { - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); goto out_unlock; } } @@ -607,7 +607,7 @@ retry: err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size); if (err) { mutex_unlock(&ubi->buf_mutex); - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); goto write_error; } @@ -615,7 +615,7 @@ retry: ubi_free_vid_hdr(ubi, vid_hdr); vol->eba_tbl[lnum] = new_pnum; - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1); ubi_msg(ubi, "data was successfully recovered"); @@ -710,7 +710,7 @@ retry: if (pnum < 0) { ubi_free_vid_hdr(ubi, vid_hdr); leb_write_unlock(ubi, vol_id, lnum); - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); return pnum; } @@ -721,7 +721,7 @@ retry: if (err) { ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d", vol_id, lnum, pnum); - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); goto write_error; } @@ -730,13 +730,13 @@ retry: if (err) { ubi_warn(ubi, "failed to write %d bytes at offset %d of LEB %d:%d, PEB %d", len, offset, vol_id, lnum, pnum); - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); goto write_error; } } vol->eba_tbl[lnum] = pnum; - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); leb_write_unlock(ubi, vol_id, lnum); ubi_free_vid_hdr(ubi, vid_hdr); @@ -833,7 +833,7 @@ retry: if (pnum < 0) { ubi_free_vid_hdr(ubi, vid_hdr); leb_write_unlock(ubi, vol_id, lnum); - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); return pnum; } @@ -844,7 +844,7 @@ retry: if (err) { ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d", vol_id, lnum, pnum); - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); goto write_error; } @@ -852,13 +852,13 @@ retry: if (err) { ubi_warn(ubi, "failed to write %d bytes of data to PEB %d", len, pnum); - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); goto write_error; } ubi_assert(vol->eba_tbl[lnum] < 0); vol->eba_tbl[lnum] = pnum; - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); leb_write_unlock(ubi, vol_id, lnum); ubi_free_vid_hdr(ubi, vid_hdr); @@ -953,7 +953,7 @@ retry: pnum = ubi_wl_get_peb(ubi); if (pnum < 0) { err = pnum; - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); goto out_leb_unlock; } @@ -964,7 +964,7 @@ retry: if (err) { ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d", vol_id, lnum, pnum); - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); goto write_error; } @@ -972,13 +972,13 @@ retry: if (err) { ubi_warn(ubi, "failed to write %d bytes of data to PEB %d", len, pnum); - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); goto write_error; } old_pnum = vol->eba_tbl[lnum]; vol->eba_tbl[lnum] = pnum; - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); if (old_pnum >= 0) { err = ubi_wl_put_peb(ubi, vol_id, lnum, old_pnum, 0); @@ -1231,9 +1231,9 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, } ubi_assert(vol->eba_tbl[lnum] == from); - down_read(&ubi->fm_sem); + down_read(&ubi->fm_eba_sem); vol->eba_tbl[lnum] = to; - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); out_unlock_buf: mutex_unlock(&ubi->buf_mutex); diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 749e2e4738fc..2cf2506b8f44 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -800,7 +800,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, __be32 crc, tmp_crc; unsigned long long sqnum = 0; - mutex_lock(&ubi->fm_mutex); + down_write(&ubi->fm_protect); memset(ubi->fm_buf, 0, ubi->fm_size); fmsb = kmalloc(sizeof(*fmsb), GFP_KERNEL); @@ -991,7 +991,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, ubi_free_vid_hdr(ubi, vh); kfree(ech); out: - mutex_unlock(&ubi->fm_mutex); + up_write(&ubi->fm_protect); if (ret == UBI_BAD_FASTMAP) ubi_err(ubi, "Attach by fastmap failed, doing a full scan!"); return ret; @@ -1340,24 +1340,24 @@ int ubi_update_fastmap(struct ubi_device *ubi) struct ubi_fastmap_layout *new_fm, *old_fm; struct ubi_wl_entry *tmp_e; - mutex_lock(&ubi->fm_mutex); + down_write(&ubi->fm_protect); ubi_refill_pools(ubi); if (ubi->ro_mode || ubi->fm_disabled) { - mutex_unlock(&ubi->fm_mutex); + up_write(&ubi->fm_protect); return 0; } ret = ubi_ensure_anchor_pebs(ubi); if (ret) { - mutex_unlock(&ubi->fm_mutex); + up_write(&ubi->fm_protect); return ret; } new_fm = kzalloc(sizeof(*new_fm), GFP_KERNEL); if (!new_fm) { - mutex_unlock(&ubi->fm_mutex); + up_write(&ubi->fm_protect); return -ENOMEM; } @@ -1447,16 +1447,16 @@ int ubi_update_fastmap(struct ubi_device *ubi) } down_write(&ubi->work_sem); - down_write(&ubi->fm_sem); + down_write(&ubi->fm_eba_sem); ret = ubi_write_fastmap(ubi, new_fm); - up_write(&ubi->fm_sem); + up_write(&ubi->fm_eba_sem); up_write(&ubi->work_sem); if (ret) goto err; out_unlock: - mutex_unlock(&ubi->fm_mutex); + up_write(&ubi->fm_protect); kfree(old_fm); return ret; diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 3ea9480bd055..058c84cac8dc 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -426,10 +426,11 @@ struct ubi_debug_info { * @fm_pool: in-memory data structure of the fastmap pool * @fm_wl_pool: in-memory data structure of the fastmap pool used by the WL * sub-system - * @fm_mutex: serializes ubi_update_fastmap() and protects @fm_buf + * @fm_protect: serializes ubi_update_fastmap(), protects @fm_buf and makes sure + * that critical sections cannot be interrupted by ubi_update_fastmap() * @fm_buf: vmalloc()'d buffer which holds the raw fastmap * @fm_size: fastmap size in bytes - * @fm_sem: allows ubi_update_fastmap() to block EBA table changes + * @fm_eba_sem: allows ubi_update_fastmap() to block EBA table changes * @fm_work: fastmap work queue * @fm_work_scheduled: non-zero if fastmap work was scheduled * @@ -534,8 +535,8 @@ struct ubi_device { struct ubi_fastmap_layout *fm; struct ubi_fm_pool fm_pool; struct ubi_fm_pool fm_wl_pool; - struct rw_semaphore fm_sem; - struct mutex fm_mutex; + struct rw_semaphore fm_eba_sem; + struct rw_semaphore fm_protect; void *fm_buf; size_t fm_size; struct work_struct fm_work; diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index b8ad5e005cdc..609b16d45406 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -641,7 +641,7 @@ void ubi_refill_pools(struct ubi_device *ubi) /* ubi_wl_get_peb - works exaclty like __wl_get_peb but keeps track of * the fastmap pool. - * Returns with ubi->fm_sem held in read mode! + * Returns with ubi->fm_eba_sem held in read mode! */ int ubi_wl_get_peb(struct ubi_device *ubi) { @@ -650,20 +650,20 @@ int ubi_wl_get_peb(struct ubi_device *ubi) struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool; again: - down_read(&ubi->fm_sem); + down_read(&ubi->fm_eba_sem); spin_lock(&ubi->wl_lock); /* We check here also for the WL pool because at this point we can * refill the WL pool synchronous. */ if (pool->used == pool->size || wl_pool->used == wl_pool->size) { spin_unlock(&ubi->wl_lock); - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); ret = ubi_update_fastmap(ubi); if (ret) { ubi_msg(ubi, "Unable to write a new fastmap: %i", ret); - down_read(&ubi->fm_sem); + down_read(&ubi->fm_eba_sem); return -ENOSPC; } - down_read(&ubi->fm_sem); + down_read(&ubi->fm_eba_sem); spin_lock(&ubi->wl_lock); } @@ -675,7 +675,7 @@ again: goto out; } retried = 1; - up_read(&ubi->fm_sem); + up_read(&ubi->fm_eba_sem); goto again; } @@ -731,7 +731,7 @@ int ubi_wl_get_peb(struct ubi_device *ubi) spin_lock(&ubi->wl_lock); peb = wl_get_peb(ubi); spin_unlock(&ubi->wl_lock); - down_read(&ubi->fm_sem); + down_read(&ubi->fm_eba_sem); if (peb < 0) return peb; @@ -1607,6 +1607,8 @@ int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum, ubi_assert(pnum >= 0); ubi_assert(pnum < ubi->peb_count); + down_read(&ubi->fm_protect); + retry: spin_lock(&ubi->wl_lock); e = ubi->lookuptbl[pnum]; @@ -1637,6 +1639,7 @@ retry: ubi_assert(!ubi->move_to_put); ubi->move_to_put = 1; spin_unlock(&ubi->wl_lock); + up_read(&ubi->fm_protect); return 0; } else { if (in_wl_tree(e, &ubi->used)) { @@ -1658,6 +1661,7 @@ retry: ubi_err(ubi, "PEB %d not found", pnum); ubi_ro_mode(ubi); spin_unlock(&ubi->wl_lock); + up_read(&ubi->fm_protect); return err; } } @@ -1671,6 +1675,7 @@ retry: spin_unlock(&ubi->wl_lock); } + up_read(&ubi->fm_protect); return err; } -- cgit v1.2.3-59-g8ed1b From 61de74ce2fa2cc9eee85cf5edc6525b12831b507 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 29 Oct 2014 16:59:32 +0100 Subject: UBI: Fastmap: Prepare for variable sized fastmaps The current code assumes that each fastmap has the same amount of PEBs. So far this is true but will change soon. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 2cf2506b8f44..762e25c6a2d2 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -1385,7 +1385,7 @@ int ubi_update_fastmap(struct ubi_device *ubi) ret = -ENOSPC; goto err; - } else if (!tmp_e && old_fm) { + } else if (!tmp_e && old_fm && old_fm->e[i]) { ret = erase_block(ubi, old_fm->e[i]->pnum); if (ret < 0) { int j; @@ -1401,12 +1401,20 @@ int ubi_update_fastmap(struct ubi_device *ubi) } else { new_fm->e[i] = tmp_e; - if (old_fm) + if (old_fm && old_fm->e[i]) ubi_wl_put_fm_peb(ubi, old_fm->e[i], i, old_fm->to_be_tortured[i]); } } + /* Old fastmap is larger than the new one */ + if (old_fm && new_fm->used_blocks < old_fm->used_blocks) { + for (i = new_fm->used_blocks; i < old_fm->used_blocks; i++) { + ubi_wl_put_fm_peb(ubi, old_fm->e[i], i, + old_fm->to_be_tortured[i]); + } + } + spin_lock(&ubi->wl_lock); tmp_e = ubi_wl_get_fm_peb(ubi, 1); spin_unlock(&ubi->wl_lock); -- cgit v1.2.3-59-g8ed1b From 5ca97ad83800938e8aeea622821a26d69d2052bf Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 10 Nov 2014 16:11:40 +0100 Subject: UBI: Fastmap: Rework fastmap error paths If UBI is unable to write the fastmap to the device we have make sure that upon next attach UBI will fall back to scanning mode. In case we cannot ensure that they only thing we can do is falling back to read-only mode. The current error handling code is not powercut proof. It could happen that a powercut while invalidating would lead to a state where an too old fastmap could be used upon attach. This patch addresses the issue by writing a fake fastmap super block to a fresh PEB instead of reerasing the existing one. The fake fastmap super block will UBI case to do a full scan. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap.c | 162 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 114 insertions(+), 48 deletions(-) diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 762e25c6a2d2..db2625d3ecd9 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -1300,31 +1300,87 @@ out: /** * invalidate_fastmap - destroys a fastmap. * @ubi: UBI device object - * @fm: the fastmap to be destroyed * + * This function ensures that upon next UBI attach a full scan + * is issued. We need this if UBI is about to write a new fastmap + * but is unable to do so. In this case we have two options: + * a) Make sure that the current fastmap will not be usued upon + * attach time and contine or b) fall back to RO mode to have the + * current fastmap in a valid state. * Returns 0 on success, < 0 indicates an internal error. */ -static int invalidate_fastmap(struct ubi_device *ubi, - struct ubi_fastmap_layout *fm) +static int invalidate_fastmap(struct ubi_device *ubi) { int ret; - struct ubi_vid_hdr *vh; + struct ubi_fastmap_layout *fm; + struct ubi_wl_entry *e; + struct ubi_vid_hdr *vh = NULL; - ret = erase_block(ubi, fm->e[0]->pnum); - if (ret < 0) - return ret; + if (!ubi->fm) + return 0; + + ubi->fm = NULL; + + ret = -ENOMEM; + fm = kzalloc(sizeof(*fm), GFP_KERNEL); + if (!fm) + goto out; vh = new_fm_vhdr(ubi, UBI_FM_SB_VOLUME_ID); if (!vh) - return -ENOMEM; + goto out_free_fm; + + ret = -ENOSPC; + e = ubi_wl_get_fm_peb(ubi, 1); + if (!e) + goto out_free_fm; - /* deleting the current fastmap SB is not enough, an old SB may exist, - * so create a (corrupted) SB such that fastmap will find it and fall - * back to scanning mode in any case */ + /* + * Create fake fastmap such that UBI will fall back + * to scanning mode. + */ vh->sqnum = cpu_to_be64(ubi_next_sqnum(ubi)); - ret = ubi_io_write_vid_hdr(ubi, fm->e[0]->pnum, vh); + ret = ubi_io_write_vid_hdr(ubi, e->pnum, vh); + if (ret < 0) { + ubi_wl_put_fm_peb(ubi, e, 0, 0); + goto out_free_fm; + } + fm->used_blocks = 1; + fm->e[0] = e; + + ubi->fm = fm; + +out: + ubi_free_vid_hdr(ubi, vh); return ret; + +out_free_fm: + kfree(fm); + goto out; +} + +/** + * return_fm_pebs - returns all PEBs used by a fastmap back to the + * WL sub-system. + * @ubi: UBI device object + * @fm: fastmap layout object + */ +static void return_fm_pebs(struct ubi_device *ubi, + struct ubi_fastmap_layout *fm) +{ + int i; + + if (!fm) + return; + + for (i = 0; i < fm->used_blocks; i++) { + if (fm->e[i]) { + ubi_wl_put_fm_peb(ubi, fm->e[i], i, + fm->to_be_tortured[i]); + fm->e[i] = NULL; + } + } } /** @@ -1336,7 +1392,7 @@ static int invalidate_fastmap(struct ubi_device *ubi, */ int ubi_update_fastmap(struct ubi_device *ubi) { - int ret, i; + int ret, i, j; struct ubi_fastmap_layout *new_fm, *old_fm; struct ubi_wl_entry *tmp_e; @@ -1376,34 +1432,40 @@ int ubi_update_fastmap(struct ubi_device *ubi) tmp_e = ubi_wl_get_fm_peb(ubi, 0); spin_unlock(&ubi->wl_lock); - if (!tmp_e && !old_fm) { - int j; - ubi_err(ubi, "could not get any free erase block"); - - for (j = 1; j < i; j++) - ubi_wl_put_fm_peb(ubi, new_fm->e[j], j, 0); - - ret = -ENOSPC; - goto err; - } else if (!tmp_e && old_fm && old_fm->e[i]) { - ret = erase_block(ubi, old_fm->e[i]->pnum); - if (ret < 0) { - int j; - - for (j = 1; j < i; j++) - ubi_wl_put_fm_peb(ubi, new_fm->e[j], - j, 0); + if (!tmp_e) { + if (old_fm && old_fm->e[i]) { + ret = erase_block(ubi, old_fm->e[i]->pnum); + if (ret < 0) { + ubi_err(ubi, "could not erase old fastmap PEB"); + + for (j = 1; j < i; j++) { + ubi_wl_put_fm_peb(ubi, new_fm->e[j], + j, 0); + new_fm->e[j] = NULL; + } + goto err; + } + new_fm->e[i] = old_fm->e[i]; + old_fm->e[i] = NULL; + } else { + ubi_err(ubi, "could not get any free erase block"); + + for (j = 1; j < i; j++) { + ubi_wl_put_fm_peb(ubi, new_fm->e[j], j, 0); + new_fm->e[j] = NULL; + } - ubi_err(ubi, "could not erase old fastmap PEB"); + ret = -ENOSPC; goto err; } - new_fm->e[i] = old_fm->e[i]; } else { new_fm->e[i] = tmp_e; - if (old_fm && old_fm->e[i]) + if (old_fm && old_fm->e[i]) { ubi_wl_put_fm_peb(ubi, old_fm->e[i], i, old_fm->to_be_tortured[i]); + old_fm->e[i] = NULL; + } } } @@ -1412,6 +1474,7 @@ int ubi_update_fastmap(struct ubi_device *ubi) for (i = new_fm->used_blocks; i < old_fm->used_blocks; i++) { ubi_wl_put_fm_peb(ubi, old_fm->e[i], i, old_fm->to_be_tortured[i]); + old_fm->e[i] = NULL; } } @@ -1424,29 +1487,33 @@ int ubi_update_fastmap(struct ubi_device *ubi) if (!tmp_e) { ret = erase_block(ubi, old_fm->e[0]->pnum); if (ret < 0) { - int i; ubi_err(ubi, "could not erase old anchor PEB"); - for (i = 1; i < new_fm->used_blocks; i++) + for (i = 1; i < new_fm->used_blocks; i++) { ubi_wl_put_fm_peb(ubi, new_fm->e[i], i, 0); + new_fm->e[i] = NULL; + } goto err; } new_fm->e[0] = old_fm->e[0]; new_fm->e[0]->ec = ret; + old_fm->e[0] = NULL; } else { /* we've got a new anchor PEB, return the old one */ ubi_wl_put_fm_peb(ubi, old_fm->e[0], 0, old_fm->to_be_tortured[0]); new_fm->e[0] = tmp_e; + old_fm->e[0] = NULL; } } else { if (!tmp_e) { - int i; ubi_err(ubi, "could not find any anchor PEB"); - for (i = 1; i < new_fm->used_blocks; i++) + for (i = 1; i < new_fm->used_blocks; i++) { ubi_wl_put_fm_peb(ubi, new_fm->e[i], i, 0); + new_fm->e[i] = NULL; + } ret = -ENOSPC; goto err; @@ -1469,19 +1536,18 @@ out_unlock: return ret; err: - kfree(new_fm); - ubi_warn(ubi, "Unable to write new fastmap, err=%i", ret); - ret = 0; - if (old_fm) { - ret = invalidate_fastmap(ubi, old_fm); - if (ret < 0) { - ubi_err(ubi, "Unable to invalidiate current fastmap!"); - ubi_ro_mode(ubi); - } - else if (ret) - ret = 0; + ret = invalidate_fastmap(ubi); + if (ret < 0) { + ubi_err(ubi, "Unable to invalidiate current fastmap!"); + ubi_ro_mode(ubi); + } else { + return_fm_pebs(ubi, old_fm); + return_fm_pebs(ubi, new_fm); + ret = 0; } + + kfree(new_fm); goto out_unlock; } -- cgit v1.2.3-59-g8ed1b From 5fa7fa5dad0cf8f2b47bb8dca91c605c48d282f6 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 22 Sep 2014 11:44:50 +0200 Subject: UBI: Add initial support for fastmap self checks Using this debugfs knob fastmap self checks can be controlled. Signed-off-by: Richard Weinberger Reviewed-by: Tanya Brokhman --- drivers/mtd/ubi/debug.c | 11 +++++++++++ drivers/mtd/ubi/debug.h | 5 +++++ drivers/mtd/ubi/ubi.h | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index 7335c9ff9d99..224fed085102 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c @@ -275,6 +275,8 @@ static ssize_t dfs_file_read(struct file *file, char __user *user_buf, val = d->chk_gen; else if (dent == d->dfs_chk_io) val = d->chk_io; + else if (dent == d->dfs_chk_fastmap) + val = d->chk_fastmap; else if (dent == d->dfs_disable_bgt) val = d->disable_bgt; else if (dent == d->dfs_emulate_bitflips) @@ -336,6 +338,8 @@ static ssize_t dfs_file_write(struct file *file, const char __user *user_buf, d->chk_gen = val; else if (dent == d->dfs_chk_io) d->chk_io = val; + else if (dent == d->dfs_chk_fastmap) + d->chk_fastmap = val; else if (dent == d->dfs_disable_bgt) d->disable_bgt = val; else if (dent == d->dfs_emulate_bitflips) @@ -406,6 +410,13 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi) goto out_remove; d->dfs_chk_io = dent; + fname = "chk_fastmap"; + dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num, + &dfs_fops); + if (IS_ERR_OR_NULL(dent)) + goto out_remove; + d->dfs_chk_fastmap = dent; + fname = "tst_disable_bgt"; dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num, &dfs_fops); diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index cba89fcd1587..e99ef37a321e 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h @@ -127,4 +127,9 @@ static inline int ubi_dbg_chk_gen(const struct ubi_device *ubi) { return ubi->dbg.chk_gen; } + +static inline int ubi_dbg_chk_fastmap(const struct ubi_device *ubi) +{ + return ubi->dbg.chk_fastmap; +} #endif /* !__UBI_DEBUG_H__ */ diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 058c84cac8dc..adc633cb89c3 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -356,6 +356,7 @@ struct ubi_wl_entry; * * @chk_gen: if UBI general extra checks are enabled * @chk_io: if UBI I/O extra checks are enabled + * @chk_fastmap: if UBI fastmap extra checks are enabled * @disable_bgt: disable the background task for testing purposes * @emulate_bitflips: emulate bit-flips for testing purposes * @emulate_io_failures: emulate write/erase failures for testing purposes @@ -363,6 +364,7 @@ struct ubi_wl_entry; * @dfs_dir: direntry object of the UBI device debugfs directory * @dfs_chk_gen: debugfs knob to enable UBI general extra checks * @dfs_chk_io: debugfs knob to enable UBI I/O extra checks + * @dfs_chk_fastmap: debugfs knob to enable UBI fastmap extra checks * @dfs_disable_bgt: debugfs knob to disable the background task * @dfs_emulate_bitflips: debugfs knob to emulate bit-flips * @dfs_emulate_io_failures: debugfs knob to emulate write/erase failures @@ -370,6 +372,7 @@ struct ubi_wl_entry; struct ubi_debug_info { unsigned int chk_gen:1; unsigned int chk_io:1; + unsigned int chk_fastmap:1; unsigned int disable_bgt:1; unsigned int emulate_bitflips:1; unsigned int emulate_io_failures:1; @@ -377,6 +380,7 @@ struct ubi_debug_info { struct dentry *dfs_dir; struct dentry *dfs_chk_gen; struct dentry *dfs_chk_io; + struct dentry *dfs_chk_fastmap; struct dentry *dfs_disable_bgt; struct dentry *dfs_emulate_bitflips; struct dentry *dfs_emulate_io_failures; -- cgit v1.2.3-59-g8ed1b From 24b7a347c37f99c9d08d2d3ae9c6a56a8333429b Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 6 Oct 2014 15:18:41 +0200 Subject: UBI: Fastmap: Enhance fastmap checking Don't update the fastmap upon detach if fastmap checking is enabled. This is poor men's power cut testing feature. :-) Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/build.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index a7571508fdab..e26fe12b1aae 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -1114,8 +1114,11 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) ubi_msg(ubi, "detaching mtd%d", ubi->mtd->index); #ifdef CONFIG_MTD_UBI_FASTMAP /* If we don't write a new fastmap at detach time we lose all - * EC updates that have been made since the last written fastmap. */ - ubi_update_fastmap(ubi); + * EC updates that have been made since the last written fastmap. + * In case of fastmap debugging we omit the update to simulate an + * unclean shutdown. */ + if (!ubi_dbg_chk_fastmap(ubi)) + ubi_update_fastmap(ubi); #endif /* * Before freeing anything, we have to stop the background thread to -- cgit v1.2.3-59-g8ed1b From ee59ba8b064f692a1dee99b6f3ba30b0e904b2c1 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 10 Nov 2014 16:16:23 +0100 Subject: UBI: Fix stale pointers in ubi->lookuptbl In some error paths the WL sub-system gives up on a PEB and frees it's ubi_wl_entry struct but does not set the entry in ubi->lookuptbl to NULL. Fastmap can stumble over such a stale pointer as it uses ubi->lookuptbl to find all PEBs. Fix this by introducing a new helper function which free()s a WL entry and removes the reference from the lookup table. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/wl.c | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 609b16d45406..83848324daa2 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -215,6 +215,20 @@ static void wl_tree_add(struct ubi_wl_entry *e, struct rb_root *root) rb_insert_color(&e->u.rb, root); } +/** + * wl_tree_destroy - destroy a wear-leveling entry. + * @ubi: UBI device description object + * @e: the wear-leveling entry to add + * + * This function destroys a wear leveling entry and removes + * the reference from the lookup table. + */ +static void wl_entry_destroy(struct ubi_device *ubi, struct ubi_wl_entry *e) +{ + ubi->lookuptbl[e->pnum] = NULL; + kmem_cache_free(ubi_wl_entry_slab, e); +} + /** * do_work - do one pending work. * @ubi: UBI device description object @@ -1258,7 +1272,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, err = do_sync_erase(ubi, e1, vol_id, lnum, 0); if (err) { if (e2) - kmem_cache_free(ubi_wl_entry_slab, e2); + wl_entry_destroy(ubi, e2); goto out_ro; } @@ -1326,8 +1340,8 @@ out_error: spin_unlock(&ubi->wl_lock); ubi_free_vid_hdr(ubi, vid_hdr); - kmem_cache_free(ubi_wl_entry_slab, e1); - kmem_cache_free(ubi_wl_entry_slab, e2); + wl_entry_destroy(ubi, e1); + wl_entry_destroy(ubi, e2); out_ro: ubi_ro_mode(ubi); @@ -1469,7 +1483,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, if (shutdown) { dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec); kfree(wl_wrk); - kmem_cache_free(ubi_wl_entry_slab, e); + wl_entry_destroy(ubi, e); return 0; } @@ -1515,7 +1529,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, return err; } - kmem_cache_free(ubi_wl_entry_slab, e); + wl_entry_destroy(ubi, e); if (err != -EIO) /* * If this is not %-EIO, we have no idea what to do. Scheduling @@ -1807,9 +1821,10 @@ int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum) /** * tree_destroy - destroy an RB-tree. + * @ubi: UBI device description object * @root: the root of the tree to destroy */ -static void tree_destroy(struct rb_root *root) +static void tree_destroy(struct ubi_device *ubi, struct rb_root *root) { struct rb_node *rb; struct ubi_wl_entry *e; @@ -1831,7 +1846,7 @@ static void tree_destroy(struct rb_root *root) rb->rb_right = NULL; } - kmem_cache_free(ubi_wl_entry_slab, e); + wl_entry_destroy(ubi, e); } } } @@ -1962,7 +1977,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) ubi_assert(!ubi_is_fm_block(ubi, e->pnum)); ubi->lookuptbl[e->pnum] = e; if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0)) { - kmem_cache_free(ubi_wl_entry_slab, e); + wl_entry_destroy(ubi, e); goto out_free; } @@ -2056,9 +2071,9 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) out_free: shutdown_work(ubi); - tree_destroy(&ubi->used); - tree_destroy(&ubi->free); - tree_destroy(&ubi->scrub); + tree_destroy(ubi, &ubi->used); + tree_destroy(ubi, &ubi->free); + tree_destroy(ubi, &ubi->scrub); kfree(ubi->lookuptbl); return err; } @@ -2075,7 +2090,7 @@ static void protection_queue_destroy(struct ubi_device *ubi) for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i) { list_for_each_entry_safe(e, tmp, &ubi->pq[i], u.list) { list_del(&e->u.list); - kmem_cache_free(ubi_wl_entry_slab, e); + wl_entry_destroy(ubi, e); } } } @@ -2107,10 +2122,10 @@ void ubi_wl_close(struct ubi_device *ubi) ubi_fastmap_close(ubi); shutdown_work(ubi); protection_queue_destroy(ubi); - tree_destroy(&ubi->used); - tree_destroy(&ubi->erroneous); - tree_destroy(&ubi->free); - tree_destroy(&ubi->scrub); + tree_destroy(ubi, &ubi->used); + tree_destroy(ubi, &ubi->erroneous); + tree_destroy(ubi, &ubi->free); + tree_destroy(ubi, &ubi->scrub); kfree(ubi->lookuptbl); } -- cgit v1.2.3-59-g8ed1b From daef3dd1f0ae71bf04a32af4ef643baf040bb73d Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 22 Sep 2014 15:36:40 +0200 Subject: UBI: Fastmap: Add self check to detect absent PEBs This self check allows Fastmap to detect absent PEBs while writing a new fastmap to the MTD device. It will help to find implementation issues in Fastmap. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap.c | 86 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index db2625d3ecd9..13492fef6471 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012 Linutronix GmbH + * Copyright (c) 2014 sigma star gmbh * Author: Richard Weinberger * * This program is free software; you can redistribute it and/or modify @@ -16,6 +17,69 @@ #include #include "ubi.h" +/** + * init_seen - allocate memory for used for debugging. + * @ubi: UBI device description object + */ +static inline int *init_seen(struct ubi_device *ubi) +{ + int *ret; + + if (!ubi_dbg_chk_fastmap(ubi)) + return NULL; + + ret = kcalloc(ubi->peb_count, sizeof(int), GFP_KERNEL); + if (!ret) + return ERR_PTR(-ENOMEM); + + return ret; +} + +/** + * free_seen - free the seen logic integer array. + * @seen: integer array of @ubi->peb_count size + */ +static inline void free_seen(int *seen) +{ + kfree(seen); +} + +/** + * set_seen - mark a PEB as seen. + * @ubi: UBI device description object + * @pnum: The PEB to be makred as seen + * @seen: integer array of @ubi->peb_count size + */ +static inline void set_seen(struct ubi_device *ubi, int pnum, int *seen) +{ + if (!ubi_dbg_chk_fastmap(ubi) || !seen) + return; + + seen[pnum] = 1; +} + +/** + * self_check_seen - check whether all PEB have been seen by fastmap. + * @ubi: UBI device description object + * @seen: integer array of @ubi->peb_count size + */ +static int self_check_seen(struct ubi_device *ubi, int *seen) +{ + int pnum, ret = 0; + + if (!ubi_dbg_chk_fastmap(ubi) || !seen) + return 0; + + for (pnum = 0; pnum < ubi->peb_count; pnum++) { + if (!seen[pnum] && ubi->lookuptbl[pnum]) { + ubi_err(ubi, "self-check failed for PEB %d, fastmap didn't see it", pnum); + ret = -EINVAL; + } + } + + return ret; +} + /** * ubi_calc_fm_size - calculates the fastmap size in bytes for an UBI device. * @ubi: UBI device description object @@ -1030,6 +1094,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, struct ubi_work *ubi_wrk; int ret, i, j, free_peb_count, used_peb_count, vol_count; int scrub_peb_count, erase_peb_count; + int *seen_pebs = NULL; fm_raw = ubi->fm_buf; memset(ubi->fm_buf, 0, ubi->fm_size); @@ -1046,6 +1111,12 @@ static int ubi_write_fastmap(struct ubi_device *ubi, goto out_kfree; } + seen_pebs = init_seen(ubi); + if (IS_ERR(seen_pebs)) { + ret = PTR_ERR(seen_pebs); + goto out_kfree; + } + spin_lock(&ubi->volumes_lock); spin_lock(&ubi->wl_lock); @@ -1076,8 +1147,10 @@ static int ubi_write_fastmap(struct ubi_device *ubi, fmpl1->size = cpu_to_be16(ubi->fm_pool.size); fmpl1->max_size = cpu_to_be16(ubi->fm_pool.max_size); - for (i = 0; i < ubi->fm_pool.size; i++) + for (i = 0; i < ubi->fm_pool.size; i++) { fmpl1->pebs[i] = cpu_to_be32(ubi->fm_pool.pebs[i]); + set_seen(ubi, ubi->fm_pool.pebs[i], seen_pebs); + } fmpl2 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos); fm_pos += sizeof(*fmpl2); @@ -1085,14 +1158,17 @@ static int ubi_write_fastmap(struct ubi_device *ubi, fmpl2->size = cpu_to_be16(ubi->fm_wl_pool.size); fmpl2->max_size = cpu_to_be16(ubi->fm_wl_pool.max_size); - for (i = 0; i < ubi->fm_wl_pool.size; i++) + for (i = 0; i < ubi->fm_wl_pool.size; i++) { fmpl2->pebs[i] = cpu_to_be32(ubi->fm_wl_pool.pebs[i]); + set_seen(ubi, ubi->fm_wl_pool.pebs[i], seen_pebs); + } for (node = rb_first(&ubi->free); node; node = rb_next(node)) { wl_e = rb_entry(node, struct ubi_wl_entry, u.rb); fec = (struct ubi_fm_ec *)(fm_raw + fm_pos); fec->pnum = cpu_to_be32(wl_e->pnum); + set_seen(ubi, wl_e->pnum, seen_pebs); fec->ec = cpu_to_be32(wl_e->ec); free_peb_count++; @@ -1106,6 +1182,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, fec = (struct ubi_fm_ec *)(fm_raw + fm_pos); fec->pnum = cpu_to_be32(wl_e->pnum); + set_seen(ubi, wl_e->pnum, seen_pebs); fec->ec = cpu_to_be32(wl_e->ec); used_peb_count++; @@ -1132,6 +1209,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, fec = (struct ubi_fm_ec *)(fm_raw + fm_pos); fec->pnum = cpu_to_be32(wl_e->pnum); + set_seen(ubi, wl_e->pnum, seen_pebs); fec->ec = cpu_to_be32(wl_e->ec); scrub_peb_count++; @@ -1149,6 +1227,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, fec = (struct ubi_fm_ec *)(fm_raw + fm_pos); fec->pnum = cpu_to_be32(wl_e->pnum); + set_seen(ubi, wl_e->pnum, seen_pebs); fec->ec = cpu_to_be32(wl_e->ec); erase_peb_count++; @@ -1208,6 +1287,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, for (i = 0; i < new_fm->used_blocks; i++) { fmsb->block_loc[i] = cpu_to_be32(new_fm->e[i]->pnum); + set_seen(ubi, new_fm->e[i]->pnum, seen_pebs); fmsb->block_ec[i] = cpu_to_be32(new_fm->e[i]->ec); } @@ -1241,11 +1321,13 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ubi_assert(new_fm); ubi->fm = new_fm; + ret = self_check_seen(ubi, seen_pebs); dbg_bld("fastmap written!"); out_kfree: ubi_free_vid_hdr(ubi, avhdr); ubi_free_vid_hdr(ubi, dvhdr); + free_seen(seen_pebs); out: return ret; } -- cgit v1.2.3-59-g8ed1b From 560d86a1a210000b33859cd66e051fcb516a3559 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 27 Oct 2014 13:00:26 +0100 Subject: UBI: Fastmap: Make self_check_eba() depend on fastmap self checking ...instead of generic self checking. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/attach.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index 5d89b3fb1d3c..42d465add385 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c @@ -1458,7 +1458,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) goto out_wl; #ifdef CONFIG_MTD_UBI_FASTMAP - if (ubi->fm && ubi_dbg_chk_gen(ubi)) { + if (ubi->fm && ubi_dbg_chk_fastmap(ubi)) { struct ubi_attach_info *scan_ai; scan_ai = alloc_ai(); -- cgit v1.2.3-59-g8ed1b From 479c2c0cac0c1d23655df15cf039b4f8e3623d23 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 8 Oct 2014 15:14:09 +0200 Subject: UBI: Fastmap: Add new module parameter fm_debug If fm_debug is set fastmap debugging is enabled by default. This is useful if one wants to debug fastmap on an UBI device with serves the rootfs. The the UBI attach mechanism runs long before debugfs can be mounted and chk_fastmap set. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/build.c | 5 +++++ drivers/mtd/ubi/debug.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index e26fe12b1aae..9690cf9aaef5 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -81,6 +81,7 @@ static struct mtd_dev_param __initdata mtd_dev_param[UBI_MAX_DEVICES]; #ifdef CONFIG_MTD_UBI_FASTMAP /* UBI module parameter to enable fastmap automatically on non-fastmap images */ static bool fm_autoconvert; +static bool fm_debug; #endif /* Root UBI "class" object (corresponds to '//class/ubi/') */ struct class *ubi_class; @@ -951,6 +952,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, ubi->fm_wl_pool.max_size = ubi->fm_pool.max_size / 2; ubi->fm_disabled = !fm_autoconvert; + if (fm_debug) + ubi_enable_dbg_chk_fastmap(ubi); if (!ubi->fm_disabled && (int)mtd_div_by_eb(ubi->mtd->size, ubi->mtd) <= UBI_FM_MAX_START) { @@ -1503,6 +1506,8 @@ MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=dbg.chk_fastmap; } + +static inline void ubi_enable_dbg_chk_fastmap(struct ubi_device *ubi) +{ + ubi->dbg.chk_fastmap = 1; +} #endif /* !__UBI_DEBUG_H__ */ -- cgit v1.2.3-59-g8ed1b From 78d6d497a648cc04ae26b27af1e01ce3e41a9c72 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 10 Nov 2014 18:21:51 +0100 Subject: UBI: Move fastmap specific functions out of wl.c Fastmap is tightly connected to the WL sub-system, many fastmap-specific functionslive in wl.c. To get rid of most #ifdefs in wl.c move this functions into a new file and include it into wl.c Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap-wl.c | 361 ++++++++++++++++++++++++++++ drivers/mtd/ubi/wl.c | 560 ++++++++----------------------------------- drivers/mtd/ubi/wl.h | 18 ++ 3 files changed, 476 insertions(+), 463 deletions(-) create mode 100644 drivers/mtd/ubi/fastmap-wl.c create mode 100644 drivers/mtd/ubi/wl.h diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c new file mode 100644 index 000000000000..88a400c52418 --- /dev/null +++ b/drivers/mtd/ubi/fastmap-wl.c @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2012 Linutronix GmbH + * Copyright (c) 2014 sigma star gmbh + * Author: Richard Weinberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + */ + +/** + * update_fastmap_work_fn - calls ubi_update_fastmap from a work queue + * @wrk: the work description object + */ +static void update_fastmap_work_fn(struct work_struct *wrk) +{ + struct ubi_device *ubi = container_of(wrk, struct ubi_device, fm_work); + ubi_update_fastmap(ubi); + spin_lock(&ubi->wl_lock); + ubi->fm_work_scheduled = 0; + spin_unlock(&ubi->wl_lock); +} + +/** + * is_fm_block - returns 1 if a PEB is currently used in a fastmap. + * @ubi: UBI device description object + * @pnum: the to be checked PEB + */ +static int is_fm_block(struct ubi_device *ubi, int pnum) +{ + int i; + + if (!ubi->fm) + return 0; + + for (i = 0; i < ubi->fm->used_blocks; i++) + if (ubi->fm->e[i]->pnum == pnum) + return 1; + + return 0; +} + +/** + * find_anchor_wl_entry - find wear-leveling entry to used as anchor PEB. + * @root: the RB-tree where to look for + */ +static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root) +{ + struct rb_node *p; + struct ubi_wl_entry *e, *victim = NULL; + int max_ec = UBI_MAX_ERASECOUNTER; + + ubi_rb_for_each_entry(p, e, root, u.rb) { + if (e->pnum < UBI_FM_MAX_START && e->ec < max_ec) { + victim = e; + max_ec = e->ec; + } + } + + return victim; +} + +/** + * return_unused_pool_pebs - returns unused PEB to the free tree. + * @ubi: UBI device description object + * @pool: fastmap pool description object + */ +static void return_unused_pool_pebs(struct ubi_device *ubi, + struct ubi_fm_pool *pool) +{ + int i; + struct ubi_wl_entry *e; + + for (i = pool->used; i < pool->size; i++) { + e = ubi->lookuptbl[pool->pebs[i]]; + wl_tree_add(e, &ubi->free); + ubi->free_count++; + } +} + +static int anchor_pebs_avalible(struct rb_root *root) +{ + struct rb_node *p; + struct ubi_wl_entry *e; + + ubi_rb_for_each_entry(p, e, root, u.rb) + if (e->pnum < UBI_FM_MAX_START) + return 1; + + return 0; +} + +/** + * ubi_wl_get_fm_peb - find a physical erase block with a given maximal number. + * @ubi: UBI device description object + * @anchor: This PEB will be used as anchor PEB by fastmap + * + * The function returns a physical erase block with a given maximal number + * and removes it from the wl subsystem. + * Must be called with wl_lock held! + */ +struct ubi_wl_entry *ubi_wl_get_fm_peb(struct ubi_device *ubi, int anchor) +{ + struct ubi_wl_entry *e = NULL; + + if (!ubi->free.rb_node || (ubi->free_count - ubi->beb_rsvd_pebs < 1)) + goto out; + + if (anchor) + e = find_anchor_wl_entry(&ubi->free); + else + e = find_mean_wl_entry(ubi, &ubi->free); + + if (!e) + goto out; + + self_check_in_wl_tree(ubi, e, &ubi->free); + + /* remove it from the free list, + * the wl subsystem does no longer know this erase block */ + rb_erase(&e->u.rb, &ubi->free); + ubi->free_count--; +out: + return e; +} + +/** + * ubi_refill_pools - refills all fastmap PEB pools. + * @ubi: UBI device description object + */ +void ubi_refill_pools(struct ubi_device *ubi) +{ + struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool; + struct ubi_fm_pool *pool = &ubi->fm_pool; + struct ubi_wl_entry *e; + int enough; + + spin_lock(&ubi->wl_lock); + + return_unused_pool_pebs(ubi, wl_pool); + return_unused_pool_pebs(ubi, pool); + + wl_pool->size = 0; + pool->size = 0; + + for (;;) { + enough = 0; + if (pool->size < pool->max_size) { + if (!ubi->free.rb_node) + break; + + e = wl_get_wle(ubi); + if (!e) + break; + + pool->pebs[pool->size] = e->pnum; + pool->size++; + } else + enough++; + + if (wl_pool->size < wl_pool->max_size) { + if (!ubi->free.rb_node || + (ubi->free_count - ubi->beb_rsvd_pebs < 5)) + break; + + e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF); + self_check_in_wl_tree(ubi, e, &ubi->free); + rb_erase(&e->u.rb, &ubi->free); + ubi->free_count--; + + wl_pool->pebs[wl_pool->size] = e->pnum; + wl_pool->size++; + } else + enough++; + + if (enough == 2) + break; + } + + wl_pool->used = 0; + pool->used = 0; + + spin_unlock(&ubi->wl_lock); +} + +/** + * ubi_wl_get_peb - get a physical eraseblock. + * @ubi: UBI device description object + * + * This function returns a physical eraseblock in case of success and a + * negative error code in case of failure. + * Returns with ubi->fm_eba_sem held in read mode! + */ +int ubi_wl_get_peb(struct ubi_device *ubi) +{ + int ret, retried = 0; + struct ubi_fm_pool *pool = &ubi->fm_pool; + struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool; + +again: + down_read(&ubi->fm_eba_sem); + spin_lock(&ubi->wl_lock); + + /* We check here also for the WL pool because at this point we can + * refill the WL pool synchronous. */ + if (pool->used == pool->size || wl_pool->used == wl_pool->size) { + spin_unlock(&ubi->wl_lock); + up_read(&ubi->fm_eba_sem); + ret = ubi_update_fastmap(ubi); + if (ret) { + ubi_msg(ubi, "Unable to write a new fastmap: %i", ret); + down_read(&ubi->fm_eba_sem); + return -ENOSPC; + } + down_read(&ubi->fm_eba_sem); + spin_lock(&ubi->wl_lock); + } + + if (pool->used == pool->size) { + spin_unlock(&ubi->wl_lock); + if (retried) { + ubi_err(ubi, "Unable to get a free PEB from user WL pool"); + ret = -ENOSPC; + goto out; + } + retried = 1; + up_read(&ubi->fm_eba_sem); + goto again; + } + + ubi_assert(pool->used < pool->size); + ret = pool->pebs[pool->used++]; + prot_queue_add(ubi, ubi->lookuptbl[ret]); + spin_unlock(&ubi->wl_lock); +out: + return ret; +} + +/* get_peb_for_wl - returns a PEB to be used internally by the WL sub-system. + * + * @ubi: UBI device description object + */ +static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi) +{ + struct ubi_fm_pool *pool = &ubi->fm_wl_pool; + int pnum; + + if (pool->used == pool->size) { + /* We cannot update the fastmap here because this + * function is called in atomic context. + * Let's fail here and refill/update it as soon as possible. */ + if (!ubi->fm_work_scheduled) { + ubi->fm_work_scheduled = 1; + schedule_work(&ubi->fm_work); + } + return NULL; + } else { + pnum = pool->pebs[pool->used++]; + return ubi->lookuptbl[pnum]; + } +} + +/** + * ubi_ensure_anchor_pebs - schedule wear-leveling to produce an anchor PEB. + * @ubi: UBI device description object + */ +int ubi_ensure_anchor_pebs(struct ubi_device *ubi) +{ + struct ubi_work *wrk; + + spin_lock(&ubi->wl_lock); + if (ubi->wl_scheduled) { + spin_unlock(&ubi->wl_lock); + return 0; + } + ubi->wl_scheduled = 1; + spin_unlock(&ubi->wl_lock); + + wrk = kmalloc(sizeof(struct ubi_work), GFP_NOFS); + if (!wrk) { + spin_lock(&ubi->wl_lock); + ubi->wl_scheduled = 0; + spin_unlock(&ubi->wl_lock); + return -ENOMEM; + } + + wrk->anchor = 1; + wrk->func = &wear_leveling_worker; + schedule_ubi_work(ubi, wrk); + return 0; +} + +/** + * ubi_wl_put_fm_peb - returns a PEB used in a fastmap to the wear-leveling + * sub-system. + * see: ubi_wl_put_peb() + * + * @ubi: UBI device description object + * @fm_e: physical eraseblock to return + * @lnum: the last used logical eraseblock number for the PEB + * @torture: if this physical eraseblock has to be tortured + */ +int ubi_wl_put_fm_peb(struct ubi_device *ubi, struct ubi_wl_entry *fm_e, + int lnum, int torture) +{ + struct ubi_wl_entry *e; + int vol_id, pnum = fm_e->pnum; + + dbg_wl("PEB %d", pnum); + + ubi_assert(pnum >= 0); + ubi_assert(pnum < ubi->peb_count); + + spin_lock(&ubi->wl_lock); + e = ubi->lookuptbl[pnum]; + + /* This can happen if we recovered from a fastmap the very + * first time and writing now a new one. In this case the wl system + * has never seen any PEB used by the original fastmap. + */ + if (!e) { + e = fm_e; + ubi_assert(e->ec >= 0); + ubi->lookuptbl[pnum] = e; + } + + spin_unlock(&ubi->wl_lock); + + vol_id = lnum ? UBI_FM_DATA_VOLUME_ID : UBI_FM_SB_VOLUME_ID; + return schedule_erase(ubi, e, vol_id, lnum, torture); +} + +/** + * ubi_is_erase_work - checks whether a work is erase work. + * @wrk: The work object to be checked + */ +int ubi_is_erase_work(struct ubi_work *wrk) +{ + return wrk->func == erase_worker; +} + +static void ubi_fastmap_close(struct ubi_device *ubi) +{ + int i; + + flush_work(&ubi->fm_work); + return_unused_pool_pebs(ubi, &ubi->fm_pool); + return_unused_pool_pebs(ubi, &ubi->fm_wl_pool); + + if (ubi->fm) { + for (i = 0; i < ubi->fm->used_blocks; i++) + kfree(ubi->fm->e[i]); + } + kfree(ubi->fm); +} diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 83848324daa2..7d49f42ca2d5 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -103,6 +103,7 @@ #include #include #include "ubi.h" +#include "wl.h" /* Number of physical eraseblocks reserved for wear-leveling purposes */ #define WL_RESERVED_PEBS 1 @@ -140,45 +141,6 @@ static int self_check_in_wl_tree(const struct ubi_device *ubi, static int self_check_in_pq(const struct ubi_device *ubi, struct ubi_wl_entry *e); -#ifdef CONFIG_MTD_UBI_FASTMAP -/** - * update_fastmap_work_fn - calls ubi_update_fastmap from a work queue - * @wrk: the work description object - */ -static void update_fastmap_work_fn(struct work_struct *wrk) -{ - struct ubi_device *ubi = container_of(wrk, struct ubi_device, fm_work); - ubi_update_fastmap(ubi); - spin_lock(&ubi->wl_lock); - ubi->fm_work_scheduled = 0; - spin_unlock(&ubi->wl_lock); -} - -/** - * ubi_ubi_is_fm_block - returns 1 if a PEB is currently used in a fastmap. - * @ubi: UBI device description object - * @pnum: the to be checked PEB - */ -static int ubi_is_fm_block(struct ubi_device *ubi, int pnum) -{ - int i; - - if (!ubi->fm) - return 0; - - for (i = 0; i < ubi->fm->used_blocks; i++) - if (ubi->fm->e[i]->pnum == pnum) - return 1; - - return 0; -} -#else -static int ubi_is_fm_block(struct ubi_device *ubi, int pnum) -{ - return 0; -} -#endif - /** * wl_tree_add - add a wear-leveling entry to a WL RB-tree. * @e: the wear-leveling entry to add @@ -276,33 +238,6 @@ static int do_work(struct ubi_device *ubi) return err; } -/** - * produce_free_peb - produce a free physical eraseblock. - * @ubi: UBI device description object - * - * This function tries to make a free PEB by means of synchronous execution of - * pending works. This may be needed if, for example the background thread is - * disabled. Returns zero in case of success and a negative error code in case - * of failure. - */ -static int produce_free_peb(struct ubi_device *ubi) -{ - int err; - - while (!ubi->free.rb_node && ubi->works_count) { - spin_unlock(&ubi->wl_lock); - - dbg_wl("do one work synchronously"); - err = do_work(ubi); - - spin_lock(&ubi->wl_lock); - if (err) - return err; - } - - return 0; -} - /** * in_wl_tree - check if wear-leveling entry is present in a WL RB-tree. * @e: the wear-leveling entry to check @@ -441,76 +376,8 @@ static struct ubi_wl_entry *find_mean_wl_entry(struct ubi_device *ubi, return e; } -#ifdef CONFIG_MTD_UBI_FASTMAP -/** - * find_anchor_wl_entry - find wear-leveling entry to used as anchor PEB. - * @root: the RB-tree where to look for - */ -static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root) -{ - struct rb_node *p; - struct ubi_wl_entry *e, *victim = NULL; - int max_ec = UBI_MAX_ERASECOUNTER; - - ubi_rb_for_each_entry(p, e, root, u.rb) { - if (e->pnum < UBI_FM_MAX_START && e->ec < max_ec) { - victim = e; - max_ec = e->ec; - } - } - - return victim; -} - -static int anchor_pebs_avalible(struct rb_root *root) -{ - struct rb_node *p; - struct ubi_wl_entry *e; - - ubi_rb_for_each_entry(p, e, root, u.rb) - if (e->pnum < UBI_FM_MAX_START) - return 1; - - return 0; -} - -/** - * ubi_wl_get_fm_peb - find a physical erase block with a given maximal number. - * @ubi: UBI device description object - * @anchor: This PEB will be used as anchor PEB by fastmap - * - * The function returns a physical erase block with a given maximal number - * and removes it from the wl subsystem. - * Must be called with wl_lock held! - */ -struct ubi_wl_entry *ubi_wl_get_fm_peb(struct ubi_device *ubi, int anchor) -{ - struct ubi_wl_entry *e = NULL; - - if (!ubi->free.rb_node || (ubi->free_count - ubi->beb_rsvd_pebs < 1)) - goto out; - - if (anchor) - e = find_anchor_wl_entry(&ubi->free); - else - e = find_mean_wl_entry(ubi, &ubi->free); - - if (!e) - goto out; - - self_check_in_wl_tree(ubi, e, &ubi->free); - - /* remove it from the free list, - * the wl subsystem does no longer know this erase block */ - rb_erase(&e->u.rb, &ubi->free); - ubi->free_count--; -out: - return e; -} -#endif - /** - * wl_get_wle - get a mean wl entry to be used by wl_get_peb() or + * wl_get_wle - get a mean wl entry to be used by ubi_wl_get_peb() or * refill_wl_user_pool(). * @ubi: UBI device description object * @@ -540,228 +407,6 @@ static struct ubi_wl_entry *wl_get_wle(struct ubi_device *ubi) return e; } -/** - * wl_get_peb - get a physical eraseblock. - * @ubi: UBI device description object - * - * This function returns a physical eraseblock in case of success and a - * negative error code in case of failure. - * It is the low level component of ubi_wl_get_peb() in the non-fastmap - * case. - */ -static int wl_get_peb(struct ubi_device *ubi) -{ - int err; - struct ubi_wl_entry *e; - -retry: - if (!ubi->free.rb_node) { - if (ubi->works_count == 0) { - ubi_err(ubi, "no free eraseblocks"); - ubi_assert(list_empty(&ubi->works)); - return -ENOSPC; - } - - err = produce_free_peb(ubi); - if (err < 0) - return err; - goto retry; - } - - e = wl_get_wle(ubi); - prot_queue_add(ubi, e); - - return e->pnum; -} - -#ifdef CONFIG_MTD_UBI_FASTMAP -/** - * return_unused_pool_pebs - returns unused PEB to the free tree. - * @ubi: UBI device description object - * @pool: fastmap pool description object - */ -static void return_unused_pool_pebs(struct ubi_device *ubi, - struct ubi_fm_pool *pool) -{ - int i; - struct ubi_wl_entry *e; - - for (i = pool->used; i < pool->size; i++) { - e = ubi->lookuptbl[pool->pebs[i]]; - wl_tree_add(e, &ubi->free); - ubi->free_count++; - } -} - -/** - * ubi_refill_pools - refills all fastmap PEB pools. - * @ubi: UBI device description object - */ -void ubi_refill_pools(struct ubi_device *ubi) -{ - struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool; - struct ubi_fm_pool *pool = &ubi->fm_pool; - struct ubi_wl_entry *e; - int enough; - - spin_lock(&ubi->wl_lock); - - return_unused_pool_pebs(ubi, wl_pool); - return_unused_pool_pebs(ubi, pool); - - wl_pool->size = 0; - pool->size = 0; - - for (;;) { - enough = 0; - if (pool->size < pool->max_size) { - if (!ubi->free.rb_node || - (ubi->free_count - ubi->beb_rsvd_pebs < 5)) - break; - - e = wl_get_wle(ubi); - if (!e) - break; - - pool->pebs[pool->size] = e->pnum; - pool->size++; - } else - enough++; - - if (wl_pool->size < wl_pool->max_size) { - if (!ubi->free.rb_node || - (ubi->free_count - ubi->beb_rsvd_pebs < 5)) - break; - - e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF); - self_check_in_wl_tree(ubi, e, &ubi->free); - rb_erase(&e->u.rb, &ubi->free); - ubi->free_count--; - - wl_pool->pebs[wl_pool->size] = e->pnum; - wl_pool->size++; - } else - enough++; - - if (enough == 2) - break; - } - - wl_pool->used = 0; - pool->used = 0; - - spin_unlock(&ubi->wl_lock); -} - -/* ubi_wl_get_peb - works exaclty like __wl_get_peb but keeps track of - * the fastmap pool. - * Returns with ubi->fm_eba_sem held in read mode! - */ -int ubi_wl_get_peb(struct ubi_device *ubi) -{ - int ret, retried = 0; - struct ubi_fm_pool *pool = &ubi->fm_pool; - struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool; - -again: - down_read(&ubi->fm_eba_sem); - spin_lock(&ubi->wl_lock); - /* We check here also for the WL pool because at this point we can - * refill the WL pool synchronous. */ - if (pool->used == pool->size || wl_pool->used == wl_pool->size) { - spin_unlock(&ubi->wl_lock); - up_read(&ubi->fm_eba_sem); - ret = ubi_update_fastmap(ubi); - if (ret) { - ubi_msg(ubi, "Unable to write a new fastmap: %i", ret); - down_read(&ubi->fm_eba_sem); - return -ENOSPC; - } - down_read(&ubi->fm_eba_sem); - spin_lock(&ubi->wl_lock); - } - - if (pool->used == pool->size) { - spin_unlock(&ubi->wl_lock); - if (retried) { - ubi_err(ubi, "Unable to get a free PEB from user WL pool"); - ret = -ENOSPC; - goto out; - } - retried = 1; - up_read(&ubi->fm_eba_sem); - goto again; - } - - ubi_assert(pool->used < pool->size); - ret = pool->pebs[pool->used++]; - prot_queue_add(ubi, ubi->lookuptbl[ret]); - spin_unlock(&ubi->wl_lock); -out: - return ret; -} - -/* get_peb_for_wl - returns a PEB to be used internally by the WL sub-system. - * - * @ubi: UBI device description object - */ -static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi) -{ - struct ubi_fm_pool *pool = &ubi->fm_wl_pool; - int pnum; - - if (pool->used == pool->size) { - /* We cannot update the fastmap here because this - * function is called in atomic context. - * Let's fail here and refill/update it as soon as possible. */ - if (!ubi->fm_work_scheduled) { - ubi->fm_work_scheduled = 1; - schedule_work(&ubi->fm_work); - } - return NULL; - } else { - pnum = pool->pebs[pool->used++]; - return ubi->lookuptbl[pnum]; - } -} -#else -static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi) -{ - struct ubi_wl_entry *e; - - e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF); - self_check_in_wl_tree(ubi, e, &ubi->free); - ubi->free_count--; - ubi_assert(ubi->free_count >= 0); - rb_erase(&e->u.rb, &ubi->free); - - return e; -} - -int ubi_wl_get_peb(struct ubi_device *ubi) -{ - int peb, err; - - spin_lock(&ubi->wl_lock); - peb = wl_get_peb(ubi); - spin_unlock(&ubi->wl_lock); - down_read(&ubi->fm_eba_sem); - - if (peb < 0) - return peb; - - err = ubi_self_check_all_ff(ubi, peb, ubi->vid_hdr_aloffset, - ubi->peb_size - ubi->vid_hdr_aloffset); - if (err) { - ubi_err(ubi, "new PEB %d does not contain all 0xFF bytes", - peb); - return err; - } - - return peb; -} -#endif - /** * prot_queue_del - remove a physical eraseblock from the protection queue. * @ubi: UBI device description object @@ -928,17 +573,6 @@ static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk) static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, int shutdown); -#ifdef CONFIG_MTD_UBI_FASTMAP -/** - * ubi_is_erase_work - checks whether a work is erase work. - * @wrk: The work object to be checked - */ -int ubi_is_erase_work(struct ubi_work *wrk) -{ - return wrk->func == erase_worker; -} -#endif - /** * schedule_erase - schedule an erase work. * @ubi: UBI device description object @@ -956,7 +590,7 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, struct ubi_work *wl_wrk; ubi_assert(e); - ubi_assert(!ubi_is_fm_block(ubi, e->pnum)); + ubi_assert(!is_fm_block(ubi, e->pnum)); dbg_wl("schedule erasure of PEB %d, EC %d, torture %d", e->pnum, e->ec, torture); @@ -1003,48 +637,6 @@ static int do_sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, return erase_worker(ubi, wl_wrk, 0); } -#ifdef CONFIG_MTD_UBI_FASTMAP -/** - * ubi_wl_put_fm_peb - returns a PEB used in a fastmap to the wear-leveling - * sub-system. - * see: ubi_wl_put_peb() - * - * @ubi: UBI device description object - * @fm_e: physical eraseblock to return - * @lnum: the last used logical eraseblock number for the PEB - * @torture: if this physical eraseblock has to be tortured - */ -int ubi_wl_put_fm_peb(struct ubi_device *ubi, struct ubi_wl_entry *fm_e, - int lnum, int torture) -{ - struct ubi_wl_entry *e; - int vol_id, pnum = fm_e->pnum; - - dbg_wl("PEB %d", pnum); - - ubi_assert(pnum >= 0); - ubi_assert(pnum < ubi->peb_count); - - spin_lock(&ubi->wl_lock); - e = ubi->lookuptbl[pnum]; - - /* This can happen if we recovered from a fastmap the very - * first time and writing now a new one. In this case the wl system - * has never seen any PEB used by the original fastmap. - */ - if (!e) { - e = fm_e; - ubi_assert(e->ec >= 0); - ubi->lookuptbl[pnum] = e; - } - - spin_unlock(&ubi->wl_lock); - - vol_id = lnum ? UBI_FM_DATA_VOLUME_ID : UBI_FM_SB_VOLUME_ID; - return schedule_erase(ubi, e, vol_id, lnum, torture); -} -#endif - /** * wear_leveling_worker - wear-leveling worker function. * @ubi: UBI device description object @@ -1427,38 +1019,6 @@ out_unlock: return err; } -#ifdef CONFIG_MTD_UBI_FASTMAP -/** - * ubi_ensure_anchor_pebs - schedule wear-leveling to produce an anchor PEB. - * @ubi: UBI device description object - */ -int ubi_ensure_anchor_pebs(struct ubi_device *ubi) -{ - struct ubi_work *wrk; - - spin_lock(&ubi->wl_lock); - if (ubi->wl_scheduled) { - spin_unlock(&ubi->wl_lock); - return 0; - } - ubi->wl_scheduled = 1; - spin_unlock(&ubi->wl_lock); - - wrk = kmalloc(sizeof(struct ubi_work), GFP_NOFS); - if (!wrk) { - spin_lock(&ubi->wl_lock); - ubi->wl_scheduled = 0; - spin_unlock(&ubi->wl_lock); - return -ENOMEM; - } - - wrk->anchor = 1; - wrk->func = &wear_leveling_worker; - schedule_ubi_work(ubi, wrk); - return 0; -} -#endif - /** * erase_worker - physical eraseblock erase worker function. * @ubi: UBI device description object @@ -1490,7 +1050,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, dbg_wl("erase PEB %d EC %d LEB %d:%d", pnum, e->ec, wl_wrk->vol_id, wl_wrk->lnum); - ubi_assert(!ubi_is_fm_block(ubi, e->pnum)); + ubi_assert(!is_fm_block(ubi, e->pnum)); err = sync_erase(ubi, e, wl_wrk->torture); if (!err) { @@ -1974,7 +1534,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) e->pnum = aeb->pnum; e->ec = aeb->ec; - ubi_assert(!ubi_is_fm_block(ubi, e->pnum)); + ubi_assert(!is_fm_block(ubi, e->pnum)); ubi->lookuptbl[e->pnum] = e; if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0)) { wl_entry_destroy(ubi, e); @@ -1995,7 +1555,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) e->pnum = aeb->pnum; e->ec = aeb->ec; ubi_assert(e->ec >= 0); - ubi_assert(!ubi_is_fm_block(ubi, e->pnum)); + ubi_assert(!is_fm_block(ubi, e->pnum)); wl_tree_add(e, &ubi->free); ubi->free_count++; @@ -2095,23 +1655,6 @@ static void protection_queue_destroy(struct ubi_device *ubi) } } -static void ubi_fastmap_close(struct ubi_device *ubi) -{ -#ifdef CONFIG_MTD_UBI_FASTMAP - int i; - - flush_work(&ubi->fm_work); - return_unused_pool_pebs(ubi, &ubi->fm_pool); - return_unused_pool_pebs(ubi, &ubi->fm_wl_pool); - - if (ubi->fm) { - for (i = 0; i < ubi->fm->used_blocks; i++) - kfree(ubi->fm->e[i]); - } - kfree(ubi->fm); -#endif -} - /** * ubi_wl_close - close the wear-leveling sub-system. * @ubi: UBI device description object @@ -2224,3 +1767,94 @@ static int self_check_in_pq(const struct ubi_device *ubi, dump_stack(); return -EINVAL; } +#ifndef CONFIG_MTD_UBI_FASTMAP +static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi) +{ + struct ubi_wl_entry *e; + + e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF); + self_check_in_wl_tree(ubi, e, &ubi->free); + ubi->free_count--; + ubi_assert(ubi->free_count >= 0); + rb_erase(&e->u.rb, &ubi->free); + + return e; +} + +/** + * produce_free_peb - produce a free physical eraseblock. + * @ubi: UBI device description object + * + * This function tries to make a free PEB by means of synchronous execution of + * pending works. This may be needed if, for example the background thread is + * disabled. Returns zero in case of success and a negative error code in case + * of failure. + */ +static int produce_free_peb(struct ubi_device *ubi) +{ + int err; + + while (!ubi->free.rb_node && ubi->works_count) { + spin_unlock(&ubi->wl_lock); + + dbg_wl("do one work synchronously"); + err = do_work(ubi); + + spin_lock(&ubi->wl_lock); + if (err) + return err; + } + + return 0; +} + +/** + * ubi_wl_get_peb - get a physical eraseblock. + * @ubi: UBI device description object + * + * This function returns a physical eraseblock in case of success and a + * negative error code in case of failure. + * Returns with ubi->fm_eba_sem held in read mode! + */ +int ubi_wl_get_peb(struct ubi_device *ubi) +{ + int err; + struct ubi_wl_entry *e; + +retry: + down_read(&ubi->fm_eba_sem); + spin_lock(&ubi->wl_lock); + if (!ubi->free.rb_node) { + if (ubi->works_count == 0) { + ubi_err(ubi, "no free eraseblocks"); + ubi_assert(list_empty(&ubi->works)); + spin_unlock(&ubi->wl_lock); + return -ENOSPC; + } + + err = produce_free_peb(ubi); + if (err < 0) { + spin_unlock(&ubi->wl_lock); + return err; + } + spin_unlock(&ubi->wl_lock); + up_read(&ubi->fm_eba_sem); + goto retry; + + } + e = wl_get_wle(ubi); + prot_queue_add(ubi, e); + spin_unlock(&ubi->wl_lock); + + err = ubi_self_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset, + ubi->peb_size - ubi->vid_hdr_aloffset); + if (err) { + ubi_err(ubi, "new PEB %d does not contain all 0xFF bytes", e->pnum); + return err; + } + + return e->pnum; +} +#else +#include "fastmap-wl.c" +#endif diff --git a/drivers/mtd/ubi/wl.h b/drivers/mtd/ubi/wl.h new file mode 100644 index 000000000000..db8681477d96 --- /dev/null +++ b/drivers/mtd/ubi/wl.h @@ -0,0 +1,18 @@ +#ifndef UBI_WL_H +#define UBI_WL_H +#ifdef CONFIG_MTD_UBI_FASTMAP +static int is_fm_block(struct ubi_device *ubi, int pnum); +static int anchor_pebs_avalible(struct rb_root *root); +static void update_fastmap_work_fn(struct work_struct *wrk); +static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root); +static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi); +static void ubi_fastmap_close(struct ubi_device *ubi); +#else /* !CONFIG_MTD_UBI_FASTMAP */ +static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi); +static inline int is_fm_block(struct ubi_device *ubi, int pnum) +{ + return 0; +} +static inline void ubi_fastmap_close(struct ubi_device *ubi) { } +#endif /* CONFIG_MTD_UBI_FASTMAP */ +#endif /* UBI_WL_H */ -- cgit v1.2.3-59-g8ed1b From 23c482ef7b7611225f70efe46a3627b889cab1a4 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 28 Oct 2014 16:18:42 +0100 Subject: UBI: Add accessor functions for WL data structures Fastmap need access to various WL data structures as fastmap tightly depends on WL. To make the access less invasive add accessor functions. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/ubi.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index adc633cb89c3..3d58c749f9f1 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -904,6 +904,42 @@ static inline int ubiblock_remove(struct ubi_volume_info *vi) } #endif +/* + * ubi_for_each_free_peb - walk the UBI free RB tree. + * @ubi: UBI device description object + * @e: a pointer to a ubi_wl_entry to use as cursor + * @pos: a pointer to RB-tree entry type to use as a loop counter + */ +#define ubi_for_each_free_peb(ubi, e, tmp_rb) \ + ubi_rb_for_each_entry((tmp_rb), (e), &(ubi)->free, u.rb) + +/* + * ubi_for_each_used_peb - walk the UBI used RB tree. + * @ubi: UBI device description object + * @e: a pointer to a ubi_wl_entry to use as cursor + * @pos: a pointer to RB-tree entry type to use as a loop counter + */ +#define ubi_for_each_used_peb(ubi, e, tmp_rb) \ + ubi_rb_for_each_entry((tmp_rb), (e), &(ubi)->used, u.rb) + +/* + * ubi_for_each_scub_peb - walk the UBI scub RB tree. + * @ubi: UBI device description object + * @e: a pointer to a ubi_wl_entry to use as cursor + * @pos: a pointer to RB-tree entry type to use as a loop counter + */ +#define ubi_for_each_scrub_peb(ubi, e, tmp_rb) \ + ubi_rb_for_each_entry((tmp_rb), (e), &(ubi)->scrub, u.rb) + +/* + * ubi_for_each_protected_peb - walk the UBI protection queue. + * @ubi: UBI device description object + * @i: a integer used as counter + * @e: a pointer to a ubi_wl_entry to use as cursor + */ +#define ubi_for_each_protected_peb(ubi, i, e) \ + for ((i) = 0; (i) < UBI_PROT_QUEUE_LEN; (i)++) \ + list_for_each_entry((e), &(ubi->pq[(i)]), u.list) /* * ubi_rb_for_each_entry - walk an RB-tree. -- cgit v1.2.3-59-g8ed1b From c5c3f3cf969e45c53345283fce0ba11fae7abd32 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 28 Oct 2014 16:24:27 +0100 Subject: UBI: Fastmap: Wire up WL accessor functions Use the new WL accessor functions in fastmap. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 13492fef6471..02a6de2f53ee 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -1087,11 +1087,11 @@ static int ubi_write_fastmap(struct ubi_device *ubi, struct ubi_fm_ec *fec; struct ubi_fm_volhdr *fvh; struct ubi_fm_eba *feba; - struct rb_node *node; struct ubi_wl_entry *wl_e; struct ubi_volume *vol; struct ubi_vid_hdr *avhdr, *dvhdr; struct ubi_work *ubi_wrk; + struct rb_node *tmp_rb; int ret, i, j, free_peb_count, used_peb_count, vol_count; int scrub_peb_count, erase_peb_count; int *seen_pebs = NULL; @@ -1163,8 +1163,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, set_seen(ubi, ubi->fm_wl_pool.pebs[i], seen_pebs); } - for (node = rb_first(&ubi->free); node; node = rb_next(node)) { - wl_e = rb_entry(node, struct ubi_wl_entry, u.rb); + ubi_for_each_free_peb(ubi, wl_e, tmp_rb) { fec = (struct ubi_fm_ec *)(fm_raw + fm_pos); fec->pnum = cpu_to_be32(wl_e->pnum); @@ -1177,8 +1176,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, } fmh->free_peb_count = cpu_to_be32(free_peb_count); - for (node = rb_first(&ubi->used); node; node = rb_next(node)) { - wl_e = rb_entry(node, struct ubi_wl_entry, u.rb); + ubi_for_each_used_peb(ubi, wl_e, tmp_rb) { fec = (struct ubi_fm_ec *)(fm_raw + fm_pos); fec->pnum = cpu_to_be32(wl_e->pnum); @@ -1190,22 +1188,20 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ubi_assert(fm_pos <= ubi->fm_size); } - for (i = 0; i < UBI_PROT_QUEUE_LEN; i++) { - list_for_each_entry(wl_e, &ubi->pq[i], u.list) { - fec = (struct ubi_fm_ec *)(fm_raw + fm_pos); + ubi_for_each_protected_peb(ubi, i, wl_e) { + fec = (struct ubi_fm_ec *)(fm_raw + fm_pos); - fec->pnum = cpu_to_be32(wl_e->pnum); - fec->ec = cpu_to_be32(wl_e->ec); + fec->pnum = cpu_to_be32(wl_e->pnum); + set_seen(ubi, wl_e->pnum, seen_pebs); + fec->ec = cpu_to_be32(wl_e->ec); - used_peb_count++; - fm_pos += sizeof(*fec); - ubi_assert(fm_pos <= ubi->fm_size); - } + used_peb_count++; + fm_pos += sizeof(*fec); + ubi_assert(fm_pos <= ubi->fm_size); } fmh->used_peb_count = cpu_to_be32(used_peb_count); - for (node = rb_first(&ubi->scrub); node; node = rb_next(node)) { - wl_e = rb_entry(node, struct ubi_wl_entry, u.rb); + ubi_for_each_scrub_peb(ubi, wl_e, tmp_rb) { fec = (struct ubi_fm_ec *)(fm_raw + fm_pos); fec->pnum = cpu_to_be32(wl_e->pnum); -- cgit v1.2.3-59-g8ed1b From acfda79f8808518b0235eb9a13c8b5f762e43a75 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 28 Oct 2014 17:07:06 +0100 Subject: UBI: Fastmap: Introduce ubi_fastmap_init() ...and kill another #ifdef in wl.c. :-) Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/wl.c | 8 +------- drivers/mtd/ubi/wl.h | 7 +++++++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 7d49f42ca2d5..c56c7a16c03b 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1510,9 +1510,6 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) init_rwsem(&ubi->work_sem); ubi->max_ec = ai->max_ec; INIT_LIST_HEAD(&ubi->works); -#ifdef CONFIG_MTD_UBI_FASTMAP - INIT_WORK(&ubi->fm_work, update_fastmap_work_fn); -#endif sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num); @@ -1606,10 +1603,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) ubi_assert(ubi->good_peb_count == found_pebs); reserved_pebs = WL_RESERVED_PEBS; -#ifdef CONFIG_MTD_UBI_FASTMAP - /* Reserve enough LEBs to store two fastmaps. */ - reserved_pebs += (ubi->fm_size / ubi->leb_size) * 2; -#endif + ubi_fastmap_init(ubi, &reserved_pebs); if (ubi->avail_pebs < reserved_pebs) { ubi_err(ubi, "no enough physical eraseblocks (%d, need %d)", diff --git a/drivers/mtd/ubi/wl.h b/drivers/mtd/ubi/wl.h index db8681477d96..4046ccf8942b 100644 --- a/drivers/mtd/ubi/wl.h +++ b/drivers/mtd/ubi/wl.h @@ -7,6 +7,12 @@ static void update_fastmap_work_fn(struct work_struct *wrk); static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root); static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi); static void ubi_fastmap_close(struct ubi_device *ubi); +static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count) +{ + /* Reserve enough LEBs to store two fastmaps. */ + *count += (ubi->fm_size / ubi->leb_size) * 2; + INIT_WORK(&ubi->fm_work, update_fastmap_work_fn); +} #else /* !CONFIG_MTD_UBI_FASTMAP */ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi); static inline int is_fm_block(struct ubi_device *ubi, int pnum) @@ -14,5 +20,6 @@ static inline int is_fm_block(struct ubi_device *ubi, int pnum) return 0; } static inline void ubi_fastmap_close(struct ubi_device *ubi) { } +static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count) { } #endif /* CONFIG_MTD_UBI_FASTMAP */ #endif /* UBI_WL_H */ -- cgit v1.2.3-59-g8ed1b From 2f84c2469e2f2e94a45d86597baec10bfbf06847 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 29 Oct 2014 10:31:41 +0100 Subject: UBI: Fastmap: Introduce may_reserve_for_fm() ...and kill another #ifdef. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap-wl.c | 19 +++++++++++++++++++ drivers/mtd/ubi/wl.c | 7 +------ drivers/mtd/ubi/wl.h | 8 ++++++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c index 88a400c52418..c4717531b24c 100644 --- a/drivers/mtd/ubi/fastmap-wl.c +++ b/drivers/mtd/ubi/fastmap-wl.c @@ -359,3 +359,22 @@ static void ubi_fastmap_close(struct ubi_device *ubi) } kfree(ubi->fm); } + +/** + * may_reserve_for_fm - tests whether a PEB shall be reserved for fastmap. + * See find_mean_wl_entry() + * + * @ubi: UBI device description object + * @e: physical eraseblock to return + * @root: RB tree to test against. + */ +static struct ubi_wl_entry *may_reserve_for_fm(struct ubi_device *ubi, + struct ubi_wl_entry *e, + struct rb_root *root) { + if (e && !ubi->fm_disabled && !ubi->fm && + e->pnum < UBI_FM_MAX_START) + e = rb_entry(rb_next(root->rb_node), + struct ubi_wl_entry, u.rb); + + return e; +} diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index c56c7a16c03b..94ffdeb370c1 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -361,15 +361,10 @@ static struct ubi_wl_entry *find_mean_wl_entry(struct ubi_device *ubi, if (last->ec - first->ec < WL_FREE_MAX_DIFF) { e = rb_entry(root->rb_node, struct ubi_wl_entry, u.rb); -#ifdef CONFIG_MTD_UBI_FASTMAP /* If no fastmap has been written and this WL entry can be used * as anchor PEB, hold it back and return the second best * WL entry such that fastmap can use the anchor PEB later. */ - if (e && !ubi->fm_disabled && !ubi->fm && - e->pnum < UBI_FM_MAX_START) - e = rb_entry(rb_next(root->rb_node), - struct ubi_wl_entry, u.rb); -#endif + e = may_reserve_for_fm(ubi, e, root); } else e = find_wl_entry(ubi, root, WL_FREE_MAX_DIFF/2); diff --git a/drivers/mtd/ubi/wl.h b/drivers/mtd/ubi/wl.h index 4046ccf8942b..fbc2d8e312df 100644 --- a/drivers/mtd/ubi/wl.h +++ b/drivers/mtd/ubi/wl.h @@ -13,6 +13,9 @@ static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count) *count += (ubi->fm_size / ubi->leb_size) * 2; INIT_WORK(&ubi->fm_work, update_fastmap_work_fn); } +static struct ubi_wl_entry *may_reserve_for_fm(struct ubi_device *ubi, + struct ubi_wl_entry *e, + struct rb_root *root); #else /* !CONFIG_MTD_UBI_FASTMAP */ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi); static inline int is_fm_block(struct ubi_device *ubi, int pnum) @@ -21,5 +24,10 @@ static inline int is_fm_block(struct ubi_device *ubi, int pnum) } static inline void ubi_fastmap_close(struct ubi_device *ubi) { } static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count) { } +static struct ubi_wl_entry *may_reserve_for_fm(struct ubi_device *ubi, + struct ubi_wl_entry *e, + struct rb_root *root) { + return e; +} #endif /* CONFIG_MTD_UBI_FASTMAP */ #endif /* UBI_WL_H */ -- cgit v1.2.3-59-g8ed1b From e1bc37ceafc04dff20a8cdc88ed250941ec2ea92 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 29 Oct 2014 11:44:45 +0100 Subject: UBI: Fastmap: Remove else after return. checkpatch.pl complains: WARNING: else is not generally useful after a break or return Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap-wl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c index c4717531b24c..7a72af2ec4ec 100644 --- a/drivers/mtd/ubi/fastmap-wl.c +++ b/drivers/mtd/ubi/fastmap-wl.c @@ -260,10 +260,10 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi) schedule_work(&ubi->fm_work); } return NULL; - } else { - pnum = pool->pebs[pool->used++]; - return ubi->lookuptbl[pnum]; } + + pnum = pool->pebs[pool->used++]; + return ubi->lookuptbl[pnum]; } /** -- cgit v1.2.3-59-g8ed1b From 1841fcfd910b4e841de40e1f6bc3dad6109a4054 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 29 Oct 2014 11:47:22 +0100 Subject: UBI: Fastmap: Add blank line after declarations Another checkpatch complaint: WARNING: Missing a blank line after declarations Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap-wl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c index 7a72af2ec4ec..067aa9042ec1 100644 --- a/drivers/mtd/ubi/fastmap-wl.c +++ b/drivers/mtd/ubi/fastmap-wl.c @@ -21,6 +21,7 @@ static void update_fastmap_work_fn(struct work_struct *wrk) { struct ubi_device *ubi = container_of(wrk, struct ubi_device, fm_work); + ubi_update_fastmap(ubi); spin_lock(&ubi->wl_lock); ubi->fm_work_scheduled = 0; -- cgit v1.2.3-59-g8ed1b From 56794c0a1ae738cb4184ab27501e4d152b0b2771 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 7 Nov 2014 13:35:41 +0100 Subject: UBI: Fastmap: Remove is_fm_block() This function was added to fastmap in a very early stage to have paranoid assertions. With the current fastmap implementation this assert will never trigger as fastmap PEBs are not seen by the WL sub-system. Remove it to save us some CPU cycles. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/fastmap-wl.c | 19 ------------------- drivers/mtd/ubi/wl.c | 5 ----- drivers/mtd/ubi/wl.h | 5 ----- 3 files changed, 29 deletions(-) diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c index 067aa9042ec1..b2a665398bca 100644 --- a/drivers/mtd/ubi/fastmap-wl.c +++ b/drivers/mtd/ubi/fastmap-wl.c @@ -28,25 +28,6 @@ static void update_fastmap_work_fn(struct work_struct *wrk) spin_unlock(&ubi->wl_lock); } -/** - * is_fm_block - returns 1 if a PEB is currently used in a fastmap. - * @ubi: UBI device description object - * @pnum: the to be checked PEB - */ -static int is_fm_block(struct ubi_device *ubi, int pnum) -{ - int i; - - if (!ubi->fm) - return 0; - - for (i = 0; i < ubi->fm->used_blocks; i++) - if (ubi->fm->e[i]->pnum == pnum) - return 1; - - return 0; -} - /** * find_anchor_wl_entry - find wear-leveling entry to used as anchor PEB. * @root: the RB-tree where to look for diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 94ffdeb370c1..16214d3d57a4 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -585,7 +585,6 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, struct ubi_work *wl_wrk; ubi_assert(e); - ubi_assert(!is_fm_block(ubi, e->pnum)); dbg_wl("schedule erasure of PEB %d, EC %d, torture %d", e->pnum, e->ec, torture); @@ -1045,8 +1044,6 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, dbg_wl("erase PEB %d EC %d LEB %d:%d", pnum, e->ec, wl_wrk->vol_id, wl_wrk->lnum); - ubi_assert(!is_fm_block(ubi, e->pnum)); - err = sync_erase(ubi, e, wl_wrk->torture); if (!err) { /* Fine, we've erased it successfully */ @@ -1526,7 +1523,6 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) e->pnum = aeb->pnum; e->ec = aeb->ec; - ubi_assert(!is_fm_block(ubi, e->pnum)); ubi->lookuptbl[e->pnum] = e; if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0)) { wl_entry_destroy(ubi, e); @@ -1547,7 +1543,6 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) e->pnum = aeb->pnum; e->ec = aeb->ec; ubi_assert(e->ec >= 0); - ubi_assert(!is_fm_block(ubi, e->pnum)); wl_tree_add(e, &ubi->free); ubi->free_count++; diff --git a/drivers/mtd/ubi/wl.h b/drivers/mtd/ubi/wl.h index fbc2d8e312df..bd1f07e5ce9a 100644 --- a/drivers/mtd/ubi/wl.h +++ b/drivers/mtd/ubi/wl.h @@ -1,7 +1,6 @@ #ifndef UBI_WL_H #define UBI_WL_H #ifdef CONFIG_MTD_UBI_FASTMAP -static int is_fm_block(struct ubi_device *ubi, int pnum); static int anchor_pebs_avalible(struct rb_root *root); static void update_fastmap_work_fn(struct work_struct *wrk); static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root); @@ -18,10 +17,6 @@ static struct ubi_wl_entry *may_reserve_for_fm(struct ubi_device *ubi, struct rb_root *root); #else /* !CONFIG_MTD_UBI_FASTMAP */ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi); -static inline int is_fm_block(struct ubi_device *ubi, int pnum) -{ - return 0; -} static inline void ubi_fastmap_close(struct ubi_device *ubi) { } static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count) { } static struct ubi_wl_entry *may_reserve_for_fm(struct ubi_device *ubi, -- cgit v1.2.3-59-g8ed1b From 180a53577b809026af744e99a35b3a3a0056520b Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 9 Mar 2015 10:04:09 +0100 Subject: UBI: Fastmap: Fall back to scanning mode after ECC error If we encounter an uncorrectable ECC error while scanning for the fastmap UBI must not fail hard. Instead fall back to scanning mode. Reported-by: Alexander Block Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/attach.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index 42d465add385..68eea5befaf1 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c @@ -1419,7 +1419,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) err = scan_all(ubi, ai, 0); else { err = scan_fast(ubi, &ai); - if (err > 0) { + if (err > 0 || mtd_is_eccerr(err)) { if (err != UBI_NO_FASTMAP) { destroy_ai(ai); ai = alloc_ai(); -- cgit v1.2.3-59-g8ed1b From 1a7e985dd1bf5939af0f56bbd6d13d2caf48dd63 Mon Sep 17 00:00:00 2001 From: Sheng Yong Date: Fri, 3 Apr 2015 03:13:42 +0000 Subject: UBIFS: fix output format of INUM_WATERMARK The INUM_WATERMARK is a unsigned 32bit value, `%d' prints it as negatave: [ 103.682255] UBIFS warning (ubi0:0 pid 691): ubifs_new_inode: running out of inode numbers (current 122763, max -256) Fix it as: [ 154.422940] UBIFS warning (ubi0:0 pid 688): ubifs_new_inode: running out of inode numbers (current 122765, max 4294967040) Signed-off-by: Sheng Yong Signed-off-by: Artem Bityutskiy --- fs/ubifs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 90fe60c2f112..02d1ee778df0 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -151,7 +151,7 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir, iput(inode); return ERR_PTR(-EINVAL); } - ubifs_warn(c, "running out of inode numbers (current %lu, max %d)", + ubifs_warn(c, "running out of inode numbers (current %lu, max %u)", (unsigned long)c->highest_inum, INUM_WATERMARK); } -- cgit v1.2.3-59-g8ed1b From 502690674281a047abd45f81e64c498bc23a8bb3 Mon Sep 17 00:00:00 2001 From: "david.oberhollenzer@sigma-star.at" Date: Thu, 26 Mar 2015 23:59:50 +0100 Subject: UBI: power cut emulation for testing Emulate random power cuts by switching device to ro after a number of writes to allow simple power cut testing with nand-sim. Maximum and minimum number of successful writes before power cut and what kind of writes (EC header, VID header or none) to interrupt configurable via debugfs. Signed-off-by: David Oberhollenzer Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/debug.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++-- drivers/mtd/ubi/debug.h | 2 ++ drivers/mtd/ubi/io.c | 6 ++++ drivers/mtd/ubi/ubi.h | 25 ++++++++++++++ 4 files changed, 120 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index 224fed085102..b077e43b5ba9 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c @@ -263,7 +263,7 @@ static ssize_t dfs_file_read(struct file *file, char __user *user_buf, struct dentry *dent = file->f_path.dentry; struct ubi_device *ubi; struct ubi_debug_info *d; - char buf[3]; + char buf[8]; int val; ubi = ubi_get_device(ubi_num); @@ -283,6 +283,22 @@ static ssize_t dfs_file_read(struct file *file, char __user *user_buf, val = d->emulate_bitflips; else if (dent == d->dfs_emulate_io_failures) val = d->emulate_io_failures; + else if (dent == d->dfs_emulate_power_cut) { + snprintf(buf, sizeof(buf), "%u\n", d->emulate_power_cut); + count = simple_read_from_buffer(user_buf, count, ppos, + buf, strlen(buf)); + goto out; + } else if (dent == d->dfs_power_cut_min) { + snprintf(buf, sizeof(buf), "%u\n", d->power_cut_min); + count = simple_read_from_buffer(user_buf, count, ppos, + buf, strlen(buf)); + goto out; + } else if (dent == d->dfs_power_cut_max) { + snprintf(buf, sizeof(buf), "%u\n", d->power_cut_max); + count = simple_read_from_buffer(user_buf, count, ppos, + buf, strlen(buf)); + goto out; + } else { count = -EINVAL; goto out; @@ -311,7 +327,7 @@ static ssize_t dfs_file_write(struct file *file, const char __user *user_buf, struct ubi_device *ubi; struct ubi_debug_info *d; size_t buf_size; - char buf[8]; + char buf[8] = {0}; int val; ubi = ubi_get_device(ubi_num); @@ -325,6 +341,21 @@ static ssize_t dfs_file_write(struct file *file, const char __user *user_buf, goto out; } + if (dent == d->dfs_power_cut_min) { + if (kstrtouint(buf, 0, &d->power_cut_min) != 0) + count = -EINVAL; + goto out; + } else if (dent == d->dfs_power_cut_max) { + if (kstrtouint(buf, 0, &d->power_cut_max) != 0) + count = -EINVAL; + goto out; + } else if (dent == d->dfs_emulate_power_cut) { + if (kstrtoint(buf, 0, &val) != 0) + count = -EINVAL; + d->emulate_power_cut = val; + goto out; + } + if (buf[0] == '1') val = 1; else if (buf[0] == '0') @@ -438,6 +469,27 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi) goto out_remove; d->dfs_emulate_io_failures = dent; + fname = "tst_emulate_power_cut"; + dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num, + &dfs_fops); + if (IS_ERR_OR_NULL(dent)) + goto out_remove; + d->dfs_emulate_power_cut = dent; + + fname = "tst_emulate_power_cut_min"; + dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num, + &dfs_fops); + if (IS_ERR_OR_NULL(dent)) + goto out_remove; + d->dfs_power_cut_min = dent; + + fname = "tst_emulate_power_cut_max"; + dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num, + &dfs_fops); + if (IS_ERR_OR_NULL(dent)) + goto out_remove; + d->dfs_power_cut_max = dent; + return 0; out_remove: @@ -458,3 +510,36 @@ void ubi_debugfs_exit_dev(struct ubi_device *ubi) if (IS_ENABLED(CONFIG_DEBUG_FS)) debugfs_remove_recursive(ubi->dbg.dfs_dir); } + +/** + * ubi_dbg_power_cut - emulate a power cut if it is time to do so + * @ubi: UBI device description object + * @caller: Flags set to indicate from where the function is being called + * + * Returns non-zero if a power cut was emulated, zero if not. + */ +int ubi_dbg_power_cut(struct ubi_device *ubi, int caller) +{ + unsigned int range; + + if ((ubi->dbg.emulate_power_cut & caller) == 0) + return 0; + + if (ubi->dbg.power_cut_counter == 0) { + ubi->dbg.power_cut_counter = ubi->dbg.power_cut_min; + + if (ubi->dbg.power_cut_max > ubi->dbg.power_cut_min) { + range = ubi->dbg.power_cut_max - ubi->dbg.power_cut_min; + ubi->dbg.power_cut_counter += prandom_u32() % range; + } + return 0; + } + + ubi->dbg.power_cut_counter--; + if (ubi->dbg.power_cut_counter) + return 0; + + ubi_msg(ubi, "XXXXXXXXXXXXXXX emulating a power cut XXXXXXXXXXXXXXXX"); + ubi_ro_mode(ubi); + return 1; +} diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index c6ea4431acf3..eb8985e5c178 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h @@ -137,4 +137,6 @@ static inline void ubi_enable_dbg_chk_fastmap(struct ubi_device *ubi) { ubi->dbg.chk_fastmap = 1; } + +int ubi_dbg_power_cut(struct ubi_device *ubi, int caller); #endif /* !__UBI_DEBUG_H__ */ diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index ed0bcb35472f..5bbd1f094f4e 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -859,6 +859,9 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, if (err) return err; + if (ubi_dbg_power_cut(ubi, POWER_CUT_EC_WRITE)) + return -EROFS; + err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize); return err; } @@ -1106,6 +1109,9 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, if (err) return err; + if (ubi_dbg_power_cut(ubi, POWER_CUT_VID_WRITE)) + return -EROFS; + p = (char *)vid_hdr - ubi->vid_hdr_shift; err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize); diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 3d58c749f9f1..c998212fc680 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -151,6 +151,17 @@ enum { UBI_BAD_FASTMAP, }; +/* + * Flags for emulate_power_cut in ubi_debug_info + * + * POWER_CUT_EC_WRITE: Emulate a power cut when writing an EC header + * POWER_CUT_VID_WRITE: Emulate a power cut when writing a VID header + */ +enum { + POWER_CUT_EC_WRITE = 0x01, + POWER_CUT_VID_WRITE = 0x02, +}; + /** * struct ubi_wl_entry - wear-leveling entry. * @u.rb: link in the corresponding (free/used) RB-tree @@ -360,6 +371,10 @@ struct ubi_wl_entry; * @disable_bgt: disable the background task for testing purposes * @emulate_bitflips: emulate bit-flips for testing purposes * @emulate_io_failures: emulate write/erase failures for testing purposes + * @emulate_power_cut: emulate power cut for testing purposes + * @power_cut_counter: count down for writes left until emulated power cut + * @power_cut_min: minimum number of writes before emulating a power cut + * @power_cut_max: maximum number of writes until emulating a power cut * @dfs_dir_name: name of debugfs directory containing files of this UBI device * @dfs_dir: direntry object of the UBI device debugfs directory * @dfs_chk_gen: debugfs knob to enable UBI general extra checks @@ -368,6 +383,9 @@ struct ubi_wl_entry; * @dfs_disable_bgt: debugfs knob to disable the background task * @dfs_emulate_bitflips: debugfs knob to emulate bit-flips * @dfs_emulate_io_failures: debugfs knob to emulate write/erase failures + * @dfs_emulate_power_cut: debugfs knob to emulate power cuts + * @dfs_power_cut_min: debugfs knob for minimum writes before power cut + * @dfs_power_cut_max: debugfs knob for maximum writes until power cut */ struct ubi_debug_info { unsigned int chk_gen:1; @@ -376,6 +394,10 @@ struct ubi_debug_info { unsigned int disable_bgt:1; unsigned int emulate_bitflips:1; unsigned int emulate_io_failures:1; + unsigned int emulate_power_cut:2; + unsigned int power_cut_counter; + unsigned int power_cut_min; + unsigned int power_cut_max; char dfs_dir_name[UBI_DFS_DIR_LEN + 1]; struct dentry *dfs_dir; struct dentry *dfs_chk_gen; @@ -384,6 +406,9 @@ struct ubi_debug_info { struct dentry *dfs_disable_bgt; struct dentry *dfs_emulate_bitflips; struct dentry *dfs_emulate_io_failures; + struct dentry *dfs_emulate_power_cut; + struct dentry *dfs_power_cut_min; + struct dentry *dfs_power_cut_max; }; /** -- cgit v1.2.3-59-g8ed1b