3197 lines · 85.7 KB · C
RawDownload
/* * 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. */ #include <linux/module.h>#include <linux/debugfs.h>#include <linux/math64.h>#include <linux/uaccess.h>#include <linux/random.h>#include "ubifs.h" static DEFINE_SPINLOCK(dbg_lock); 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";	}} static const char *get_dent_type(int type){	switch (type) {	case UBIFS_ITYPE_REG:		return "file";	case UBIFS_ITYPE_DIR:		return "dir";	case UBIFS_ITYPE_LNK:		return "symlink";	case UBIFS_ITYPE_BLK:		return "blkdev";	case UBIFS_ITYPE_CHR:		return "char dev";	case UBIFS_ITYPE_FIFO:		return "fifo";	case UBIFS_ITYPE_SOCK:		return "socket";	default:		return "unknown/invalid type";	}} const char *dbg_snprintf_key(const struct ubifs_info *c,			     const union ubifs_key *key, char *buffer, int len){	char *p = buffer;	int type = key_type(c, key); 	if (c->key_fmt == UBIFS_SIMPLE_KEY_FMT) {		switch (type) {		case UBIFS_INO_KEY:			len -= snprintf(p, len, "(%lu, %s)",					(unsigned long)key_inum(c, key),					get_key_type(type));			break;		case UBIFS_DENT_KEY:		case UBIFS_XENT_KEY:			len -= snprintf(p, len, "(%lu, %s, %#08x)",					(unsigned long)key_inum(c, key),					get_key_type(type), key_hash(c, key));			break;		case UBIFS_DATA_KEY:			len -= snprintf(p, len, "(%lu, %s, %u)",					(unsigned long)key_inum(c, key),					get_key_type(type), key_block(c, key));			break;		case UBIFS_TRUN_KEY:			len -= snprintf(p, len, "(%lu, %s)",					(unsigned long)key_inum(c, key),					get_key_type(type));			break;		default:			len -= snprintf(p, len, "(bad key type: %#08x, %#08x)",					key->u32[0], key->u32[1]);		}	} else		len -= snprintf(p, len, "bad key format %d", c->key_fmt);	ubifs_assert(len > 0);	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";	}} const char *dbg_jhead(int jhead){	switch (jhead) {	case GCHD:		return "0 (GC)";	case BASEHD:		return "1 (base)";	case DATAHD:		return "2 (data)";	default:		return "unknown journal head";	}} static void dump_ch(const struct ubifs_ch *ch){	printk(KERN_ERR "\tmagic          %#x\n", le32_to_cpu(ch->magic));	printk(KERN_ERR "\tcrc            %#x\n", le32_to_cpu(ch->crc));	printk(KERN_ERR "\tnode_type      %d (%s)\n", ch->node_type,	       dbg_ntype(ch->node_type));	printk(KERN_ERR "\tgroup_type     %d (%s)\n", ch->group_type,	       dbg_gtype(ch->group_type));	printk(KERN_ERR "\tsqnum          %llu\n",	       (unsigned long long)le64_to_cpu(ch->sqnum));	printk(KERN_ERR "\tlen            %u\n", le32_to_cpu(ch->len));} void ubifs_dump_inode(struct ubifs_info *c, const struct inode *inode){	const struct ubifs_inode *ui = ubifs_inode(inode);	struct qstr nm = { .name = NULL };	union ubifs_key key;	struct ubifs_dent_node *dent, *pdent = NULL;	int count = 2; 	printk(KERN_ERR "Dump in-memory inode:");	printk(KERN_ERR "\tinode          %lu\n", inode->i_ino);	printk(KERN_ERR "\tsize           %llu\n",	       (unsigned long long)i_size_read(inode));	printk(KERN_ERR "\tnlink          %u\n", inode->i_nlink);	printk(KERN_ERR "\tuid            %u\n", (unsigned int)inode->i_uid);	printk(KERN_ERR "\tgid            %u\n", (unsigned int)inode->i_gid);	printk(KERN_ERR "\tatime          %u.%u\n",	       (unsigned int)inode->i_atime.tv_sec,	       (unsigned int)inode->i_atime.tv_nsec);	printk(KERN_ERR "\tmtime          %u.%u\n",	       (unsigned int)inode->i_mtime.tv_sec,	       (unsigned int)inode->i_mtime.tv_nsec);	printk(KERN_ERR "\tctime          %u.%u\n",	       (unsigned int)inode->i_ctime.tv_sec,	       (unsigned int)inode->i_ctime.tv_nsec);	printk(KERN_ERR "\tcreat_sqnum    %llu\n", ui->creat_sqnum);	printk(KERN_ERR "\txattr_size     %u\n", ui->xattr_size);	printk(KERN_ERR "\txattr_cnt      %u\n", ui->xattr_cnt);	printk(KERN_ERR "\txattr_names    %u\n", ui->xattr_names);	printk(KERN_ERR "\tdirty          %u\n", ui->dirty);	printk(KERN_ERR "\txattr          %u\n", ui->xattr);	printk(KERN_ERR "\tbulk_read      %u\n", ui->xattr);	printk(KERN_ERR "\tsynced_i_size  %llu\n",	       (unsigned long long)ui->synced_i_size);	printk(KERN_ERR "\tui_size        %llu\n",	       (unsigned long long)ui->ui_size);	printk(KERN_ERR "\tflags          %d\n", ui->flags);	printk(KERN_ERR "\tcompr_type     %d\n", ui->compr_type);	printk(KERN_ERR "\tlast_page_read %lu\n", ui->last_page_read);	printk(KERN_ERR "\tread_in_a_row  %lu\n", ui->read_in_a_row);	printk(KERN_ERR "\tdata_len       %d\n", ui->data_len); 	if (!S_ISDIR(inode->i_mode))		return; 	printk(KERN_ERR "List of directory entries:\n");	ubifs_assert(!mutex_is_locked(&c->tnc_mutex)); 	lowest_dent_key(c, &key, inode->i_ino);	while (1) {		dent = ubifs_tnc_next_ent(c, &key, &nm);		if (IS_ERR(dent)) {			if (PTR_ERR(dent) != -ENOENT)				printk(KERN_ERR "error %ld\n", PTR_ERR(dent));			break;		} 		printk(KERN_ERR "\t%d: %s (%s)\n",		       count++, dent->name, get_dent_type(dent->type)); 		nm.name = dent->name;		nm.len = le16_to_cpu(dent->nlen);		kfree(pdent);		pdent = dent;		key_read(c, &dent->key, &key);	}	kfree(pdent);} void ubifs_dump_node(const struct ubifs_info *c, const void *node){	int i, n;	union ubifs_key key;	const struct ubifs_ch *ch = node;	char key_buf[DBG_KEY_BUF_LEN]; 	if (dbg_is_tst_rcvry(c))		return; 	/* If the magic is incorrect, just hexdump the first bytes */	if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC) {		printk(KERN_ERR "Not a node, first %zu bytes:", UBIFS_CH_SZ);		print_hex_dump(KERN_ERR, "", 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_ERR "\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_ERR "\tkey_hash       %d (%s)\n",		       (int)sup->key_hash, get_key_hash(sup->key_hash));		printk(KERN_ERR "\tkey_fmt        %d (%s)\n",		       (int)sup->key_fmt, get_key_fmt(sup->key_fmt));		printk(KERN_ERR "\tflags          %#x\n", sup_flags);		printk(KERN_ERR "\t  big_lpt      %u\n",		       !!(sup_flags & UBIFS_FLG_BIGLPT));		printk(KERN_ERR "\t  space_fixup  %u\n",		       !!(sup_flags & UBIFS_FLG_SPACE_FIXUP));		printk(KERN_ERR "\tmin_io_size    %u\n",		       le32_to_cpu(sup->min_io_size));		printk(KERN_ERR "\tleb_size       %u\n",		       le32_to_cpu(sup->leb_size));		printk(KERN_ERR "\tleb_cnt        %u\n",		       le32_to_cpu(sup->leb_cnt));		printk(KERN_ERR "\tmax_leb_cnt    %u\n",		       le32_to_cpu(sup->max_leb_cnt));		printk(KERN_ERR "\tmax_bud_bytes  %llu\n",		       (unsigned long long)le64_to_cpu(sup->max_bud_bytes));		printk(KERN_ERR "\tlog_lebs       %u\n",		       le32_to_cpu(sup->log_lebs));		printk(KERN_ERR "\tlpt_lebs       %u\n",		       le32_to_cpu(sup->lpt_lebs));		printk(KERN_ERR "\torph_lebs      %u\n",		       le32_to_cpu(sup->orph_lebs));		printk(KERN_ERR "\tjhead_cnt      %u\n",		       le32_to_cpu(sup->jhead_cnt));		printk(KERN_ERR "\tfanout         %u\n",		       le32_to_cpu(sup->fanout));		printk(KERN_ERR "\tlsave_cnt      %u\n",		       le32_to_cpu(sup->lsave_cnt));		printk(KERN_ERR "\tdefault_compr  %u\n",		       (int)le16_to_cpu(sup->default_compr));		printk(KERN_ERR "\trp_size        %llu\n",		       (unsigned long long)le64_to_cpu(sup->rp_size));		printk(KERN_ERR "\trp_uid         %u\n",		       le32_to_cpu(sup->rp_uid));		printk(KERN_ERR "\trp_gid         %u\n",		       le32_to_cpu(sup->rp_gid));		printk(KERN_ERR "\tfmt_version    %u\n",		       le32_to_cpu(sup->fmt_version));		printk(KERN_ERR "\ttime_gran      %u\n",		       le32_to_cpu(sup->time_gran));		printk(KERN_ERR "\tUUID           %pUB\n",		       sup->uuid);		break;	}	case UBIFS_MST_NODE:	{		const struct ubifs_mst_node *mst = node; 		printk(KERN_ERR "\thighest_inum   %llu\n",		       (unsigned long long)le64_to_cpu(mst->highest_inum));		printk(KERN_ERR "\tcommit number  %llu\n",		       (unsigned long long)le64_to_cpu(mst->cmt_no));		printk(KERN_ERR "\tflags          %#x\n",		       le32_to_cpu(mst->flags));		printk(KERN_ERR "\tlog_lnum       %u\n",		       le32_to_cpu(mst->log_lnum));		printk(KERN_ERR "\troot_lnum      %u\n",		       le32_to_cpu(mst->root_lnum));		printk(KERN_ERR "\troot_offs      %u\n",		       le32_to_cpu(mst->root_offs));		printk(KERN_ERR "\troot_len       %u\n",		       le32_to_cpu(mst->root_len));		printk(KERN_ERR "\tgc_lnum        %u\n",		       le32_to_cpu(mst->gc_lnum));		printk(KERN_ERR "\tihead_lnum     %u\n",		       le32_to_cpu(mst->ihead_lnum));		printk(KERN_ERR "\tihead_offs     %u\n",		       le32_to_cpu(mst->ihead_offs));		printk(KERN_ERR "\tindex_size     %llu\n",		       (unsigned long long)le64_to_cpu(mst->index_size));		printk(KERN_ERR "\tlpt_lnum       %u\n",		       le32_to_cpu(mst->lpt_lnum));		printk(KERN_ERR "\tlpt_offs       %u\n",		       le32_to_cpu(mst->lpt_offs));		printk(KERN_ERR "\tnhead_lnum     %u\n",		       le32_to_cpu(mst->nhead_lnum));		printk(KERN_ERR "\tnhead_offs     %u\n",		       le32_to_cpu(mst->nhead_offs));		printk(KERN_ERR "\tltab_lnum      %u\n",		       le32_to_cpu(mst->ltab_lnum));		printk(KERN_ERR "\tltab_offs      %u\n",		       le32_to_cpu(mst->ltab_offs));		printk(KERN_ERR "\tlsave_lnum     %u\n",		       le32_to_cpu(mst->lsave_lnum));		printk(KERN_ERR "\tlsave_offs     %u\n",		       le32_to_cpu(mst->lsave_offs));		printk(KERN_ERR "\tlscan_lnum     %u\n",		       le32_to_cpu(mst->lscan_lnum));		printk(KERN_ERR "\tleb_cnt        %u\n",		       le32_to_cpu(mst->leb_cnt));		printk(KERN_ERR "\tempty_lebs     %u\n",		       le32_to_cpu(mst->empty_lebs));		printk(KERN_ERR "\tidx_lebs       %u\n",		       le32_to_cpu(mst->idx_lebs));		printk(KERN_ERR "\ttotal_free     %llu\n",		       (unsigned long long)le64_to_cpu(mst->total_free));		printk(KERN_ERR "\ttotal_dirty    %llu\n",		       (unsigned long long)le64_to_cpu(mst->total_dirty));		printk(KERN_ERR "\ttotal_used     %llu\n",		       (unsigned long long)le64_to_cpu(mst->total_used));		printk(KERN_ERR "\ttotal_dead     %llu\n",		       (unsigned long long)le64_to_cpu(mst->total_dead));		printk(KERN_ERR "\ttotal_dark     %llu\n",		       (unsigned long long)le64_to_cpu(mst->total_dark));		break;	}	case UBIFS_REF_NODE:	{		const struct ubifs_ref_node *ref = node; 		printk(KERN_ERR "\tlnum           %u\n",		       le32_to_cpu(ref->lnum));		printk(KERN_ERR "\toffs           %u\n",		       le32_to_cpu(ref->offs));		printk(KERN_ERR "\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_ERR "\tkey            %s\n",		       dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));		printk(KERN_ERR "\tcreat_sqnum    %llu\n",		       (unsigned long long)le64_to_cpu(ino->creat_sqnum));		printk(KERN_ERR "\tsize           %llu\n",		       (unsigned long long)le64_to_cpu(ino->size));		printk(KERN_ERR "\tnlink          %u\n",		       le32_to_cpu(ino->nlink));		printk(KERN_ERR "\tatime          %lld.%u\n",		       (long long)le64_to_cpu(ino->atime_sec),		       le32_to_cpu(ino->atime_nsec));		printk(KERN_ERR "\tmtime          %lld.%u\n",		       (long long)le64_to_cpu(ino->mtime_sec),		       le32_to_cpu(ino->mtime_nsec));		printk(KERN_ERR "\tctime          %lld.%u\n",		       (long long)le64_to_cpu(ino->ctime_sec),		       le32_to_cpu(ino->ctime_nsec));		printk(KERN_ERR "\tuid            %u\n",		       le32_to_cpu(ino->uid));		printk(KERN_ERR "\tgid            %u\n",		       le32_to_cpu(ino->gid));		printk(KERN_ERR "\tmode           %u\n",		       le32_to_cpu(ino->mode));		printk(KERN_ERR "\tflags          %#x\n",		       le32_to_cpu(ino->flags));		printk(KERN_ERR "\txattr_cnt      %u\n",		       le32_to_cpu(ino->xattr_cnt));		printk(KERN_ERR "\txattr_size     %u\n",		       le32_to_cpu(ino->xattr_size));		printk(KERN_ERR "\txattr_names    %u\n",		       le32_to_cpu(ino->xattr_names));		printk(KERN_ERR "\tcompr_type     %#x\n",		       (int)le16_to_cpu(ino->compr_type));		printk(KERN_ERR "\tdata len       %u\n",		       le32_to_cpu(ino->data_len));		break;	}	case UBIFS_DENT_NODE:	case UBIFS_XENT_NODE:

Lines 1–500 of 3197.