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