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