1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 29eefe2a2SStefan Roese /* 39eefe2a2SStefan Roese * This file is part of UBIFS. 49eefe2a2SStefan Roese * 59eefe2a2SStefan Roese * Copyright (C) 2006-2008 Nokia Corporation 69eefe2a2SStefan Roese * 79eefe2a2SStefan Roese * Authors: Artem Bityutskiy (Битюцкий Артём) 89eefe2a2SStefan Roese * Adrian Hunter 99eefe2a2SStefan Roese */ 109eefe2a2SStefan Roese 119eefe2a2SStefan Roese /* 129eefe2a2SStefan Roese * This file implements most of the debugging stuff which is compiled in only 139eefe2a2SStefan Roese * when it is enabled. But some debugging check functions are implemented in 149eefe2a2SStefan Roese * corresponding subsystem, just because they are closely related and utilize 159eefe2a2SStefan Roese * various local functions of those subsystems. 169eefe2a2SStefan Roese */ 179eefe2a2SStefan Roese 18ff94bc40SHeiko Schocher #ifndef __UBOOT__ 19ff94bc40SHeiko Schocher #include <linux/module.h> 20ff94bc40SHeiko Schocher #include <linux/debugfs.h> 21ff94bc40SHeiko Schocher #include <linux/math64.h> 22ff94bc40SHeiko Schocher #include <linux/uaccess.h> 23ff94bc40SHeiko Schocher #include <linux/random.h> 24ff94bc40SHeiko Schocher #else 25ff94bc40SHeiko Schocher #include <linux/compat.h> 26ff94bc40SHeiko Schocher #include <linux/err.h> 27ff94bc40SHeiko Schocher #endif 289eefe2a2SStefan Roese #include "ubifs.h" 299eefe2a2SStefan Roese 30ff94bc40SHeiko Schocher #ifndef __UBOOT__ 31ff94bc40SHeiko Schocher static DEFINE_SPINLOCK(dbg_lock); 32ff94bc40SHeiko Schocher #endif 339eefe2a2SStefan Roese 34ff94bc40SHeiko Schocher static const char *get_key_fmt(int fmt) 35ff94bc40SHeiko Schocher { 36ff94bc40SHeiko Schocher switch (fmt) { 37ff94bc40SHeiko Schocher case UBIFS_SIMPLE_KEY_FMT: 38ff94bc40SHeiko Schocher return "simple"; 39ff94bc40SHeiko Schocher default: 40ff94bc40SHeiko Schocher return "unknown/invalid format"; 41ff94bc40SHeiko Schocher } 42ff94bc40SHeiko Schocher } 439eefe2a2SStefan Roese 44ff94bc40SHeiko Schocher static const char *get_key_hash(int hash) 45ff94bc40SHeiko Schocher { 46ff94bc40SHeiko Schocher switch (hash) { 47ff94bc40SHeiko Schocher case UBIFS_KEY_HASH_R5: 48ff94bc40SHeiko Schocher return "R5"; 49ff94bc40SHeiko Schocher case UBIFS_KEY_HASH_TEST: 50ff94bc40SHeiko Schocher return "test"; 51ff94bc40SHeiko Schocher default: 52ff94bc40SHeiko Schocher return "unknown/invalid name hash"; 53ff94bc40SHeiko Schocher } 54ff94bc40SHeiko Schocher } 559eefe2a2SStefan Roese 569eefe2a2SStefan Roese static const char *get_key_type(int type) 579eefe2a2SStefan Roese { 589eefe2a2SStefan Roese switch (type) { 599eefe2a2SStefan Roese case UBIFS_INO_KEY: 609eefe2a2SStefan Roese return "inode"; 619eefe2a2SStefan Roese case UBIFS_DENT_KEY: 629eefe2a2SStefan Roese return "direntry"; 639eefe2a2SStefan Roese case UBIFS_XENT_KEY: 649eefe2a2SStefan Roese return "xentry"; 659eefe2a2SStefan Roese case UBIFS_DATA_KEY: 669eefe2a2SStefan Roese return "data"; 679eefe2a2SStefan Roese case UBIFS_TRUN_KEY: 689eefe2a2SStefan Roese return "truncate"; 699eefe2a2SStefan Roese default: 709eefe2a2SStefan Roese return "unknown/invalid key"; 719eefe2a2SStefan Roese } 729eefe2a2SStefan Roese } 739eefe2a2SStefan Roese 74ff94bc40SHeiko Schocher #ifndef __UBOOT__ 75ff94bc40SHeiko Schocher static const char *get_dent_type(int type) 76ff94bc40SHeiko Schocher { 77ff94bc40SHeiko Schocher switch (type) { 78ff94bc40SHeiko Schocher case UBIFS_ITYPE_REG: 79ff94bc40SHeiko Schocher return "file"; 80ff94bc40SHeiko Schocher case UBIFS_ITYPE_DIR: 81ff94bc40SHeiko Schocher return "dir"; 82ff94bc40SHeiko Schocher case UBIFS_ITYPE_LNK: 83ff94bc40SHeiko Schocher return "symlink"; 84ff94bc40SHeiko Schocher case UBIFS_ITYPE_BLK: 85ff94bc40SHeiko Schocher return "blkdev"; 86ff94bc40SHeiko Schocher case UBIFS_ITYPE_CHR: 87ff94bc40SHeiko Schocher return "char dev"; 88ff94bc40SHeiko Schocher case UBIFS_ITYPE_FIFO: 89ff94bc40SHeiko Schocher return "fifo"; 90ff94bc40SHeiko Schocher case UBIFS_ITYPE_SOCK: 91ff94bc40SHeiko Schocher return "socket"; 92ff94bc40SHeiko Schocher default: 93ff94bc40SHeiko Schocher return "unknown/invalid type"; 94ff94bc40SHeiko Schocher } 95ff94bc40SHeiko Schocher } 96ff94bc40SHeiko Schocher #endif 97ff94bc40SHeiko Schocher 98ff94bc40SHeiko Schocher const char *dbg_snprintf_key(const struct ubifs_info *c, 99ff94bc40SHeiko Schocher const union ubifs_key *key, char *buffer, int len) 1009eefe2a2SStefan Roese { 1019eefe2a2SStefan Roese char *p = buffer; 1029eefe2a2SStefan Roese int type = key_type(c, key); 1039eefe2a2SStefan Roese 1049eefe2a2SStefan Roese if (c->key_fmt == UBIFS_SIMPLE_KEY_FMT) { 1059eefe2a2SStefan Roese switch (type) { 1069eefe2a2SStefan Roese case UBIFS_INO_KEY: 107ff94bc40SHeiko Schocher len -= snprintf(p, len, "(%lu, %s)", 108ff94bc40SHeiko Schocher (unsigned long)key_inum(c, key), 1099eefe2a2SStefan Roese get_key_type(type)); 1109eefe2a2SStefan Roese break; 1119eefe2a2SStefan Roese case UBIFS_DENT_KEY: 1129eefe2a2SStefan Roese case UBIFS_XENT_KEY: 113ff94bc40SHeiko Schocher len -= snprintf(p, len, "(%lu, %s, %#08x)", 1149eefe2a2SStefan Roese (unsigned long)key_inum(c, key), 1159eefe2a2SStefan Roese get_key_type(type), key_hash(c, key)); 1169eefe2a2SStefan Roese break; 1179eefe2a2SStefan Roese case UBIFS_DATA_KEY: 118ff94bc40SHeiko Schocher len -= snprintf(p, len, "(%lu, %s, %u)", 1199eefe2a2SStefan Roese (unsigned long)key_inum(c, key), 1209eefe2a2SStefan Roese get_key_type(type), key_block(c, key)); 1219eefe2a2SStefan Roese break; 1229eefe2a2SStefan Roese case UBIFS_TRUN_KEY: 123ff94bc40SHeiko Schocher len -= snprintf(p, len, "(%lu, %s)", 1249eefe2a2SStefan Roese (unsigned long)key_inum(c, key), 1259eefe2a2SStefan Roese get_key_type(type)); 1269eefe2a2SStefan Roese break; 1279eefe2a2SStefan Roese default: 128ff94bc40SHeiko Schocher len -= snprintf(p, len, "(bad key type: %#08x, %#08x)", 1299eefe2a2SStefan Roese key->u32[0], key->u32[1]); 1309eefe2a2SStefan Roese } 1319eefe2a2SStefan Roese } else 132ff94bc40SHeiko Schocher len -= snprintf(p, len, "bad key format %d", c->key_fmt); 133ff94bc40SHeiko Schocher ubifs_assert(len > 0); 134ff94bc40SHeiko Schocher return p; 1359eefe2a2SStefan Roese } 1369eefe2a2SStefan Roese 137ff94bc40SHeiko Schocher const char *dbg_ntype(int type) 1389eefe2a2SStefan Roese { 139ff94bc40SHeiko Schocher switch (type) { 140ff94bc40SHeiko Schocher case UBIFS_PAD_NODE: 141ff94bc40SHeiko Schocher return "padding node"; 142ff94bc40SHeiko Schocher case UBIFS_SB_NODE: 143ff94bc40SHeiko Schocher return "superblock node"; 144ff94bc40SHeiko Schocher case UBIFS_MST_NODE: 145ff94bc40SHeiko Schocher return "master node"; 146ff94bc40SHeiko Schocher case UBIFS_REF_NODE: 147ff94bc40SHeiko Schocher return "reference node"; 148ff94bc40SHeiko Schocher case UBIFS_INO_NODE: 149ff94bc40SHeiko Schocher return "inode node"; 150ff94bc40SHeiko Schocher case UBIFS_DENT_NODE: 151ff94bc40SHeiko Schocher return "direntry node"; 152ff94bc40SHeiko Schocher case UBIFS_XENT_NODE: 153ff94bc40SHeiko Schocher return "xentry node"; 154ff94bc40SHeiko Schocher case UBIFS_DATA_NODE: 155ff94bc40SHeiko Schocher return "data node"; 156ff94bc40SHeiko Schocher case UBIFS_TRUN_NODE: 157ff94bc40SHeiko Schocher return "truncate node"; 158ff94bc40SHeiko Schocher case UBIFS_IDX_NODE: 159ff94bc40SHeiko Schocher return "indexing node"; 160ff94bc40SHeiko Schocher case UBIFS_CS_NODE: 161ff94bc40SHeiko Schocher return "commit start node"; 162ff94bc40SHeiko Schocher case UBIFS_ORPH_NODE: 163ff94bc40SHeiko Schocher return "orphan node"; 164ff94bc40SHeiko Schocher default: 165ff94bc40SHeiko Schocher return "unknown node"; 166ff94bc40SHeiko Schocher } 1679eefe2a2SStefan Roese } 1689eefe2a2SStefan Roese 169ff94bc40SHeiko Schocher static const char *dbg_gtype(int type) 1709eefe2a2SStefan Roese { 171ff94bc40SHeiko Schocher switch (type) { 172ff94bc40SHeiko Schocher case UBIFS_NO_NODE_GROUP: 173ff94bc40SHeiko Schocher return "no node group"; 174ff94bc40SHeiko Schocher case UBIFS_IN_NODE_GROUP: 175ff94bc40SHeiko Schocher return "in node group"; 176ff94bc40SHeiko Schocher case UBIFS_LAST_OF_NODE_GROUP: 177ff94bc40SHeiko Schocher return "last of node group"; 178ff94bc40SHeiko Schocher default: 179ff94bc40SHeiko Schocher return "unknown"; 180ff94bc40SHeiko Schocher } 181ff94bc40SHeiko Schocher } 182ff94bc40SHeiko Schocher 183ff94bc40SHeiko Schocher const char *dbg_cstate(int cmt_state) 184ff94bc40SHeiko Schocher { 185ff94bc40SHeiko Schocher switch (cmt_state) { 186ff94bc40SHeiko Schocher case COMMIT_RESTING: 187ff94bc40SHeiko Schocher return "commit resting"; 188ff94bc40SHeiko Schocher case COMMIT_BACKGROUND: 189ff94bc40SHeiko Schocher return "background commit requested"; 190ff94bc40SHeiko Schocher case COMMIT_REQUIRED: 191ff94bc40SHeiko Schocher return "commit required"; 192ff94bc40SHeiko Schocher case COMMIT_RUNNING_BACKGROUND: 193ff94bc40SHeiko Schocher return "BACKGROUND commit running"; 194ff94bc40SHeiko Schocher case COMMIT_RUNNING_REQUIRED: 195ff94bc40SHeiko Schocher return "commit running and required"; 196ff94bc40SHeiko Schocher case COMMIT_BROKEN: 197ff94bc40SHeiko Schocher return "broken commit"; 198ff94bc40SHeiko Schocher default: 199ff94bc40SHeiko Schocher return "unknown commit state"; 200ff94bc40SHeiko Schocher } 201ff94bc40SHeiko Schocher } 202ff94bc40SHeiko Schocher 203ff94bc40SHeiko Schocher const char *dbg_jhead(int jhead) 204ff94bc40SHeiko Schocher { 205ff94bc40SHeiko Schocher switch (jhead) { 206ff94bc40SHeiko Schocher case GCHD: 207ff94bc40SHeiko Schocher return "0 (GC)"; 208ff94bc40SHeiko Schocher case BASEHD: 209ff94bc40SHeiko Schocher return "1 (base)"; 210ff94bc40SHeiko Schocher case DATAHD: 211ff94bc40SHeiko Schocher return "2 (data)"; 212ff94bc40SHeiko Schocher default: 213ff94bc40SHeiko Schocher return "unknown journal head"; 214ff94bc40SHeiko Schocher } 215ff94bc40SHeiko Schocher } 216ff94bc40SHeiko Schocher 217ff94bc40SHeiko Schocher static void dump_ch(const struct ubifs_ch *ch) 218ff94bc40SHeiko Schocher { 219ff94bc40SHeiko Schocher pr_err("\tmagic %#x\n", le32_to_cpu(ch->magic)); 220ff94bc40SHeiko Schocher pr_err("\tcrc %#x\n", le32_to_cpu(ch->crc)); 221ff94bc40SHeiko Schocher pr_err("\tnode_type %d (%s)\n", ch->node_type, 222ff94bc40SHeiko Schocher dbg_ntype(ch->node_type)); 223ff94bc40SHeiko Schocher pr_err("\tgroup_type %d (%s)\n", ch->group_type, 224ff94bc40SHeiko Schocher dbg_gtype(ch->group_type)); 225ff94bc40SHeiko Schocher pr_err("\tsqnum %llu\n", 226ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(ch->sqnum)); 227ff94bc40SHeiko Schocher pr_err("\tlen %u\n", le32_to_cpu(ch->len)); 228ff94bc40SHeiko Schocher } 229ff94bc40SHeiko Schocher 230ff94bc40SHeiko Schocher void ubifs_dump_inode(struct ubifs_info *c, const struct inode *inode) 231ff94bc40SHeiko Schocher { 232ff94bc40SHeiko Schocher #ifndef __UBOOT__ 233ff94bc40SHeiko Schocher const struct ubifs_inode *ui = ubifs_inode(inode); 234ff94bc40SHeiko Schocher struct qstr nm = { .name = NULL }; 235ff94bc40SHeiko Schocher union ubifs_key key; 236ff94bc40SHeiko Schocher struct ubifs_dent_node *dent, *pdent = NULL; 237ff94bc40SHeiko Schocher int count = 2; 238ff94bc40SHeiko Schocher 239ff94bc40SHeiko Schocher pr_err("Dump in-memory inode:"); 240ff94bc40SHeiko Schocher pr_err("\tinode %lu\n", inode->i_ino); 241ff94bc40SHeiko Schocher pr_err("\tsize %llu\n", 242ff94bc40SHeiko Schocher (unsigned long long)i_size_read(inode)); 243ff94bc40SHeiko Schocher pr_err("\tnlink %u\n", inode->i_nlink); 244ff94bc40SHeiko Schocher pr_err("\tuid %u\n", (unsigned int)i_uid_read(inode)); 245ff94bc40SHeiko Schocher pr_err("\tgid %u\n", (unsigned int)i_gid_read(inode)); 246ff94bc40SHeiko Schocher pr_err("\tatime %u.%u\n", 247ff94bc40SHeiko Schocher (unsigned int)inode->i_atime.tv_sec, 248ff94bc40SHeiko Schocher (unsigned int)inode->i_atime.tv_nsec); 249ff94bc40SHeiko Schocher pr_err("\tmtime %u.%u\n", 250ff94bc40SHeiko Schocher (unsigned int)inode->i_mtime.tv_sec, 251ff94bc40SHeiko Schocher (unsigned int)inode->i_mtime.tv_nsec); 252ff94bc40SHeiko Schocher pr_err("\tctime %u.%u\n", 253ff94bc40SHeiko Schocher (unsigned int)inode->i_ctime.tv_sec, 254ff94bc40SHeiko Schocher (unsigned int)inode->i_ctime.tv_nsec); 255ff94bc40SHeiko Schocher pr_err("\tcreat_sqnum %llu\n", ui->creat_sqnum); 256ff94bc40SHeiko Schocher pr_err("\txattr_size %u\n", ui->xattr_size); 257ff94bc40SHeiko Schocher pr_err("\txattr_cnt %u\n", ui->xattr_cnt); 258ff94bc40SHeiko Schocher pr_err("\txattr_names %u\n", ui->xattr_names); 259ff94bc40SHeiko Schocher pr_err("\tdirty %u\n", ui->dirty); 260ff94bc40SHeiko Schocher pr_err("\txattr %u\n", ui->xattr); 261ff94bc40SHeiko Schocher pr_err("\tbulk_read %u\n", ui->xattr); 262ff94bc40SHeiko Schocher pr_err("\tsynced_i_size %llu\n", 263ff94bc40SHeiko Schocher (unsigned long long)ui->synced_i_size); 264ff94bc40SHeiko Schocher pr_err("\tui_size %llu\n", 265ff94bc40SHeiko Schocher (unsigned long long)ui->ui_size); 266ff94bc40SHeiko Schocher pr_err("\tflags %d\n", ui->flags); 267ff94bc40SHeiko Schocher pr_err("\tcompr_type %d\n", ui->compr_type); 268ff94bc40SHeiko Schocher pr_err("\tlast_page_read %lu\n", ui->last_page_read); 269ff94bc40SHeiko Schocher pr_err("\tread_in_a_row %lu\n", ui->read_in_a_row); 270ff94bc40SHeiko Schocher pr_err("\tdata_len %d\n", ui->data_len); 271ff94bc40SHeiko Schocher 272ff94bc40SHeiko Schocher if (!S_ISDIR(inode->i_mode)) 273ff94bc40SHeiko Schocher return; 274ff94bc40SHeiko Schocher 275ff94bc40SHeiko Schocher pr_err("List of directory entries:\n"); 276ff94bc40SHeiko Schocher ubifs_assert(!mutex_is_locked(&c->tnc_mutex)); 277ff94bc40SHeiko Schocher 278ff94bc40SHeiko Schocher lowest_dent_key(c, &key, inode->i_ino); 279ff94bc40SHeiko Schocher while (1) { 280ff94bc40SHeiko Schocher dent = ubifs_tnc_next_ent(c, &key, &nm); 281ff94bc40SHeiko Schocher if (IS_ERR(dent)) { 282ff94bc40SHeiko Schocher if (PTR_ERR(dent) != -ENOENT) 283ff94bc40SHeiko Schocher pr_err("error %ld\n", PTR_ERR(dent)); 284ff94bc40SHeiko Schocher break; 285ff94bc40SHeiko Schocher } 286ff94bc40SHeiko Schocher 287ff94bc40SHeiko Schocher pr_err("\t%d: %s (%s)\n", 288ff94bc40SHeiko Schocher count++, dent->name, get_dent_type(dent->type)); 289ff94bc40SHeiko Schocher 290ff94bc40SHeiko Schocher nm.name = dent->name; 291ff94bc40SHeiko Schocher nm.len = le16_to_cpu(dent->nlen); 292ff94bc40SHeiko Schocher kfree(pdent); 293ff94bc40SHeiko Schocher pdent = dent; 294ff94bc40SHeiko Schocher key_read(c, &dent->key, &key); 295ff94bc40SHeiko Schocher } 296ff94bc40SHeiko Schocher kfree(pdent); 297ff94bc40SHeiko Schocher #endif 298ff94bc40SHeiko Schocher } 299ff94bc40SHeiko Schocher 300ff94bc40SHeiko Schocher void ubifs_dump_node(const struct ubifs_info *c, const void *node) 301ff94bc40SHeiko Schocher { 302ff94bc40SHeiko Schocher int i, n; 303ff94bc40SHeiko Schocher union ubifs_key key; 304ff94bc40SHeiko Schocher const struct ubifs_ch *ch = node; 305ff94bc40SHeiko Schocher char key_buf[DBG_KEY_BUF_LEN]; 306ff94bc40SHeiko Schocher 307ff94bc40SHeiko Schocher /* If the magic is incorrect, just hexdump the first bytes */ 308ff94bc40SHeiko Schocher if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC) { 309ff94bc40SHeiko Schocher pr_err("Not a node, first %zu bytes:", UBIFS_CH_SZ); 310ff94bc40SHeiko Schocher print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 32, 1, 311ff94bc40SHeiko Schocher (void *)node, UBIFS_CH_SZ, 1); 312ff94bc40SHeiko Schocher return; 313ff94bc40SHeiko Schocher } 314ff94bc40SHeiko Schocher 315ff94bc40SHeiko Schocher spin_lock(&dbg_lock); 316ff94bc40SHeiko Schocher dump_ch(node); 317ff94bc40SHeiko Schocher 318ff94bc40SHeiko Schocher switch (ch->node_type) { 319ff94bc40SHeiko Schocher case UBIFS_PAD_NODE: 320ff94bc40SHeiko Schocher { 321ff94bc40SHeiko Schocher const struct ubifs_pad_node *pad = node; 322ff94bc40SHeiko Schocher 323ff94bc40SHeiko Schocher pr_err("\tpad_len %u\n", le32_to_cpu(pad->pad_len)); 324ff94bc40SHeiko Schocher break; 325ff94bc40SHeiko Schocher } 326ff94bc40SHeiko Schocher case UBIFS_SB_NODE: 327ff94bc40SHeiko Schocher { 328ff94bc40SHeiko Schocher const struct ubifs_sb_node *sup = node; 329ff94bc40SHeiko Schocher unsigned int sup_flags = le32_to_cpu(sup->flags); 330ff94bc40SHeiko Schocher 331ff94bc40SHeiko Schocher pr_err("\tkey_hash %d (%s)\n", 332ff94bc40SHeiko Schocher (int)sup->key_hash, get_key_hash(sup->key_hash)); 333ff94bc40SHeiko Schocher pr_err("\tkey_fmt %d (%s)\n", 334ff94bc40SHeiko Schocher (int)sup->key_fmt, get_key_fmt(sup->key_fmt)); 335ff94bc40SHeiko Schocher pr_err("\tflags %#x\n", sup_flags); 336ff94bc40SHeiko Schocher pr_err("\tbig_lpt %u\n", 337ff94bc40SHeiko Schocher !!(sup_flags & UBIFS_FLG_BIGLPT)); 338ff94bc40SHeiko Schocher pr_err("\tspace_fixup %u\n", 339ff94bc40SHeiko Schocher !!(sup_flags & UBIFS_FLG_SPACE_FIXUP)); 340ff94bc40SHeiko Schocher pr_err("\tmin_io_size %u\n", le32_to_cpu(sup->min_io_size)); 341ff94bc40SHeiko Schocher pr_err("\tleb_size %u\n", le32_to_cpu(sup->leb_size)); 342ff94bc40SHeiko Schocher pr_err("\tleb_cnt %u\n", le32_to_cpu(sup->leb_cnt)); 343ff94bc40SHeiko Schocher pr_err("\tmax_leb_cnt %u\n", le32_to_cpu(sup->max_leb_cnt)); 344ff94bc40SHeiko Schocher pr_err("\tmax_bud_bytes %llu\n", 345ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(sup->max_bud_bytes)); 346ff94bc40SHeiko Schocher pr_err("\tlog_lebs %u\n", le32_to_cpu(sup->log_lebs)); 347ff94bc40SHeiko Schocher pr_err("\tlpt_lebs %u\n", le32_to_cpu(sup->lpt_lebs)); 348ff94bc40SHeiko Schocher pr_err("\torph_lebs %u\n", le32_to_cpu(sup->orph_lebs)); 349ff94bc40SHeiko Schocher pr_err("\tjhead_cnt %u\n", le32_to_cpu(sup->jhead_cnt)); 350ff94bc40SHeiko Schocher pr_err("\tfanout %u\n", le32_to_cpu(sup->fanout)); 351ff94bc40SHeiko Schocher pr_err("\tlsave_cnt %u\n", le32_to_cpu(sup->lsave_cnt)); 352ff94bc40SHeiko Schocher pr_err("\tdefault_compr %u\n", 353ff94bc40SHeiko Schocher (int)le16_to_cpu(sup->default_compr)); 354ff94bc40SHeiko Schocher pr_err("\trp_size %llu\n", 355ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(sup->rp_size)); 356ff94bc40SHeiko Schocher pr_err("\trp_uid %u\n", le32_to_cpu(sup->rp_uid)); 357ff94bc40SHeiko Schocher pr_err("\trp_gid %u\n", le32_to_cpu(sup->rp_gid)); 358ff94bc40SHeiko Schocher pr_err("\tfmt_version %u\n", le32_to_cpu(sup->fmt_version)); 359ff94bc40SHeiko Schocher pr_err("\ttime_gran %u\n", le32_to_cpu(sup->time_gran)); 360ff94bc40SHeiko Schocher pr_err("\tUUID %pUB\n", sup->uuid); 361ff94bc40SHeiko Schocher break; 362ff94bc40SHeiko Schocher } 363ff94bc40SHeiko Schocher case UBIFS_MST_NODE: 364ff94bc40SHeiko Schocher { 365ff94bc40SHeiko Schocher const struct ubifs_mst_node *mst = node; 366ff94bc40SHeiko Schocher 367ff94bc40SHeiko Schocher pr_err("\thighest_inum %llu\n", 368ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(mst->highest_inum)); 369ff94bc40SHeiko Schocher pr_err("\tcommit number %llu\n", 370ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(mst->cmt_no)); 371ff94bc40SHeiko Schocher pr_err("\tflags %#x\n", le32_to_cpu(mst->flags)); 372ff94bc40SHeiko Schocher pr_err("\tlog_lnum %u\n", le32_to_cpu(mst->log_lnum)); 373ff94bc40SHeiko Schocher pr_err("\troot_lnum %u\n", le32_to_cpu(mst->root_lnum)); 374ff94bc40SHeiko Schocher pr_err("\troot_offs %u\n", le32_to_cpu(mst->root_offs)); 375ff94bc40SHeiko Schocher pr_err("\troot_len %u\n", le32_to_cpu(mst->root_len)); 376ff94bc40SHeiko Schocher pr_err("\tgc_lnum %u\n", le32_to_cpu(mst->gc_lnum)); 377ff94bc40SHeiko Schocher pr_err("\tihead_lnum %u\n", le32_to_cpu(mst->ihead_lnum)); 378ff94bc40SHeiko Schocher pr_err("\tihead_offs %u\n", le32_to_cpu(mst->ihead_offs)); 379ff94bc40SHeiko Schocher pr_err("\tindex_size %llu\n", 380ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(mst->index_size)); 381ff94bc40SHeiko Schocher pr_err("\tlpt_lnum %u\n", le32_to_cpu(mst->lpt_lnum)); 382ff94bc40SHeiko Schocher pr_err("\tlpt_offs %u\n", le32_to_cpu(mst->lpt_offs)); 383ff94bc40SHeiko Schocher pr_err("\tnhead_lnum %u\n", le32_to_cpu(mst->nhead_lnum)); 384ff94bc40SHeiko Schocher pr_err("\tnhead_offs %u\n", le32_to_cpu(mst->nhead_offs)); 385ff94bc40SHeiko Schocher pr_err("\tltab_lnum %u\n", le32_to_cpu(mst->ltab_lnum)); 386ff94bc40SHeiko Schocher pr_err("\tltab_offs %u\n", le32_to_cpu(mst->ltab_offs)); 387ff94bc40SHeiko Schocher pr_err("\tlsave_lnum %u\n", le32_to_cpu(mst->lsave_lnum)); 388ff94bc40SHeiko Schocher pr_err("\tlsave_offs %u\n", le32_to_cpu(mst->lsave_offs)); 389ff94bc40SHeiko Schocher pr_err("\tlscan_lnum %u\n", le32_to_cpu(mst->lscan_lnum)); 390ff94bc40SHeiko Schocher pr_err("\tleb_cnt %u\n", le32_to_cpu(mst->leb_cnt)); 391ff94bc40SHeiko Schocher pr_err("\tempty_lebs %u\n", le32_to_cpu(mst->empty_lebs)); 392ff94bc40SHeiko Schocher pr_err("\tidx_lebs %u\n", le32_to_cpu(mst->idx_lebs)); 393ff94bc40SHeiko Schocher pr_err("\ttotal_free %llu\n", 394ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(mst->total_free)); 395ff94bc40SHeiko Schocher pr_err("\ttotal_dirty %llu\n", 396ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(mst->total_dirty)); 397ff94bc40SHeiko Schocher pr_err("\ttotal_used %llu\n", 398ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(mst->total_used)); 399ff94bc40SHeiko Schocher pr_err("\ttotal_dead %llu\n", 400ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(mst->total_dead)); 401ff94bc40SHeiko Schocher pr_err("\ttotal_dark %llu\n", 402ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(mst->total_dark)); 403ff94bc40SHeiko Schocher break; 404ff94bc40SHeiko Schocher } 405ff94bc40SHeiko Schocher case UBIFS_REF_NODE: 406ff94bc40SHeiko Schocher { 407ff94bc40SHeiko Schocher const struct ubifs_ref_node *ref = node; 408ff94bc40SHeiko Schocher 409ff94bc40SHeiko Schocher pr_err("\tlnum %u\n", le32_to_cpu(ref->lnum)); 410ff94bc40SHeiko Schocher pr_err("\toffs %u\n", le32_to_cpu(ref->offs)); 411ff94bc40SHeiko Schocher pr_err("\tjhead %u\n", le32_to_cpu(ref->jhead)); 412ff94bc40SHeiko Schocher break; 413ff94bc40SHeiko Schocher } 414ff94bc40SHeiko Schocher case UBIFS_INO_NODE: 415ff94bc40SHeiko Schocher { 416ff94bc40SHeiko Schocher const struct ubifs_ino_node *ino = node; 417ff94bc40SHeiko Schocher 418ff94bc40SHeiko Schocher key_read(c, &ino->key, &key); 419ff94bc40SHeiko Schocher pr_err("\tkey %s\n", 420ff94bc40SHeiko Schocher dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN)); 421ff94bc40SHeiko Schocher pr_err("\tcreat_sqnum %llu\n", 422ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(ino->creat_sqnum)); 423ff94bc40SHeiko Schocher pr_err("\tsize %llu\n", 424ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(ino->size)); 425ff94bc40SHeiko Schocher pr_err("\tnlink %u\n", le32_to_cpu(ino->nlink)); 426ff94bc40SHeiko Schocher pr_err("\tatime %lld.%u\n", 427ff94bc40SHeiko Schocher (long long)le64_to_cpu(ino->atime_sec), 428ff94bc40SHeiko Schocher le32_to_cpu(ino->atime_nsec)); 429ff94bc40SHeiko Schocher pr_err("\tmtime %lld.%u\n", 430ff94bc40SHeiko Schocher (long long)le64_to_cpu(ino->mtime_sec), 431ff94bc40SHeiko Schocher le32_to_cpu(ino->mtime_nsec)); 432ff94bc40SHeiko Schocher pr_err("\tctime %lld.%u\n", 433ff94bc40SHeiko Schocher (long long)le64_to_cpu(ino->ctime_sec), 434ff94bc40SHeiko Schocher le32_to_cpu(ino->ctime_nsec)); 435ff94bc40SHeiko Schocher pr_err("\tuid %u\n", le32_to_cpu(ino->uid)); 436ff94bc40SHeiko Schocher pr_err("\tgid %u\n", le32_to_cpu(ino->gid)); 437ff94bc40SHeiko Schocher pr_err("\tmode %u\n", le32_to_cpu(ino->mode)); 438ff94bc40SHeiko Schocher pr_err("\tflags %#x\n", le32_to_cpu(ino->flags)); 439ff94bc40SHeiko Schocher pr_err("\txattr_cnt %u\n", le32_to_cpu(ino->xattr_cnt)); 440ff94bc40SHeiko Schocher pr_err("\txattr_size %u\n", le32_to_cpu(ino->xattr_size)); 441ff94bc40SHeiko Schocher pr_err("\txattr_names %u\n", le32_to_cpu(ino->xattr_names)); 442ff94bc40SHeiko Schocher pr_err("\tcompr_type %#x\n", 443ff94bc40SHeiko Schocher (int)le16_to_cpu(ino->compr_type)); 444ff94bc40SHeiko Schocher pr_err("\tdata len %u\n", le32_to_cpu(ino->data_len)); 445ff94bc40SHeiko Schocher break; 446ff94bc40SHeiko Schocher } 447ff94bc40SHeiko Schocher case UBIFS_DENT_NODE: 448ff94bc40SHeiko Schocher case UBIFS_XENT_NODE: 449ff94bc40SHeiko Schocher { 450ff94bc40SHeiko Schocher const struct ubifs_dent_node *dent = node; 451ff94bc40SHeiko Schocher int nlen = le16_to_cpu(dent->nlen); 452ff94bc40SHeiko Schocher 453ff94bc40SHeiko Schocher key_read(c, &dent->key, &key); 454ff94bc40SHeiko Schocher pr_err("\tkey %s\n", 455ff94bc40SHeiko Schocher dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN)); 456ff94bc40SHeiko Schocher pr_err("\tinum %llu\n", 457ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(dent->inum)); 458ff94bc40SHeiko Schocher pr_err("\ttype %d\n", (int)dent->type); 459ff94bc40SHeiko Schocher pr_err("\tnlen %d\n", nlen); 460ff94bc40SHeiko Schocher pr_err("\tname "); 461ff94bc40SHeiko Schocher 462ff94bc40SHeiko Schocher if (nlen > UBIFS_MAX_NLEN) 463ff94bc40SHeiko Schocher pr_err("(bad name length, not printing, bad or corrupted node)"); 464ff94bc40SHeiko Schocher else { 465ff94bc40SHeiko Schocher for (i = 0; i < nlen && dent->name[i]; i++) 466ff94bc40SHeiko Schocher pr_cont("%c", dent->name[i]); 467ff94bc40SHeiko Schocher } 468ff94bc40SHeiko Schocher pr_cont("\n"); 469ff94bc40SHeiko Schocher 470ff94bc40SHeiko Schocher break; 471ff94bc40SHeiko Schocher } 472ff94bc40SHeiko Schocher case UBIFS_DATA_NODE: 473ff94bc40SHeiko Schocher { 474ff94bc40SHeiko Schocher const struct ubifs_data_node *dn = node; 475ff94bc40SHeiko Schocher int dlen = le32_to_cpu(ch->len) - UBIFS_DATA_NODE_SZ; 476ff94bc40SHeiko Schocher 477ff94bc40SHeiko Schocher key_read(c, &dn->key, &key); 478ff94bc40SHeiko Schocher pr_err("\tkey %s\n", 479ff94bc40SHeiko Schocher dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN)); 480ff94bc40SHeiko Schocher pr_err("\tsize %u\n", le32_to_cpu(dn->size)); 481ff94bc40SHeiko Schocher pr_err("\tcompr_typ %d\n", 482ff94bc40SHeiko Schocher (int)le16_to_cpu(dn->compr_type)); 483ff94bc40SHeiko Schocher pr_err("\tdata size %d\n", dlen); 484ff94bc40SHeiko Schocher pr_err("\tdata:\n"); 485ff94bc40SHeiko Schocher print_hex_dump(KERN_ERR, "\t", DUMP_PREFIX_OFFSET, 32, 1, 486ff94bc40SHeiko Schocher (void *)&dn->data, dlen, 0); 487ff94bc40SHeiko Schocher break; 488ff94bc40SHeiko Schocher } 489ff94bc40SHeiko Schocher case UBIFS_TRUN_NODE: 490ff94bc40SHeiko Schocher { 491ff94bc40SHeiko Schocher const struct ubifs_trun_node *trun = node; 492ff94bc40SHeiko Schocher 493ff94bc40SHeiko Schocher pr_err("\tinum %u\n", le32_to_cpu(trun->inum)); 494ff94bc40SHeiko Schocher pr_err("\told_size %llu\n", 495ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(trun->old_size)); 496ff94bc40SHeiko Schocher pr_err("\tnew_size %llu\n", 497ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(trun->new_size)); 498ff94bc40SHeiko Schocher break; 499ff94bc40SHeiko Schocher } 500ff94bc40SHeiko Schocher case UBIFS_IDX_NODE: 501ff94bc40SHeiko Schocher { 502ff94bc40SHeiko Schocher const struct ubifs_idx_node *idx = node; 503ff94bc40SHeiko Schocher 504ff94bc40SHeiko Schocher n = le16_to_cpu(idx->child_cnt); 505ff94bc40SHeiko Schocher pr_err("\tchild_cnt %d\n", n); 506ff94bc40SHeiko Schocher pr_err("\tlevel %d\n", (int)le16_to_cpu(idx->level)); 507ff94bc40SHeiko Schocher pr_err("\tBranches:\n"); 508ff94bc40SHeiko Schocher 509ff94bc40SHeiko Schocher for (i = 0; i < n && i < c->fanout - 1; i++) { 510ff94bc40SHeiko Schocher const struct ubifs_branch *br; 511ff94bc40SHeiko Schocher 512ff94bc40SHeiko Schocher br = ubifs_idx_branch(c, idx, i); 513ff94bc40SHeiko Schocher key_read(c, &br->key, &key); 514ff94bc40SHeiko Schocher pr_err("\t%d: LEB %d:%d len %d key %s\n", 515ff94bc40SHeiko Schocher i, le32_to_cpu(br->lnum), le32_to_cpu(br->offs), 516ff94bc40SHeiko Schocher le32_to_cpu(br->len), 517ff94bc40SHeiko Schocher dbg_snprintf_key(c, &key, key_buf, 518ff94bc40SHeiko Schocher DBG_KEY_BUF_LEN)); 519ff94bc40SHeiko Schocher } 520ff94bc40SHeiko Schocher break; 521ff94bc40SHeiko Schocher } 522ff94bc40SHeiko Schocher case UBIFS_CS_NODE: 523ff94bc40SHeiko Schocher break; 524ff94bc40SHeiko Schocher case UBIFS_ORPH_NODE: 525ff94bc40SHeiko Schocher { 526ff94bc40SHeiko Schocher const struct ubifs_orph_node *orph = node; 527ff94bc40SHeiko Schocher 528ff94bc40SHeiko Schocher pr_err("\tcommit number %llu\n", 529ff94bc40SHeiko Schocher (unsigned long long) 530ff94bc40SHeiko Schocher le64_to_cpu(orph->cmt_no) & LLONG_MAX); 531ff94bc40SHeiko Schocher pr_err("\tlast node flag %llu\n", 532ff94bc40SHeiko Schocher (unsigned long long)(le64_to_cpu(orph->cmt_no)) >> 63); 533ff94bc40SHeiko Schocher n = (le32_to_cpu(ch->len) - UBIFS_ORPH_NODE_SZ) >> 3; 534ff94bc40SHeiko Schocher pr_err("\t%d orphan inode numbers:\n", n); 535ff94bc40SHeiko Schocher for (i = 0; i < n; i++) 536ff94bc40SHeiko Schocher pr_err("\t ino %llu\n", 537ff94bc40SHeiko Schocher (unsigned long long)le64_to_cpu(orph->inos[i])); 538ff94bc40SHeiko Schocher break; 539ff94bc40SHeiko Schocher } 540ff94bc40SHeiko Schocher default: 541ff94bc40SHeiko Schocher pr_err("node type %d was not recognized\n", 542ff94bc40SHeiko Schocher (int)ch->node_type); 543ff94bc40SHeiko Schocher } 544ff94bc40SHeiko Schocher spin_unlock(&dbg_lock); 545ff94bc40SHeiko Schocher } 546ff94bc40SHeiko Schocher 547ff94bc40SHeiko Schocher void ubifs_dump_budget_req(const struct ubifs_budget_req *req) 548ff94bc40SHeiko Schocher { 549ff94bc40SHeiko Schocher spin_lock(&dbg_lock); 550ff94bc40SHeiko Schocher pr_err("Budgeting request: new_ino %d, dirtied_ino %d\n", 551ff94bc40SHeiko Schocher req->new_ino, req->dirtied_ino); 552ff94bc40SHeiko Schocher pr_err("\tnew_ino_d %d, dirtied_ino_d %d\n", 553ff94bc40SHeiko Schocher req->new_ino_d, req->dirtied_ino_d); 554ff94bc40SHeiko Schocher pr_err("\tnew_page %d, dirtied_page %d\n", 555ff94bc40SHeiko Schocher req->new_page, req->dirtied_page); 556ff94bc40SHeiko Schocher pr_err("\tnew_dent %d, mod_dent %d\n", 557ff94bc40SHeiko Schocher req->new_dent, req->mod_dent); 558ff94bc40SHeiko Schocher pr_err("\tidx_growth %d\n", req->idx_growth); 559ff94bc40SHeiko Schocher pr_err("\tdata_growth %d dd_growth %d\n", 560ff94bc40SHeiko Schocher req->data_growth, req->dd_growth); 561ff94bc40SHeiko Schocher spin_unlock(&dbg_lock); 562ff94bc40SHeiko Schocher } 563ff94bc40SHeiko Schocher 564ff94bc40SHeiko Schocher void ubifs_dump_lstats(const struct ubifs_lp_stats *lst) 565ff94bc40SHeiko Schocher { 566ff94bc40SHeiko Schocher spin_lock(&dbg_lock); 567ff94bc40SHeiko Schocher pr_err("(pid %d) Lprops statistics: empty_lebs %d, idx_lebs %d\n", 568ff94bc40SHeiko Schocher current->pid, lst->empty_lebs, lst->idx_lebs); 569ff94bc40SHeiko Schocher pr_err("\ttaken_empty_lebs %d, total_free %lld, total_dirty %lld\n", 570ff94bc40SHeiko Schocher lst->taken_empty_lebs, lst->total_free, lst->total_dirty); 571ff94bc40SHeiko Schocher pr_err("\ttotal_used %lld, total_dark %lld, total_dead %lld\n", 572ff94bc40SHeiko Schocher lst->total_used, lst->total_dark, lst->total_dead); 573ff94bc40SHeiko Schocher spin_unlock(&dbg_lock); 574ff94bc40SHeiko Schocher } 575ff94bc40SHeiko Schocher 576ff94bc40SHeiko Schocher #ifndef __UBOOT__ 577ff94bc40SHeiko Schocher void ubifs_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi) 578ff94bc40SHeiko Schocher { 579ff94bc40SHeiko Schocher int i; 580ff94bc40SHeiko Schocher struct rb_node *rb; 581ff94bc40SHeiko Schocher struct ubifs_bud *bud; 582ff94bc40SHeiko Schocher struct ubifs_gced_idx_leb *idx_gc; 583ff94bc40SHeiko Schocher long long available, outstanding, free; 584ff94bc40SHeiko Schocher 585ff94bc40SHeiko Schocher spin_lock(&c->space_lock); 586ff94bc40SHeiko Schocher spin_lock(&dbg_lock); 587ff94bc40SHeiko Schocher pr_err("(pid %d) Budgeting info: data budget sum %lld, total budget sum %lld\n", 588ff94bc40SHeiko Schocher current->pid, bi->data_growth + bi->dd_growth, 589ff94bc40SHeiko Schocher bi->data_growth + bi->dd_growth + bi->idx_growth); 590ff94bc40SHeiko Schocher pr_err("\tbudg_data_growth %lld, budg_dd_growth %lld, budg_idx_growth %lld\n", 591ff94bc40SHeiko Schocher bi->data_growth, bi->dd_growth, bi->idx_growth); 592ff94bc40SHeiko Schocher pr_err("\tmin_idx_lebs %d, old_idx_sz %llu, uncommitted_idx %lld\n", 593ff94bc40SHeiko Schocher bi->min_idx_lebs, bi->old_idx_sz, bi->uncommitted_idx); 594ff94bc40SHeiko Schocher pr_err("\tpage_budget %d, inode_budget %d, dent_budget %d\n", 595ff94bc40SHeiko Schocher bi->page_budget, bi->inode_budget, bi->dent_budget); 596ff94bc40SHeiko Schocher pr_err("\tnospace %u, nospace_rp %u\n", bi->nospace, bi->nospace_rp); 597ff94bc40SHeiko Schocher pr_err("\tdark_wm %d, dead_wm %d, max_idx_node_sz %d\n", 598ff94bc40SHeiko Schocher c->dark_wm, c->dead_wm, c->max_idx_node_sz); 599ff94bc40SHeiko Schocher 600ff94bc40SHeiko Schocher if (bi != &c->bi) 601ff94bc40SHeiko Schocher /* 602ff94bc40SHeiko Schocher * If we are dumping saved budgeting data, do not print 603ff94bc40SHeiko Schocher * additional information which is about the current state, not 604ff94bc40SHeiko Schocher * the old one which corresponded to the saved budgeting data. 605ff94bc40SHeiko Schocher */ 606ff94bc40SHeiko Schocher goto out_unlock; 607ff94bc40SHeiko Schocher 608ff94bc40SHeiko Schocher pr_err("\tfreeable_cnt %d, calc_idx_sz %lld, idx_gc_cnt %d\n", 609ff94bc40SHeiko Schocher c->freeable_cnt, c->calc_idx_sz, c->idx_gc_cnt); 610ff94bc40SHeiko Schocher pr_err("\tdirty_pg_cnt %ld, dirty_zn_cnt %ld, clean_zn_cnt %ld\n", 611ff94bc40SHeiko Schocher atomic_long_read(&c->dirty_pg_cnt), 612ff94bc40SHeiko Schocher atomic_long_read(&c->dirty_zn_cnt), 613ff94bc40SHeiko Schocher atomic_long_read(&c->clean_zn_cnt)); 614ff94bc40SHeiko Schocher pr_err("\tgc_lnum %d, ihead_lnum %d\n", c->gc_lnum, c->ihead_lnum); 615ff94bc40SHeiko Schocher 616ff94bc40SHeiko Schocher /* If we are in R/O mode, journal heads do not exist */ 617ff94bc40SHeiko Schocher if (c->jheads) 618ff94bc40SHeiko Schocher for (i = 0; i < c->jhead_cnt; i++) 619ff94bc40SHeiko Schocher pr_err("\tjhead %s\t LEB %d\n", 620ff94bc40SHeiko Schocher dbg_jhead(c->jheads[i].wbuf.jhead), 621ff94bc40SHeiko Schocher c->jheads[i].wbuf.lnum); 622ff94bc40SHeiko Schocher for (rb = rb_first(&c->buds); rb; rb = rb_next(rb)) { 623ff94bc40SHeiko Schocher bud = rb_entry(rb, struct ubifs_bud, rb); 624ff94bc40SHeiko Schocher pr_err("\tbud LEB %d\n", bud->lnum); 625ff94bc40SHeiko Schocher } 626ff94bc40SHeiko Schocher list_for_each_entry(bud, &c->old_buds, list) 627ff94bc40SHeiko Schocher pr_err("\told bud LEB %d\n", bud->lnum); 628ff94bc40SHeiko Schocher list_for_each_entry(idx_gc, &c->idx_gc, list) 629ff94bc40SHeiko Schocher pr_err("\tGC'ed idx LEB %d unmap %d\n", 630ff94bc40SHeiko Schocher idx_gc->lnum, idx_gc->unmap); 631ff94bc40SHeiko Schocher pr_err("\tcommit state %d\n", c->cmt_state); 632ff94bc40SHeiko Schocher 633ff94bc40SHeiko Schocher /* Print budgeting predictions */ 634ff94bc40SHeiko Schocher available = ubifs_calc_available(c, c->bi.min_idx_lebs); 635ff94bc40SHeiko Schocher outstanding = c->bi.data_growth + c->bi.dd_growth; 636ff94bc40SHeiko Schocher free = ubifs_get_free_space_nolock(c); 637ff94bc40SHeiko Schocher pr_err("Budgeting predictions:\n"); 638ff94bc40SHeiko Schocher pr_err("\tavailable: %lld, outstanding %lld, free %lld\n", 639ff94bc40SHeiko Schocher available, outstanding, free); 640ff94bc40SHeiko Schocher out_unlock: 641ff94bc40SHeiko Schocher spin_unlock(&dbg_lock); 642ff94bc40SHeiko Schocher spin_unlock(&c->space_lock); 643ff94bc40SHeiko Schocher } 644ff94bc40SHeiko Schocher #else 645ff94bc40SHeiko Schocher void ubifs_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi) 646ff94bc40SHeiko Schocher { 647ff94bc40SHeiko Schocher } 648ff94bc40SHeiko Schocher #endif 649ff94bc40SHeiko Schocher 650ff94bc40SHeiko Schocher void ubifs_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp) 651ff94bc40SHeiko Schocher { 652ff94bc40SHeiko Schocher int i, spc, dark = 0, dead = 0; 653ff94bc40SHeiko Schocher struct rb_node *rb; 654ff94bc40SHeiko Schocher struct ubifs_bud *bud; 655ff94bc40SHeiko Schocher 656ff94bc40SHeiko Schocher spc = lp->free + lp->dirty; 657ff94bc40SHeiko Schocher if (spc < c->dead_wm) 658ff94bc40SHeiko Schocher dead = spc; 659ff94bc40SHeiko Schocher else 660ff94bc40SHeiko Schocher dark = ubifs_calc_dark(c, spc); 661ff94bc40SHeiko Schocher 662ff94bc40SHeiko Schocher if (lp->flags & LPROPS_INDEX) 663ff94bc40SHeiko Schocher pr_err("LEB %-7d free %-8d dirty %-8d used %-8d free + dirty %-8d flags %#x (", 664ff94bc40SHeiko Schocher lp->lnum, lp->free, lp->dirty, c->leb_size - spc, spc, 665ff94bc40SHeiko Schocher lp->flags); 666ff94bc40SHeiko Schocher else 667ff94bc40SHeiko Schocher pr_err("LEB %-7d free %-8d dirty %-8d used %-8d free + dirty %-8d dark %-4d dead %-4d nodes fit %-3d flags %#-4x (", 668ff94bc40SHeiko Schocher lp->lnum, lp->free, lp->dirty, c->leb_size - spc, spc, 669ff94bc40SHeiko Schocher dark, dead, (int)(spc / UBIFS_MAX_NODE_SZ), lp->flags); 670ff94bc40SHeiko Schocher 671ff94bc40SHeiko Schocher if (lp->flags & LPROPS_TAKEN) { 672ff94bc40SHeiko Schocher if (lp->flags & LPROPS_INDEX) 673ff94bc40SHeiko Schocher pr_cont("index, taken"); 674ff94bc40SHeiko Schocher else 675ff94bc40SHeiko Schocher pr_cont("taken"); 676ff94bc40SHeiko Schocher } else { 677ff94bc40SHeiko Schocher const char *s; 678ff94bc40SHeiko Schocher 679ff94bc40SHeiko Schocher if (lp->flags & LPROPS_INDEX) { 680ff94bc40SHeiko Schocher switch (lp->flags & LPROPS_CAT_MASK) { 681ff94bc40SHeiko Schocher case LPROPS_DIRTY_IDX: 682ff94bc40SHeiko Schocher s = "dirty index"; 683ff94bc40SHeiko Schocher break; 684ff94bc40SHeiko Schocher case LPROPS_FRDI_IDX: 685ff94bc40SHeiko Schocher s = "freeable index"; 686ff94bc40SHeiko Schocher break; 687ff94bc40SHeiko Schocher default: 688ff94bc40SHeiko Schocher s = "index"; 689ff94bc40SHeiko Schocher } 690ff94bc40SHeiko Schocher } else { 691ff94bc40SHeiko Schocher switch (lp->flags & LPROPS_CAT_MASK) { 692ff94bc40SHeiko Schocher case LPROPS_UNCAT: 693ff94bc40SHeiko Schocher s = "not categorized"; 694ff94bc40SHeiko Schocher break; 695ff94bc40SHeiko Schocher case LPROPS_DIRTY: 696ff94bc40SHeiko Schocher s = "dirty"; 697ff94bc40SHeiko Schocher break; 698ff94bc40SHeiko Schocher case LPROPS_FREE: 699ff94bc40SHeiko Schocher s = "free"; 700ff94bc40SHeiko Schocher break; 701ff94bc40SHeiko Schocher case LPROPS_EMPTY: 702ff94bc40SHeiko Schocher s = "empty"; 703ff94bc40SHeiko Schocher break; 704ff94bc40SHeiko Schocher case LPROPS_FREEABLE: 705ff94bc40SHeiko Schocher s = "freeable"; 706ff94bc40SHeiko Schocher break; 707ff94bc40SHeiko Schocher default: 708ff94bc40SHeiko Schocher s = NULL; 709ff94bc40SHeiko Schocher break; 710ff94bc40SHeiko Schocher } 711ff94bc40SHeiko Schocher } 712ff94bc40SHeiko Schocher pr_cont("%s", s); 713ff94bc40SHeiko Schocher } 714ff94bc40SHeiko Schocher 715ff94bc40SHeiko Schocher for (rb = rb_first((struct rb_root *)&c->buds); rb; rb = rb_next(rb)) { 716ff94bc40SHeiko Schocher bud = rb_entry(rb, struct ubifs_bud, rb); 717ff94bc40SHeiko Schocher if (bud->lnum == lp->lnum) { 718ff94bc40SHeiko Schocher int head = 0; 719ff94bc40SHeiko Schocher for (i = 0; i < c->jhead_cnt; i++) { 720ff94bc40SHeiko Schocher /* 721ff94bc40SHeiko Schocher * Note, if we are in R/O mode or in the middle 722ff94bc40SHeiko Schocher * of mounting/re-mounting, the write-buffers do 723ff94bc40SHeiko Schocher * not exist. 724ff94bc40SHeiko Schocher */ 725ff94bc40SHeiko Schocher if (c->jheads && 726ff94bc40SHeiko Schocher lp->lnum == c->jheads[i].wbuf.lnum) { 727ff94bc40SHeiko Schocher pr_cont(", jhead %s", dbg_jhead(i)); 728ff94bc40SHeiko Schocher head = 1; 729ff94bc40SHeiko Schocher } 730ff94bc40SHeiko Schocher } 731ff94bc40SHeiko Schocher if (!head) 732ff94bc40SHeiko Schocher pr_cont(", bud of jhead %s", 733ff94bc40SHeiko Schocher dbg_jhead(bud->jhead)); 734ff94bc40SHeiko Schocher } 735ff94bc40SHeiko Schocher } 736ff94bc40SHeiko Schocher if (lp->lnum == c->gc_lnum) 737ff94bc40SHeiko Schocher pr_cont(", GC LEB"); 738ff94bc40SHeiko Schocher pr_cont(")\n"); 739ff94bc40SHeiko Schocher } 740ff94bc40SHeiko Schocher 741ff94bc40SHeiko Schocher void ubifs_dump_lprops(struct ubifs_info *c) 742ff94bc40SHeiko Schocher { 743ff94bc40SHeiko Schocher int lnum, err; 744ff94bc40SHeiko Schocher struct ubifs_lprops lp; 745ff94bc40SHeiko Schocher struct ubifs_lp_stats lst; 746ff94bc40SHeiko Schocher 747ff94bc40SHeiko Schocher pr_err("(pid %d) start dumping LEB properties\n", current->pid); 748ff94bc40SHeiko Schocher ubifs_get_lp_stats(c, &lst); 749ff94bc40SHeiko Schocher ubifs_dump_lstats(&lst); 750ff94bc40SHeiko Schocher 751ff94bc40SHeiko Schocher for (lnum = c->main_first; lnum < c->leb_cnt; lnum++) { 752ff94bc40SHeiko Schocher err = ubifs_read_one_lp(c, lnum, &lp); 7530195a7bbSHeiko Schocher if (err) { 7540195a7bbSHeiko Schocher ubifs_err(c, "cannot read lprops for LEB %d", lnum); 7550195a7bbSHeiko Schocher continue; 7560195a7bbSHeiko Schocher } 757ff94bc40SHeiko Schocher 758ff94bc40SHeiko Schocher ubifs_dump_lprop(c, &lp); 759ff94bc40SHeiko Schocher } 760ff94bc40SHeiko Schocher pr_err("(pid %d) finish dumping LEB properties\n", current->pid); 761ff94bc40SHeiko Schocher } 762ff94bc40SHeiko Schocher 763ff94bc40SHeiko Schocher void ubifs_dump_lpt_info(struct ubifs_info *c) 764ff94bc40SHeiko Schocher { 765ff94bc40SHeiko Schocher int i; 766ff94bc40SHeiko Schocher 767ff94bc40SHeiko Schocher spin_lock(&dbg_lock); 768ff94bc40SHeiko Schocher pr_err("(pid %d) dumping LPT information\n", current->pid); 769ff94bc40SHeiko Schocher pr_err("\tlpt_sz: %lld\n", c->lpt_sz); 770ff94bc40SHeiko Schocher pr_err("\tpnode_sz: %d\n", c->pnode_sz); 771ff94bc40SHeiko Schocher pr_err("\tnnode_sz: %d\n", c->nnode_sz); 772ff94bc40SHeiko Schocher pr_err("\tltab_sz: %d\n", c->ltab_sz); 773ff94bc40SHeiko Schocher pr_err("\tlsave_sz: %d\n", c->lsave_sz); 774ff94bc40SHeiko Schocher pr_err("\tbig_lpt: %d\n", c->big_lpt); 775ff94bc40SHeiko Schocher pr_err("\tlpt_hght: %d\n", c->lpt_hght); 776ff94bc40SHeiko Schocher pr_err("\tpnode_cnt: %d\n", c->pnode_cnt); 777ff94bc40SHeiko Schocher pr_err("\tnnode_cnt: %d\n", c->nnode_cnt); 778ff94bc40SHeiko Schocher pr_err("\tdirty_pn_cnt: %d\n", c->dirty_pn_cnt); 779ff94bc40SHeiko Schocher pr_err("\tdirty_nn_cnt: %d\n", c->dirty_nn_cnt); 780ff94bc40SHeiko Schocher pr_err("\tlsave_cnt: %d\n", c->lsave_cnt); 781ff94bc40SHeiko Schocher pr_err("\tspace_bits: %d\n", c->space_bits); 782ff94bc40SHeiko Schocher pr_err("\tlpt_lnum_bits: %d\n", c->lpt_lnum_bits); 783ff94bc40SHeiko Schocher pr_err("\tlpt_offs_bits: %d\n", c->lpt_offs_bits); 784ff94bc40SHeiko Schocher pr_err("\tlpt_spc_bits: %d\n", c->lpt_spc_bits); 785ff94bc40SHeiko Schocher pr_err("\tpcnt_bits: %d\n", c->pcnt_bits); 786ff94bc40SHeiko Schocher pr_err("\tlnum_bits: %d\n", c->lnum_bits); 787ff94bc40SHeiko Schocher pr_err("\tLPT root is at %d:%d\n", c->lpt_lnum, c->lpt_offs); 788ff94bc40SHeiko Schocher pr_err("\tLPT head is at %d:%d\n", 789ff94bc40SHeiko Schocher c->nhead_lnum, c->nhead_offs); 790ff94bc40SHeiko Schocher pr_err("\tLPT ltab is at %d:%d\n", c->ltab_lnum, c->ltab_offs); 791ff94bc40SHeiko Schocher if (c->big_lpt) 792ff94bc40SHeiko Schocher pr_err("\tLPT lsave is at %d:%d\n", 793ff94bc40SHeiko Schocher c->lsave_lnum, c->lsave_offs); 794ff94bc40SHeiko Schocher for (i = 0; i < c->lpt_lebs; i++) 795ff94bc40SHeiko Schocher pr_err("\tLPT LEB %d free %d dirty %d tgc %d cmt %d\n", 796ff94bc40SHeiko Schocher i + c->lpt_first, c->ltab[i].free, c->ltab[i].dirty, 797ff94bc40SHeiko Schocher c->ltab[i].tgc, c->ltab[i].cmt); 798ff94bc40SHeiko Schocher spin_unlock(&dbg_lock); 799ff94bc40SHeiko Schocher } 800ff94bc40SHeiko Schocher 801ff94bc40SHeiko Schocher void ubifs_dump_sleb(const struct ubifs_info *c, 802ff94bc40SHeiko Schocher const struct ubifs_scan_leb *sleb, int offs) 803ff94bc40SHeiko Schocher { 804ff94bc40SHeiko Schocher struct ubifs_scan_node *snod; 805ff94bc40SHeiko Schocher 806ff94bc40SHeiko Schocher pr_err("(pid %d) start dumping scanned data from LEB %d:%d\n", 807ff94bc40SHeiko Schocher current->pid, sleb->lnum, offs); 808ff94bc40SHeiko Schocher 809ff94bc40SHeiko Schocher list_for_each_entry(snod, &sleb->nodes, list) { 810ff94bc40SHeiko Schocher cond_resched(); 811ff94bc40SHeiko Schocher pr_err("Dumping node at LEB %d:%d len %d\n", 812ff94bc40SHeiko Schocher sleb->lnum, snod->offs, snod->len); 813ff94bc40SHeiko Schocher ubifs_dump_node(c, snod->node); 814ff94bc40SHeiko Schocher } 815ff94bc40SHeiko Schocher } 816ff94bc40SHeiko Schocher 817ff94bc40SHeiko Schocher void ubifs_dump_leb(const struct ubifs_info *c, int lnum) 818ff94bc40SHeiko Schocher { 819ff94bc40SHeiko Schocher struct ubifs_scan_leb *sleb; 820ff94bc40SHeiko Schocher struct ubifs_scan_node *snod; 821ff94bc40SHeiko Schocher void *buf; 822ff94bc40SHeiko Schocher 823ff94bc40SHeiko Schocher pr_err("(pid %d) start dumping LEB %d\n", current->pid, lnum); 824ff94bc40SHeiko Schocher 825ff94bc40SHeiko Schocher buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); 826ff94bc40SHeiko Schocher if (!buf) { 8270195a7bbSHeiko Schocher ubifs_err(c, "cannot allocate memory for dumping LEB %d", lnum); 828ff94bc40SHeiko Schocher return; 829ff94bc40SHeiko Schocher } 830ff94bc40SHeiko Schocher 831ff94bc40SHeiko Schocher sleb = ubifs_scan(c, lnum, 0, buf, 0); 832ff94bc40SHeiko Schocher if (IS_ERR(sleb)) { 8330195a7bbSHeiko Schocher ubifs_err(c, "scan error %d", (int)PTR_ERR(sleb)); 834ff94bc40SHeiko Schocher goto out; 835ff94bc40SHeiko Schocher } 836ff94bc40SHeiko Schocher 837ff94bc40SHeiko Schocher pr_err("LEB %d has %d nodes ending at %d\n", lnum, 838ff94bc40SHeiko Schocher sleb->nodes_cnt, sleb->endpt); 839ff94bc40SHeiko Schocher 840ff94bc40SHeiko Schocher list_for_each_entry(snod, &sleb->nodes, list) { 841ff94bc40SHeiko Schocher cond_resched(); 842ff94bc40SHeiko Schocher pr_err("Dumping node at LEB %d:%d len %d\n", lnum, 843ff94bc40SHeiko Schocher snod->offs, snod->len); 844ff94bc40SHeiko Schocher ubifs_dump_node(c, snod->node); 845ff94bc40SHeiko Schocher } 846ff94bc40SHeiko Schocher 847ff94bc40SHeiko Schocher pr_err("(pid %d) finish dumping LEB %d\n", current->pid, lnum); 848ff94bc40SHeiko Schocher ubifs_scan_destroy(sleb); 849ff94bc40SHeiko Schocher 850ff94bc40SHeiko Schocher out: 851ff94bc40SHeiko Schocher vfree(buf); 852ff94bc40SHeiko Schocher return; 853ff94bc40SHeiko Schocher } 854ff94bc40SHeiko Schocher 855ff94bc40SHeiko Schocher void ubifs_dump_znode(const struct ubifs_info *c, 856ff94bc40SHeiko Schocher const struct ubifs_znode *znode) 857ff94bc40SHeiko Schocher { 858ff94bc40SHeiko Schocher int n; 859ff94bc40SHeiko Schocher const struct ubifs_zbranch *zbr; 860ff94bc40SHeiko Schocher char key_buf[DBG_KEY_BUF_LEN]; 861ff94bc40SHeiko Schocher 862ff94bc40SHeiko Schocher spin_lock(&dbg_lock); 863ff94bc40SHeiko Schocher if (znode->parent) 864ff94bc40SHeiko Schocher zbr = &znode->parent->zbranch[znode->iip]; 865ff94bc40SHeiko Schocher else 866ff94bc40SHeiko Schocher zbr = &c->zroot; 867ff94bc40SHeiko Schocher 868ff94bc40SHeiko Schocher pr_err("znode %p, LEB %d:%d len %d parent %p iip %d level %d child_cnt %d flags %lx\n", 869ff94bc40SHeiko Schocher znode, zbr->lnum, zbr->offs, zbr->len, znode->parent, znode->iip, 870ff94bc40SHeiko Schocher znode->level, znode->child_cnt, znode->flags); 871ff94bc40SHeiko Schocher 872ff94bc40SHeiko Schocher if (znode->child_cnt <= 0 || znode->child_cnt > c->fanout) { 873ff94bc40SHeiko Schocher spin_unlock(&dbg_lock); 874ff94bc40SHeiko Schocher return; 875ff94bc40SHeiko Schocher } 876ff94bc40SHeiko Schocher 877ff94bc40SHeiko Schocher pr_err("zbranches:\n"); 878ff94bc40SHeiko Schocher for (n = 0; n < znode->child_cnt; n++) { 879ff94bc40SHeiko Schocher zbr = &znode->zbranch[n]; 880ff94bc40SHeiko Schocher if (znode->level > 0) 881ff94bc40SHeiko Schocher pr_err("\t%d: znode %p LEB %d:%d len %d key %s\n", 882ff94bc40SHeiko Schocher n, zbr->znode, zbr->lnum, zbr->offs, zbr->len, 883ff94bc40SHeiko Schocher dbg_snprintf_key(c, &zbr->key, key_buf, 884ff94bc40SHeiko Schocher DBG_KEY_BUF_LEN)); 885ff94bc40SHeiko Schocher else 886ff94bc40SHeiko Schocher pr_err("\t%d: LNC %p LEB %d:%d len %d key %s\n", 887ff94bc40SHeiko Schocher n, zbr->znode, zbr->lnum, zbr->offs, zbr->len, 888ff94bc40SHeiko Schocher dbg_snprintf_key(c, &zbr->key, key_buf, 889ff94bc40SHeiko Schocher DBG_KEY_BUF_LEN)); 890ff94bc40SHeiko Schocher } 891ff94bc40SHeiko Schocher spin_unlock(&dbg_lock); 892ff94bc40SHeiko Schocher } 893ff94bc40SHeiko Schocher 894ff94bc40SHeiko Schocher void ubifs_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat) 895ff94bc40SHeiko Schocher { 896ff94bc40SHeiko Schocher int i; 897ff94bc40SHeiko Schocher 898ff94bc40SHeiko Schocher pr_err("(pid %d) start dumping heap cat %d (%d elements)\n", 899ff94bc40SHeiko Schocher current->pid, cat, heap->cnt); 900ff94bc40SHeiko Schocher for (i = 0; i < heap->cnt; i++) { 901ff94bc40SHeiko Schocher struct ubifs_lprops *lprops = heap->arr[i]; 902ff94bc40SHeiko Schocher 903ff94bc40SHeiko Schocher pr_err("\t%d. LEB %d hpos %d free %d dirty %d flags %d\n", 904ff94bc40SHeiko Schocher i, lprops->lnum, lprops->hpos, lprops->free, 905ff94bc40SHeiko Schocher lprops->dirty, lprops->flags); 906ff94bc40SHeiko Schocher } 907ff94bc40SHeiko Schocher pr_err("(pid %d) finish dumping heap\n", current->pid); 908ff94bc40SHeiko Schocher } 909ff94bc40SHeiko Schocher 910ff94bc40SHeiko Schocher void ubifs_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, 911ff94bc40SHeiko Schocher struct ubifs_nnode *parent, int iip) 912ff94bc40SHeiko Schocher { 913ff94bc40SHeiko Schocher int i; 914ff94bc40SHeiko Schocher 915ff94bc40SHeiko Schocher pr_err("(pid %d) dumping pnode:\n", current->pid); 916ff94bc40SHeiko Schocher pr_err("\taddress %zx parent %zx cnext %zx\n", 917ff94bc40SHeiko Schocher (size_t)pnode, (size_t)parent, (size_t)pnode->cnext); 918ff94bc40SHeiko Schocher pr_err("\tflags %lu iip %d level %d num %d\n", 919ff94bc40SHeiko Schocher pnode->flags, iip, pnode->level, pnode->num); 920ff94bc40SHeiko Schocher for (i = 0; i < UBIFS_LPT_FANOUT; i++) { 921ff94bc40SHeiko Schocher struct ubifs_lprops *lp = &pnode->lprops[i]; 922ff94bc40SHeiko Schocher 923ff94bc40SHeiko Schocher pr_err("\t%d: free %d dirty %d flags %d lnum %d\n", 924ff94bc40SHeiko Schocher i, lp->free, lp->dirty, lp->flags, lp->lnum); 925ff94bc40SHeiko Schocher } 926ff94bc40SHeiko Schocher } 927ff94bc40SHeiko Schocher 928ff94bc40SHeiko Schocher void ubifs_dump_tnc(struct ubifs_info *c) 929ff94bc40SHeiko Schocher { 930ff94bc40SHeiko Schocher struct ubifs_znode *znode; 931ff94bc40SHeiko Schocher int level; 932ff94bc40SHeiko Schocher 933ff94bc40SHeiko Schocher pr_err("\n"); 934ff94bc40SHeiko Schocher pr_err("(pid %d) start dumping TNC tree\n", current->pid); 935ff94bc40SHeiko Schocher znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL); 936ff94bc40SHeiko Schocher level = znode->level; 937ff94bc40SHeiko Schocher pr_err("== Level %d ==\n", level); 938ff94bc40SHeiko Schocher while (znode) { 939ff94bc40SHeiko Schocher if (level != znode->level) { 940ff94bc40SHeiko Schocher level = znode->level; 941ff94bc40SHeiko Schocher pr_err("== Level %d ==\n", level); 942ff94bc40SHeiko Schocher } 943ff94bc40SHeiko Schocher ubifs_dump_znode(c, znode); 944ff94bc40SHeiko Schocher znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode); 945ff94bc40SHeiko Schocher } 946ff94bc40SHeiko Schocher pr_err("(pid %d) finish dumping TNC tree\n", current->pid); 947ff94bc40SHeiko Schocher } 948ff94bc40SHeiko Schocher 949ff94bc40SHeiko Schocher static int dump_znode(struct ubifs_info *c, struct ubifs_znode *znode, 950ff94bc40SHeiko Schocher void *priv) 951ff94bc40SHeiko Schocher { 952ff94bc40SHeiko Schocher ubifs_dump_znode(c, znode); 953ff94bc40SHeiko Schocher return 0; 954ff94bc40SHeiko Schocher } 955ff94bc40SHeiko Schocher 956ff94bc40SHeiko Schocher /** 957ff94bc40SHeiko Schocher * ubifs_dump_index - dump the on-flash index. 958ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 959ff94bc40SHeiko Schocher * 960ff94bc40SHeiko Schocher * This function dumps whole UBIFS indexing B-tree, unlike 'ubifs_dump_tnc()' 961ff94bc40SHeiko Schocher * which dumps only in-memory znodes and does not read znodes which from flash. 962ff94bc40SHeiko Schocher */ 963ff94bc40SHeiko Schocher void ubifs_dump_index(struct ubifs_info *c) 964ff94bc40SHeiko Schocher { 965ff94bc40SHeiko Schocher dbg_walk_index(c, NULL, dump_znode, NULL); 966ff94bc40SHeiko Schocher } 967ff94bc40SHeiko Schocher 968ff94bc40SHeiko Schocher #ifndef __UBOOT__ 969ff94bc40SHeiko Schocher /** 970ff94bc40SHeiko Schocher * dbg_save_space_info - save information about flash space. 971ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 972ff94bc40SHeiko Schocher * 973ff94bc40SHeiko Schocher * This function saves information about UBIFS free space, dirty space, etc, in 974ff94bc40SHeiko Schocher * order to check it later. 975ff94bc40SHeiko Schocher */ 976ff94bc40SHeiko Schocher void dbg_save_space_info(struct ubifs_info *c) 977ff94bc40SHeiko Schocher { 978ff94bc40SHeiko Schocher struct ubifs_debug_info *d = c->dbg; 979ff94bc40SHeiko Schocher int freeable_cnt; 980ff94bc40SHeiko Schocher 981ff94bc40SHeiko Schocher spin_lock(&c->space_lock); 982ff94bc40SHeiko Schocher memcpy(&d->saved_lst, &c->lst, sizeof(struct ubifs_lp_stats)); 983ff94bc40SHeiko Schocher memcpy(&d->saved_bi, &c->bi, sizeof(struct ubifs_budg_info)); 984ff94bc40SHeiko Schocher d->saved_idx_gc_cnt = c->idx_gc_cnt; 985ff94bc40SHeiko Schocher 986ff94bc40SHeiko Schocher /* 987ff94bc40SHeiko Schocher * We use a dirty hack here and zero out @c->freeable_cnt, because it 988ff94bc40SHeiko Schocher * affects the free space calculations, and UBIFS might not know about 989ff94bc40SHeiko Schocher * all freeable eraseblocks. Indeed, we know about freeable eraseblocks 990ff94bc40SHeiko Schocher * only when we read their lprops, and we do this only lazily, upon the 991ff94bc40SHeiko Schocher * need. So at any given point of time @c->freeable_cnt might be not 992ff94bc40SHeiko Schocher * exactly accurate. 993ff94bc40SHeiko Schocher * 994ff94bc40SHeiko Schocher * Just one example about the issue we hit when we did not zero 995ff94bc40SHeiko Schocher * @c->freeable_cnt. 996ff94bc40SHeiko Schocher * 1. The file-system is mounted R/O, c->freeable_cnt is %0. We save the 997ff94bc40SHeiko Schocher * amount of free space in @d->saved_free 998ff94bc40SHeiko Schocher * 2. We re-mount R/W, which makes UBIFS to read the "lsave" 999ff94bc40SHeiko Schocher * information from flash, where we cache LEBs from various 1000ff94bc40SHeiko Schocher * categories ('ubifs_remount_fs()' -> 'ubifs_lpt_init()' 1001ff94bc40SHeiko Schocher * -> 'lpt_init_wr()' -> 'read_lsave()' -> 'ubifs_lpt_lookup()' 1002ff94bc40SHeiko Schocher * -> 'ubifs_get_pnode()' -> 'update_cats()' 1003ff94bc40SHeiko Schocher * -> 'ubifs_add_to_cat()'). 1004ff94bc40SHeiko Schocher * 3. Lsave contains a freeable eraseblock, and @c->freeable_cnt 1005ff94bc40SHeiko Schocher * becomes %1. 1006ff94bc40SHeiko Schocher * 4. We calculate the amount of free space when the re-mount is 1007ff94bc40SHeiko Schocher * finished in 'dbg_check_space_info()' and it does not match 1008ff94bc40SHeiko Schocher * @d->saved_free. 1009ff94bc40SHeiko Schocher */ 1010ff94bc40SHeiko Schocher freeable_cnt = c->freeable_cnt; 1011ff94bc40SHeiko Schocher c->freeable_cnt = 0; 1012ff94bc40SHeiko Schocher d->saved_free = ubifs_get_free_space_nolock(c); 1013ff94bc40SHeiko Schocher c->freeable_cnt = freeable_cnt; 1014ff94bc40SHeiko Schocher spin_unlock(&c->space_lock); 1015ff94bc40SHeiko Schocher } 1016ff94bc40SHeiko Schocher 1017ff94bc40SHeiko Schocher /** 1018ff94bc40SHeiko Schocher * dbg_check_space_info - check flash space information. 1019ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1020ff94bc40SHeiko Schocher * 1021ff94bc40SHeiko Schocher * This function compares current flash space information with the information 1022ff94bc40SHeiko Schocher * which was saved when the 'dbg_save_space_info()' function was called. 1023ff94bc40SHeiko Schocher * Returns zero if the information has not changed, and %-EINVAL it it has 1024ff94bc40SHeiko Schocher * changed. 1025ff94bc40SHeiko Schocher */ 1026ff94bc40SHeiko Schocher int dbg_check_space_info(struct ubifs_info *c) 1027ff94bc40SHeiko Schocher { 1028ff94bc40SHeiko Schocher struct ubifs_debug_info *d = c->dbg; 1029ff94bc40SHeiko Schocher struct ubifs_lp_stats lst; 1030ff94bc40SHeiko Schocher long long free; 1031ff94bc40SHeiko Schocher int freeable_cnt; 1032ff94bc40SHeiko Schocher 1033ff94bc40SHeiko Schocher spin_lock(&c->space_lock); 1034ff94bc40SHeiko Schocher freeable_cnt = c->freeable_cnt; 1035ff94bc40SHeiko Schocher c->freeable_cnt = 0; 1036ff94bc40SHeiko Schocher free = ubifs_get_free_space_nolock(c); 1037ff94bc40SHeiko Schocher c->freeable_cnt = freeable_cnt; 1038ff94bc40SHeiko Schocher spin_unlock(&c->space_lock); 1039ff94bc40SHeiko Schocher 1040ff94bc40SHeiko Schocher if (free != d->saved_free) { 10410195a7bbSHeiko Schocher ubifs_err(c, "free space changed from %lld to %lld", 1042ff94bc40SHeiko Schocher d->saved_free, free); 1043ff94bc40SHeiko Schocher goto out; 1044ff94bc40SHeiko Schocher } 1045ff94bc40SHeiko Schocher 1046ff94bc40SHeiko Schocher return 0; 1047ff94bc40SHeiko Schocher 1048ff94bc40SHeiko Schocher out: 10490195a7bbSHeiko Schocher ubifs_msg(c, "saved lprops statistics dump"); 1050ff94bc40SHeiko Schocher ubifs_dump_lstats(&d->saved_lst); 10510195a7bbSHeiko Schocher ubifs_msg(c, "saved budgeting info dump"); 1052ff94bc40SHeiko Schocher ubifs_dump_budg(c, &d->saved_bi); 10530195a7bbSHeiko Schocher ubifs_msg(c, "saved idx_gc_cnt %d", d->saved_idx_gc_cnt); 10540195a7bbSHeiko Schocher ubifs_msg(c, "current lprops statistics dump"); 1055ff94bc40SHeiko Schocher ubifs_get_lp_stats(c, &lst); 1056ff94bc40SHeiko Schocher ubifs_dump_lstats(&lst); 10570195a7bbSHeiko Schocher ubifs_msg(c, "current budgeting info dump"); 1058ff94bc40SHeiko Schocher ubifs_dump_budg(c, &c->bi); 1059ff94bc40SHeiko Schocher dump_stack(); 1060ff94bc40SHeiko Schocher return -EINVAL; 1061ff94bc40SHeiko Schocher } 1062ff94bc40SHeiko Schocher 1063ff94bc40SHeiko Schocher /** 1064ff94bc40SHeiko Schocher * dbg_check_synced_i_size - check synchronized inode size. 1065ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1066ff94bc40SHeiko Schocher * @inode: inode to check 1067ff94bc40SHeiko Schocher * 1068ff94bc40SHeiko Schocher * If inode is clean, synchronized inode size has to be equivalent to current 1069ff94bc40SHeiko Schocher * inode size. This function has to be called only for locked inodes (@i_mutex 1070ff94bc40SHeiko Schocher * has to be locked). Returns %0 if synchronized inode size if correct, and 1071ff94bc40SHeiko Schocher * %-EINVAL if not. 1072ff94bc40SHeiko Schocher */ 1073ff94bc40SHeiko Schocher int dbg_check_synced_i_size(const struct ubifs_info *c, struct inode *inode) 1074ff94bc40SHeiko Schocher { 1075ff94bc40SHeiko Schocher int err = 0; 1076ff94bc40SHeiko Schocher struct ubifs_inode *ui = ubifs_inode(inode); 1077ff94bc40SHeiko Schocher 1078ff94bc40SHeiko Schocher if (!dbg_is_chk_gen(c)) 1079ff94bc40SHeiko Schocher return 0; 1080ff94bc40SHeiko Schocher if (!S_ISREG(inode->i_mode)) 1081ff94bc40SHeiko Schocher return 0; 1082ff94bc40SHeiko Schocher 1083ff94bc40SHeiko Schocher mutex_lock(&ui->ui_mutex); 1084ff94bc40SHeiko Schocher spin_lock(&ui->ui_lock); 1085ff94bc40SHeiko Schocher if (ui->ui_size != ui->synced_i_size && !ui->dirty) { 10860195a7bbSHeiko Schocher ubifs_err(c, "ui_size is %lld, synced_i_size is %lld, but inode is clean", 1087ff94bc40SHeiko Schocher ui->ui_size, ui->synced_i_size); 10880195a7bbSHeiko Schocher ubifs_err(c, "i_ino %lu, i_mode %#x, i_size %lld", inode->i_ino, 1089ff94bc40SHeiko Schocher inode->i_mode, i_size_read(inode)); 1090ff94bc40SHeiko Schocher dump_stack(); 1091ff94bc40SHeiko Schocher err = -EINVAL; 1092ff94bc40SHeiko Schocher } 1093ff94bc40SHeiko Schocher spin_unlock(&ui->ui_lock); 1094ff94bc40SHeiko Schocher mutex_unlock(&ui->ui_mutex); 1095ff94bc40SHeiko Schocher return err; 1096ff94bc40SHeiko Schocher } 1097ff94bc40SHeiko Schocher 1098ff94bc40SHeiko Schocher /* 1099ff94bc40SHeiko Schocher * dbg_check_dir - check directory inode size and link count. 1100ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1101ff94bc40SHeiko Schocher * @dir: the directory to calculate size for 1102ff94bc40SHeiko Schocher * @size: the result is returned here 1103ff94bc40SHeiko Schocher * 1104ff94bc40SHeiko Schocher * This function makes sure that directory size and link count are correct. 1105ff94bc40SHeiko Schocher * Returns zero in case of success and a negative error code in case of 1106ff94bc40SHeiko Schocher * failure. 1107ff94bc40SHeiko Schocher * 1108ff94bc40SHeiko Schocher * Note, it is good idea to make sure the @dir->i_mutex is locked before 1109ff94bc40SHeiko Schocher * calling this function. 1110ff94bc40SHeiko Schocher */ 1111ff94bc40SHeiko Schocher int dbg_check_dir(struct ubifs_info *c, const struct inode *dir) 1112ff94bc40SHeiko Schocher { 1113ff94bc40SHeiko Schocher unsigned int nlink = 2; 1114ff94bc40SHeiko Schocher union ubifs_key key; 1115ff94bc40SHeiko Schocher struct ubifs_dent_node *dent, *pdent = NULL; 1116ff94bc40SHeiko Schocher struct qstr nm = { .name = NULL }; 1117ff94bc40SHeiko Schocher loff_t size = UBIFS_INO_NODE_SZ; 1118ff94bc40SHeiko Schocher 1119ff94bc40SHeiko Schocher if (!dbg_is_chk_gen(c)) 1120ff94bc40SHeiko Schocher return 0; 1121ff94bc40SHeiko Schocher 1122ff94bc40SHeiko Schocher if (!S_ISDIR(dir->i_mode)) 1123ff94bc40SHeiko Schocher return 0; 1124ff94bc40SHeiko Schocher 1125ff94bc40SHeiko Schocher lowest_dent_key(c, &key, dir->i_ino); 1126ff94bc40SHeiko Schocher while (1) { 1127ff94bc40SHeiko Schocher int err; 1128ff94bc40SHeiko Schocher 1129ff94bc40SHeiko Schocher dent = ubifs_tnc_next_ent(c, &key, &nm); 1130ff94bc40SHeiko Schocher if (IS_ERR(dent)) { 1131ff94bc40SHeiko Schocher err = PTR_ERR(dent); 1132ff94bc40SHeiko Schocher if (err == -ENOENT) 1133ff94bc40SHeiko Schocher break; 1134ff94bc40SHeiko Schocher return err; 1135ff94bc40SHeiko Schocher } 1136ff94bc40SHeiko Schocher 1137ff94bc40SHeiko Schocher nm.name = dent->name; 1138ff94bc40SHeiko Schocher nm.len = le16_to_cpu(dent->nlen); 1139ff94bc40SHeiko Schocher size += CALC_DENT_SIZE(nm.len); 1140ff94bc40SHeiko Schocher if (dent->type == UBIFS_ITYPE_DIR) 1141ff94bc40SHeiko Schocher nlink += 1; 1142ff94bc40SHeiko Schocher kfree(pdent); 1143ff94bc40SHeiko Schocher pdent = dent; 1144ff94bc40SHeiko Schocher key_read(c, &dent->key, &key); 1145ff94bc40SHeiko Schocher } 1146ff94bc40SHeiko Schocher kfree(pdent); 1147ff94bc40SHeiko Schocher 1148ff94bc40SHeiko Schocher if (i_size_read(dir) != size) { 11490195a7bbSHeiko Schocher ubifs_err(c, "directory inode %lu has size %llu, but calculated size is %llu", 1150ff94bc40SHeiko Schocher dir->i_ino, (unsigned long long)i_size_read(dir), 1151ff94bc40SHeiko Schocher (unsigned long long)size); 1152ff94bc40SHeiko Schocher ubifs_dump_inode(c, dir); 1153ff94bc40SHeiko Schocher dump_stack(); 1154ff94bc40SHeiko Schocher return -EINVAL; 1155ff94bc40SHeiko Schocher } 1156ff94bc40SHeiko Schocher if (dir->i_nlink != nlink) { 11570195a7bbSHeiko Schocher ubifs_err(c, "directory inode %lu has nlink %u, but calculated nlink is %u", 1158ff94bc40SHeiko Schocher dir->i_ino, dir->i_nlink, nlink); 1159ff94bc40SHeiko Schocher ubifs_dump_inode(c, dir); 1160ff94bc40SHeiko Schocher dump_stack(); 1161ff94bc40SHeiko Schocher return -EINVAL; 1162ff94bc40SHeiko Schocher } 1163ff94bc40SHeiko Schocher 1164ff94bc40SHeiko Schocher return 0; 1165ff94bc40SHeiko Schocher } 1166ff94bc40SHeiko Schocher 1167ff94bc40SHeiko Schocher /** 1168ff94bc40SHeiko Schocher * dbg_check_key_order - make sure that colliding keys are properly ordered. 1169ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1170ff94bc40SHeiko Schocher * @zbr1: first zbranch 1171ff94bc40SHeiko Schocher * @zbr2: following zbranch 1172ff94bc40SHeiko Schocher * 1173ff94bc40SHeiko Schocher * In UBIFS indexing B-tree colliding keys has to be sorted in binary order of 1174ff94bc40SHeiko Schocher * names of the direntries/xentries which are referred by the keys. This 1175ff94bc40SHeiko Schocher * function reads direntries/xentries referred by @zbr1 and @zbr2 and makes 1176ff94bc40SHeiko Schocher * sure the name of direntry/xentry referred by @zbr1 is less than 1177ff94bc40SHeiko Schocher * direntry/xentry referred by @zbr2. Returns zero if this is true, %1 if not, 1178ff94bc40SHeiko Schocher * and a negative error code in case of failure. 1179ff94bc40SHeiko Schocher */ 1180ff94bc40SHeiko Schocher static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1, 1181ff94bc40SHeiko Schocher struct ubifs_zbranch *zbr2) 1182ff94bc40SHeiko Schocher { 1183ff94bc40SHeiko Schocher int err, nlen1, nlen2, cmp; 1184ff94bc40SHeiko Schocher struct ubifs_dent_node *dent1, *dent2; 1185ff94bc40SHeiko Schocher union ubifs_key key; 1186ff94bc40SHeiko Schocher char key_buf[DBG_KEY_BUF_LEN]; 1187ff94bc40SHeiko Schocher 1188ff94bc40SHeiko Schocher ubifs_assert(!keys_cmp(c, &zbr1->key, &zbr2->key)); 1189ff94bc40SHeiko Schocher dent1 = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS); 1190ff94bc40SHeiko Schocher if (!dent1) 1191ff94bc40SHeiko Schocher return -ENOMEM; 1192ff94bc40SHeiko Schocher dent2 = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS); 1193ff94bc40SHeiko Schocher if (!dent2) { 1194ff94bc40SHeiko Schocher err = -ENOMEM; 1195ff94bc40SHeiko Schocher goto out_free; 1196ff94bc40SHeiko Schocher } 1197ff94bc40SHeiko Schocher 1198ff94bc40SHeiko Schocher err = ubifs_tnc_read_node(c, zbr1, dent1); 1199ff94bc40SHeiko Schocher if (err) 1200ff94bc40SHeiko Schocher goto out_free; 1201ff94bc40SHeiko Schocher err = ubifs_validate_entry(c, dent1); 1202ff94bc40SHeiko Schocher if (err) 1203ff94bc40SHeiko Schocher goto out_free; 1204ff94bc40SHeiko Schocher 1205ff94bc40SHeiko Schocher err = ubifs_tnc_read_node(c, zbr2, dent2); 1206ff94bc40SHeiko Schocher if (err) 1207ff94bc40SHeiko Schocher goto out_free; 1208ff94bc40SHeiko Schocher err = ubifs_validate_entry(c, dent2); 1209ff94bc40SHeiko Schocher if (err) 1210ff94bc40SHeiko Schocher goto out_free; 1211ff94bc40SHeiko Schocher 1212ff94bc40SHeiko Schocher /* Make sure node keys are the same as in zbranch */ 1213ff94bc40SHeiko Schocher err = 1; 1214ff94bc40SHeiko Schocher key_read(c, &dent1->key, &key); 1215ff94bc40SHeiko Schocher if (keys_cmp(c, &zbr1->key, &key)) { 12160195a7bbSHeiko Schocher ubifs_err(c, "1st entry at %d:%d has key %s", zbr1->lnum, 1217ff94bc40SHeiko Schocher zbr1->offs, dbg_snprintf_key(c, &key, key_buf, 1218ff94bc40SHeiko Schocher DBG_KEY_BUF_LEN)); 12190195a7bbSHeiko Schocher ubifs_err(c, "but it should have key %s according to tnc", 1220ff94bc40SHeiko Schocher dbg_snprintf_key(c, &zbr1->key, key_buf, 1221ff94bc40SHeiko Schocher DBG_KEY_BUF_LEN)); 1222ff94bc40SHeiko Schocher ubifs_dump_node(c, dent1); 1223ff94bc40SHeiko Schocher goto out_free; 1224ff94bc40SHeiko Schocher } 1225ff94bc40SHeiko Schocher 1226ff94bc40SHeiko Schocher key_read(c, &dent2->key, &key); 1227ff94bc40SHeiko Schocher if (keys_cmp(c, &zbr2->key, &key)) { 12280195a7bbSHeiko Schocher ubifs_err(c, "2nd entry at %d:%d has key %s", zbr1->lnum, 1229ff94bc40SHeiko Schocher zbr1->offs, dbg_snprintf_key(c, &key, key_buf, 1230ff94bc40SHeiko Schocher DBG_KEY_BUF_LEN)); 12310195a7bbSHeiko Schocher ubifs_err(c, "but it should have key %s according to tnc", 1232ff94bc40SHeiko Schocher dbg_snprintf_key(c, &zbr2->key, key_buf, 1233ff94bc40SHeiko Schocher DBG_KEY_BUF_LEN)); 1234ff94bc40SHeiko Schocher ubifs_dump_node(c, dent2); 1235ff94bc40SHeiko Schocher goto out_free; 1236ff94bc40SHeiko Schocher } 1237ff94bc40SHeiko Schocher 1238ff94bc40SHeiko Schocher nlen1 = le16_to_cpu(dent1->nlen); 1239ff94bc40SHeiko Schocher nlen2 = le16_to_cpu(dent2->nlen); 1240ff94bc40SHeiko Schocher 1241ff94bc40SHeiko Schocher cmp = memcmp(dent1->name, dent2->name, min_t(int, nlen1, nlen2)); 1242ff94bc40SHeiko Schocher if (cmp < 0 || (cmp == 0 && nlen1 < nlen2)) { 1243ff94bc40SHeiko Schocher err = 0; 1244ff94bc40SHeiko Schocher goto out_free; 1245ff94bc40SHeiko Schocher } 1246ff94bc40SHeiko Schocher if (cmp == 0 && nlen1 == nlen2) 12470195a7bbSHeiko Schocher ubifs_err(c, "2 xent/dent nodes with the same name"); 1248ff94bc40SHeiko Schocher else 12490195a7bbSHeiko Schocher ubifs_err(c, "bad order of colliding key %s", 1250ff94bc40SHeiko Schocher dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN)); 1251ff94bc40SHeiko Schocher 12520195a7bbSHeiko Schocher ubifs_msg(c, "first node at %d:%d\n", zbr1->lnum, zbr1->offs); 1253ff94bc40SHeiko Schocher ubifs_dump_node(c, dent1); 12540195a7bbSHeiko Schocher ubifs_msg(c, "second node at %d:%d\n", zbr2->lnum, zbr2->offs); 1255ff94bc40SHeiko Schocher ubifs_dump_node(c, dent2); 1256ff94bc40SHeiko Schocher 1257ff94bc40SHeiko Schocher out_free: 1258ff94bc40SHeiko Schocher kfree(dent2); 1259ff94bc40SHeiko Schocher kfree(dent1); 1260ff94bc40SHeiko Schocher return err; 1261ff94bc40SHeiko Schocher } 1262ff94bc40SHeiko Schocher 1263ff94bc40SHeiko Schocher /** 1264ff94bc40SHeiko Schocher * dbg_check_znode - check if znode is all right. 1265ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1266ff94bc40SHeiko Schocher * @zbr: zbranch which points to this znode 1267ff94bc40SHeiko Schocher * 1268ff94bc40SHeiko Schocher * This function makes sure that znode referred to by @zbr is all right. 1269ff94bc40SHeiko Schocher * Returns zero if it is, and %-EINVAL if it is not. 1270ff94bc40SHeiko Schocher */ 1271ff94bc40SHeiko Schocher static int dbg_check_znode(struct ubifs_info *c, struct ubifs_zbranch *zbr) 1272ff94bc40SHeiko Schocher { 1273ff94bc40SHeiko Schocher struct ubifs_znode *znode = zbr->znode; 1274ff94bc40SHeiko Schocher struct ubifs_znode *zp = znode->parent; 1275ff94bc40SHeiko Schocher int n, err, cmp; 1276ff94bc40SHeiko Schocher 1277ff94bc40SHeiko Schocher if (znode->child_cnt <= 0 || znode->child_cnt > c->fanout) { 1278ff94bc40SHeiko Schocher err = 1; 1279ff94bc40SHeiko Schocher goto out; 1280ff94bc40SHeiko Schocher } 1281ff94bc40SHeiko Schocher if (znode->level < 0) { 1282ff94bc40SHeiko Schocher err = 2; 1283ff94bc40SHeiko Schocher goto out; 1284ff94bc40SHeiko Schocher } 1285ff94bc40SHeiko Schocher if (znode->iip < 0 || znode->iip >= c->fanout) { 1286ff94bc40SHeiko Schocher err = 3; 1287ff94bc40SHeiko Schocher goto out; 1288ff94bc40SHeiko Schocher } 1289ff94bc40SHeiko Schocher 1290ff94bc40SHeiko Schocher if (zbr->len == 0) 1291ff94bc40SHeiko Schocher /* Only dirty zbranch may have no on-flash nodes */ 1292ff94bc40SHeiko Schocher if (!ubifs_zn_dirty(znode)) { 1293ff94bc40SHeiko Schocher err = 4; 1294ff94bc40SHeiko Schocher goto out; 1295ff94bc40SHeiko Schocher } 1296ff94bc40SHeiko Schocher 1297ff94bc40SHeiko Schocher if (ubifs_zn_dirty(znode)) { 1298ff94bc40SHeiko Schocher /* 1299ff94bc40SHeiko Schocher * If znode is dirty, its parent has to be dirty as well. The 1300ff94bc40SHeiko Schocher * order of the operation is important, so we have to have 1301ff94bc40SHeiko Schocher * memory barriers. 1302ff94bc40SHeiko Schocher */ 1303ff94bc40SHeiko Schocher smp_mb(); 1304ff94bc40SHeiko Schocher if (zp && !ubifs_zn_dirty(zp)) { 1305ff94bc40SHeiko Schocher /* 1306ff94bc40SHeiko Schocher * The dirty flag is atomic and is cleared outside the 1307ff94bc40SHeiko Schocher * TNC mutex, so znode's dirty flag may now have 1308ff94bc40SHeiko Schocher * been cleared. The child is always cleared before the 1309ff94bc40SHeiko Schocher * parent, so we just need to check again. 1310ff94bc40SHeiko Schocher */ 1311ff94bc40SHeiko Schocher smp_mb(); 1312ff94bc40SHeiko Schocher if (ubifs_zn_dirty(znode)) { 1313ff94bc40SHeiko Schocher err = 5; 1314ff94bc40SHeiko Schocher goto out; 1315ff94bc40SHeiko Schocher } 1316ff94bc40SHeiko Schocher } 1317ff94bc40SHeiko Schocher } 1318ff94bc40SHeiko Schocher 1319ff94bc40SHeiko Schocher if (zp) { 1320ff94bc40SHeiko Schocher const union ubifs_key *min, *max; 1321ff94bc40SHeiko Schocher 1322ff94bc40SHeiko Schocher if (znode->level != zp->level - 1) { 1323ff94bc40SHeiko Schocher err = 6; 1324ff94bc40SHeiko Schocher goto out; 1325ff94bc40SHeiko Schocher } 1326ff94bc40SHeiko Schocher 1327ff94bc40SHeiko Schocher /* Make sure the 'parent' pointer in our znode is correct */ 1328ff94bc40SHeiko Schocher err = ubifs_search_zbranch(c, zp, &zbr->key, &n); 1329ff94bc40SHeiko Schocher if (!err) { 1330ff94bc40SHeiko Schocher /* This zbranch does not exist in the parent */ 1331ff94bc40SHeiko Schocher err = 7; 1332ff94bc40SHeiko Schocher goto out; 1333ff94bc40SHeiko Schocher } 1334ff94bc40SHeiko Schocher 1335ff94bc40SHeiko Schocher if (znode->iip >= zp->child_cnt) { 1336ff94bc40SHeiko Schocher err = 8; 1337ff94bc40SHeiko Schocher goto out; 1338ff94bc40SHeiko Schocher } 1339ff94bc40SHeiko Schocher 1340ff94bc40SHeiko Schocher if (znode->iip != n) { 1341ff94bc40SHeiko Schocher /* This may happen only in case of collisions */ 1342ff94bc40SHeiko Schocher if (keys_cmp(c, &zp->zbranch[n].key, 1343ff94bc40SHeiko Schocher &zp->zbranch[znode->iip].key)) { 1344ff94bc40SHeiko Schocher err = 9; 1345ff94bc40SHeiko Schocher goto out; 1346ff94bc40SHeiko Schocher } 1347ff94bc40SHeiko Schocher n = znode->iip; 1348ff94bc40SHeiko Schocher } 1349ff94bc40SHeiko Schocher 1350ff94bc40SHeiko Schocher /* 1351ff94bc40SHeiko Schocher * Make sure that the first key in our znode is greater than or 1352ff94bc40SHeiko Schocher * equal to the key in the pointing zbranch. 1353ff94bc40SHeiko Schocher */ 1354ff94bc40SHeiko Schocher min = &zbr->key; 1355ff94bc40SHeiko Schocher cmp = keys_cmp(c, min, &znode->zbranch[0].key); 1356ff94bc40SHeiko Schocher if (cmp == 1) { 1357ff94bc40SHeiko Schocher err = 10; 1358ff94bc40SHeiko Schocher goto out; 1359ff94bc40SHeiko Schocher } 1360ff94bc40SHeiko Schocher 1361ff94bc40SHeiko Schocher if (n + 1 < zp->child_cnt) { 1362ff94bc40SHeiko Schocher max = &zp->zbranch[n + 1].key; 1363ff94bc40SHeiko Schocher 1364ff94bc40SHeiko Schocher /* 1365ff94bc40SHeiko Schocher * Make sure the last key in our znode is less or 1366ff94bc40SHeiko Schocher * equivalent than the key in the zbranch which goes 1367ff94bc40SHeiko Schocher * after our pointing zbranch. 1368ff94bc40SHeiko Schocher */ 1369ff94bc40SHeiko Schocher cmp = keys_cmp(c, max, 1370ff94bc40SHeiko Schocher &znode->zbranch[znode->child_cnt - 1].key); 1371ff94bc40SHeiko Schocher if (cmp == -1) { 1372ff94bc40SHeiko Schocher err = 11; 1373ff94bc40SHeiko Schocher goto out; 1374ff94bc40SHeiko Schocher } 1375ff94bc40SHeiko Schocher } 1376ff94bc40SHeiko Schocher } else { 1377ff94bc40SHeiko Schocher /* This may only be root znode */ 1378ff94bc40SHeiko Schocher if (zbr != &c->zroot) { 1379ff94bc40SHeiko Schocher err = 12; 1380ff94bc40SHeiko Schocher goto out; 1381ff94bc40SHeiko Schocher } 1382ff94bc40SHeiko Schocher } 1383ff94bc40SHeiko Schocher 1384ff94bc40SHeiko Schocher /* 1385ff94bc40SHeiko Schocher * Make sure that next key is greater or equivalent then the previous 1386ff94bc40SHeiko Schocher * one. 1387ff94bc40SHeiko Schocher */ 1388ff94bc40SHeiko Schocher for (n = 1; n < znode->child_cnt; n++) { 1389ff94bc40SHeiko Schocher cmp = keys_cmp(c, &znode->zbranch[n - 1].key, 1390ff94bc40SHeiko Schocher &znode->zbranch[n].key); 1391ff94bc40SHeiko Schocher if (cmp > 0) { 1392ff94bc40SHeiko Schocher err = 13; 1393ff94bc40SHeiko Schocher goto out; 1394ff94bc40SHeiko Schocher } 1395ff94bc40SHeiko Schocher if (cmp == 0) { 1396ff94bc40SHeiko Schocher /* This can only be keys with colliding hash */ 1397ff94bc40SHeiko Schocher if (!is_hash_key(c, &znode->zbranch[n].key)) { 1398ff94bc40SHeiko Schocher err = 14; 1399ff94bc40SHeiko Schocher goto out; 1400ff94bc40SHeiko Schocher } 1401ff94bc40SHeiko Schocher 1402ff94bc40SHeiko Schocher if (znode->level != 0 || c->replaying) 1403ff94bc40SHeiko Schocher continue; 1404ff94bc40SHeiko Schocher 1405ff94bc40SHeiko Schocher /* 1406ff94bc40SHeiko Schocher * Colliding keys should follow binary order of 1407ff94bc40SHeiko Schocher * corresponding xentry/dentry names. 1408ff94bc40SHeiko Schocher */ 1409ff94bc40SHeiko Schocher err = dbg_check_key_order(c, &znode->zbranch[n - 1], 1410ff94bc40SHeiko Schocher &znode->zbranch[n]); 1411ff94bc40SHeiko Schocher if (err < 0) 1412ff94bc40SHeiko Schocher return err; 1413ff94bc40SHeiko Schocher if (err) { 1414ff94bc40SHeiko Schocher err = 15; 1415ff94bc40SHeiko Schocher goto out; 1416ff94bc40SHeiko Schocher } 1417ff94bc40SHeiko Schocher } 1418ff94bc40SHeiko Schocher } 1419ff94bc40SHeiko Schocher 1420ff94bc40SHeiko Schocher for (n = 0; n < znode->child_cnt; n++) { 1421ff94bc40SHeiko Schocher if (!znode->zbranch[n].znode && 1422ff94bc40SHeiko Schocher (znode->zbranch[n].lnum == 0 || 1423ff94bc40SHeiko Schocher znode->zbranch[n].len == 0)) { 1424ff94bc40SHeiko Schocher err = 16; 1425ff94bc40SHeiko Schocher goto out; 1426ff94bc40SHeiko Schocher } 1427ff94bc40SHeiko Schocher 1428ff94bc40SHeiko Schocher if (znode->zbranch[n].lnum != 0 && 1429ff94bc40SHeiko Schocher znode->zbranch[n].len == 0) { 1430ff94bc40SHeiko Schocher err = 17; 1431ff94bc40SHeiko Schocher goto out; 1432ff94bc40SHeiko Schocher } 1433ff94bc40SHeiko Schocher 1434ff94bc40SHeiko Schocher if (znode->zbranch[n].lnum == 0 && 1435ff94bc40SHeiko Schocher znode->zbranch[n].len != 0) { 1436ff94bc40SHeiko Schocher err = 18; 1437ff94bc40SHeiko Schocher goto out; 1438ff94bc40SHeiko Schocher } 1439ff94bc40SHeiko Schocher 1440ff94bc40SHeiko Schocher if (znode->zbranch[n].lnum == 0 && 1441ff94bc40SHeiko Schocher znode->zbranch[n].offs != 0) { 1442ff94bc40SHeiko Schocher err = 19; 1443ff94bc40SHeiko Schocher goto out; 1444ff94bc40SHeiko Schocher } 1445ff94bc40SHeiko Schocher 1446ff94bc40SHeiko Schocher if (znode->level != 0 && znode->zbranch[n].znode) 1447ff94bc40SHeiko Schocher if (znode->zbranch[n].znode->parent != znode) { 1448ff94bc40SHeiko Schocher err = 20; 1449ff94bc40SHeiko Schocher goto out; 1450ff94bc40SHeiko Schocher } 1451ff94bc40SHeiko Schocher } 1452ff94bc40SHeiko Schocher 1453ff94bc40SHeiko Schocher return 0; 1454ff94bc40SHeiko Schocher 1455ff94bc40SHeiko Schocher out: 14560195a7bbSHeiko Schocher ubifs_err(c, "failed, error %d", err); 14570195a7bbSHeiko Schocher ubifs_msg(c, "dump of the znode"); 1458ff94bc40SHeiko Schocher ubifs_dump_znode(c, znode); 1459ff94bc40SHeiko Schocher if (zp) { 14600195a7bbSHeiko Schocher ubifs_msg(c, "dump of the parent znode"); 1461ff94bc40SHeiko Schocher ubifs_dump_znode(c, zp); 1462ff94bc40SHeiko Schocher } 1463ff94bc40SHeiko Schocher dump_stack(); 1464ff94bc40SHeiko Schocher return -EINVAL; 1465ff94bc40SHeiko Schocher } 1466ff94bc40SHeiko Schocher #else 1467ff94bc40SHeiko Schocher 1468ff94bc40SHeiko Schocher int dbg_check_dir(struct ubifs_info *c, const struct inode *dir) 1469ff94bc40SHeiko Schocher { 1470ff94bc40SHeiko Schocher return 0; 1471ff94bc40SHeiko Schocher } 1472ff94bc40SHeiko Schocher 1473ff94bc40SHeiko Schocher void dbg_debugfs_exit_fs(struct ubifs_info *c) 1474ff94bc40SHeiko Schocher { 1475ff94bc40SHeiko Schocher return; 1476ff94bc40SHeiko Schocher } 1477ff94bc40SHeiko Schocher 1478ff94bc40SHeiko Schocher int ubifs_debugging_init(struct ubifs_info *c) 1479ff94bc40SHeiko Schocher { 1480ff94bc40SHeiko Schocher return 0; 1481ff94bc40SHeiko Schocher } 1482ff94bc40SHeiko Schocher void ubifs_debugging_exit(struct ubifs_info *c) 1483ff94bc40SHeiko Schocher { 1484ff94bc40SHeiko Schocher } 1485ff94bc40SHeiko Schocher int dbg_check_filesystem(struct ubifs_info *c) 1486ff94bc40SHeiko Schocher { 1487ff94bc40SHeiko Schocher return 0; 1488ff94bc40SHeiko Schocher } 1489ff94bc40SHeiko Schocher int dbg_debugfs_init_fs(struct ubifs_info *c) 1490ff94bc40SHeiko Schocher { 1491ff94bc40SHeiko Schocher return 0; 1492ff94bc40SHeiko Schocher } 1493ff94bc40SHeiko Schocher #endif 1494ff94bc40SHeiko Schocher 1495ff94bc40SHeiko Schocher #ifndef __UBOOT__ 1496ff94bc40SHeiko Schocher /** 1497ff94bc40SHeiko Schocher * dbg_check_tnc - check TNC tree. 1498ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1499ff94bc40SHeiko Schocher * @extra: do extra checks that are possible at start commit 1500ff94bc40SHeiko Schocher * 1501ff94bc40SHeiko Schocher * This function traverses whole TNC tree and checks every znode. Returns zero 1502ff94bc40SHeiko Schocher * if everything is all right and %-EINVAL if something is wrong with TNC. 1503ff94bc40SHeiko Schocher */ 1504ff94bc40SHeiko Schocher int dbg_check_tnc(struct ubifs_info *c, int extra) 1505ff94bc40SHeiko Schocher { 1506ff94bc40SHeiko Schocher struct ubifs_znode *znode; 1507ff94bc40SHeiko Schocher long clean_cnt = 0, dirty_cnt = 0; 1508ff94bc40SHeiko Schocher int err, last; 1509ff94bc40SHeiko Schocher 1510ff94bc40SHeiko Schocher if (!dbg_is_chk_index(c)) 1511ff94bc40SHeiko Schocher return 0; 1512ff94bc40SHeiko Schocher 1513ff94bc40SHeiko Schocher ubifs_assert(mutex_is_locked(&c->tnc_mutex)); 1514ff94bc40SHeiko Schocher if (!c->zroot.znode) 1515ff94bc40SHeiko Schocher return 0; 1516ff94bc40SHeiko Schocher 1517ff94bc40SHeiko Schocher znode = ubifs_tnc_postorder_first(c->zroot.znode); 1518ff94bc40SHeiko Schocher while (1) { 1519ff94bc40SHeiko Schocher struct ubifs_znode *prev; 1520ff94bc40SHeiko Schocher struct ubifs_zbranch *zbr; 1521ff94bc40SHeiko Schocher 1522ff94bc40SHeiko Schocher if (!znode->parent) 1523ff94bc40SHeiko Schocher zbr = &c->zroot; 1524ff94bc40SHeiko Schocher else 1525ff94bc40SHeiko Schocher zbr = &znode->parent->zbranch[znode->iip]; 1526ff94bc40SHeiko Schocher 1527ff94bc40SHeiko Schocher err = dbg_check_znode(c, zbr); 1528ff94bc40SHeiko Schocher if (err) 1529ff94bc40SHeiko Schocher return err; 1530ff94bc40SHeiko Schocher 1531ff94bc40SHeiko Schocher if (extra) { 1532ff94bc40SHeiko Schocher if (ubifs_zn_dirty(znode)) 1533ff94bc40SHeiko Schocher dirty_cnt += 1; 1534ff94bc40SHeiko Schocher else 1535ff94bc40SHeiko Schocher clean_cnt += 1; 1536ff94bc40SHeiko Schocher } 1537ff94bc40SHeiko Schocher 1538ff94bc40SHeiko Schocher prev = znode; 1539ff94bc40SHeiko Schocher znode = ubifs_tnc_postorder_next(znode); 1540ff94bc40SHeiko Schocher if (!znode) 1541ff94bc40SHeiko Schocher break; 1542ff94bc40SHeiko Schocher 1543ff94bc40SHeiko Schocher /* 1544ff94bc40SHeiko Schocher * If the last key of this znode is equivalent to the first key 1545ff94bc40SHeiko Schocher * of the next znode (collision), then check order of the keys. 1546ff94bc40SHeiko Schocher */ 1547ff94bc40SHeiko Schocher last = prev->child_cnt - 1; 1548ff94bc40SHeiko Schocher if (prev->level == 0 && znode->level == 0 && !c->replaying && 1549ff94bc40SHeiko Schocher !keys_cmp(c, &prev->zbranch[last].key, 1550ff94bc40SHeiko Schocher &znode->zbranch[0].key)) { 1551ff94bc40SHeiko Schocher err = dbg_check_key_order(c, &prev->zbranch[last], 1552ff94bc40SHeiko Schocher &znode->zbranch[0]); 1553ff94bc40SHeiko Schocher if (err < 0) 1554ff94bc40SHeiko Schocher return err; 1555ff94bc40SHeiko Schocher if (err) { 15560195a7bbSHeiko Schocher ubifs_msg(c, "first znode"); 1557ff94bc40SHeiko Schocher ubifs_dump_znode(c, prev); 15580195a7bbSHeiko Schocher ubifs_msg(c, "second znode"); 1559ff94bc40SHeiko Schocher ubifs_dump_znode(c, znode); 1560ff94bc40SHeiko Schocher return -EINVAL; 1561ff94bc40SHeiko Schocher } 1562ff94bc40SHeiko Schocher } 1563ff94bc40SHeiko Schocher } 1564ff94bc40SHeiko Schocher 1565ff94bc40SHeiko Schocher if (extra) { 1566ff94bc40SHeiko Schocher if (clean_cnt != atomic_long_read(&c->clean_zn_cnt)) { 15670195a7bbSHeiko Schocher ubifs_err(c, "incorrect clean_zn_cnt %ld, calculated %ld", 1568ff94bc40SHeiko Schocher atomic_long_read(&c->clean_zn_cnt), 1569ff94bc40SHeiko Schocher clean_cnt); 1570ff94bc40SHeiko Schocher return -EINVAL; 1571ff94bc40SHeiko Schocher } 1572ff94bc40SHeiko Schocher if (dirty_cnt != atomic_long_read(&c->dirty_zn_cnt)) { 15730195a7bbSHeiko Schocher ubifs_err(c, "incorrect dirty_zn_cnt %ld, calculated %ld", 1574ff94bc40SHeiko Schocher atomic_long_read(&c->dirty_zn_cnt), 1575ff94bc40SHeiko Schocher dirty_cnt); 1576ff94bc40SHeiko Schocher return -EINVAL; 1577ff94bc40SHeiko Schocher } 1578ff94bc40SHeiko Schocher } 1579ff94bc40SHeiko Schocher 1580ff94bc40SHeiko Schocher return 0; 1581ff94bc40SHeiko Schocher } 1582ff94bc40SHeiko Schocher #else 1583ff94bc40SHeiko Schocher int dbg_check_tnc(struct ubifs_info *c, int extra) 1584ff94bc40SHeiko Schocher { 1585ff94bc40SHeiko Schocher return 0; 1586ff94bc40SHeiko Schocher } 1587ff94bc40SHeiko Schocher #endif 1588ff94bc40SHeiko Schocher 1589ff94bc40SHeiko Schocher /** 1590ff94bc40SHeiko Schocher * dbg_walk_index - walk the on-flash index. 1591ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1592ff94bc40SHeiko Schocher * @leaf_cb: called for each leaf node 1593ff94bc40SHeiko Schocher * @znode_cb: called for each indexing node 1594ff94bc40SHeiko Schocher * @priv: private data which is passed to callbacks 1595ff94bc40SHeiko Schocher * 1596ff94bc40SHeiko Schocher * This function walks the UBIFS index and calls the @leaf_cb for each leaf 1597ff94bc40SHeiko Schocher * node and @znode_cb for each indexing node. Returns zero in case of success 1598ff94bc40SHeiko Schocher * and a negative error code in case of failure. 1599ff94bc40SHeiko Schocher * 1600ff94bc40SHeiko Schocher * It would be better if this function removed every znode it pulled to into 1601ff94bc40SHeiko Schocher * the TNC, so that the behavior more closely matched the non-debugging 1602ff94bc40SHeiko Schocher * behavior. 1603ff94bc40SHeiko Schocher */ 1604ff94bc40SHeiko Schocher int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb, 1605ff94bc40SHeiko Schocher dbg_znode_callback znode_cb, void *priv) 1606ff94bc40SHeiko Schocher { 1607ff94bc40SHeiko Schocher int err; 1608ff94bc40SHeiko Schocher struct ubifs_zbranch *zbr; 1609ff94bc40SHeiko Schocher struct ubifs_znode *znode, *child; 1610ff94bc40SHeiko Schocher 1611ff94bc40SHeiko Schocher mutex_lock(&c->tnc_mutex); 1612ff94bc40SHeiko Schocher /* If the root indexing node is not in TNC - pull it */ 1613ff94bc40SHeiko Schocher if (!c->zroot.znode) { 1614ff94bc40SHeiko Schocher c->zroot.znode = ubifs_load_znode(c, &c->zroot, NULL, 0); 1615ff94bc40SHeiko Schocher if (IS_ERR(c->zroot.znode)) { 1616ff94bc40SHeiko Schocher err = PTR_ERR(c->zroot.znode); 1617ff94bc40SHeiko Schocher c->zroot.znode = NULL; 1618ff94bc40SHeiko Schocher goto out_unlock; 1619ff94bc40SHeiko Schocher } 1620ff94bc40SHeiko Schocher } 1621ff94bc40SHeiko Schocher 1622ff94bc40SHeiko Schocher /* 1623ff94bc40SHeiko Schocher * We are going to traverse the indexing tree in the postorder manner. 1624ff94bc40SHeiko Schocher * Go down and find the leftmost indexing node where we are going to 1625ff94bc40SHeiko Schocher * start from. 1626ff94bc40SHeiko Schocher */ 1627ff94bc40SHeiko Schocher znode = c->zroot.znode; 1628ff94bc40SHeiko Schocher while (znode->level > 0) { 1629ff94bc40SHeiko Schocher zbr = &znode->zbranch[0]; 1630ff94bc40SHeiko Schocher child = zbr->znode; 1631ff94bc40SHeiko Schocher if (!child) { 1632ff94bc40SHeiko Schocher child = ubifs_load_znode(c, zbr, znode, 0); 1633ff94bc40SHeiko Schocher if (IS_ERR(child)) { 1634ff94bc40SHeiko Schocher err = PTR_ERR(child); 1635ff94bc40SHeiko Schocher goto out_unlock; 1636ff94bc40SHeiko Schocher } 1637ff94bc40SHeiko Schocher zbr->znode = child; 1638ff94bc40SHeiko Schocher } 1639ff94bc40SHeiko Schocher 1640ff94bc40SHeiko Schocher znode = child; 1641ff94bc40SHeiko Schocher } 1642ff94bc40SHeiko Schocher 1643ff94bc40SHeiko Schocher /* Iterate over all indexing nodes */ 1644ff94bc40SHeiko Schocher while (1) { 1645ff94bc40SHeiko Schocher int idx; 1646ff94bc40SHeiko Schocher 1647ff94bc40SHeiko Schocher cond_resched(); 1648ff94bc40SHeiko Schocher 1649ff94bc40SHeiko Schocher if (znode_cb) { 1650ff94bc40SHeiko Schocher err = znode_cb(c, znode, priv); 1651ff94bc40SHeiko Schocher if (err) { 16520195a7bbSHeiko Schocher ubifs_err(c, "znode checking function returned error %d", 1653ff94bc40SHeiko Schocher err); 1654ff94bc40SHeiko Schocher ubifs_dump_znode(c, znode); 1655ff94bc40SHeiko Schocher goto out_dump; 1656ff94bc40SHeiko Schocher } 1657ff94bc40SHeiko Schocher } 1658ff94bc40SHeiko Schocher if (leaf_cb && znode->level == 0) { 1659ff94bc40SHeiko Schocher for (idx = 0; idx < znode->child_cnt; idx++) { 1660ff94bc40SHeiko Schocher zbr = &znode->zbranch[idx]; 1661ff94bc40SHeiko Schocher err = leaf_cb(c, zbr, priv); 1662ff94bc40SHeiko Schocher if (err) { 16630195a7bbSHeiko Schocher ubifs_err(c, "leaf checking function returned error %d, for leaf at LEB %d:%d", 1664ff94bc40SHeiko Schocher err, zbr->lnum, zbr->offs); 1665ff94bc40SHeiko Schocher goto out_dump; 1666ff94bc40SHeiko Schocher } 1667ff94bc40SHeiko Schocher } 1668ff94bc40SHeiko Schocher } 1669ff94bc40SHeiko Schocher 1670ff94bc40SHeiko Schocher if (!znode->parent) 1671ff94bc40SHeiko Schocher break; 1672ff94bc40SHeiko Schocher 1673ff94bc40SHeiko Schocher idx = znode->iip + 1; 1674ff94bc40SHeiko Schocher znode = znode->parent; 1675ff94bc40SHeiko Schocher if (idx < znode->child_cnt) { 1676ff94bc40SHeiko Schocher /* Switch to the next index in the parent */ 1677ff94bc40SHeiko Schocher zbr = &znode->zbranch[idx]; 1678ff94bc40SHeiko Schocher child = zbr->znode; 1679ff94bc40SHeiko Schocher if (!child) { 1680ff94bc40SHeiko Schocher child = ubifs_load_znode(c, zbr, znode, idx); 1681ff94bc40SHeiko Schocher if (IS_ERR(child)) { 1682ff94bc40SHeiko Schocher err = PTR_ERR(child); 1683ff94bc40SHeiko Schocher goto out_unlock; 1684ff94bc40SHeiko Schocher } 1685ff94bc40SHeiko Schocher zbr->znode = child; 1686ff94bc40SHeiko Schocher } 1687ff94bc40SHeiko Schocher znode = child; 1688ff94bc40SHeiko Schocher } else 1689ff94bc40SHeiko Schocher /* 1690ff94bc40SHeiko Schocher * This is the last child, switch to the parent and 1691ff94bc40SHeiko Schocher * continue. 1692ff94bc40SHeiko Schocher */ 1693ff94bc40SHeiko Schocher continue; 1694ff94bc40SHeiko Schocher 1695ff94bc40SHeiko Schocher /* Go to the lowest leftmost znode in the new sub-tree */ 1696ff94bc40SHeiko Schocher while (znode->level > 0) { 1697ff94bc40SHeiko Schocher zbr = &znode->zbranch[0]; 1698ff94bc40SHeiko Schocher child = zbr->znode; 1699ff94bc40SHeiko Schocher if (!child) { 1700ff94bc40SHeiko Schocher child = ubifs_load_znode(c, zbr, znode, 0); 1701ff94bc40SHeiko Schocher if (IS_ERR(child)) { 1702ff94bc40SHeiko Schocher err = PTR_ERR(child); 1703ff94bc40SHeiko Schocher goto out_unlock; 1704ff94bc40SHeiko Schocher } 1705ff94bc40SHeiko Schocher zbr->znode = child; 1706ff94bc40SHeiko Schocher } 1707ff94bc40SHeiko Schocher znode = child; 1708ff94bc40SHeiko Schocher } 1709ff94bc40SHeiko Schocher } 1710ff94bc40SHeiko Schocher 1711ff94bc40SHeiko Schocher mutex_unlock(&c->tnc_mutex); 1712ff94bc40SHeiko Schocher return 0; 1713ff94bc40SHeiko Schocher 1714ff94bc40SHeiko Schocher out_dump: 1715ff94bc40SHeiko Schocher if (znode->parent) 1716ff94bc40SHeiko Schocher zbr = &znode->parent->zbranch[znode->iip]; 1717ff94bc40SHeiko Schocher else 1718ff94bc40SHeiko Schocher zbr = &c->zroot; 17190195a7bbSHeiko Schocher ubifs_msg(c, "dump of znode at LEB %d:%d", zbr->lnum, zbr->offs); 1720ff94bc40SHeiko Schocher ubifs_dump_znode(c, znode); 1721ff94bc40SHeiko Schocher out_unlock: 1722ff94bc40SHeiko Schocher mutex_unlock(&c->tnc_mutex); 1723ff94bc40SHeiko Schocher return err; 1724ff94bc40SHeiko Schocher } 1725ff94bc40SHeiko Schocher 1726ff94bc40SHeiko Schocher /** 1727ff94bc40SHeiko Schocher * add_size - add znode size to partially calculated index size. 1728ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1729ff94bc40SHeiko Schocher * @znode: znode to add size for 1730ff94bc40SHeiko Schocher * @priv: partially calculated index size 1731ff94bc40SHeiko Schocher * 1732ff94bc40SHeiko Schocher * This is a helper function for 'dbg_check_idx_size()' which is called for 1733ff94bc40SHeiko Schocher * every indexing node and adds its size to the 'long long' variable pointed to 1734ff94bc40SHeiko Schocher * by @priv. 1735ff94bc40SHeiko Schocher */ 1736ff94bc40SHeiko Schocher static int add_size(struct ubifs_info *c, struct ubifs_znode *znode, void *priv) 1737ff94bc40SHeiko Schocher { 1738ff94bc40SHeiko Schocher long long *idx_size = priv; 1739ff94bc40SHeiko Schocher int add; 1740ff94bc40SHeiko Schocher 1741ff94bc40SHeiko Schocher add = ubifs_idx_node_sz(c, znode->child_cnt); 1742ff94bc40SHeiko Schocher add = ALIGN(add, 8); 1743ff94bc40SHeiko Schocher *idx_size += add; 1744ff94bc40SHeiko Schocher return 0; 1745ff94bc40SHeiko Schocher } 1746ff94bc40SHeiko Schocher 1747ff94bc40SHeiko Schocher /** 1748ff94bc40SHeiko Schocher * dbg_check_idx_size - check index size. 1749ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1750ff94bc40SHeiko Schocher * @idx_size: size to check 1751ff94bc40SHeiko Schocher * 1752ff94bc40SHeiko Schocher * This function walks the UBIFS index, calculates its size and checks that the 1753ff94bc40SHeiko Schocher * size is equivalent to @idx_size. Returns zero in case of success and a 1754ff94bc40SHeiko Schocher * negative error code in case of failure. 1755ff94bc40SHeiko Schocher */ 1756ff94bc40SHeiko Schocher int dbg_check_idx_size(struct ubifs_info *c, long long idx_size) 1757ff94bc40SHeiko Schocher { 1758ff94bc40SHeiko Schocher int err; 1759ff94bc40SHeiko Schocher long long calc = 0; 1760ff94bc40SHeiko Schocher 1761ff94bc40SHeiko Schocher if (!dbg_is_chk_index(c)) 1762ff94bc40SHeiko Schocher return 0; 1763ff94bc40SHeiko Schocher 1764ff94bc40SHeiko Schocher err = dbg_walk_index(c, NULL, add_size, &calc); 1765ff94bc40SHeiko Schocher if (err) { 17660195a7bbSHeiko Schocher ubifs_err(c, "error %d while walking the index", err); 1767ff94bc40SHeiko Schocher return err; 1768ff94bc40SHeiko Schocher } 1769ff94bc40SHeiko Schocher 1770ff94bc40SHeiko Schocher if (calc != idx_size) { 17710195a7bbSHeiko Schocher ubifs_err(c, "index size check failed: calculated size is %lld, should be %lld", 1772ff94bc40SHeiko Schocher calc, idx_size); 1773ff94bc40SHeiko Schocher dump_stack(); 1774ff94bc40SHeiko Schocher return -EINVAL; 1775ff94bc40SHeiko Schocher } 1776ff94bc40SHeiko Schocher 1777ff94bc40SHeiko Schocher return 0; 1778ff94bc40SHeiko Schocher } 1779ff94bc40SHeiko Schocher 1780ff94bc40SHeiko Schocher #ifndef __UBOOT__ 1781ff94bc40SHeiko Schocher /** 1782ff94bc40SHeiko Schocher * struct fsck_inode - information about an inode used when checking the file-system. 1783ff94bc40SHeiko Schocher * @rb: link in the RB-tree of inodes 1784ff94bc40SHeiko Schocher * @inum: inode number 1785ff94bc40SHeiko Schocher * @mode: inode type, permissions, etc 1786ff94bc40SHeiko Schocher * @nlink: inode link count 1787ff94bc40SHeiko Schocher * @xattr_cnt: count of extended attributes 1788ff94bc40SHeiko Schocher * @references: how many directory/xattr entries refer this inode (calculated 1789ff94bc40SHeiko Schocher * while walking the index) 1790ff94bc40SHeiko Schocher * @calc_cnt: for directory inode count of child directories 1791ff94bc40SHeiko Schocher * @size: inode size (read from on-flash inode) 1792ff94bc40SHeiko Schocher * @xattr_sz: summary size of all extended attributes (read from on-flash 1793ff94bc40SHeiko Schocher * inode) 1794ff94bc40SHeiko Schocher * @calc_sz: for directories calculated directory size 1795ff94bc40SHeiko Schocher * @calc_xcnt: count of extended attributes 1796ff94bc40SHeiko Schocher * @calc_xsz: calculated summary size of all extended attributes 1797ff94bc40SHeiko Schocher * @xattr_nms: sum of lengths of all extended attribute names belonging to this 1798ff94bc40SHeiko Schocher * inode (read from on-flash inode) 1799ff94bc40SHeiko Schocher * @calc_xnms: calculated sum of lengths of all extended attribute names 1800ff94bc40SHeiko Schocher */ 1801ff94bc40SHeiko Schocher struct fsck_inode { 1802ff94bc40SHeiko Schocher struct rb_node rb; 1803ff94bc40SHeiko Schocher ino_t inum; 1804ff94bc40SHeiko Schocher umode_t mode; 1805ff94bc40SHeiko Schocher unsigned int nlink; 1806ff94bc40SHeiko Schocher unsigned int xattr_cnt; 1807ff94bc40SHeiko Schocher int references; 1808ff94bc40SHeiko Schocher int calc_cnt; 1809ff94bc40SHeiko Schocher long long size; 1810ff94bc40SHeiko Schocher unsigned int xattr_sz; 1811ff94bc40SHeiko Schocher long long calc_sz; 1812ff94bc40SHeiko Schocher long long calc_xcnt; 1813ff94bc40SHeiko Schocher long long calc_xsz; 1814ff94bc40SHeiko Schocher unsigned int xattr_nms; 1815ff94bc40SHeiko Schocher long long calc_xnms; 1816ff94bc40SHeiko Schocher }; 1817ff94bc40SHeiko Schocher 1818ff94bc40SHeiko Schocher /** 1819ff94bc40SHeiko Schocher * struct fsck_data - private FS checking information. 1820ff94bc40SHeiko Schocher * @inodes: RB-tree of all inodes (contains @struct fsck_inode objects) 1821ff94bc40SHeiko Schocher */ 1822ff94bc40SHeiko Schocher struct fsck_data { 1823ff94bc40SHeiko Schocher struct rb_root inodes; 1824ff94bc40SHeiko Schocher }; 1825ff94bc40SHeiko Schocher 1826ff94bc40SHeiko Schocher /** 1827ff94bc40SHeiko Schocher * add_inode - add inode information to RB-tree of inodes. 1828ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1829ff94bc40SHeiko Schocher * @fsckd: FS checking information 1830ff94bc40SHeiko Schocher * @ino: raw UBIFS inode to add 1831ff94bc40SHeiko Schocher * 1832ff94bc40SHeiko Schocher * This is a helper function for 'check_leaf()' which adds information about 1833ff94bc40SHeiko Schocher * inode @ino to the RB-tree of inodes. Returns inode information pointer in 1834ff94bc40SHeiko Schocher * case of success and a negative error code in case of failure. 1835ff94bc40SHeiko Schocher */ 1836ff94bc40SHeiko Schocher static struct fsck_inode *add_inode(struct ubifs_info *c, 1837ff94bc40SHeiko Schocher struct fsck_data *fsckd, 1838ff94bc40SHeiko Schocher struct ubifs_ino_node *ino) 1839ff94bc40SHeiko Schocher { 1840ff94bc40SHeiko Schocher struct rb_node **p, *parent = NULL; 1841ff94bc40SHeiko Schocher struct fsck_inode *fscki; 1842ff94bc40SHeiko Schocher ino_t inum = key_inum_flash(c, &ino->key); 1843ff94bc40SHeiko Schocher struct inode *inode; 1844ff94bc40SHeiko Schocher struct ubifs_inode *ui; 1845ff94bc40SHeiko Schocher 1846ff94bc40SHeiko Schocher p = &fsckd->inodes.rb_node; 1847ff94bc40SHeiko Schocher while (*p) { 1848ff94bc40SHeiko Schocher parent = *p; 1849ff94bc40SHeiko Schocher fscki = rb_entry(parent, struct fsck_inode, rb); 1850ff94bc40SHeiko Schocher if (inum < fscki->inum) 1851ff94bc40SHeiko Schocher p = &(*p)->rb_left; 1852ff94bc40SHeiko Schocher else if (inum > fscki->inum) 1853ff94bc40SHeiko Schocher p = &(*p)->rb_right; 1854ff94bc40SHeiko Schocher else 1855ff94bc40SHeiko Schocher return fscki; 1856ff94bc40SHeiko Schocher } 1857ff94bc40SHeiko Schocher 1858ff94bc40SHeiko Schocher if (inum > c->highest_inum) { 18590195a7bbSHeiko Schocher ubifs_err(c, "too high inode number, max. is %lu", 1860ff94bc40SHeiko Schocher (unsigned long)c->highest_inum); 1861ff94bc40SHeiko Schocher return ERR_PTR(-EINVAL); 1862ff94bc40SHeiko Schocher } 1863ff94bc40SHeiko Schocher 1864ff94bc40SHeiko Schocher fscki = kzalloc(sizeof(struct fsck_inode), GFP_NOFS); 1865ff94bc40SHeiko Schocher if (!fscki) 1866ff94bc40SHeiko Schocher return ERR_PTR(-ENOMEM); 1867ff94bc40SHeiko Schocher 1868ff94bc40SHeiko Schocher inode = ilookup(c->vfs_sb, inum); 1869ff94bc40SHeiko Schocher 1870ff94bc40SHeiko Schocher fscki->inum = inum; 1871ff94bc40SHeiko Schocher /* 1872ff94bc40SHeiko Schocher * If the inode is present in the VFS inode cache, use it instead of 1873ff94bc40SHeiko Schocher * the on-flash inode which might be out-of-date. E.g., the size might 1874ff94bc40SHeiko Schocher * be out-of-date. If we do not do this, the following may happen, for 1875ff94bc40SHeiko Schocher * example: 1876ff94bc40SHeiko Schocher * 1. A power cut happens 1877ff94bc40SHeiko Schocher * 2. We mount the file-system R/O, the replay process fixes up the 1878ff94bc40SHeiko Schocher * inode size in the VFS cache, but on on-flash. 1879ff94bc40SHeiko Schocher * 3. 'check_leaf()' fails because it hits a data node beyond inode 1880ff94bc40SHeiko Schocher * size. 1881ff94bc40SHeiko Schocher */ 1882ff94bc40SHeiko Schocher if (!inode) { 1883ff94bc40SHeiko Schocher fscki->nlink = le32_to_cpu(ino->nlink); 1884ff94bc40SHeiko Schocher fscki->size = le64_to_cpu(ino->size); 1885ff94bc40SHeiko Schocher fscki->xattr_cnt = le32_to_cpu(ino->xattr_cnt); 1886ff94bc40SHeiko Schocher fscki->xattr_sz = le32_to_cpu(ino->xattr_size); 1887ff94bc40SHeiko Schocher fscki->xattr_nms = le32_to_cpu(ino->xattr_names); 1888ff94bc40SHeiko Schocher fscki->mode = le32_to_cpu(ino->mode); 1889ff94bc40SHeiko Schocher } else { 1890ff94bc40SHeiko Schocher ui = ubifs_inode(inode); 1891ff94bc40SHeiko Schocher fscki->nlink = inode->i_nlink; 1892ff94bc40SHeiko Schocher fscki->size = inode->i_size; 1893ff94bc40SHeiko Schocher fscki->xattr_cnt = ui->xattr_cnt; 1894ff94bc40SHeiko Schocher fscki->xattr_sz = ui->xattr_size; 1895ff94bc40SHeiko Schocher fscki->xattr_nms = ui->xattr_names; 1896ff94bc40SHeiko Schocher fscki->mode = inode->i_mode; 1897ff94bc40SHeiko Schocher iput(inode); 1898ff94bc40SHeiko Schocher } 1899ff94bc40SHeiko Schocher 1900ff94bc40SHeiko Schocher if (S_ISDIR(fscki->mode)) { 1901ff94bc40SHeiko Schocher fscki->calc_sz = UBIFS_INO_NODE_SZ; 1902ff94bc40SHeiko Schocher fscki->calc_cnt = 2; 1903ff94bc40SHeiko Schocher } 1904ff94bc40SHeiko Schocher 1905ff94bc40SHeiko Schocher rb_link_node(&fscki->rb, parent, p); 1906ff94bc40SHeiko Schocher rb_insert_color(&fscki->rb, &fsckd->inodes); 1907ff94bc40SHeiko Schocher 1908ff94bc40SHeiko Schocher return fscki; 1909ff94bc40SHeiko Schocher } 1910ff94bc40SHeiko Schocher 1911ff94bc40SHeiko Schocher /** 1912ff94bc40SHeiko Schocher * search_inode - search inode in the RB-tree of inodes. 1913ff94bc40SHeiko Schocher * @fsckd: FS checking information 1914ff94bc40SHeiko Schocher * @inum: inode number to search 1915ff94bc40SHeiko Schocher * 1916ff94bc40SHeiko Schocher * This is a helper function for 'check_leaf()' which searches inode @inum in 1917ff94bc40SHeiko Schocher * the RB-tree of inodes and returns an inode information pointer or %NULL if 1918ff94bc40SHeiko Schocher * the inode was not found. 1919ff94bc40SHeiko Schocher */ 1920ff94bc40SHeiko Schocher static struct fsck_inode *search_inode(struct fsck_data *fsckd, ino_t inum) 1921ff94bc40SHeiko Schocher { 1922ff94bc40SHeiko Schocher struct rb_node *p; 1923ff94bc40SHeiko Schocher struct fsck_inode *fscki; 1924ff94bc40SHeiko Schocher 1925ff94bc40SHeiko Schocher p = fsckd->inodes.rb_node; 1926ff94bc40SHeiko Schocher while (p) { 1927ff94bc40SHeiko Schocher fscki = rb_entry(p, struct fsck_inode, rb); 1928ff94bc40SHeiko Schocher if (inum < fscki->inum) 1929ff94bc40SHeiko Schocher p = p->rb_left; 1930ff94bc40SHeiko Schocher else if (inum > fscki->inum) 1931ff94bc40SHeiko Schocher p = p->rb_right; 1932ff94bc40SHeiko Schocher else 1933ff94bc40SHeiko Schocher return fscki; 1934ff94bc40SHeiko Schocher } 1935ff94bc40SHeiko Schocher return NULL; 1936ff94bc40SHeiko Schocher } 1937ff94bc40SHeiko Schocher 1938ff94bc40SHeiko Schocher /** 1939ff94bc40SHeiko Schocher * read_add_inode - read inode node and add it to RB-tree of inodes. 1940ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1941ff94bc40SHeiko Schocher * @fsckd: FS checking information 1942ff94bc40SHeiko Schocher * @inum: inode number to read 1943ff94bc40SHeiko Schocher * 1944ff94bc40SHeiko Schocher * This is a helper function for 'check_leaf()' which finds inode node @inum in 1945ff94bc40SHeiko Schocher * the index, reads it, and adds it to the RB-tree of inodes. Returns inode 1946ff94bc40SHeiko Schocher * information pointer in case of success and a negative error code in case of 1947ff94bc40SHeiko Schocher * failure. 1948ff94bc40SHeiko Schocher */ 1949ff94bc40SHeiko Schocher static struct fsck_inode *read_add_inode(struct ubifs_info *c, 1950ff94bc40SHeiko Schocher struct fsck_data *fsckd, ino_t inum) 1951ff94bc40SHeiko Schocher { 1952ff94bc40SHeiko Schocher int n, err; 1953ff94bc40SHeiko Schocher union ubifs_key key; 1954ff94bc40SHeiko Schocher struct ubifs_znode *znode; 1955ff94bc40SHeiko Schocher struct ubifs_zbranch *zbr; 1956ff94bc40SHeiko Schocher struct ubifs_ino_node *ino; 1957ff94bc40SHeiko Schocher struct fsck_inode *fscki; 1958ff94bc40SHeiko Schocher 1959ff94bc40SHeiko Schocher fscki = search_inode(fsckd, inum); 1960ff94bc40SHeiko Schocher if (fscki) 1961ff94bc40SHeiko Schocher return fscki; 1962ff94bc40SHeiko Schocher 1963ff94bc40SHeiko Schocher ino_key_init(c, &key, inum); 1964ff94bc40SHeiko Schocher err = ubifs_lookup_level0(c, &key, &znode, &n); 1965ff94bc40SHeiko Schocher if (!err) { 19660195a7bbSHeiko Schocher ubifs_err(c, "inode %lu not found in index", (unsigned long)inum); 1967ff94bc40SHeiko Schocher return ERR_PTR(-ENOENT); 1968ff94bc40SHeiko Schocher } else if (err < 0) { 19690195a7bbSHeiko Schocher ubifs_err(c, "error %d while looking up inode %lu", 1970ff94bc40SHeiko Schocher err, (unsigned long)inum); 1971ff94bc40SHeiko Schocher return ERR_PTR(err); 1972ff94bc40SHeiko Schocher } 1973ff94bc40SHeiko Schocher 1974ff94bc40SHeiko Schocher zbr = &znode->zbranch[n]; 1975ff94bc40SHeiko Schocher if (zbr->len < UBIFS_INO_NODE_SZ) { 19760195a7bbSHeiko Schocher ubifs_err(c, "bad node %lu node length %d", 1977ff94bc40SHeiko Schocher (unsigned long)inum, zbr->len); 1978ff94bc40SHeiko Schocher return ERR_PTR(-EINVAL); 1979ff94bc40SHeiko Schocher } 1980ff94bc40SHeiko Schocher 1981ff94bc40SHeiko Schocher ino = kmalloc(zbr->len, GFP_NOFS); 1982ff94bc40SHeiko Schocher if (!ino) 1983ff94bc40SHeiko Schocher return ERR_PTR(-ENOMEM); 1984ff94bc40SHeiko Schocher 1985ff94bc40SHeiko Schocher err = ubifs_tnc_read_node(c, zbr, ino); 1986ff94bc40SHeiko Schocher if (err) { 19870195a7bbSHeiko Schocher ubifs_err(c, "cannot read inode node at LEB %d:%d, error %d", 1988ff94bc40SHeiko Schocher zbr->lnum, zbr->offs, err); 1989ff94bc40SHeiko Schocher kfree(ino); 1990ff94bc40SHeiko Schocher return ERR_PTR(err); 1991ff94bc40SHeiko Schocher } 1992ff94bc40SHeiko Schocher 1993ff94bc40SHeiko Schocher fscki = add_inode(c, fsckd, ino); 1994ff94bc40SHeiko Schocher kfree(ino); 1995ff94bc40SHeiko Schocher if (IS_ERR(fscki)) { 19960195a7bbSHeiko Schocher ubifs_err(c, "error %ld while adding inode %lu node", 1997ff94bc40SHeiko Schocher PTR_ERR(fscki), (unsigned long)inum); 1998ff94bc40SHeiko Schocher return fscki; 1999ff94bc40SHeiko Schocher } 2000ff94bc40SHeiko Schocher 2001ff94bc40SHeiko Schocher return fscki; 2002ff94bc40SHeiko Schocher } 2003ff94bc40SHeiko Schocher 2004ff94bc40SHeiko Schocher /** 2005ff94bc40SHeiko Schocher * check_leaf - check leaf node. 2006ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 2007ff94bc40SHeiko Schocher * @zbr: zbranch of the leaf node to check 2008ff94bc40SHeiko Schocher * @priv: FS checking information 2009ff94bc40SHeiko Schocher * 2010ff94bc40SHeiko Schocher * This is a helper function for 'dbg_check_filesystem()' which is called for 2011ff94bc40SHeiko Schocher * every single leaf node while walking the indexing tree. It checks that the 2012ff94bc40SHeiko Schocher * leaf node referred from the indexing tree exists, has correct CRC, and does 2013ff94bc40SHeiko Schocher * some other basic validation. This function is also responsible for building 2014ff94bc40SHeiko Schocher * an RB-tree of inodes - it adds all inodes into the RB-tree. It also 2015ff94bc40SHeiko Schocher * calculates reference count, size, etc for each inode in order to later 2016ff94bc40SHeiko Schocher * compare them to the information stored inside the inodes and detect possible 2017ff94bc40SHeiko Schocher * inconsistencies. Returns zero in case of success and a negative error code 2018ff94bc40SHeiko Schocher * in case of failure. 2019ff94bc40SHeiko Schocher */ 2020ff94bc40SHeiko Schocher static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr, 2021ff94bc40SHeiko Schocher void *priv) 2022ff94bc40SHeiko Schocher { 2023ff94bc40SHeiko Schocher ino_t inum; 2024ff94bc40SHeiko Schocher void *node; 2025ff94bc40SHeiko Schocher struct ubifs_ch *ch; 2026ff94bc40SHeiko Schocher int err, type = key_type(c, &zbr->key); 2027ff94bc40SHeiko Schocher struct fsck_inode *fscki; 2028ff94bc40SHeiko Schocher 2029ff94bc40SHeiko Schocher if (zbr->len < UBIFS_CH_SZ) { 20300195a7bbSHeiko Schocher ubifs_err(c, "bad leaf length %d (LEB %d:%d)", 2031ff94bc40SHeiko Schocher zbr->len, zbr->lnum, zbr->offs); 2032ff94bc40SHeiko Schocher return -EINVAL; 2033ff94bc40SHeiko Schocher } 2034ff94bc40SHeiko Schocher 2035ff94bc40SHeiko Schocher node = kmalloc(zbr->len, GFP_NOFS); 2036ff94bc40SHeiko Schocher if (!node) 2037ff94bc40SHeiko Schocher return -ENOMEM; 2038ff94bc40SHeiko Schocher 2039ff94bc40SHeiko Schocher err = ubifs_tnc_read_node(c, zbr, node); 2040ff94bc40SHeiko Schocher if (err) { 20410195a7bbSHeiko Schocher ubifs_err(c, "cannot read leaf node at LEB %d:%d, error %d", 2042ff94bc40SHeiko Schocher zbr->lnum, zbr->offs, err); 2043ff94bc40SHeiko Schocher goto out_free; 2044ff94bc40SHeiko Schocher } 2045ff94bc40SHeiko Schocher 2046ff94bc40SHeiko Schocher /* If this is an inode node, add it to RB-tree of inodes */ 2047ff94bc40SHeiko Schocher if (type == UBIFS_INO_KEY) { 2048ff94bc40SHeiko Schocher fscki = add_inode(c, priv, node); 2049ff94bc40SHeiko Schocher if (IS_ERR(fscki)) { 2050ff94bc40SHeiko Schocher err = PTR_ERR(fscki); 20510195a7bbSHeiko Schocher ubifs_err(c, "error %d while adding inode node", err); 2052ff94bc40SHeiko Schocher goto out_dump; 2053ff94bc40SHeiko Schocher } 2054ff94bc40SHeiko Schocher goto out; 2055ff94bc40SHeiko Schocher } 2056ff94bc40SHeiko Schocher 2057ff94bc40SHeiko Schocher if (type != UBIFS_DENT_KEY && type != UBIFS_XENT_KEY && 2058ff94bc40SHeiko Schocher type != UBIFS_DATA_KEY) { 20590195a7bbSHeiko Schocher ubifs_err(c, "unexpected node type %d at LEB %d:%d", 2060ff94bc40SHeiko Schocher type, zbr->lnum, zbr->offs); 2061ff94bc40SHeiko Schocher err = -EINVAL; 2062ff94bc40SHeiko Schocher goto out_free; 2063ff94bc40SHeiko Schocher } 2064ff94bc40SHeiko Schocher 2065ff94bc40SHeiko Schocher ch = node; 2066ff94bc40SHeiko Schocher if (le64_to_cpu(ch->sqnum) > c->max_sqnum) { 20670195a7bbSHeiko Schocher ubifs_err(c, "too high sequence number, max. is %llu", 2068ff94bc40SHeiko Schocher c->max_sqnum); 2069ff94bc40SHeiko Schocher err = -EINVAL; 2070ff94bc40SHeiko Schocher goto out_dump; 2071ff94bc40SHeiko Schocher } 2072ff94bc40SHeiko Schocher 2073ff94bc40SHeiko Schocher if (type == UBIFS_DATA_KEY) { 2074ff94bc40SHeiko Schocher long long blk_offs; 2075ff94bc40SHeiko Schocher struct ubifs_data_node *dn = node; 2076ff94bc40SHeiko Schocher 20770195a7bbSHeiko Schocher ubifs_assert(zbr->len >= UBIFS_DATA_NODE_SZ); 20780195a7bbSHeiko Schocher 2079ff94bc40SHeiko Schocher /* 2080ff94bc40SHeiko Schocher * Search the inode node this data node belongs to and insert 2081ff94bc40SHeiko Schocher * it to the RB-tree of inodes. 2082ff94bc40SHeiko Schocher */ 2083ff94bc40SHeiko Schocher inum = key_inum_flash(c, &dn->key); 2084ff94bc40SHeiko Schocher fscki = read_add_inode(c, priv, inum); 2085ff94bc40SHeiko Schocher if (IS_ERR(fscki)) { 2086ff94bc40SHeiko Schocher err = PTR_ERR(fscki); 20870195a7bbSHeiko Schocher ubifs_err(c, "error %d while processing data node and trying to find inode node %lu", 2088ff94bc40SHeiko Schocher err, (unsigned long)inum); 2089ff94bc40SHeiko Schocher goto out_dump; 2090ff94bc40SHeiko Schocher } 2091ff94bc40SHeiko Schocher 2092ff94bc40SHeiko Schocher /* Make sure the data node is within inode size */ 2093ff94bc40SHeiko Schocher blk_offs = key_block_flash(c, &dn->key); 2094ff94bc40SHeiko Schocher blk_offs <<= UBIFS_BLOCK_SHIFT; 2095ff94bc40SHeiko Schocher blk_offs += le32_to_cpu(dn->size); 2096ff94bc40SHeiko Schocher if (blk_offs > fscki->size) { 20970195a7bbSHeiko Schocher ubifs_err(c, "data node at LEB %d:%d is not within inode size %lld", 2098ff94bc40SHeiko Schocher zbr->lnum, zbr->offs, fscki->size); 2099ff94bc40SHeiko Schocher err = -EINVAL; 2100ff94bc40SHeiko Schocher goto out_dump; 2101ff94bc40SHeiko Schocher } 2102ff94bc40SHeiko Schocher } else { 2103ff94bc40SHeiko Schocher int nlen; 2104ff94bc40SHeiko Schocher struct ubifs_dent_node *dent = node; 2105ff94bc40SHeiko Schocher struct fsck_inode *fscki1; 2106ff94bc40SHeiko Schocher 21070195a7bbSHeiko Schocher ubifs_assert(zbr->len >= UBIFS_DENT_NODE_SZ); 21080195a7bbSHeiko Schocher 2109ff94bc40SHeiko Schocher err = ubifs_validate_entry(c, dent); 2110ff94bc40SHeiko Schocher if (err) 2111ff94bc40SHeiko Schocher goto out_dump; 2112ff94bc40SHeiko Schocher 2113ff94bc40SHeiko Schocher /* 2114ff94bc40SHeiko Schocher * Search the inode node this entry refers to and the parent 2115ff94bc40SHeiko Schocher * inode node and insert them to the RB-tree of inodes. 2116ff94bc40SHeiko Schocher */ 2117ff94bc40SHeiko Schocher inum = le64_to_cpu(dent->inum); 2118ff94bc40SHeiko Schocher fscki = read_add_inode(c, priv, inum); 2119ff94bc40SHeiko Schocher if (IS_ERR(fscki)) { 2120ff94bc40SHeiko Schocher err = PTR_ERR(fscki); 21210195a7bbSHeiko Schocher ubifs_err(c, "error %d while processing entry node and trying to find inode node %lu", 2122ff94bc40SHeiko Schocher err, (unsigned long)inum); 2123ff94bc40SHeiko Schocher goto out_dump; 2124ff94bc40SHeiko Schocher } 2125ff94bc40SHeiko Schocher 2126ff94bc40SHeiko Schocher /* Count how many direntries or xentries refers this inode */ 2127ff94bc40SHeiko Schocher fscki->references += 1; 2128ff94bc40SHeiko Schocher 2129ff94bc40SHeiko Schocher inum = key_inum_flash(c, &dent->key); 2130ff94bc40SHeiko Schocher fscki1 = read_add_inode(c, priv, inum); 2131ff94bc40SHeiko Schocher if (IS_ERR(fscki1)) { 2132ff94bc40SHeiko Schocher err = PTR_ERR(fscki1); 21330195a7bbSHeiko Schocher ubifs_err(c, "error %d while processing entry node and trying to find parent inode node %lu", 2134ff94bc40SHeiko Schocher err, (unsigned long)inum); 2135ff94bc40SHeiko Schocher goto out_dump; 2136ff94bc40SHeiko Schocher } 2137ff94bc40SHeiko Schocher 2138ff94bc40SHeiko Schocher nlen = le16_to_cpu(dent->nlen); 2139ff94bc40SHeiko Schocher if (type == UBIFS_XENT_KEY) { 2140ff94bc40SHeiko Schocher fscki1->calc_xcnt += 1; 2141ff94bc40SHeiko Schocher fscki1->calc_xsz += CALC_DENT_SIZE(nlen); 2142ff94bc40SHeiko Schocher fscki1->calc_xsz += CALC_XATTR_BYTES(fscki->size); 2143ff94bc40SHeiko Schocher fscki1->calc_xnms += nlen; 2144ff94bc40SHeiko Schocher } else { 2145ff94bc40SHeiko Schocher fscki1->calc_sz += CALC_DENT_SIZE(nlen); 2146ff94bc40SHeiko Schocher if (dent->type == UBIFS_ITYPE_DIR) 2147ff94bc40SHeiko Schocher fscki1->calc_cnt += 1; 2148ff94bc40SHeiko Schocher } 2149ff94bc40SHeiko Schocher } 2150ff94bc40SHeiko Schocher 2151ff94bc40SHeiko Schocher out: 2152ff94bc40SHeiko Schocher kfree(node); 2153ff94bc40SHeiko Schocher return 0; 2154ff94bc40SHeiko Schocher 2155ff94bc40SHeiko Schocher out_dump: 21560195a7bbSHeiko Schocher ubifs_msg(c, "dump of node at LEB %d:%d", zbr->lnum, zbr->offs); 2157ff94bc40SHeiko Schocher ubifs_dump_node(c, node); 2158ff94bc40SHeiko Schocher out_free: 2159ff94bc40SHeiko Schocher kfree(node); 2160ff94bc40SHeiko Schocher return err; 2161ff94bc40SHeiko Schocher } 2162ff94bc40SHeiko Schocher 2163ff94bc40SHeiko Schocher /** 2164ff94bc40SHeiko Schocher * free_inodes - free RB-tree of inodes. 2165ff94bc40SHeiko Schocher * @fsckd: FS checking information 2166ff94bc40SHeiko Schocher */ 2167ff94bc40SHeiko Schocher static void free_inodes(struct fsck_data *fsckd) 2168ff94bc40SHeiko Schocher { 2169ff94bc40SHeiko Schocher struct fsck_inode *fscki, *n; 2170ff94bc40SHeiko Schocher 2171ff94bc40SHeiko Schocher rbtree_postorder_for_each_entry_safe(fscki, n, &fsckd->inodes, rb) 2172ff94bc40SHeiko Schocher kfree(fscki); 2173ff94bc40SHeiko Schocher } 2174ff94bc40SHeiko Schocher 2175ff94bc40SHeiko Schocher /** 2176ff94bc40SHeiko Schocher * check_inodes - checks all inodes. 2177ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 2178ff94bc40SHeiko Schocher * @fsckd: FS checking information 2179ff94bc40SHeiko Schocher * 2180ff94bc40SHeiko Schocher * This is a helper function for 'dbg_check_filesystem()' which walks the 2181ff94bc40SHeiko Schocher * RB-tree of inodes after the index scan has been finished, and checks that 2182ff94bc40SHeiko Schocher * inode nlink, size, etc are correct. Returns zero if inodes are fine, 2183ff94bc40SHeiko Schocher * %-EINVAL if not, and a negative error code in case of failure. 2184ff94bc40SHeiko Schocher */ 2185ff94bc40SHeiko Schocher static int check_inodes(struct ubifs_info *c, struct fsck_data *fsckd) 2186ff94bc40SHeiko Schocher { 2187ff94bc40SHeiko Schocher int n, err; 2188ff94bc40SHeiko Schocher union ubifs_key key; 2189ff94bc40SHeiko Schocher struct ubifs_znode *znode; 2190ff94bc40SHeiko Schocher struct ubifs_zbranch *zbr; 2191ff94bc40SHeiko Schocher struct ubifs_ino_node *ino; 2192ff94bc40SHeiko Schocher struct fsck_inode *fscki; 2193ff94bc40SHeiko Schocher struct rb_node *this = rb_first(&fsckd->inodes); 2194ff94bc40SHeiko Schocher 2195ff94bc40SHeiko Schocher while (this) { 2196ff94bc40SHeiko Schocher fscki = rb_entry(this, struct fsck_inode, rb); 2197ff94bc40SHeiko Schocher this = rb_next(this); 2198ff94bc40SHeiko Schocher 2199ff94bc40SHeiko Schocher if (S_ISDIR(fscki->mode)) { 2200ff94bc40SHeiko Schocher /* 2201ff94bc40SHeiko Schocher * Directories have to have exactly one reference (they 2202ff94bc40SHeiko Schocher * cannot have hardlinks), although root inode is an 2203ff94bc40SHeiko Schocher * exception. 2204ff94bc40SHeiko Schocher */ 2205ff94bc40SHeiko Schocher if (fscki->inum != UBIFS_ROOT_INO && 2206ff94bc40SHeiko Schocher fscki->references != 1) { 22070195a7bbSHeiko Schocher ubifs_err(c, "directory inode %lu has %d direntries which refer it, but should be 1", 2208ff94bc40SHeiko Schocher (unsigned long)fscki->inum, 2209ff94bc40SHeiko Schocher fscki->references); 2210ff94bc40SHeiko Schocher goto out_dump; 2211ff94bc40SHeiko Schocher } 2212ff94bc40SHeiko Schocher if (fscki->inum == UBIFS_ROOT_INO && 2213ff94bc40SHeiko Schocher fscki->references != 0) { 22140195a7bbSHeiko Schocher ubifs_err(c, "root inode %lu has non-zero (%d) direntries which refer it", 2215ff94bc40SHeiko Schocher (unsigned long)fscki->inum, 2216ff94bc40SHeiko Schocher fscki->references); 2217ff94bc40SHeiko Schocher goto out_dump; 2218ff94bc40SHeiko Schocher } 2219ff94bc40SHeiko Schocher if (fscki->calc_sz != fscki->size) { 22200195a7bbSHeiko Schocher ubifs_err(c, "directory inode %lu size is %lld, but calculated size is %lld", 2221ff94bc40SHeiko Schocher (unsigned long)fscki->inum, 2222ff94bc40SHeiko Schocher fscki->size, fscki->calc_sz); 2223ff94bc40SHeiko Schocher goto out_dump; 2224ff94bc40SHeiko Schocher } 2225ff94bc40SHeiko Schocher if (fscki->calc_cnt != fscki->nlink) { 22260195a7bbSHeiko Schocher ubifs_err(c, "directory inode %lu nlink is %d, but calculated nlink is %d", 2227ff94bc40SHeiko Schocher (unsigned long)fscki->inum, 2228ff94bc40SHeiko Schocher fscki->nlink, fscki->calc_cnt); 2229ff94bc40SHeiko Schocher goto out_dump; 2230ff94bc40SHeiko Schocher } 2231ff94bc40SHeiko Schocher } else { 2232ff94bc40SHeiko Schocher if (fscki->references != fscki->nlink) { 22330195a7bbSHeiko Schocher ubifs_err(c, "inode %lu nlink is %d, but calculated nlink is %d", 2234ff94bc40SHeiko Schocher (unsigned long)fscki->inum, 2235ff94bc40SHeiko Schocher fscki->nlink, fscki->references); 2236ff94bc40SHeiko Schocher goto out_dump; 2237ff94bc40SHeiko Schocher } 2238ff94bc40SHeiko Schocher } 2239ff94bc40SHeiko Schocher if (fscki->xattr_sz != fscki->calc_xsz) { 22400195a7bbSHeiko Schocher ubifs_err(c, "inode %lu has xattr size %u, but calculated size is %lld", 2241ff94bc40SHeiko Schocher (unsigned long)fscki->inum, fscki->xattr_sz, 2242ff94bc40SHeiko Schocher fscki->calc_xsz); 2243ff94bc40SHeiko Schocher goto out_dump; 2244ff94bc40SHeiko Schocher } 2245ff94bc40SHeiko Schocher if (fscki->xattr_cnt != fscki->calc_xcnt) { 22460195a7bbSHeiko Schocher ubifs_err(c, "inode %lu has %u xattrs, but calculated count is %lld", 2247ff94bc40SHeiko Schocher (unsigned long)fscki->inum, 2248ff94bc40SHeiko Schocher fscki->xattr_cnt, fscki->calc_xcnt); 2249ff94bc40SHeiko Schocher goto out_dump; 2250ff94bc40SHeiko Schocher } 2251ff94bc40SHeiko Schocher if (fscki->xattr_nms != fscki->calc_xnms) { 22520195a7bbSHeiko Schocher ubifs_err(c, "inode %lu has xattr names' size %u, but calculated names' size is %lld", 2253ff94bc40SHeiko Schocher (unsigned long)fscki->inum, fscki->xattr_nms, 2254ff94bc40SHeiko Schocher fscki->calc_xnms); 2255ff94bc40SHeiko Schocher goto out_dump; 2256ff94bc40SHeiko Schocher } 2257ff94bc40SHeiko Schocher } 2258ff94bc40SHeiko Schocher 2259ff94bc40SHeiko Schocher return 0; 2260ff94bc40SHeiko Schocher 2261ff94bc40SHeiko Schocher out_dump: 2262ff94bc40SHeiko Schocher /* Read the bad inode and dump it */ 2263ff94bc40SHeiko Schocher ino_key_init(c, &key, fscki->inum); 2264ff94bc40SHeiko Schocher err = ubifs_lookup_level0(c, &key, &znode, &n); 2265ff94bc40SHeiko Schocher if (!err) { 22660195a7bbSHeiko Schocher ubifs_err(c, "inode %lu not found in index", 2267ff94bc40SHeiko Schocher (unsigned long)fscki->inum); 2268ff94bc40SHeiko Schocher return -ENOENT; 2269ff94bc40SHeiko Schocher } else if (err < 0) { 22700195a7bbSHeiko Schocher ubifs_err(c, "error %d while looking up inode %lu", 2271ff94bc40SHeiko Schocher err, (unsigned long)fscki->inum); 2272ff94bc40SHeiko Schocher return err; 2273ff94bc40SHeiko Schocher } 2274ff94bc40SHeiko Schocher 2275ff94bc40SHeiko Schocher zbr = &znode->zbranch[n]; 2276ff94bc40SHeiko Schocher ino = kmalloc(zbr->len, GFP_NOFS); 2277ff94bc40SHeiko Schocher if (!ino) 2278ff94bc40SHeiko Schocher return -ENOMEM; 2279ff94bc40SHeiko Schocher 2280ff94bc40SHeiko Schocher err = ubifs_tnc_read_node(c, zbr, ino); 2281ff94bc40SHeiko Schocher if (err) { 22820195a7bbSHeiko Schocher ubifs_err(c, "cannot read inode node at LEB %d:%d, error %d", 2283ff94bc40SHeiko Schocher zbr->lnum, zbr->offs, err); 2284ff94bc40SHeiko Schocher kfree(ino); 2285ff94bc40SHeiko Schocher return err; 2286ff94bc40SHeiko Schocher } 2287ff94bc40SHeiko Schocher 22880195a7bbSHeiko Schocher ubifs_msg(c, "dump of the inode %lu sitting in LEB %d:%d", 2289ff94bc40SHeiko Schocher (unsigned long)fscki->inum, zbr->lnum, zbr->offs); 2290ff94bc40SHeiko Schocher ubifs_dump_node(c, ino); 2291ff94bc40SHeiko Schocher kfree(ino); 2292ff94bc40SHeiko Schocher return -EINVAL; 2293ff94bc40SHeiko Schocher } 2294ff94bc40SHeiko Schocher 2295ff94bc40SHeiko Schocher /** 2296ff94bc40SHeiko Schocher * dbg_check_filesystem - check the file-system. 2297ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 2298ff94bc40SHeiko Schocher * 2299ff94bc40SHeiko Schocher * This function checks the file system, namely: 2300ff94bc40SHeiko Schocher * o makes sure that all leaf nodes exist and their CRCs are correct; 2301ff94bc40SHeiko Schocher * o makes sure inode nlink, size, xattr size/count are correct (for all 2302ff94bc40SHeiko Schocher * inodes). 2303ff94bc40SHeiko Schocher * 2304ff94bc40SHeiko Schocher * The function reads whole indexing tree and all nodes, so it is pretty 2305ff94bc40SHeiko Schocher * heavy-weight. Returns zero if the file-system is consistent, %-EINVAL if 2306ff94bc40SHeiko Schocher * not, and a negative error code in case of failure. 2307ff94bc40SHeiko Schocher */ 2308ff94bc40SHeiko Schocher int dbg_check_filesystem(struct ubifs_info *c) 2309ff94bc40SHeiko Schocher { 2310ff94bc40SHeiko Schocher int err; 2311ff94bc40SHeiko Schocher struct fsck_data fsckd; 2312ff94bc40SHeiko Schocher 2313ff94bc40SHeiko Schocher if (!dbg_is_chk_fs(c)) 2314ff94bc40SHeiko Schocher return 0; 2315ff94bc40SHeiko Schocher 2316ff94bc40SHeiko Schocher fsckd.inodes = RB_ROOT; 2317ff94bc40SHeiko Schocher err = dbg_walk_index(c, check_leaf, NULL, &fsckd); 2318ff94bc40SHeiko Schocher if (err) 2319ff94bc40SHeiko Schocher goto out_free; 2320ff94bc40SHeiko Schocher 2321ff94bc40SHeiko Schocher err = check_inodes(c, &fsckd); 2322ff94bc40SHeiko Schocher if (err) 2323ff94bc40SHeiko Schocher goto out_free; 2324ff94bc40SHeiko Schocher 2325ff94bc40SHeiko Schocher free_inodes(&fsckd); 2326ff94bc40SHeiko Schocher return 0; 2327ff94bc40SHeiko Schocher 2328ff94bc40SHeiko Schocher out_free: 23290195a7bbSHeiko Schocher ubifs_err(c, "file-system check failed with error %d", err); 2330ff94bc40SHeiko Schocher dump_stack(); 2331ff94bc40SHeiko Schocher free_inodes(&fsckd); 2332ff94bc40SHeiko Schocher return err; 2333ff94bc40SHeiko Schocher } 2334ff94bc40SHeiko Schocher 2335ff94bc40SHeiko Schocher /** 2336ff94bc40SHeiko Schocher * dbg_check_data_nodes_order - check that list of data nodes is sorted. 2337ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 2338ff94bc40SHeiko Schocher * @head: the list of nodes ('struct ubifs_scan_node' objects) 2339ff94bc40SHeiko Schocher * 2340ff94bc40SHeiko Schocher * This function returns zero if the list of data nodes is sorted correctly, 2341ff94bc40SHeiko Schocher * and %-EINVAL if not. 2342ff94bc40SHeiko Schocher */ 2343ff94bc40SHeiko Schocher int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head) 2344ff94bc40SHeiko Schocher { 2345ff94bc40SHeiko Schocher struct list_head *cur; 2346ff94bc40SHeiko Schocher struct ubifs_scan_node *sa, *sb; 2347ff94bc40SHeiko Schocher 2348ff94bc40SHeiko Schocher if (!dbg_is_chk_gen(c)) 2349ff94bc40SHeiko Schocher return 0; 2350ff94bc40SHeiko Schocher 2351ff94bc40SHeiko Schocher for (cur = head->next; cur->next != head; cur = cur->next) { 2352ff94bc40SHeiko Schocher ino_t inuma, inumb; 2353ff94bc40SHeiko Schocher uint32_t blka, blkb; 2354ff94bc40SHeiko Schocher 2355ff94bc40SHeiko Schocher cond_resched(); 2356ff94bc40SHeiko Schocher sa = container_of(cur, struct ubifs_scan_node, list); 2357ff94bc40SHeiko Schocher sb = container_of(cur->next, struct ubifs_scan_node, list); 2358ff94bc40SHeiko Schocher 2359ff94bc40SHeiko Schocher if (sa->type != UBIFS_DATA_NODE) { 23600195a7bbSHeiko Schocher ubifs_err(c, "bad node type %d", sa->type); 2361ff94bc40SHeiko Schocher ubifs_dump_node(c, sa->node); 2362ff94bc40SHeiko Schocher return -EINVAL; 2363ff94bc40SHeiko Schocher } 2364ff94bc40SHeiko Schocher if (sb->type != UBIFS_DATA_NODE) { 23650195a7bbSHeiko Schocher ubifs_err(c, "bad node type %d", sb->type); 2366ff94bc40SHeiko Schocher ubifs_dump_node(c, sb->node); 2367ff94bc40SHeiko Schocher return -EINVAL; 2368ff94bc40SHeiko Schocher } 2369ff94bc40SHeiko Schocher 2370ff94bc40SHeiko Schocher inuma = key_inum(c, &sa->key); 2371ff94bc40SHeiko Schocher inumb = key_inum(c, &sb->key); 2372ff94bc40SHeiko Schocher 2373ff94bc40SHeiko Schocher if (inuma < inumb) 2374ff94bc40SHeiko Schocher continue; 2375ff94bc40SHeiko Schocher if (inuma > inumb) { 23760195a7bbSHeiko Schocher ubifs_err(c, "larger inum %lu goes before inum %lu", 2377ff94bc40SHeiko Schocher (unsigned long)inuma, (unsigned long)inumb); 2378ff94bc40SHeiko Schocher goto error_dump; 2379ff94bc40SHeiko Schocher } 2380ff94bc40SHeiko Schocher 2381ff94bc40SHeiko Schocher blka = key_block(c, &sa->key); 2382ff94bc40SHeiko Schocher blkb = key_block(c, &sb->key); 2383ff94bc40SHeiko Schocher 2384ff94bc40SHeiko Schocher if (blka > blkb) { 23850195a7bbSHeiko Schocher ubifs_err(c, "larger block %u goes before %u", blka, blkb); 2386ff94bc40SHeiko Schocher goto error_dump; 2387ff94bc40SHeiko Schocher } 2388ff94bc40SHeiko Schocher if (blka == blkb) { 23890195a7bbSHeiko Schocher ubifs_err(c, "two data nodes for the same block"); 2390ff94bc40SHeiko Schocher goto error_dump; 2391ff94bc40SHeiko Schocher } 2392ff94bc40SHeiko Schocher } 2393ff94bc40SHeiko Schocher 2394ff94bc40SHeiko Schocher return 0; 2395ff94bc40SHeiko Schocher 2396ff94bc40SHeiko Schocher error_dump: 2397ff94bc40SHeiko Schocher ubifs_dump_node(c, sa->node); 2398ff94bc40SHeiko Schocher ubifs_dump_node(c, sb->node); 2399ff94bc40SHeiko Schocher return -EINVAL; 2400ff94bc40SHeiko Schocher } 2401ff94bc40SHeiko Schocher 2402ff94bc40SHeiko Schocher /** 2403ff94bc40SHeiko Schocher * dbg_check_nondata_nodes_order - check that list of data nodes is sorted. 2404ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 2405ff94bc40SHeiko Schocher * @head: the list of nodes ('struct ubifs_scan_node' objects) 2406ff94bc40SHeiko Schocher * 2407ff94bc40SHeiko Schocher * This function returns zero if the list of non-data nodes is sorted correctly, 2408ff94bc40SHeiko Schocher * and %-EINVAL if not. 2409ff94bc40SHeiko Schocher */ 2410ff94bc40SHeiko Schocher int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head) 2411ff94bc40SHeiko Schocher { 2412ff94bc40SHeiko Schocher struct list_head *cur; 2413ff94bc40SHeiko Schocher struct ubifs_scan_node *sa, *sb; 2414ff94bc40SHeiko Schocher 2415ff94bc40SHeiko Schocher if (!dbg_is_chk_gen(c)) 2416ff94bc40SHeiko Schocher return 0; 2417ff94bc40SHeiko Schocher 2418ff94bc40SHeiko Schocher for (cur = head->next; cur->next != head; cur = cur->next) { 2419ff94bc40SHeiko Schocher ino_t inuma, inumb; 2420ff94bc40SHeiko Schocher uint32_t hasha, hashb; 2421ff94bc40SHeiko Schocher 2422ff94bc40SHeiko Schocher cond_resched(); 2423ff94bc40SHeiko Schocher sa = container_of(cur, struct ubifs_scan_node, list); 2424ff94bc40SHeiko Schocher sb = container_of(cur->next, struct ubifs_scan_node, list); 2425ff94bc40SHeiko Schocher 2426ff94bc40SHeiko Schocher if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE && 2427ff94bc40SHeiko Schocher sa->type != UBIFS_XENT_NODE) { 24280195a7bbSHeiko Schocher ubifs_err(c, "bad node type %d", sa->type); 2429ff94bc40SHeiko Schocher ubifs_dump_node(c, sa->node); 2430ff94bc40SHeiko Schocher return -EINVAL; 2431ff94bc40SHeiko Schocher } 2432ff94bc40SHeiko Schocher if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE && 2433ff94bc40SHeiko Schocher sa->type != UBIFS_XENT_NODE) { 24340195a7bbSHeiko Schocher ubifs_err(c, "bad node type %d", sb->type); 2435ff94bc40SHeiko Schocher ubifs_dump_node(c, sb->node); 2436ff94bc40SHeiko Schocher return -EINVAL; 2437ff94bc40SHeiko Schocher } 2438ff94bc40SHeiko Schocher 2439ff94bc40SHeiko Schocher if (sa->type != UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) { 24400195a7bbSHeiko Schocher ubifs_err(c, "non-inode node goes before inode node"); 2441ff94bc40SHeiko Schocher goto error_dump; 2442ff94bc40SHeiko Schocher } 2443ff94bc40SHeiko Schocher 2444ff94bc40SHeiko Schocher if (sa->type == UBIFS_INO_NODE && sb->type != UBIFS_INO_NODE) 2445ff94bc40SHeiko Schocher continue; 2446ff94bc40SHeiko Schocher 2447ff94bc40SHeiko Schocher if (sa->type == UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) { 2448ff94bc40SHeiko Schocher /* Inode nodes are sorted in descending size order */ 2449ff94bc40SHeiko Schocher if (sa->len < sb->len) { 24500195a7bbSHeiko Schocher ubifs_err(c, "smaller inode node goes first"); 2451ff94bc40SHeiko Schocher goto error_dump; 2452ff94bc40SHeiko Schocher } 2453ff94bc40SHeiko Schocher continue; 2454ff94bc40SHeiko Schocher } 2455ff94bc40SHeiko Schocher 2456ff94bc40SHeiko Schocher /* 2457ff94bc40SHeiko Schocher * This is either a dentry or xentry, which should be sorted in 2458ff94bc40SHeiko Schocher * ascending (parent ino, hash) order. 2459ff94bc40SHeiko Schocher */ 2460ff94bc40SHeiko Schocher inuma = key_inum(c, &sa->key); 2461ff94bc40SHeiko Schocher inumb = key_inum(c, &sb->key); 2462ff94bc40SHeiko Schocher 2463ff94bc40SHeiko Schocher if (inuma < inumb) 2464ff94bc40SHeiko Schocher continue; 2465ff94bc40SHeiko Schocher if (inuma > inumb) { 24660195a7bbSHeiko Schocher ubifs_err(c, "larger inum %lu goes before inum %lu", 2467ff94bc40SHeiko Schocher (unsigned long)inuma, (unsigned long)inumb); 2468ff94bc40SHeiko Schocher goto error_dump; 2469ff94bc40SHeiko Schocher } 2470ff94bc40SHeiko Schocher 2471ff94bc40SHeiko Schocher hasha = key_block(c, &sa->key); 2472ff94bc40SHeiko Schocher hashb = key_block(c, &sb->key); 2473ff94bc40SHeiko Schocher 2474ff94bc40SHeiko Schocher if (hasha > hashb) { 24750195a7bbSHeiko Schocher ubifs_err(c, "larger hash %u goes before %u", 2476ff94bc40SHeiko Schocher hasha, hashb); 2477ff94bc40SHeiko Schocher goto error_dump; 2478ff94bc40SHeiko Schocher } 2479ff94bc40SHeiko Schocher } 2480ff94bc40SHeiko Schocher 2481ff94bc40SHeiko Schocher return 0; 2482ff94bc40SHeiko Schocher 2483ff94bc40SHeiko Schocher error_dump: 24840195a7bbSHeiko Schocher ubifs_msg(c, "dumping first node"); 2485ff94bc40SHeiko Schocher ubifs_dump_node(c, sa->node); 24860195a7bbSHeiko Schocher ubifs_msg(c, "dumping second node"); 2487ff94bc40SHeiko Schocher ubifs_dump_node(c, sb->node); 2488ff94bc40SHeiko Schocher return -EINVAL; 2489ff94bc40SHeiko Schocher return 0; 2490ff94bc40SHeiko Schocher } 2491ff94bc40SHeiko Schocher 2492ff94bc40SHeiko Schocher static inline int chance(unsigned int n, unsigned int out_of) 2493ff94bc40SHeiko Schocher { 2494ff94bc40SHeiko Schocher return !!((prandom_u32() % out_of) + 1 <= n); 2495ff94bc40SHeiko Schocher 2496ff94bc40SHeiko Schocher } 2497ff94bc40SHeiko Schocher 2498ff94bc40SHeiko Schocher static int power_cut_emulated(struct ubifs_info *c, int lnum, int write) 2499ff94bc40SHeiko Schocher { 2500ff94bc40SHeiko Schocher struct ubifs_debug_info *d = c->dbg; 2501ff94bc40SHeiko Schocher 2502ff94bc40SHeiko Schocher ubifs_assert(dbg_is_tst_rcvry(c)); 2503ff94bc40SHeiko Schocher 2504ff94bc40SHeiko Schocher if (!d->pc_cnt) { 2505ff94bc40SHeiko Schocher /* First call - decide delay to the power cut */ 2506ff94bc40SHeiko Schocher if (chance(1, 2)) { 2507ff94bc40SHeiko Schocher unsigned long delay; 2508ff94bc40SHeiko Schocher 2509ff94bc40SHeiko Schocher if (chance(1, 2)) { 2510ff94bc40SHeiko Schocher d->pc_delay = 1; 25110195a7bbSHeiko Schocher /* Fail within 1 minute */ 2512ff94bc40SHeiko Schocher delay = prandom_u32() % 60000; 2513ff94bc40SHeiko Schocher d->pc_timeout = jiffies; 2514ff94bc40SHeiko Schocher d->pc_timeout += msecs_to_jiffies(delay); 25150195a7bbSHeiko Schocher ubifs_warn(c, "failing after %lums", delay); 2516ff94bc40SHeiko Schocher } else { 2517ff94bc40SHeiko Schocher d->pc_delay = 2; 2518ff94bc40SHeiko Schocher delay = prandom_u32() % 10000; 2519ff94bc40SHeiko Schocher /* Fail within 10000 operations */ 2520ff94bc40SHeiko Schocher d->pc_cnt_max = delay; 25210195a7bbSHeiko Schocher ubifs_warn(c, "failing after %lu calls", delay); 2522ff94bc40SHeiko Schocher } 2523ff94bc40SHeiko Schocher } 2524ff94bc40SHeiko Schocher 2525ff94bc40SHeiko Schocher d->pc_cnt += 1; 2526ff94bc40SHeiko Schocher } 2527ff94bc40SHeiko Schocher 2528ff94bc40SHeiko Schocher /* Determine if failure delay has expired */ 2529ff94bc40SHeiko Schocher if (d->pc_delay == 1 && time_before(jiffies, d->pc_timeout)) 2530ff94bc40SHeiko Schocher return 0; 2531ff94bc40SHeiko Schocher if (d->pc_delay == 2 && d->pc_cnt++ < d->pc_cnt_max) 2532ff94bc40SHeiko Schocher return 0; 2533ff94bc40SHeiko Schocher 2534ff94bc40SHeiko Schocher if (lnum == UBIFS_SB_LNUM) { 2535ff94bc40SHeiko Schocher if (write && chance(1, 2)) 2536ff94bc40SHeiko Schocher return 0; 2537ff94bc40SHeiko Schocher if (chance(19, 20)) 2538ff94bc40SHeiko Schocher return 0; 25390195a7bbSHeiko Schocher ubifs_warn(c, "failing in super block LEB %d", lnum); 2540ff94bc40SHeiko Schocher } else if (lnum == UBIFS_MST_LNUM || lnum == UBIFS_MST_LNUM + 1) { 2541ff94bc40SHeiko Schocher if (chance(19, 20)) 2542ff94bc40SHeiko Schocher return 0; 25430195a7bbSHeiko Schocher ubifs_warn(c, "failing in master LEB %d", lnum); 2544ff94bc40SHeiko Schocher } else if (lnum >= UBIFS_LOG_LNUM && lnum <= c->log_last) { 2545ff94bc40SHeiko Schocher if (write && chance(99, 100)) 2546ff94bc40SHeiko Schocher return 0; 2547ff94bc40SHeiko Schocher if (chance(399, 400)) 2548ff94bc40SHeiko Schocher return 0; 25490195a7bbSHeiko Schocher ubifs_warn(c, "failing in log LEB %d", lnum); 2550ff94bc40SHeiko Schocher } else if (lnum >= c->lpt_first && lnum <= c->lpt_last) { 2551ff94bc40SHeiko Schocher if (write && chance(7, 8)) 2552ff94bc40SHeiko Schocher return 0; 2553ff94bc40SHeiko Schocher if (chance(19, 20)) 2554ff94bc40SHeiko Schocher return 0; 25550195a7bbSHeiko Schocher ubifs_warn(c, "failing in LPT LEB %d", lnum); 2556ff94bc40SHeiko Schocher } else if (lnum >= c->orph_first && lnum <= c->orph_last) { 2557ff94bc40SHeiko Schocher if (write && chance(1, 2)) 2558ff94bc40SHeiko Schocher return 0; 2559ff94bc40SHeiko Schocher if (chance(9, 10)) 2560ff94bc40SHeiko Schocher return 0; 25610195a7bbSHeiko Schocher ubifs_warn(c, "failing in orphan LEB %d", lnum); 2562ff94bc40SHeiko Schocher } else if (lnum == c->ihead_lnum) { 2563ff94bc40SHeiko Schocher if (chance(99, 100)) 2564ff94bc40SHeiko Schocher return 0; 25650195a7bbSHeiko Schocher ubifs_warn(c, "failing in index head LEB %d", lnum); 2566ff94bc40SHeiko Schocher } else if (c->jheads && lnum == c->jheads[GCHD].wbuf.lnum) { 2567ff94bc40SHeiko Schocher if (chance(9, 10)) 2568ff94bc40SHeiko Schocher return 0; 25690195a7bbSHeiko Schocher ubifs_warn(c, "failing in GC head LEB %d", lnum); 2570ff94bc40SHeiko Schocher } else if (write && !RB_EMPTY_ROOT(&c->buds) && 2571ff94bc40SHeiko Schocher !ubifs_search_bud(c, lnum)) { 2572ff94bc40SHeiko Schocher if (chance(19, 20)) 2573ff94bc40SHeiko Schocher return 0; 25740195a7bbSHeiko Schocher ubifs_warn(c, "failing in non-bud LEB %d", lnum); 2575ff94bc40SHeiko Schocher } else if (c->cmt_state == COMMIT_RUNNING_BACKGROUND || 2576ff94bc40SHeiko Schocher c->cmt_state == COMMIT_RUNNING_REQUIRED) { 2577ff94bc40SHeiko Schocher if (chance(999, 1000)) 2578ff94bc40SHeiko Schocher return 0; 25790195a7bbSHeiko Schocher ubifs_warn(c, "failing in bud LEB %d commit running", lnum); 2580ff94bc40SHeiko Schocher } else { 2581ff94bc40SHeiko Schocher if (chance(9999, 10000)) 2582ff94bc40SHeiko Schocher return 0; 25830195a7bbSHeiko Schocher ubifs_warn(c, "failing in bud LEB %d commit not running", lnum); 2584ff94bc40SHeiko Schocher } 2585ff94bc40SHeiko Schocher 2586ff94bc40SHeiko Schocher d->pc_happened = 1; 25870195a7bbSHeiko Schocher ubifs_warn(c, "========== Power cut emulated =========="); 2588ff94bc40SHeiko Schocher dump_stack(); 2589ff94bc40SHeiko Schocher return 1; 2590ff94bc40SHeiko Schocher } 2591ff94bc40SHeiko Schocher 2592ff94bc40SHeiko Schocher static int corrupt_data(const struct ubifs_info *c, const void *buf, 2593ff94bc40SHeiko Schocher unsigned int len) 2594ff94bc40SHeiko Schocher { 2595ff94bc40SHeiko Schocher unsigned int from, to, ffs = chance(1, 2); 2596ff94bc40SHeiko Schocher unsigned char *p = (void *)buf; 2597ff94bc40SHeiko Schocher 2598ff94bc40SHeiko Schocher from = prandom_u32() % len; 2599ff94bc40SHeiko Schocher /* Corruption span max to end of write unit */ 2600ff94bc40SHeiko Schocher to = min(len, ALIGN(from + 1, c->max_write_size)); 2601ff94bc40SHeiko Schocher 26020195a7bbSHeiko Schocher ubifs_warn(c, "filled bytes %u-%u with %s", from, to - 1, 2603ff94bc40SHeiko Schocher ffs ? "0xFFs" : "random data"); 2604ff94bc40SHeiko Schocher 2605ff94bc40SHeiko Schocher if (ffs) 2606ff94bc40SHeiko Schocher memset(p + from, 0xFF, to - from); 2607ff94bc40SHeiko Schocher else 2608ff94bc40SHeiko Schocher prandom_bytes(p + from, to - from); 2609ff94bc40SHeiko Schocher 2610ff94bc40SHeiko Schocher return to; 2611ff94bc40SHeiko Schocher } 2612ff94bc40SHeiko Schocher 2613ff94bc40SHeiko Schocher int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf, 2614ff94bc40SHeiko Schocher int offs, int len) 2615ff94bc40SHeiko Schocher { 2616ff94bc40SHeiko Schocher int err, failing; 2617ff94bc40SHeiko Schocher 2618ff94bc40SHeiko Schocher if (c->dbg->pc_happened) 2619ff94bc40SHeiko Schocher return -EROFS; 2620ff94bc40SHeiko Schocher 2621ff94bc40SHeiko Schocher failing = power_cut_emulated(c, lnum, 1); 2622ff94bc40SHeiko Schocher if (failing) { 2623ff94bc40SHeiko Schocher len = corrupt_data(c, buf, len); 26240195a7bbSHeiko Schocher ubifs_warn(c, "actually write %d bytes to LEB %d:%d (the buffer was corrupted)", 2625ff94bc40SHeiko Schocher len, lnum, offs); 2626ff94bc40SHeiko Schocher } 2627ff94bc40SHeiko Schocher err = ubi_leb_write(c->ubi, lnum, buf, offs, len); 2628ff94bc40SHeiko Schocher if (err) 2629ff94bc40SHeiko Schocher return err; 2630ff94bc40SHeiko Schocher if (failing) 2631ff94bc40SHeiko Schocher return -EROFS; 2632ff94bc40SHeiko Schocher return 0; 2633ff94bc40SHeiko Schocher } 2634ff94bc40SHeiko Schocher 2635ff94bc40SHeiko Schocher int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf, 2636ff94bc40SHeiko Schocher int len) 2637ff94bc40SHeiko Schocher { 2638ff94bc40SHeiko Schocher int err; 2639ff94bc40SHeiko Schocher 2640ff94bc40SHeiko Schocher if (c->dbg->pc_happened) 2641ff94bc40SHeiko Schocher return -EROFS; 2642ff94bc40SHeiko Schocher if (power_cut_emulated(c, lnum, 1)) 2643ff94bc40SHeiko Schocher return -EROFS; 2644ff94bc40SHeiko Schocher err = ubi_leb_change(c->ubi, lnum, buf, len); 2645ff94bc40SHeiko Schocher if (err) 2646ff94bc40SHeiko Schocher return err; 2647ff94bc40SHeiko Schocher if (power_cut_emulated(c, lnum, 1)) 2648ff94bc40SHeiko Schocher return -EROFS; 2649ff94bc40SHeiko Schocher return 0; 2650ff94bc40SHeiko Schocher } 2651ff94bc40SHeiko Schocher 2652ff94bc40SHeiko Schocher int dbg_leb_unmap(struct ubifs_info *c, int lnum) 2653ff94bc40SHeiko Schocher { 2654ff94bc40SHeiko Schocher int err; 2655ff94bc40SHeiko Schocher 2656ff94bc40SHeiko Schocher if (c->dbg->pc_happened) 2657ff94bc40SHeiko Schocher return -EROFS; 2658ff94bc40SHeiko Schocher if (power_cut_emulated(c, lnum, 0)) 2659ff94bc40SHeiko Schocher return -EROFS; 2660ff94bc40SHeiko Schocher err = ubi_leb_unmap(c->ubi, lnum); 2661ff94bc40SHeiko Schocher if (err) 2662ff94bc40SHeiko Schocher return err; 2663ff94bc40SHeiko Schocher if (power_cut_emulated(c, lnum, 0)) 2664ff94bc40SHeiko Schocher return -EROFS; 2665ff94bc40SHeiko Schocher return 0; 2666ff94bc40SHeiko Schocher } 2667ff94bc40SHeiko Schocher 2668ff94bc40SHeiko Schocher int dbg_leb_map(struct ubifs_info *c, int lnum) 2669ff94bc40SHeiko Schocher { 2670ff94bc40SHeiko Schocher int err; 2671ff94bc40SHeiko Schocher 2672ff94bc40SHeiko Schocher if (c->dbg->pc_happened) 2673ff94bc40SHeiko Schocher return -EROFS; 2674ff94bc40SHeiko Schocher if (power_cut_emulated(c, lnum, 0)) 2675ff94bc40SHeiko Schocher return -EROFS; 2676ff94bc40SHeiko Schocher err = ubi_leb_map(c->ubi, lnum); 2677ff94bc40SHeiko Schocher if (err) 2678ff94bc40SHeiko Schocher return err; 2679ff94bc40SHeiko Schocher if (power_cut_emulated(c, lnum, 0)) 2680ff94bc40SHeiko Schocher return -EROFS; 2681ff94bc40SHeiko Schocher return 0; 2682ff94bc40SHeiko Schocher } 2683ff94bc40SHeiko Schocher 2684ff94bc40SHeiko Schocher /* 2685ff94bc40SHeiko Schocher * Root directory for UBIFS stuff in debugfs. Contains sub-directories which 2686ff94bc40SHeiko Schocher * contain the stuff specific to particular file-system mounts. 2687ff94bc40SHeiko Schocher */ 2688ff94bc40SHeiko Schocher static struct dentry *dfs_rootdir; 2689ff94bc40SHeiko Schocher 2690ff94bc40SHeiko Schocher static int dfs_file_open(struct inode *inode, struct file *file) 2691ff94bc40SHeiko Schocher { 2692ff94bc40SHeiko Schocher file->private_data = inode->i_private; 2693ff94bc40SHeiko Schocher return nonseekable_open(inode, file); 2694ff94bc40SHeiko Schocher } 2695ff94bc40SHeiko Schocher 2696ff94bc40SHeiko Schocher /** 2697ff94bc40SHeiko Schocher * provide_user_output - provide output to the user reading a debugfs file. 2698ff94bc40SHeiko Schocher * @val: boolean value for the answer 2699ff94bc40SHeiko Schocher * @u: the buffer to store the answer at 2700ff94bc40SHeiko Schocher * @count: size of the buffer 2701ff94bc40SHeiko Schocher * @ppos: position in the @u output buffer 2702ff94bc40SHeiko Schocher * 2703ff94bc40SHeiko Schocher * This is a simple helper function which stores @val boolean value in the user 2704ff94bc40SHeiko Schocher * buffer when the user reads one of UBIFS debugfs files. Returns amount of 2705ff94bc40SHeiko Schocher * bytes written to @u in case of success and a negative error code in case of 2706ff94bc40SHeiko Schocher * failure. 2707ff94bc40SHeiko Schocher */ 2708ff94bc40SHeiko Schocher static int provide_user_output(int val, char __user *u, size_t count, 2709ff94bc40SHeiko Schocher loff_t *ppos) 2710ff94bc40SHeiko Schocher { 2711ff94bc40SHeiko Schocher char buf[3]; 2712ff94bc40SHeiko Schocher 2713ff94bc40SHeiko Schocher if (val) 2714ff94bc40SHeiko Schocher buf[0] = '1'; 2715ff94bc40SHeiko Schocher else 2716ff94bc40SHeiko Schocher buf[0] = '0'; 2717ff94bc40SHeiko Schocher buf[1] = '\n'; 2718ff94bc40SHeiko Schocher buf[2] = 0x00; 2719ff94bc40SHeiko Schocher 2720ff94bc40SHeiko Schocher return simple_read_from_buffer(u, count, ppos, buf, 2); 2721ff94bc40SHeiko Schocher } 2722ff94bc40SHeiko Schocher 2723ff94bc40SHeiko Schocher static ssize_t dfs_file_read(struct file *file, char __user *u, size_t count, 2724ff94bc40SHeiko Schocher loff_t *ppos) 2725ff94bc40SHeiko Schocher { 2726ff94bc40SHeiko Schocher struct dentry *dent = file->f_path.dentry; 2727ff94bc40SHeiko Schocher struct ubifs_info *c = file->private_data; 2728ff94bc40SHeiko Schocher struct ubifs_debug_info *d = c->dbg; 2729ff94bc40SHeiko Schocher int val; 2730ff94bc40SHeiko Schocher 2731ff94bc40SHeiko Schocher if (dent == d->dfs_chk_gen) 2732ff94bc40SHeiko Schocher val = d->chk_gen; 2733ff94bc40SHeiko Schocher else if (dent == d->dfs_chk_index) 2734ff94bc40SHeiko Schocher val = d->chk_index; 2735ff94bc40SHeiko Schocher else if (dent == d->dfs_chk_orph) 2736ff94bc40SHeiko Schocher val = d->chk_orph; 2737ff94bc40SHeiko Schocher else if (dent == d->dfs_chk_lprops) 2738ff94bc40SHeiko Schocher val = d->chk_lprops; 2739ff94bc40SHeiko Schocher else if (dent == d->dfs_chk_fs) 2740ff94bc40SHeiko Schocher val = d->chk_fs; 2741ff94bc40SHeiko Schocher else if (dent == d->dfs_tst_rcvry) 2742ff94bc40SHeiko Schocher val = d->tst_rcvry; 2743ff94bc40SHeiko Schocher else if (dent == d->dfs_ro_error) 2744ff94bc40SHeiko Schocher val = c->ro_error; 2745ff94bc40SHeiko Schocher else 2746ff94bc40SHeiko Schocher return -EINVAL; 2747ff94bc40SHeiko Schocher 2748ff94bc40SHeiko Schocher return provide_user_output(val, u, count, ppos); 2749ff94bc40SHeiko Schocher } 2750ff94bc40SHeiko Schocher 2751ff94bc40SHeiko Schocher /** 2752ff94bc40SHeiko Schocher * interpret_user_input - interpret user debugfs file input. 2753ff94bc40SHeiko Schocher * @u: user-provided buffer with the input 2754ff94bc40SHeiko Schocher * @count: buffer size 2755ff94bc40SHeiko Schocher * 2756ff94bc40SHeiko Schocher * This is a helper function which interpret user input to a boolean UBIFS 2757ff94bc40SHeiko Schocher * debugfs file. Returns %0 or %1 in case of success and a negative error code 2758ff94bc40SHeiko Schocher * in case of failure. 2759ff94bc40SHeiko Schocher */ 2760ff94bc40SHeiko Schocher static int interpret_user_input(const char __user *u, size_t count) 2761ff94bc40SHeiko Schocher { 2762ff94bc40SHeiko Schocher size_t buf_size; 2763ff94bc40SHeiko Schocher char buf[8]; 2764ff94bc40SHeiko Schocher 2765ff94bc40SHeiko Schocher buf_size = min_t(size_t, count, (sizeof(buf) - 1)); 2766ff94bc40SHeiko Schocher if (copy_from_user(buf, u, buf_size)) 2767ff94bc40SHeiko Schocher return -EFAULT; 2768ff94bc40SHeiko Schocher 2769ff94bc40SHeiko Schocher if (buf[0] == '1') 2770ff94bc40SHeiko Schocher return 1; 2771ff94bc40SHeiko Schocher else if (buf[0] == '0') 2772ff94bc40SHeiko Schocher return 0; 2773ff94bc40SHeiko Schocher 2774ff94bc40SHeiko Schocher return -EINVAL; 2775ff94bc40SHeiko Schocher } 2776ff94bc40SHeiko Schocher 2777ff94bc40SHeiko Schocher static ssize_t dfs_file_write(struct file *file, const char __user *u, 2778ff94bc40SHeiko Schocher size_t count, loff_t *ppos) 2779ff94bc40SHeiko Schocher { 2780ff94bc40SHeiko Schocher struct ubifs_info *c = file->private_data; 2781ff94bc40SHeiko Schocher struct ubifs_debug_info *d = c->dbg; 2782ff94bc40SHeiko Schocher struct dentry *dent = file->f_path.dentry; 2783ff94bc40SHeiko Schocher int val; 2784ff94bc40SHeiko Schocher 2785ff94bc40SHeiko Schocher /* 2786ff94bc40SHeiko Schocher * TODO: this is racy - the file-system might have already been 2787ff94bc40SHeiko Schocher * unmounted and we'd oops in this case. The plan is to fix it with 2788ff94bc40SHeiko Schocher * help of 'iterate_supers_type()' which we should have in v3.0: when 2789ff94bc40SHeiko Schocher * a debugfs opened, we rember FS's UUID in file->private_data. Then 2790ff94bc40SHeiko Schocher * whenever we access the FS via a debugfs file, we iterate all UBIFS 2791ff94bc40SHeiko Schocher * superblocks and fine the one with the same UUID, and take the 2792ff94bc40SHeiko Schocher * locking right. 2793ff94bc40SHeiko Schocher * 2794ff94bc40SHeiko Schocher * The other way to go suggested by Al Viro is to create a separate 2795ff94bc40SHeiko Schocher * 'ubifs-debug' file-system instead. 2796ff94bc40SHeiko Schocher */ 2797ff94bc40SHeiko Schocher if (file->f_path.dentry == d->dfs_dump_lprops) { 2798ff94bc40SHeiko Schocher ubifs_dump_lprops(c); 2799ff94bc40SHeiko Schocher return count; 2800ff94bc40SHeiko Schocher } 2801ff94bc40SHeiko Schocher if (file->f_path.dentry == d->dfs_dump_budg) { 2802ff94bc40SHeiko Schocher ubifs_dump_budg(c, &c->bi); 2803ff94bc40SHeiko Schocher return count; 2804ff94bc40SHeiko Schocher } 2805ff94bc40SHeiko Schocher if (file->f_path.dentry == d->dfs_dump_tnc) { 2806ff94bc40SHeiko Schocher mutex_lock(&c->tnc_mutex); 2807ff94bc40SHeiko Schocher ubifs_dump_tnc(c); 2808ff94bc40SHeiko Schocher mutex_unlock(&c->tnc_mutex); 2809ff94bc40SHeiko Schocher return count; 2810ff94bc40SHeiko Schocher } 2811ff94bc40SHeiko Schocher 2812ff94bc40SHeiko Schocher val = interpret_user_input(u, count); 2813ff94bc40SHeiko Schocher if (val < 0) 2814ff94bc40SHeiko Schocher return val; 2815ff94bc40SHeiko Schocher 2816ff94bc40SHeiko Schocher if (dent == d->dfs_chk_gen) 2817ff94bc40SHeiko Schocher d->chk_gen = val; 2818ff94bc40SHeiko Schocher else if (dent == d->dfs_chk_index) 2819ff94bc40SHeiko Schocher d->chk_index = val; 2820ff94bc40SHeiko Schocher else if (dent == d->dfs_chk_orph) 2821ff94bc40SHeiko Schocher d->chk_orph = val; 2822ff94bc40SHeiko Schocher else if (dent == d->dfs_chk_lprops) 2823ff94bc40SHeiko Schocher d->chk_lprops = val; 2824ff94bc40SHeiko Schocher else if (dent == d->dfs_chk_fs) 2825ff94bc40SHeiko Schocher d->chk_fs = val; 2826ff94bc40SHeiko Schocher else if (dent == d->dfs_tst_rcvry) 2827ff94bc40SHeiko Schocher d->tst_rcvry = val; 2828ff94bc40SHeiko Schocher else if (dent == d->dfs_ro_error) 2829ff94bc40SHeiko Schocher c->ro_error = !!val; 2830ff94bc40SHeiko Schocher else 2831ff94bc40SHeiko Schocher return -EINVAL; 2832ff94bc40SHeiko Schocher 2833ff94bc40SHeiko Schocher return count; 2834ff94bc40SHeiko Schocher } 2835ff94bc40SHeiko Schocher 2836ff94bc40SHeiko Schocher static const struct file_operations dfs_fops = { 2837ff94bc40SHeiko Schocher .open = dfs_file_open, 2838ff94bc40SHeiko Schocher .read = dfs_file_read, 2839ff94bc40SHeiko Schocher .write = dfs_file_write, 2840ff94bc40SHeiko Schocher .owner = THIS_MODULE, 2841ff94bc40SHeiko Schocher .llseek = no_llseek, 2842ff94bc40SHeiko Schocher }; 2843ff94bc40SHeiko Schocher 2844ff94bc40SHeiko Schocher /** 2845ff94bc40SHeiko Schocher * dbg_debugfs_init_fs - initialize debugfs for UBIFS instance. 2846ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 2847ff94bc40SHeiko Schocher * 2848ff94bc40SHeiko Schocher * This function creates all debugfs files for this instance of UBIFS. Returns 2849ff94bc40SHeiko Schocher * zero in case of success and a negative error code in case of failure. 2850ff94bc40SHeiko Schocher * 2851ff94bc40SHeiko Schocher * Note, the only reason we have not merged this function with the 2852ff94bc40SHeiko Schocher * 'ubifs_debugging_init()' function is because it is better to initialize 2853ff94bc40SHeiko Schocher * debugfs interfaces at the very end of the mount process, and remove them at 2854ff94bc40SHeiko Schocher * the very beginning of the mount process. 2855ff94bc40SHeiko Schocher */ 2856ff94bc40SHeiko Schocher int dbg_debugfs_init_fs(struct ubifs_info *c) 2857ff94bc40SHeiko Schocher { 2858ff94bc40SHeiko Schocher int err, n; 2859ff94bc40SHeiko Schocher const char *fname; 2860ff94bc40SHeiko Schocher struct dentry *dent; 2861ff94bc40SHeiko Schocher struct ubifs_debug_info *d = c->dbg; 2862ff94bc40SHeiko Schocher 2863ff94bc40SHeiko Schocher if (!IS_ENABLED(CONFIG_DEBUG_FS)) 2864ff94bc40SHeiko Schocher return 0; 2865ff94bc40SHeiko Schocher 2866ff94bc40SHeiko Schocher n = snprintf(d->dfs_dir_name, UBIFS_DFS_DIR_LEN + 1, UBIFS_DFS_DIR_NAME, 2867ff94bc40SHeiko Schocher c->vi.ubi_num, c->vi.vol_id); 2868ff94bc40SHeiko Schocher if (n == UBIFS_DFS_DIR_LEN) { 2869ff94bc40SHeiko Schocher /* The array size is too small */ 2870ff94bc40SHeiko Schocher fname = UBIFS_DFS_DIR_NAME; 2871ff94bc40SHeiko Schocher dent = ERR_PTR(-EINVAL); 2872ff94bc40SHeiko Schocher goto out; 2873ff94bc40SHeiko Schocher } 2874ff94bc40SHeiko Schocher 2875ff94bc40SHeiko Schocher fname = d->dfs_dir_name; 2876ff94bc40SHeiko Schocher dent = debugfs_create_dir(fname, dfs_rootdir); 2877ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 2878ff94bc40SHeiko Schocher goto out; 2879ff94bc40SHeiko Schocher d->dfs_dir = dent; 2880ff94bc40SHeiko Schocher 2881ff94bc40SHeiko Schocher fname = "dump_lprops"; 2882ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); 2883ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 2884ff94bc40SHeiko Schocher goto out_remove; 2885ff94bc40SHeiko Schocher d->dfs_dump_lprops = dent; 2886ff94bc40SHeiko Schocher 2887ff94bc40SHeiko Schocher fname = "dump_budg"; 2888ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); 2889ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 2890ff94bc40SHeiko Schocher goto out_remove; 2891ff94bc40SHeiko Schocher d->dfs_dump_budg = dent; 2892ff94bc40SHeiko Schocher 2893ff94bc40SHeiko Schocher fname = "dump_tnc"; 2894ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); 2895ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 2896ff94bc40SHeiko Schocher goto out_remove; 2897ff94bc40SHeiko Schocher d->dfs_dump_tnc = dent; 2898ff94bc40SHeiko Schocher 2899ff94bc40SHeiko Schocher fname = "chk_general"; 2900ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c, 2901ff94bc40SHeiko Schocher &dfs_fops); 2902ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 2903ff94bc40SHeiko Schocher goto out_remove; 2904ff94bc40SHeiko Schocher d->dfs_chk_gen = dent; 2905ff94bc40SHeiko Schocher 2906ff94bc40SHeiko Schocher fname = "chk_index"; 2907ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c, 2908ff94bc40SHeiko Schocher &dfs_fops); 2909ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 2910ff94bc40SHeiko Schocher goto out_remove; 2911ff94bc40SHeiko Schocher d->dfs_chk_index = dent; 2912ff94bc40SHeiko Schocher 2913ff94bc40SHeiko Schocher fname = "chk_orphans"; 2914ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c, 2915ff94bc40SHeiko Schocher &dfs_fops); 2916ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 2917ff94bc40SHeiko Schocher goto out_remove; 2918ff94bc40SHeiko Schocher d->dfs_chk_orph = dent; 2919ff94bc40SHeiko Schocher 2920ff94bc40SHeiko Schocher fname = "chk_lprops"; 2921ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c, 2922ff94bc40SHeiko Schocher &dfs_fops); 2923ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 2924ff94bc40SHeiko Schocher goto out_remove; 2925ff94bc40SHeiko Schocher d->dfs_chk_lprops = dent; 2926ff94bc40SHeiko Schocher 2927ff94bc40SHeiko Schocher fname = "chk_fs"; 2928ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c, 2929ff94bc40SHeiko Schocher &dfs_fops); 2930ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 2931ff94bc40SHeiko Schocher goto out_remove; 2932ff94bc40SHeiko Schocher d->dfs_chk_fs = dent; 2933ff94bc40SHeiko Schocher 2934ff94bc40SHeiko Schocher fname = "tst_recovery"; 2935ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c, 2936ff94bc40SHeiko Schocher &dfs_fops); 2937ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 2938ff94bc40SHeiko Schocher goto out_remove; 2939ff94bc40SHeiko Schocher d->dfs_tst_rcvry = dent; 2940ff94bc40SHeiko Schocher 2941ff94bc40SHeiko Schocher fname = "ro_error"; 2942ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c, 2943ff94bc40SHeiko Schocher &dfs_fops); 2944ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 2945ff94bc40SHeiko Schocher goto out_remove; 2946ff94bc40SHeiko Schocher d->dfs_ro_error = dent; 2947ff94bc40SHeiko Schocher 2948ff94bc40SHeiko Schocher return 0; 2949ff94bc40SHeiko Schocher 2950ff94bc40SHeiko Schocher out_remove: 2951ff94bc40SHeiko Schocher debugfs_remove_recursive(d->dfs_dir); 2952ff94bc40SHeiko Schocher out: 2953ff94bc40SHeiko Schocher err = dent ? PTR_ERR(dent) : -ENODEV; 29540195a7bbSHeiko Schocher ubifs_err(c, "cannot create \"%s\" debugfs file or directory, error %d\n", 2955ff94bc40SHeiko Schocher fname, err); 2956ff94bc40SHeiko Schocher return err; 2957ff94bc40SHeiko Schocher } 2958ff94bc40SHeiko Schocher 2959ff94bc40SHeiko Schocher /** 2960ff94bc40SHeiko Schocher * dbg_debugfs_exit_fs - remove all debugfs files. 2961ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 2962ff94bc40SHeiko Schocher */ 2963ff94bc40SHeiko Schocher void dbg_debugfs_exit_fs(struct ubifs_info *c) 2964ff94bc40SHeiko Schocher { 2965ff94bc40SHeiko Schocher if (IS_ENABLED(CONFIG_DEBUG_FS)) 2966ff94bc40SHeiko Schocher debugfs_remove_recursive(c->dbg->dfs_dir); 2967ff94bc40SHeiko Schocher } 2968ff94bc40SHeiko Schocher 2969ff94bc40SHeiko Schocher struct ubifs_global_debug_info ubifs_dbg; 2970ff94bc40SHeiko Schocher 2971ff94bc40SHeiko Schocher static struct dentry *dfs_chk_gen; 2972ff94bc40SHeiko Schocher static struct dentry *dfs_chk_index; 2973ff94bc40SHeiko Schocher static struct dentry *dfs_chk_orph; 2974ff94bc40SHeiko Schocher static struct dentry *dfs_chk_lprops; 2975ff94bc40SHeiko Schocher static struct dentry *dfs_chk_fs; 2976ff94bc40SHeiko Schocher static struct dentry *dfs_tst_rcvry; 2977ff94bc40SHeiko Schocher 2978ff94bc40SHeiko Schocher static ssize_t dfs_global_file_read(struct file *file, char __user *u, 2979ff94bc40SHeiko Schocher size_t count, loff_t *ppos) 2980ff94bc40SHeiko Schocher { 2981ff94bc40SHeiko Schocher struct dentry *dent = file->f_path.dentry; 2982ff94bc40SHeiko Schocher int val; 2983ff94bc40SHeiko Schocher 2984ff94bc40SHeiko Schocher if (dent == dfs_chk_gen) 2985ff94bc40SHeiko Schocher val = ubifs_dbg.chk_gen; 2986ff94bc40SHeiko Schocher else if (dent == dfs_chk_index) 2987ff94bc40SHeiko Schocher val = ubifs_dbg.chk_index; 2988ff94bc40SHeiko Schocher else if (dent == dfs_chk_orph) 2989ff94bc40SHeiko Schocher val = ubifs_dbg.chk_orph; 2990ff94bc40SHeiko Schocher else if (dent == dfs_chk_lprops) 2991ff94bc40SHeiko Schocher val = ubifs_dbg.chk_lprops; 2992ff94bc40SHeiko Schocher else if (dent == dfs_chk_fs) 2993ff94bc40SHeiko Schocher val = ubifs_dbg.chk_fs; 2994ff94bc40SHeiko Schocher else if (dent == dfs_tst_rcvry) 2995ff94bc40SHeiko Schocher val = ubifs_dbg.tst_rcvry; 2996ff94bc40SHeiko Schocher else 2997ff94bc40SHeiko Schocher return -EINVAL; 2998ff94bc40SHeiko Schocher 2999ff94bc40SHeiko Schocher return provide_user_output(val, u, count, ppos); 3000ff94bc40SHeiko Schocher } 3001ff94bc40SHeiko Schocher 3002ff94bc40SHeiko Schocher static ssize_t dfs_global_file_write(struct file *file, const char __user *u, 3003ff94bc40SHeiko Schocher size_t count, loff_t *ppos) 3004ff94bc40SHeiko Schocher { 3005ff94bc40SHeiko Schocher struct dentry *dent = file->f_path.dentry; 3006ff94bc40SHeiko Schocher int val; 3007ff94bc40SHeiko Schocher 3008ff94bc40SHeiko Schocher val = interpret_user_input(u, count); 3009ff94bc40SHeiko Schocher if (val < 0) 3010ff94bc40SHeiko Schocher return val; 3011ff94bc40SHeiko Schocher 3012ff94bc40SHeiko Schocher if (dent == dfs_chk_gen) 3013ff94bc40SHeiko Schocher ubifs_dbg.chk_gen = val; 3014ff94bc40SHeiko Schocher else if (dent == dfs_chk_index) 3015ff94bc40SHeiko Schocher ubifs_dbg.chk_index = val; 3016ff94bc40SHeiko Schocher else if (dent == dfs_chk_orph) 3017ff94bc40SHeiko Schocher ubifs_dbg.chk_orph = val; 3018ff94bc40SHeiko Schocher else if (dent == dfs_chk_lprops) 3019ff94bc40SHeiko Schocher ubifs_dbg.chk_lprops = val; 3020ff94bc40SHeiko Schocher else if (dent == dfs_chk_fs) 3021ff94bc40SHeiko Schocher ubifs_dbg.chk_fs = val; 3022ff94bc40SHeiko Schocher else if (dent == dfs_tst_rcvry) 3023ff94bc40SHeiko Schocher ubifs_dbg.tst_rcvry = val; 3024ff94bc40SHeiko Schocher else 3025ff94bc40SHeiko Schocher return -EINVAL; 3026ff94bc40SHeiko Schocher 3027ff94bc40SHeiko Schocher return count; 3028ff94bc40SHeiko Schocher } 3029ff94bc40SHeiko Schocher 3030ff94bc40SHeiko Schocher static const struct file_operations dfs_global_fops = { 3031ff94bc40SHeiko Schocher .read = dfs_global_file_read, 3032ff94bc40SHeiko Schocher .write = dfs_global_file_write, 3033ff94bc40SHeiko Schocher .owner = THIS_MODULE, 3034ff94bc40SHeiko Schocher .llseek = no_llseek, 3035ff94bc40SHeiko Schocher }; 3036ff94bc40SHeiko Schocher 3037ff94bc40SHeiko Schocher /** 3038ff94bc40SHeiko Schocher * dbg_debugfs_init - initialize debugfs file-system. 3039ff94bc40SHeiko Schocher * 3040ff94bc40SHeiko Schocher * UBIFS uses debugfs file-system to expose various debugging knobs to 3041ff94bc40SHeiko Schocher * user-space. This function creates "ubifs" directory in the debugfs 3042ff94bc40SHeiko Schocher * file-system. Returns zero in case of success and a negative error code in 3043ff94bc40SHeiko Schocher * case of failure. 3044ff94bc40SHeiko Schocher */ 3045ff94bc40SHeiko Schocher int dbg_debugfs_init(void) 3046ff94bc40SHeiko Schocher { 3047ff94bc40SHeiko Schocher int err; 3048ff94bc40SHeiko Schocher const char *fname; 3049ff94bc40SHeiko Schocher struct dentry *dent; 3050ff94bc40SHeiko Schocher 3051ff94bc40SHeiko Schocher if (!IS_ENABLED(CONFIG_DEBUG_FS)) 3052ff94bc40SHeiko Schocher return 0; 3053ff94bc40SHeiko Schocher 3054ff94bc40SHeiko Schocher fname = "ubifs"; 3055ff94bc40SHeiko Schocher dent = debugfs_create_dir(fname, NULL); 3056ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 3057ff94bc40SHeiko Schocher goto out; 3058ff94bc40SHeiko Schocher dfs_rootdir = dent; 3059ff94bc40SHeiko Schocher 3060ff94bc40SHeiko Schocher fname = "chk_general"; 3061ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL, 3062ff94bc40SHeiko Schocher &dfs_global_fops); 3063ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 3064ff94bc40SHeiko Schocher goto out_remove; 3065ff94bc40SHeiko Schocher dfs_chk_gen = dent; 3066ff94bc40SHeiko Schocher 3067ff94bc40SHeiko Schocher fname = "chk_index"; 3068ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL, 3069ff94bc40SHeiko Schocher &dfs_global_fops); 3070ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 3071ff94bc40SHeiko Schocher goto out_remove; 3072ff94bc40SHeiko Schocher dfs_chk_index = dent; 3073ff94bc40SHeiko Schocher 3074ff94bc40SHeiko Schocher fname = "chk_orphans"; 3075ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL, 3076ff94bc40SHeiko Schocher &dfs_global_fops); 3077ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 3078ff94bc40SHeiko Schocher goto out_remove; 3079ff94bc40SHeiko Schocher dfs_chk_orph = dent; 3080ff94bc40SHeiko Schocher 3081ff94bc40SHeiko Schocher fname = "chk_lprops"; 3082ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL, 3083ff94bc40SHeiko Schocher &dfs_global_fops); 3084ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 3085ff94bc40SHeiko Schocher goto out_remove; 3086ff94bc40SHeiko Schocher dfs_chk_lprops = dent; 3087ff94bc40SHeiko Schocher 3088ff94bc40SHeiko Schocher fname = "chk_fs"; 3089ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL, 3090ff94bc40SHeiko Schocher &dfs_global_fops); 3091ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 3092ff94bc40SHeiko Schocher goto out_remove; 3093ff94bc40SHeiko Schocher dfs_chk_fs = dent; 3094ff94bc40SHeiko Schocher 3095ff94bc40SHeiko Schocher fname = "tst_recovery"; 3096ff94bc40SHeiko Schocher dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL, 3097ff94bc40SHeiko Schocher &dfs_global_fops); 3098ff94bc40SHeiko Schocher if (IS_ERR_OR_NULL(dent)) 3099ff94bc40SHeiko Schocher goto out_remove; 3100ff94bc40SHeiko Schocher dfs_tst_rcvry = dent; 3101ff94bc40SHeiko Schocher 3102ff94bc40SHeiko Schocher return 0; 3103ff94bc40SHeiko Schocher 3104ff94bc40SHeiko Schocher out_remove: 3105ff94bc40SHeiko Schocher debugfs_remove_recursive(dfs_rootdir); 3106ff94bc40SHeiko Schocher out: 3107ff94bc40SHeiko Schocher err = dent ? PTR_ERR(dent) : -ENODEV; 31080195a7bbSHeiko Schocher pr_err("UBIFS error (pid %d): cannot create \"%s\" debugfs file or directory, error %d\n", 31090195a7bbSHeiko Schocher current->pid, fname, err); 3110ff94bc40SHeiko Schocher return err; 3111ff94bc40SHeiko Schocher } 3112ff94bc40SHeiko Schocher 3113ff94bc40SHeiko Schocher /** 3114ff94bc40SHeiko Schocher * dbg_debugfs_exit - remove the "ubifs" directory from debugfs file-system. 3115ff94bc40SHeiko Schocher */ 3116ff94bc40SHeiko Schocher void dbg_debugfs_exit(void) 3117ff94bc40SHeiko Schocher { 3118ff94bc40SHeiko Schocher if (IS_ENABLED(CONFIG_DEBUG_FS)) 3119ff94bc40SHeiko Schocher debugfs_remove_recursive(dfs_rootdir); 31209eefe2a2SStefan Roese } 31219eefe2a2SStefan Roese 31229eefe2a2SStefan Roese /** 31239eefe2a2SStefan Roese * ubifs_debugging_init - initialize UBIFS debugging. 31249eefe2a2SStefan Roese * @c: UBIFS file-system description object 31259eefe2a2SStefan Roese * 31269eefe2a2SStefan Roese * This function initializes debugging-related data for the file system. 31279eefe2a2SStefan Roese * Returns zero in case of success and a negative error code in case of 31289eefe2a2SStefan Roese * failure. 31299eefe2a2SStefan Roese */ 31309eefe2a2SStefan Roese int ubifs_debugging_init(struct ubifs_info *c) 31319eefe2a2SStefan Roese { 31329eefe2a2SStefan Roese c->dbg = kzalloc(sizeof(struct ubifs_debug_info), GFP_KERNEL); 31339eefe2a2SStefan Roese if (!c->dbg) 31349eefe2a2SStefan Roese return -ENOMEM; 31359eefe2a2SStefan Roese 31369eefe2a2SStefan Roese return 0; 31379eefe2a2SStefan Roese } 31389eefe2a2SStefan Roese 31399eefe2a2SStefan Roese /** 31409eefe2a2SStefan Roese * ubifs_debugging_exit - free debugging data. 31419eefe2a2SStefan Roese * @c: UBIFS file-system description object 31429eefe2a2SStefan Roese */ 31439eefe2a2SStefan Roese void ubifs_debugging_exit(struct ubifs_info *c) 31449eefe2a2SStefan Roese { 31459eefe2a2SStefan Roese kfree(c->dbg); 31469eefe2a2SStefan Roese } 3147ff94bc40SHeiko Schocher #endif 3148