Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758398AbYC0NLB (ORCPT ); Thu, 27 Mar 2008 09:11:01 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1759036AbYC0NH4 (ORCPT ); Thu, 27 Mar 2008 09:07:56 -0400 Received: from smtp.nokia.com ([192.100.122.230]:64472 "EHLO mgw-mx03.nokia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755910AbYC0NHX (ORCPT ); Thu, 27 Mar 2008 09:07:23 -0400 From: Artem Bityutskiy To: LKML Cc: Adrian Hunter , Artem Bityutskiy Subject: [RFC PATCH 25/26] UBIFS: add debugging stuff Date: Thu, 27 Mar 2008 16:55:45 +0200 Message-Id: <1206629746-4298-26-git-send-email-Artem.Bityutskiy@nokia.com> X-Mailer: git-send-email 1.5.4.1 In-Reply-To: <1206629746-4298-1-git-send-email-Artem.Bityutskiy@nokia.com> References: <1206629746-4298-1-git-send-email-Artem.Bityutskiy@nokia.com> MIME-Version: 1.0 Content-Type: text/plain; charset=unknown-8bit Content-Transfer-Encoding: 8bit X-OriginalArrivalTime: 27 Mar 2008 13:06:54.0945 (UTC) FILETIME=[6E4A1D10:01C8900B] X-Nokia-AV: Clean Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 44273 Lines: 1499 The UBIFS code is large, and we have a plenty of debugging stuff in there which helps to catch bugs. Some of the debugging stuff will be deleted later. Signed-off-by: Artem Bityutskiy Signed-off-by: Adrian Hunter --- fs/ubifs/debug.c | 1125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/ubifs/debug.h | 343 +++++++++++++++++ 2 files changed, 1468 insertions(+), 0 deletions(-) diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c new file mode 100644 index 0000000..5ccb5a4 --- /dev/null +++ b/fs/ubifs/debug.c @@ -0,0 +1,1125 @@ +/* + * This file is part of UBIFS. + * + * Copyright (C) 2006-2008 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * 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. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Artem Bityutskiy (Битюцкий Артём) + * Adrian Hunter + */ + +/* + * This file implements most of the debugging stuff which is compiled in only + * when it is enabled. But some debugging check functions are implemented in + * corresponding subsystem, just because they are closely related and utilize + * various local functions of those subsystems. + */ + +#define UBIFS_DBG_PRESERVE_KMALLOC +#define UBIFS_DBG_PRESERVE_UBI + +#include "ubifs.h" + +#ifdef CONFIG_UBIFS_FS_DEBUG + +DEFINE_SPINLOCK(dbg_lock); + +static char dbg_get_key_dump_dump_buf[100]; + +static size_t km_alloc_cnt; +static size_t vm_alloc_cnt; + +static const char *get_key_fmt(int fmt) +{ + switch (fmt) { + case UBIFS_SIMPLE_KEY_FMT: + return "simple"; + default: + return "unknown/invalid format"; + } +} + +static const char *get_key_hash(int hash) +{ + switch (hash) { + case UBIFS_KEY_HASH_R5: + return "R5"; + case UBIFS_KEY_HASH_TEST: + return "test"; + default: + return "unknown/invalid name hash"; + } +} + +static const char *get_key_type(int type) +{ + switch (type) { + case UBIFS_INO_KEY: + return "inode"; + case UBIFS_DENT_KEY: + return "direntry"; + case UBIFS_XENT_KEY: + return "xentry"; + case UBIFS_DATA_KEY: + return "data"; + case UBIFS_TRUN_KEY: + return "truncate"; + default: + return "unknown/invalid key"; + } +} + +const char *dbg_get_key_dump(const struct ubifs_info *c, + const union ubifs_key *key) +{ + char *p = &dbg_get_key_dump_dump_buf[0]; + int type = key_type(c, key); + + if (c->key_fmt == UBIFS_SIMPLE_KEY_FMT) { + switch (type) { + case UBIFS_INO_KEY: + sprintf(p, "(%lu, %s)", key_ino(c, key), + get_key_type(type)); + break; + case UBIFS_DENT_KEY: + case UBIFS_XENT_KEY: + sprintf(p, "(%lu, %s, %#08x)", key_ino(c, key), + get_key_type(type), key_hash(c, key)); + break; + case UBIFS_DATA_KEY: + sprintf(p, "(%lu, %s, %u)", key_ino(c, key), + get_key_type(type), key_block(c, key)); + break; + case UBIFS_TRUN_KEY: + sprintf(p, "(%lu, %s)", + key_ino(c, key), get_key_type(type)); + break; + default: + sprintf(p, "(bad key type: %#08x, %#08x)", + key->u32[0], key->u32[1]); + } + } else + sprintf(p, "bad key format %d", c->key_fmt); + + return p; +} + +const char *dbg_ntype(int type) +{ + switch (type) { + case UBIFS_PAD_NODE: + return "padding node"; + case UBIFS_SB_NODE: + return "superblock node"; + case UBIFS_MST_NODE: + return "master node"; + case UBIFS_REF_NODE: + return "reference node"; + case UBIFS_INO_NODE: + return "inode node"; + case UBIFS_DENT_NODE: + return "direntry node"; + case UBIFS_XENT_NODE: + return "xentry node"; + case UBIFS_DATA_NODE: + return "data node"; + case UBIFS_TRUN_NODE: + return "truncate node"; + case UBIFS_IDX_NODE: + return "indexing node"; + case UBIFS_CS_NODE: + return "commit start node"; + case UBIFS_ORPH_NODE: + return "orphan node"; + default: + return "unknown node"; + } +} + +static const char *dbg_gtype(int type) +{ + switch (type) { + case UBIFS_NO_NODE_GROUP: + return "no node group"; + case UBIFS_IN_NODE_GROUP: + return "in node group"; + case UBIFS_LAST_OF_NODE_GROUP: + return "last of node group"; + default: + return "unknown"; + } +} + +const char *dbg_cstate(int cmt_state) +{ + switch (cmt_state) { + case COMMIT_RESTING: + return "commit resting"; + case COMMIT_BACKGROUND: + return "background commit requested"; + case COMMIT_REQUIRED: + return "commit required"; + case COMMIT_RUNNING_BACKGROUND: + return "BACKGROUND commit running"; + case COMMIT_RUNNING_REQUIRED: + return "commit running and required"; + case COMMIT_BROKEN: + return "broken commit"; + default: + return "unknown commit state"; + } +} + +static void dump_ch(const struct ubifs_ch *ch) +{ + printk(KERN_DEBUG "\tmagic %#x\n", le32_to_cpu(ch->magic)); + printk(KERN_DEBUG "\tcrc %#x\n", le32_to_cpu(ch->crc)); + printk(KERN_DEBUG "\tnode_type %d (%s)\n", ch->node_type, + dbg_ntype(ch->node_type)); + printk(KERN_DEBUG "\tgroup_type %d (%s)\n", ch->group_type, + dbg_gtype(ch->group_type)); + printk(KERN_DEBUG "\tsqnum %llu\n", le64_to_cpu(ch->sqnum)); + printk(KERN_DEBUG "\tlen %u\n", le32_to_cpu(ch->len)); +} + +void dbg_dump_node(const struct ubifs_info *c, const void *node) +{ + int i, n; + union ubifs_key key; + const struct ubifs_ch *ch = node; + + if (dbg_failure_mode) + return; + + /* If the magic is incorrect, just hexdump the first bytes */ + if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC) { + printk(KERN_DEBUG "Not a node, first %zu bytes:", UBIFS_CH_SZ); + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, + (void *)node, UBIFS_CH_SZ, 1); + return; + } + + spin_lock(&dbg_lock); + dump_ch(node); + + switch (ch->node_type) { + case UBIFS_PAD_NODE: + { + const struct ubifs_pad_node *pad = node; + + printk(KERN_DEBUG "\tpad_len %u\n", + le32_to_cpu(pad->pad_len)); + break; + } + case UBIFS_SB_NODE: + { + const struct ubifs_sb_node *sup = node; + unsigned int sup_flags = le32_to_cpu(sup->flags); + + printk(KERN_DEBUG "\tkey_hash %d (%s)\n", + (int)sup->key_hash, get_key_hash(sup->key_hash)); + printk(KERN_DEBUG "\tkey_fmt %d (%s)\n", + (int)sup->key_fmt, get_key_fmt(sup->key_fmt)); + printk(KERN_DEBUG "\tflags %#x\n", sup_flags); + printk(KERN_DEBUG "\t\tbig_lpt %u\n", + !!(sup_flags & UBIFS_FLG_BIGLPT)); + printk(KERN_DEBUG "\tmin_io_size %u\n", + le32_to_cpu(sup->min_io_size)); + printk(KERN_DEBUG "\tleb_size %u\n", + le32_to_cpu(sup->leb_size)); + printk(KERN_DEBUG "\tleb_cnt %u\n", + le32_to_cpu(sup->leb_cnt)); + printk(KERN_DEBUG "\tmax_leb_cnt %u\n", + le32_to_cpu(sup->max_leb_cnt)); + printk(KERN_DEBUG "\tmax_bud_bytes %llu\n", + le64_to_cpu(sup->max_bud_bytes)); + printk(KERN_DEBUG "\tlog_lebs %u\n", + le32_to_cpu(sup->log_lebs)); + printk(KERN_DEBUG "\tlpt_lebs %u\n", + le32_to_cpu(sup->lpt_lebs)); + printk(KERN_DEBUG "\torph_lebs %u\n", + le32_to_cpu(sup->orph_lebs)); + printk(KERN_DEBUG "\tjhead_cnt %u\n", + le32_to_cpu(sup->jhead_cnt)); + printk(KERN_DEBUG "\tfanout %u\n", + le32_to_cpu(sup->fanout)); + printk(KERN_DEBUG "\tlsave_cnt %u\n", + le32_to_cpu(sup->lsave_cnt)); + printk(KERN_DEBUG "\tdefault_compr %u\n", + (int)le16_to_cpu(sup->default_compr)); + printk(KERN_DEBUG "\trp_size %llu\n", + le64_to_cpu(sup->rp_size)); + printk(KERN_DEBUG "\trp_uid %u\n", + le32_to_cpu(sup->rp_uid)); + printk(KERN_DEBUG "\trp_gid %u\n", + le32_to_cpu(sup->rp_gid)); + break; + } + case UBIFS_MST_NODE: + { + const struct ubifs_mst_node *mst = node; + + printk(KERN_DEBUG "\thighest_inum %llu\n", + le64_to_cpu(mst->highest_inum)); + printk(KERN_DEBUG "\tcommit number %llu\n", + le64_to_cpu(mst->cmt_no)); + printk(KERN_DEBUG "\tflags %#x\n", + le32_to_cpu(mst->flags)); + printk(KERN_DEBUG "\tlog_lnum %u\n", + le32_to_cpu(mst->log_lnum)); + printk(KERN_DEBUG "\troot_lnum %u\n", + le32_to_cpu(mst->root_lnum)); + printk(KERN_DEBUG "\troot_offs %u\n", + le32_to_cpu(mst->root_offs)); + printk(KERN_DEBUG "\troot_len %u\n", + le32_to_cpu(mst->root_len)); + printk(KERN_DEBUG "\tgc_lnum %u\n", + le32_to_cpu(mst->gc_lnum)); + printk(KERN_DEBUG "\tihead_lnum %u\n", + le32_to_cpu(mst->ihead_lnum)); + printk(KERN_DEBUG "\tihead_offs %u\n", + le32_to_cpu(mst->ihead_offs)); + printk(KERN_DEBUG "\tindex_size %u\n", + le32_to_cpu(mst->index_size)); + printk(KERN_DEBUG "\tlpt_lnum %u\n", + le32_to_cpu(mst->lpt_lnum)); + printk(KERN_DEBUG "\tlpt_offs %u\n", + le32_to_cpu(mst->lpt_offs)); + printk(KERN_DEBUG "\tnhead_lnum %u\n", + le32_to_cpu(mst->nhead_lnum)); + printk(KERN_DEBUG "\tnhead_offs %u\n", + le32_to_cpu(mst->nhead_offs)); + printk(KERN_DEBUG "\tltab_lnum %u\n", + le32_to_cpu(mst->ltab_lnum)); + printk(KERN_DEBUG "\tltab_offs %u\n", + le32_to_cpu(mst->ltab_offs)); + printk(KERN_DEBUG "\tlsave_lnum %u\n", + le32_to_cpu(mst->lsave_lnum)); + printk(KERN_DEBUG "\tlsave_offs %u\n", + le32_to_cpu(mst->lsave_offs)); + printk(KERN_DEBUG "\tlscan_lnum %u\n", + le32_to_cpu(mst->lscan_lnum)); + printk(KERN_DEBUG "\tleb_cnt %u\n", + le32_to_cpu(mst->leb_cnt)); + printk(KERN_DEBUG "\tempty_lebs %u\n", + le32_to_cpu(mst->empty_lebs)); + printk(KERN_DEBUG "\tidx_lebs %u\n", + le32_to_cpu(mst->idx_lebs)); + printk(KERN_DEBUG "\ttotal_free %llu\n", + le64_to_cpu(mst->total_free)); + printk(KERN_DEBUG "\ttotal_dirty %llu\n", + le64_to_cpu(mst->total_dirty)); + printk(KERN_DEBUG "\ttotal_used %llu\n", + le64_to_cpu(mst->total_used)); + printk(KERN_DEBUG "\ttotal_dead %llu\n", + le64_to_cpu(mst->total_dead)); + printk(KERN_DEBUG "\ttotal_dark %llu\n", + le64_to_cpu(mst->total_dark)); + break; + } + case UBIFS_REF_NODE: + { + const struct ubifs_ref_node *ref = node; + + printk(KERN_DEBUG "\tlnum %u\n", + le32_to_cpu(ref->lnum)); + printk(KERN_DEBUG "\toffs %u\n", + le32_to_cpu(ref->offs)); + printk(KERN_DEBUG "\tjhead %u\n", + le32_to_cpu(ref->jhead)); + break; + } + case UBIFS_INO_NODE: + { + const struct ubifs_ino_node *ino = node; + + key_read(c, &ino->key, &key); + printk(KERN_DEBUG "\tkey %s\n", + dbg_get_key_dump(c, &key)); + printk(KERN_DEBUG "\tsize %llu\n", + le64_to_cpu(ino->size)); + printk(KERN_DEBUG "\tnlink %u\n", + le32_to_cpu(ino->nlink)); + printk(KERN_DEBUG "\tatime %u\n", + le32_to_cpu(ino->atime)); + printk(KERN_DEBUG "\tctime %u\n", + le32_to_cpu(ino->ctime)); + printk(KERN_DEBUG "\tmtime %u\n", + le32_to_cpu(ino->mtime)); + printk(KERN_DEBUG "\tuid %u\n", + le32_to_cpu(ino->uid)); + printk(KERN_DEBUG "\tgid %u\n", + le32_to_cpu(ino->gid)); + printk(KERN_DEBUG "\tmode %u\n", + le32_to_cpu(ino->mode)); + printk(KERN_DEBUG "\tflags %#x\n", + le32_to_cpu(ino->flags)); + printk(KERN_DEBUG "\txattr_cnt %u\n", + le32_to_cpu(ino->xattr_cnt)); + printk(KERN_DEBUG "\txattr_size %llu\n", + le64_to_cpu(ino->xattr_size)); + printk(KERN_DEBUG "\txattr_msize %llu\n", + le64_to_cpu(ino->xattr_msize)); + printk(KERN_DEBUG "\txattr_names %u\n", + le32_to_cpu(ino->xattr_names)); + printk(KERN_DEBUG "\tcompr_type %#x\n", + (int)le16_to_cpu(ino->compr_type)); + printk(KERN_DEBUG "\tdata len %u\n", + le32_to_cpu(ino->data_len)); + break; + } + case UBIFS_DENT_NODE: + case UBIFS_XENT_NODE: + { + const struct ubifs_dent_node *dent = node; + int nlen = le16_to_cpu(dent->nlen); + + key_read(c, &dent->key, &key); + printk(KERN_DEBUG "\tkey %s\n", + dbg_get_key_dump(c, &key)); + printk(KERN_DEBUG "\tinum %llu\n", + le64_to_cpu(dent->inum)); + printk(KERN_DEBUG "\ttype %d\n", (int)dent->type); + printk(KERN_DEBUG "\tnlen %d\n", nlen); + printk(KERN_DEBUG "\tname "); + + if (nlen > UBIFS_MAX_NLEN) { + nlen = UBIFS_MAX_NLEN; + printk(KERN_DEBUG "\tWarning! Node is corrupted\n"); + } + + for (i = 0; i < nlen && dent->name[i]; i++) + printk("%c", dent->name[i]); + printk("\n"); + + break; + } + case UBIFS_DATA_NODE: + { + const struct ubifs_data_node *dn = node; + int dlen = le32_to_cpu(ch->len) - UBIFS_DATA_NODE_SZ; + + key_read(c, &dn->key, &key); + printk(KERN_DEBUG "\tkey %s\n", + dbg_get_key_dump(c, &key)); + printk(KERN_DEBUG "\tsize %u\n", + le32_to_cpu(dn->size)); + printk(KERN_DEBUG "\tcompr_typ %d\n", + (int)le16_to_cpu(dn->compr_type)); + printk(KERN_DEBUG "\tdata size %d\n", + dlen); + printk(KERN_DEBUG "\tdata:\n"); + print_hex_dump(KERN_DEBUG, "\t", DUMP_PREFIX_OFFSET, 32, 1, + (void *)&dn->data, dlen, 0); + break; + } + case UBIFS_TRUN_NODE: + { + const struct ubifs_trun_node *trun = node; + + key_read(c, &trun->key, &key); + printk(KERN_DEBUG "\tkey %s\n", + dbg_get_key_dump(c, &key)); + printk(KERN_DEBUG "\told_size %llu\n", + le64_to_cpu(trun->old_size)); + printk(KERN_DEBUG "\tnew_size %llu\n", + le64_to_cpu(trun->new_size)); + break; + } + case UBIFS_IDX_NODE: + { + const struct ubifs_idx_node *idx = node; + + n = le16_to_cpu(idx->child_cnt); + printk(KERN_DEBUG "\tchild_cnt %d\n", n); + printk(KERN_DEBUG "\tlevel %d\n", + (int)le16_to_cpu(idx->level)); + printk(KERN_DEBUG "Branches:\n"); + + for (i = 0; i < n && i < c->fanout - 1; i++) { + const struct ubifs_branch *br; + + br = ubifs_idx_branch(c, idx, i); + key_read(c, &br->key, &key); + printk(KERN_DEBUG "\t %04d: key %s", + i, dbg_get_key_dump(c, &key)); + printk(KERN_DEBUG "\t lnum %6d, offs %6d, " + "len %6d\n", le32_to_cpu(br->lnum), + le32_to_cpu(br->offs), le32_to_cpu(br->len)); + } + break; + } + case UBIFS_CS_NODE: + break; + case UBIFS_ORPH_NODE: + { + const struct ubifs_orph_node *orph = node; + + printk(KERN_DEBUG "\tcommit number %llu\n", + le64_to_cpu(orph->cmt_no) & LLONG_MAX); + printk(KERN_DEBUG "\tlast node flag %llu\n", + le64_to_cpu(orph->cmt_no) >> 63); + n = (le32_to_cpu(ch->len) - UBIFS_ORPH_NODE_SZ) >> 3; + printk(KERN_DEBUG "\t%d orphan inode numbers:\n", n); + for (i = 0; i < n; i++) + printk(KERN_DEBUG "\t ino %llu\n", + le64_to_cpu(orph->inos[i])); + break; + } + default: + printk(KERN_DEBUG "node type %d was not recognized\n", + (int)ch->node_type); + } + spin_unlock(&dbg_lock); +} + +void dbg_dump_budget_req(const struct ubifs_budget_req *req) +{ + spin_lock(&dbg_lock); + printk(KERN_DEBUG "Budgeting request: new_ino %d, dirtied_ino %d\n", + req->new_ino, req->dirtied_ino); + printk(KERN_DEBUG "\tnew_ino_d %d, dirtied_ino_d %d\n", + req->new_ino_d, req->dirtied_ino_d); + printk(KERN_DEBUG "\tnew_page %d, dirtied_page %d\n", + req->new_page, req->dirtied_page); + printk(KERN_DEBUG "\tnew_dent %d, mod_dent %d\n", + req->new_dent, req->mod_dent); + printk(KERN_DEBUG "\tidx_growth %d\n", req->idx_growth); + printk(KERN_DEBUG "\tdata_growth %d dd_growth %d\n", + req->data_growth, req->dd_growth); + spin_unlock(&dbg_lock); +} + +void dbg_dump_lstats(const struct ubifs_lp_stats *lst) +{ + spin_lock(&dbg_lock); + printk(KERN_DEBUG "Lprops statistics: empty_lebs %d, idx_lebs %d\n", + lst->empty_lebs, lst->idx_lebs); + printk(KERN_DEBUG "\ttaken_empty_lebs %d, total_free %lld, " + "total_dirty %lld\n", lst->taken_empty_lebs, lst->total_free, + lst->total_dirty); + printk(KERN_DEBUG "\ttotal_used %lld, total_dark %lld, " + "total_dead %lld\n", lst->total_used, lst->total_dark, + lst->total_dead); + spin_unlock(&dbg_lock); +} + +void dbg_dump_budg(struct ubifs_info *c) +{ + int i; + struct rb_node *rb; + struct ubifs_bud *bud; + struct ubifs_gced_idx_leb *idx_gc; + + spin_lock(&dbg_lock); + printk(KERN_DEBUG "Budgeting info: budg_data_growth %lld, " + "budg_dd_growth %lld, budg_idx_growth %lld\n", + c->budg_data_growth, c->budg_dd_growth, c->budg_idx_growth); + printk(KERN_DEBUG "\tdata budget sum %lld, total budget sum %lld, " + "freeable_cnt %d\n", c->budg_data_growth + c->budg_dd_growth, + c->budg_data_growth + c->budg_dd_growth + c->budg_idx_growth, + c->freeable_cnt); + printk(KERN_DEBUG "\tmin_idx_lebs %d, old_idx_sz %lld, " + "calc_idx_sz %lld, idx_gc_cnt %d\n", c->min_idx_lebs, + c->old_idx_sz, c->calc_idx_sz, c->idx_gc_cnt); + printk(KERN_DEBUG "\tdirty_pg_cnt %ld, dirty_ino_cnt %ld, " + "dirty_zn_cnt %ld, clean_zn_cnt %ld\n", + atomic_long_read(&c->dirty_pg_cnt), + atomic_long_read(&c->dirty_ino_cnt), + atomic_long_read(&c->dirty_zn_cnt), + atomic_long_read(&c->clean_zn_cnt)); + printk(KERN_DEBUG "\tdark_wm %d, dead_wm %d, max_idx_node_sz %d\n", + c->dark_wm, c->dead_wm, c->max_idx_node_sz); + printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n", + c->gc_lnum, c->ihead_lnum); + for (i = 0; i < c->jhead_cnt; i++) + printk(KERN_DEBUG "\tjhead %d\t LEB %d\n", + c->jheads[i].wbuf.jhead, c->jheads[i].wbuf.lnum); + for (rb = rb_first(&c->buds); rb; rb = rb_next(rb)) { + bud = rb_entry(rb, struct ubifs_bud, rb); + printk(KERN_DEBUG "\tbud LEB %d\n", bud->lnum); + } + list_for_each_entry(bud, &c->old_buds, list) + printk(KERN_DEBUG "\told bud LEB %d\n", bud->lnum); + list_for_each_entry(idx_gc, &c->idx_gc, list) + printk(KERN_DEBUG "\tGC'ed idx LEB %d unmap %d\n", + idx_gc->lnum, idx_gc->unmap); + printk(KERN_DEBUG "\tcommit state %d\n", c->cmt_state); + spin_unlock(&dbg_lock); +} + +void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp) +{ + printk(KERN_DEBUG "LEB %d lprops: free %d, dirty %d (used %d), " + "flags %#x\n", lp->lnum, lp->free, lp->dirty, + c->leb_size - lp->free - lp->dirty, lp->flags); +} + +void dbg_dump_lprops(struct ubifs_info *c) +{ + int lnum, err; + struct ubifs_lprops lp; + struct ubifs_lp_stats lst; + + printk(KERN_DEBUG "Dumping LEB properties\n"); + ubifs_get_lp_stats(c, &lst); + dbg_dump_lstats(&lst); + + 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); + + dbg_dump_lprop(c, &lp); + } +} + +void dbg_dump_leb(const struct ubifs_info *c, int lnum) +{ + struct ubifs_scan_leb *sleb; + struct ubifs_scan_node *snod; + + if (dbg_failure_mode) + return; + + printk(KERN_DEBUG "Dumping LEB %d\n", lnum); + + sleb = ubifs_scan(c, lnum, 0, c->dbg_buf); + if (IS_ERR(sleb)) { + ubifs_err("scan error %d", (int)PTR_ERR(sleb)); + return; + } + + printk(KERN_DEBUG "LEB %d has %d nodes ending at %d\n", lnum, + sleb->nodes_cnt, sleb->endpt); + + list_for_each_entry(snod, &sleb->nodes, list) { + cond_resched(); + printk(KERN_DEBUG "Dumping node at LEB %d:%d len %d\n", lnum, + snod->offs, snod->len); + dbg_dump_node(c, snod->node); + } + + ubifs_scan_destroy(sleb); + return; +} + +void dbg_dump_znode(const struct ubifs_info *c, const struct ubifs_znode *znode) +{ + int n; + + spin_lock(&dbg_lock); + printk(KERN_DEBUG "znode %p, parent %p iip %d level %d child_cnt %d " + "flags %lx\n", znode, znode->parent, znode->iip, znode->level, + znode->child_cnt, znode->flags); + + if (znode->child_cnt <= 0 || znode->child_cnt > c->fanout) { + spin_unlock(&dbg_lock); + return; + } + + printk(KERN_DEBUG "zbranches:\n"); + for (n = 0; n < znode->child_cnt; n++) { + const struct ubifs_zbranch *zbr = &znode->zbranch[n]; + + cond_resched(); + if (znode->level > 0) + printk(KERN_DEBUG "\t%d: znode %p lnum %d offs %d " + "len %d key %s\n", n, zbr->znode, + zbr->lnum, zbr->offs, zbr->len, + dbg_get_key_dump(c, &zbr->key)); + else + printk(KERN_DEBUG "\t%d: LNC %p lnum %d offs %d " + "len %d key %s\n", n, zbr->znode, + zbr->lnum, zbr->offs, zbr->len, + dbg_get_key_dump(c, &zbr->key)); + } + spin_unlock(&dbg_lock); +} + +void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat) +{ + int i; + + printk(KERN_DEBUG "Dumping heap cat %d (%d elements)\n", + cat, heap->cnt); + for (i = 0; i < heap->cnt; i++) { + struct ubifs_lprops *lprops = heap->arr[i]; + + printk(KERN_DEBUG "\t%d. LEB %d hpos %d free %d dirty %d " + "flags %d\n", i, lprops->lnum, lprops->hpos, + lprops->free, lprops->dirty, lprops->flags); + } +} + +void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, + struct ubifs_nnode *parent, int iip) +{ + int i; + + printk(KERN_DEBUG "Dumping pnode:\n"); + printk(KERN_DEBUG "\taddress %zx parent %zx cnext %zx\n", + (size_t)pnode, (size_t)parent, (size_t)pnode->cnext); + printk(KERN_DEBUG "\tflags %lu iip %d level %d num %d\n", + pnode->flags, iip, pnode->level, pnode->num); + for (i = 0; i < UBIFS_LPT_FANOUT; i++) { + struct ubifs_lprops *lp = &pnode->lprops[i]; + + printk(KERN_DEBUG "\t%d: free %d dirty %d flags %d lnum %d\n", + i, lp->free, lp->dirty, lp->flags, lp->lnum); + } +} + +#ifdef CONFIG_UBIFS_FS_DEBUG_CHK_OTHER + +/* + * dbg_check_dir - check directory inode size. + * @c: UBIFS file-system description object + * @dir: the directory to calculate size for + * @size: the result is returned here + * + * This function makes sure that directory size is correct. Returns zero + * in case of success and a negative error code in case of failure. + * + * Note, it is good idea to make sure the @dir->i_mutex is locked before + * calling this function. + */ +int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir) +{ + union ubifs_key key; + struct ubifs_dent_node *dent, *pdent = NULL; + struct qstr nm = { .name = NULL }; + loff_t size = 0; + + if (!S_ISDIR(dir->i_mode)) + return 0; + + lowest_dent_key(c, &key, dir->i_ino); + while (1) { + int err; + + dent = ubifs_tnc_next_ent(c, &key, &nm); + if (IS_ERR(dent)) { + err = PTR_ERR(dent); + if (err == -ENOENT) + break; + return err; + } + + size += CALC_DENT_SIZE(dent->nlen); + nm.name = dent->name; + nm.len = le16_to_cpu(dent->nlen); + dbg_kfree(pdent); /* kfree via debug function */ + pdent = dent; + key_read(c, &dent->key, &key); + } + + dbg_kfree(pdent); /* kfree via debug function */ + + if (i_size_read(dir) != size) { + ubifs_err("bad directory dir %lu size %llu, " + "calculated %llu", dir->i_ino, + i_size_read(dir), size); + dump_stack(); + return -EINVAL; + } + + return 0; +} + +#endif /* CONFIG_UBIFS_FS_DEBUG_CHK_OTHER */ + +void *dbg_kmalloc(size_t size, gfp_t flags) +{ + void *addr; + + addr = kmalloc(size, flags); + if (addr != NULL) { + spin_lock(&dbg_lock); + km_alloc_cnt += 1; + spin_unlock(&dbg_lock); + } + return addr; +} + +void *dbg_kzalloc(size_t size, gfp_t flags) +{ + void *addr; + + addr = kzalloc(size, flags); + if (addr != NULL) { + spin_lock(&dbg_lock); + km_alloc_cnt += 1; + spin_unlock(&dbg_lock); + } + return addr; +} + +void dbg_kfree(const void *addr) +{ + if (addr != NULL) { + spin_lock(&dbg_lock); + km_alloc_cnt -= 1; + spin_unlock(&dbg_lock); + kfree(addr); + } +} + +void *dbg_vmalloc(size_t size) +{ + void *addr; + + addr = vmalloc(size); + if (addr != NULL) { + spin_lock(&dbg_lock); + vm_alloc_cnt += 1; + spin_unlock(&dbg_lock); + } + return addr; +} + +void dbg_vfree(void *addr) +{ + if (addr != NULL) { + spin_lock(&dbg_lock); + vm_alloc_cnt -= 1; + spin_unlock(&dbg_lock); + vfree(addr); + } +} + +void dbg_leak_report(void) +{ + spin_lock(&dbg_lock); + if (km_alloc_cnt || vm_alloc_cnt) { + ubifs_err("kmalloc: leak count %zd", km_alloc_cnt); + ubifs_err("vmalloc: leak count %zd", vm_alloc_cnt); + } + spin_unlock(&dbg_lock); +} + +#ifdef CONFIG_UBIFS_FS_DEBUG_CHK_MEMPRESS + +/* + * The below debugging stuff helps to make fake Linux memory pressure in order + * to make UBIFS shrinker be invoked. Useful for testing. + */ + +/* + * struct eaten_memory - memory object eaten by UBIFS to cause memory pressure. + * @list: link in the list of eaten memory objects + * @pad: just pads to memory page size + */ +struct eaten_memory { + struct list_head list; + uint8_t pad[PAGE_CACHE_SIZE - sizeof(struct list_head)]; +}; + +/* List of eaten memory pages */ +static LIST_HEAD(eaten_list); +/* Count of allocated 'struct eaten_memory' objects */ +static unsigned long eaten_cnt; +/* Protects 'eaten_list' and 'eaten_cnt' */ +static DEFINE_SPINLOCK(eaten_lock); + +void dbg_eat_memory(void) +{ + struct eaten_memory *em; + + em = kmalloc(sizeof(struct eaten_memory), GFP_NOFS); + if (!em) { + ubifs_err("cannot allocate eaten memory structure"); + return; + } + + spin_lock(&eaten_lock); + list_add_tail(&em->list, &eaten_list); + eaten_cnt += 1; + spin_unlock(&eaten_lock); +} + +static int return_eaten_memory(int nr) +{ + int free_all = 0, freed = 0; + struct eaten_memory *em; + + if (nr == 0) + return eaten_cnt; + + if (nr == -1) + free_all = 1; + + while (nr > 0 || free_all) { + spin_lock(&eaten_lock); + if (eaten_cnt == 0) { + spin_unlock(&eaten_lock); + break; + } + + em = list_entry(eaten_list.next, struct eaten_memory, list); + list_del(&em->list); + eaten_cnt -= 1; + spin_unlock(&eaten_lock); + + kfree(em); + nr -= 1; + freed += 1; + } + + return freed; +} + +static int dbg_shrinker(int nr, gfp_t gfp_mask) +{ + return return_eaten_memory(nr); +} + +static struct shrinker dbg_shrinker_info = { + .shrink = dbg_shrinker, + .seeks = DEFAULT_SEEKS, +}; + +void __init dbg_mempressure_init(void) +{ + register_shrinker(&dbg_shrinker_info); +} + +void dbg_mempressure_exit(void) +{ + unregister_shrinker(&dbg_shrinker_info); + return_eaten_memory(-1); +} + +#endif /* CONFIG_UBIFS_FS_DEBUG_CHK_MEMPRESS */ + +#ifdef CONFIG_UBIFS_FS_DEBUG_TEST_RCVRY + +#define chance(n, d) (simple_rand() <= (n) * 32768LL / (d)) + +struct failure_mode_info { + struct list_head list; + struct ubifs_info *c; +}; + +static LIST_HEAD(fmi_list); +static DEFINE_SPINLOCK(fmi_lock); + +static unsigned int next; + +static int simple_rand(void) +{ + if (next == 0) + next = current->pid; + next = next * 1103515245 + 12345; + return (next >> 16) & 32767; +} + +void dbg_failure_mode_registration(struct ubifs_info *c) +{ + struct failure_mode_info *fmi; + + fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS); + if (!fmi) { + dbg_err("Failed to register failure mode - no memory"); + return; + } + fmi->c = c; + spin_lock(&fmi_lock); + list_add_tail(&fmi->list, &fmi_list); + spin_unlock(&fmi_lock); +} + +void dbg_failure_mode_deregistration(struct ubifs_info *c) +{ + struct failure_mode_info *fmi, *tmp; + + spin_lock(&fmi_lock); + list_for_each_entry_safe(fmi, tmp, &fmi_list, list) + if (fmi->c == c) { + list_del(&fmi->list); + kfree(fmi); + } + spin_unlock(&fmi_lock); +} + +static struct ubifs_info *dbg_find_info(struct ubi_volume_desc *desc) +{ + struct failure_mode_info *fmi; + + spin_lock(&fmi_lock); + list_for_each_entry(fmi, &fmi_list, list) + if (fmi->c->ubi == desc) { + struct ubifs_info *c = fmi->c; + + spin_unlock(&fmi_lock); + return c; + } + spin_unlock(&fmi_lock); + return NULL; +} + +static int in_failure_mode(struct ubi_volume_desc *desc) +{ + struct ubifs_info *c = dbg_find_info(desc); + + if (c) + return c->failure_mode; + return 0; +} + +static int do_fail(struct ubi_volume_desc *desc, int lnum, int write) +{ + struct ubifs_info *c = dbg_find_info(desc); + + if (!c) + return 0; + if (c->failure_mode) + return 1; + if (lnum == UBIFS_SB_LNUM) + return 0; + else if (lnum == UBIFS_MST_LNUM || lnum == UBIFS_MST_LNUM + 1) { + if (chance(19, 20)) + return 0; + dbg_mnt("failing in master LEB %d", lnum); + } else if (lnum >= UBIFS_LOG_LNUM && lnum <= c->log_last) { + if (write && chance(99, 100)) + return 0; + else if (chance(399, 400)) + return 0; + dbg_mnt("failing in log LEB %d", lnum); + } else if (lnum >= c->lpt_first && lnum <= c->lpt_last) { + if (write && chance(99, 100)) + return 0; + else if (chance(399, 400)) + return 0; + dbg_mnt("failing in LPT LEB %d", lnum); + } else if (lnum >= c->orph_first && lnum <= c->orph_last) { + if (write && chance(9, 10)) + return 0; + else if (chance(39, 40)) + return 0; + dbg_mnt("failing in orphan LEB %d", lnum); + } else if (lnum == c->ihead_lnum) { + if (chance(99, 100)) + return 0; + dbg_mnt("failing in index head LEB %d", lnum); + } else if (write && !RB_EMPTY_ROOT(&c->buds) && + ubifs_search_bud(c, lnum) == NULL) { + if (chance(19, 20)) + return 0; + dbg_mnt("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; + dbg_mnt("failing in bud LEB %d commit running", lnum); + } else { + if (chance(9999, 10000)) + return 0; + dbg_mnt("failing in bud LEB %d commit not running", lnum); + } + ubifs_err("*** SETTING FAILURE MODE ON ***"); + c->failure_mode = 1; + dump_stack(); + return 1; +} + +static void cut_data(const void *buf, int len) +{ + int flen, i; + unsigned char *p = (void *)buf; + + flen = (len * (long long)simple_rand()) >> 15; + for (i = flen; i < len; i++) + p[i] = 0xff; +} + +int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, + int len, int check) +{ + if (in_failure_mode(desc)) + return -EIO; + return ubi_leb_read(desc, lnum, buf, offset, len, check); +} + +int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, + int offset, int len, int dtype) +{ + int err; + + if (in_failure_mode(desc)) + return -EIO; + if (do_fail(desc, lnum, 1)) + cut_data(buf, len); + err = ubi_leb_write(desc, lnum, buf, offset, len, dtype); + if (err) + return err; + if (in_failure_mode(desc)) + return -EIO; + return 0; +} + +int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, + int len, int dtype) +{ + int err; + + if (do_fail(desc, lnum, 1)) + return -EIO; + err = ubi_leb_change(desc, lnum, buf, len, dtype); + if (err) + return err; + if (do_fail(desc, lnum, 1)) + return -EIO; + return 0; +} + +int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum) +{ + int err; + + if (do_fail(desc, lnum, 0)) + return -EIO; + err = ubi_leb_erase(desc, lnum); + if (err) + return err; + if (do_fail(desc, lnum, 0)) + return -EIO; + return 0; +} + +int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum) +{ + int err; + + if (do_fail(desc, lnum, 0)) + return -EIO; + err = ubi_leb_unmap(desc, lnum); + if (err) + return err; + if (do_fail(desc, lnum, 0)) + return -EIO; + return 0; +} + +int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum) +{ + if (in_failure_mode(desc)) + return -EIO; + return ubi_is_mapped(desc, lnum); +} + +#endif /* CONFIG_UBIFS_FS_DEBUG_TEST_RCVRY */ +#endif /* CONFIG_UBIFS_FS_DEBUG */ diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h new file mode 100644 index 0000000..7746ad6 --- /dev/null +++ b/fs/ubifs/debug.h @@ -0,0 +1,343 @@ +/* + * This file is part of UBIFS. + * + * Copyright (C) 2006-2008 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * 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. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Artem Bityutskiy (Битюцкий Артём) + * Adrian Hunter + */ + +#ifndef __UBIFS_DEBUG_H__ +#define __UBIFS_DEBUG_H__ + +#ifdef CONFIG_UBIFS_FS_DEBUG +#define UBIFS_DBG(op) op +#define ubifs_assert(expr) do { \ + if (unlikely(!(expr))) { \ + printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \ + __func__, __LINE__, current->pid); \ + dump_stack(); \ + } \ +} while (0) + +/* Generic debugging message */ +#define dbg_msg(fmt, ...) do { \ + printk(KERN_DEBUG "UBIFS DBG (pid %d): %s: " fmt "\n", current->pid, \ + __func__, ##__VA_ARGS__); \ +} while (0) + +/* Debugging message which prints UBIFS key */ +#define dbg_key(c, key, fmt, ...) do { \ + spin_lock(&dbg_lock); \ + printk(KERN_DEBUG "UBIFS DBG (pid %d): %s: " fmt " %s\n", \ + current->pid, __func__, ##__VA_ARGS__, \ + dbg_get_key_dump(c, key)); \ + spin_unlock(&dbg_lock); \ +} while (0) + +#define dbg_err(fmt, ...) ubifs_err(fmt, ##__VA_ARGS__) +#define dbg_dump_stack() dump_stack() + +#define ubifs_assert_cmt_locked(c) do { \ + if (unlikely(down_write_trylock(&(c)->commit_sem))) { \ + up_write(&(c)->commit_sem); \ + printk(KERN_CRIT "commit lock is not locked!\n"); \ + ubifs_assert(0); \ + } \ +} while (0) + +#ifndef UBIFS_DBG_PRESERVE_KMALLOC +#define kmalloc dbg_kmalloc +#define kzalloc dbg_kzalloc +#define kfree dbg_kfree +#define vmalloc dbg_vmalloc +#define vfree dbg_vfree +#endif + +#else + +#define UBIFS_DBG(op) +#define ubifs_assert(expr) ({}) +#define dbg_msg(fmt, ...) ({}) +#define dbg_key(c, key, fmt, ...) ({}) +#define dbg_err(fmt, ...) ({}) +#define dbg_dump_stack() +#define ubifs_assert_cmt_locked(c) + +#endif /* !CONFIG_UBIFS_FS_DEBUG */ + +#ifdef CONFIG_UBIFS_FS_DEBUG + +extern spinlock_t dbg_lock; +const char *dbg_ntype(int type); +const char *dbg_cstate(int cmt_state); +const char *dbg_get_key_dump(const struct ubifs_info *c, + const union ubifs_key *key); +void dbg_dump_node(const struct ubifs_info *c, const void *node); +void dbg_dump_budget_req(const struct ubifs_budget_req *req); +void dbg_dump_lstats(const struct ubifs_lp_stats *lst); +void dbg_dump_budg(struct ubifs_info *c); +void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp); +void dbg_dump_lprops(struct ubifs_info *c); +void dbg_dump_leb(const struct ubifs_info *c, int lnum); +void dbg_dump_znode(const struct ubifs_info *c, + const struct ubifs_znode *znode); +void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat); +void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, + struct ubifs_nnode *parent, int iip); + +void *dbg_kmalloc(size_t size, gfp_t flags); +void *dbg_kzalloc(size_t size, gfp_t flags); +void dbg_kfree(const void *addr); +void *dbg_vmalloc(size_t size); +void dbg_vfree(void *addr); +void dbg_leak_report(void); + +typedef int (*dbg_leaf_callback)(struct ubifs_info *c, + struct ubifs_zbranch *zbr, void *priv); +typedef int (*dbg_znode_callback)(struct ubifs_info *c, + struct ubifs_znode *znode, void *priv); + +int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb, + dbg_znode_callback znode_cb, void *priv); +int dbg_read_leaf_nolock(struct ubifs_info *c, struct ubifs_zbranch *zbr, + void *node); +#else + +#define dbg_ntype(type) "" +#define dbg_cstate(cmt_state) "" +#define dbg_get_key_dump(c, key) ({}) +#define dbg_dump_node(c, node) ({}) +#define dbg_dump_budget_req(req) ({}) +#define dbg_dump_lstats(lst) ({}) +#define dbg_dump_budg(c) ({}) +#define dbg_dump_lprop(c, lp) ({}) +#define dbg_dump_lprops(c) ({}) +#define dbg_dump_leb(c, lnum) ({}) +#define dbg_dump_znode(c, znode) ({}) +#define dbg_dump_heap(c, heap, cat) ({}) +#define dbg_dump_pnode(c, pnode, parent, iip) ({}) + +#define dbg_leak_report() ({}) +#define dbg_walk_index(c, leaf_cb, znode_cb, priv) 0 +#define dbg_read_leaf_nolock(c, zbr, node) 0 + +#endif /* !CONFIG_UBIFS_FS_DEBUG */ + +#ifdef CONFIG_UBIFS_FS_DEBUG_CHK_MEMPRESS +void dbg_eat_memory(void); +void __init dbg_mempressure_init(void); +void dbg_mempressure_exit(void); +#else +#define dbg_eat_memory() ({}) +#define dbg_mempressure_init() ({}) +#define dbg_mempressure_exit() ({}) +#endif + +#ifdef CONFIG_UBIFS_FS_DEBUG_CHK_LPROPS +int dbg_check_lprops(struct ubifs_info *c); +#else +#define dbg_check_lprops(c) 0 +#endif + +#ifdef CONFIG_UBIFS_FS_DEBUG_CHK_OLD_IDX +int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot); +int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot); +#else +#define dbg_old_index_check_init(c, zroot) 0 +#define dbg_check_old_index(c, zroot) 0 +#endif + +#if defined(CONFIG_UBIFS_FS_DEBUG_CHK_LPROPS) || \ + defined(CONFIG_UBIFS_FS_DEBUG_CHK_OTHER) +int dbg_check_cats(struct ubifs_info *c); +#else +#define dbg_check_cats(c) 0 +#endif + +/* General messages */ +#ifdef CONFIG_UBIFS_FS_DEBUG_MSG_GEN +#define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_gen_key(c, key, fmt, ...) dbg_key(c, key, fmt, ##__VA_ARGS__) +#else +#define dbg_gen(fmt, ...) ({}) +#define dbg_gen_key(c, key, fmt, ...) ({}) +#endif + +/* Additional journal messages */ +#ifdef CONFIG_UBIFS_FS_DEBUG_MSG_JRN +#define dbg_jrn(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_jrn_key(c, key, fmt, ...) dbg_key(c, key, fmt, ##__VA_ARGS__) +#else +#define dbg_jrn(fmt, ...) ({}) +#define dbg_jrn_key(c, key, fmt, ...) ({}) +#endif + +/* Additional TNC messages */ +#ifdef CONFIG_UBIFS_FS_DEBUG_MSG_TNC +#define dbg_tnc(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_tnc_key(c, key, fmt, ...) dbg_key(c, key, fmt, ##__VA_ARGS__) +#else +#define dbg_tnc(fmt, ...) ({}) +#define dbg_tnc_key(c, key, fmt, ...) ({}) +#endif + +/* Additional lprops messages */ +#ifdef CONFIG_UBIFS_FS_DEBUG_MSG_LP +#define dbg_lp(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#else +#define dbg_lp(fmt, ...) ({}) +#endif + +/* Additional LEB find messages */ +#ifdef CONFIG_UBIFS_FS_DEBUG_MSG_FIND +#define dbg_find(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#else +#define dbg_find(fmt, ...) ({}) +#endif + +/* Additional mount messages */ +#ifdef CONFIG_UBIFS_FS_DEBUG_MSG_MNT +#define dbg_mnt(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_mnt_key(c, key, fmt, ...) dbg_key(c, key, fmt, ##__VA_ARGS__) +#else +#define dbg_mnt(fmt, ...) ({}) +#define dbg_mnt_key(c, key, fmt, ...) ({}) +#endif + +/* Additional I/O messages */ +#ifdef CONFIG_UBIFS_FS_DEBUG_MSG_IO +#define dbg_io(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#else +#define dbg_io(fmt, ...) ({}) +#endif + +/* Additional commit messages */ +#ifdef CONFIG_UBIFS_FS_DEBUG_MSG_CMT +#define dbg_cmt(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#else +#define dbg_cmt(fmt, ...) ({}) +#endif + +/* Additional budgeting messages */ +#ifdef CONFIG_UBIFS_FS_DEBUG_MSG_BUDG +#define dbg_budg(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#else +#define dbg_budg(fmt, ...) ({}) +#endif + +/* Additional log messages */ +#ifdef CONFIG_UBIFS_FS_DEBUG_MSG_LOG +#define dbg_log(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#else +#define dbg_log(fmt, ...) ({}) +#endif + +/* Additional gc messages */ +#ifdef CONFIG_UBIFS_FS_DEBUG_MSG_GC +#define dbg_gc(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_gc_key(c, key, fmt, ...) dbg_key(c, key, fmt, ##__VA_ARGS__) +#else +#define dbg_gc(fmt, ...) ({}) +#define dbg_gc_key(c, key, fmt, ...) ({}) +#endif + +/* Additional scan messages */ +#ifdef CONFIG_UBIFS_FS_DEBUG_MSG_SCAN +#define dbg_scan(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#else +#define dbg_scan(fmt, ...) ({}) +#endif + +#ifdef CONFIG_UBIFS_FS_DEBUG_CHK_OTHER +int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir); +#else +#define dbg_check_dir_size(c, dir) 0 +#endif + +#ifdef CONFIG_UBIFS_FS_DEBUG_CHK_TNC +int dbg_check_tnc(struct ubifs_info *c, int extra); +#else +#define dbg_check_tnc(c, x) 0 +#endif + +#ifdef CONFIG_UBIFS_FS_DEBUG_CHK_IDX_SZ +int dbg_check_idx_size(struct ubifs_info *c, long long idx_size); +#else +#define dbg_check_idx_size(c, idx_size) 0 +#endif + +#ifdef CONFIG_UBIFS_FS_DEBUG_CHK_LPROPS +int dbg_check_lprops(struct ubifs_info *c); +int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode, + int row, int col); +#else +#define dbg_check_lprops(c) 0 +#define dbg_check_lpt_nodes(c, cnode, row, col) 0 +#endif + +#ifdef CONFIG_UBIFS_FS_DEBUG_TEST_RCVRY + +void dbg_failure_mode_registration(struct ubifs_info *c); +void dbg_failure_mode_deregistration(struct ubifs_info *c); + +#undef dbg_dump_stack +#define dbg_dump_stack() +#define dbg_failure_mode 1 + +#ifndef UBIFS_DBG_PRESERVE_UBI +#define ubi_leb_read dbg_leb_read +#define ubi_leb_write dbg_leb_write +#define ubi_leb_change dbg_leb_change +#define ubi_leb_erase dbg_leb_erase +#define ubi_leb_unmap dbg_leb_unmap +#define ubi_is_mapped dbg_is_mapped + +int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, + int len, int check); +int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, + int offset, int len, int dtype); +int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, + int len, int dtype); +int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum); +int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum); +int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum); +static inline int dbg_read(struct ubi_volume_desc *desc, int lnum, char *buf, + int offset, int len) +{ + return dbg_leb_read(desc, lnum, buf, offset, len, 0); +} +static inline int dbg_write(struct ubi_volume_desc *desc, int lnum, + const void *buf, int offset, int len) +{ + return dbg_leb_write(desc, lnum, buf, offset, len, UBI_UNKNOWN); +} +static inline int dbg_change(struct ubi_volume_desc *desc, int lnum, + const void *buf, int len) +{ + return dbg_leb_change(desc, lnum, buf, len, UBI_UNKNOWN); +} +#endif /* !UBIFS_DBG_PRESERVE_UBI */ + +#else + +#define dbg_failure_mode_registration(c) ({}) +#define dbg_failure_mode_deregistration(c) ({}) +#define dbg_failure_mode 0 + +#endif /* !CONFIG_UBIFS_FS_DEBUG_TEST_RCVRY */ + +#endif /* !__UBIFS_DEBUG_H__ */ -- 1.5.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/