blob: fb88eb19711b7338f10b3dbd53ead5c2c20c2973 [file] [log] [blame]
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +01001/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc.
5 *
6 * Created by David Woodhouse <dwmw2@infradead.org>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010010 * $Id: debug.c,v 1.7 2005/07/24 15:14:14 dedekind Exp $
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010011 *
12 */
13#include <linux/kernel.h>
14#include <linux/pagemap.h>
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010015#include <linux/crc32.h>
16#include <linux/jffs2.h>
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010017#include "nodelist.h"
18#include "debug.h"
19
20#ifdef JFFS2_DBG_PARANOIA_CHECKS
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010021/*
22 * Check the fragtree.
23 */
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010024void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010025__jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
26{
27 down(&f->sem);
28 __jffs2_dbg_fragtree_paranoia_check_nolock(f);
29 up(&f->sem);
30}
31
32void
33__jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010034{
35 struct jffs2_node_frag *frag;
36 int bitched = 0;
37
38 for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
39 struct jffs2_full_dnode *fn = frag->node;
40
41 if (!fn || !fn->raw)
42 continue;
43
44 if (ref_flags(fn->raw) == REF_PRISTINE) {
45 if (fn->frags > 1) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010046 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010047 ref_offset(fn->raw), fn->frags);
48 bitched = 1;
49 }
50
51 /* A hole node which isn't multi-page should be garbage-collected
52 and merged anyway, so we just check for the frag size here,
53 rather than mucking around with actually reading the node
54 and checking the compression type, which is the real way
55 to tell a hole node. */
56 if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag)
57 && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010058 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag "
59 "in the same page. Tell dwmw2.\n", ref_offset(fn->raw));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010060 bitched = 1;
61 }
62
63 if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag)
64 && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010065 JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following "
66 "non-hole frag in the same page. Tell dwmw2.\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010067 ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
68 bitched = 1;
69 }
70 }
71 }
72
73 if (bitched) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010074 JFFS2_ERROR("fragtree is corrupted.\n");
75 __jffs2_dbg_dump_fragtree_nolock(f);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010076 BUG();
77 }
78}
79
80/*
81 * Check if the flash contains all 0xFF before we start writing.
82 */
83void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010084__jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
85 uint32_t ofs, int len)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010086{
87 size_t retlen;
88 int ret, i;
89 unsigned char *buf;
90
91 buf = kmalloc(len, GFP_KERNEL);
92 if (!buf)
93 return;
94
95 ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
96 if (ret || (retlen != len)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010097 JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n",
98 len, ret, retlen);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010099 kfree(buf);
100 return;
101 }
102
103 ret = 0;
104 for (i = 0; i < len; i++)
105 if (buf[i] != 0xff)
106 ret = 1;
107
108 if (ret) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100109 JFFS2_ERROR("argh, about to write node to %#08x on flash, but there are data "
110 "already there. The first corrupted byte is at %#08x offset.\n", ofs, ofs + i);
111 __jffs2_dbg_dump_buffer(buf, len, ofs);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100112 kfree(buf);
113 BUG();
114 }
115
116 kfree(buf);
117}
118
119/*
120 * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
121 */
122void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100123__jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
124 struct jffs2_eraseblock *jeb)
125{
126 spin_lock(&c->erase_completion_lock);
127 __jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
128 spin_unlock(&c->erase_completion_lock);
129}
130
131void
132__jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
133 struct jffs2_eraseblock *jeb)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100134{
135 uint32_t my_used_size = 0;
136 uint32_t my_unchecked_size = 0;
137 uint32_t my_dirty_size = 0;
138 struct jffs2_raw_node_ref *ref2 = jeb->first_node;
139
140 while (ref2) {
141 uint32_t totlen = ref_totlen(c, jeb, ref2);
142
143 if (ref2->flash_offset < jeb->offset ||
144 ref2->flash_offset > jeb->offset + c->sector_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100145 JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100146 ref_offset(ref2), jeb->offset);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100147 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100148
149 }
150 if (ref_flags(ref2) == REF_UNCHECKED)
151 my_unchecked_size += totlen;
152 else if (!ref_obsolete(ref2))
153 my_used_size += totlen;
154 else
155 my_dirty_size += totlen;
156
157 if ((!ref2->next_phys) != (ref2 == jeb->last_node)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100158 JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), "
159 "last_node is at %#08x (mem %p).\n",
160 ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys,
161 ref_offset(jeb->last_node), jeb->last_node);
162 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100163 }
164 ref2 = ref2->next_phys;
165 }
166
167 if (my_used_size != jeb->used_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100168 JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
169 my_used_size, jeb->used_size);
170 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100171 }
172
173 if (my_unchecked_size != jeb->unchecked_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100174 JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
175 my_unchecked_size, jeb->unchecked_size);
176 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100177 }
178
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100179#if 0
180 /* This should work when we implement ref->__totlen elemination */
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100181 if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100182 JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100183 my_dirty_size, jeb->dirty_size + jeb->wasted_size);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100184 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100185 }
186
187 if (jeb->free_size == 0
188 && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100189 JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100190 my_used_size + my_unchecked_size + my_dirty_size,
191 c->sector_size);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100192 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100193 }
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100194#endif
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100195
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100196 return;
197
198error:
199 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
200 __jffs2_dbg_dump_jeb_nolock(jeb);
201 __jffs2_dbg_dump_block_lists_nolock(c);
202 BUG();
203
204}
205#endif /* JFFS2_DBG_PARANOIA_CHECKS */
206
207#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100208/*
209 * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
210 */
211void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100212__jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
213 struct jffs2_eraseblock *jeb)
214{
215 spin_lock(&c->erase_completion_lock);
216 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
217 spin_unlock(&c->erase_completion_lock);
218}
219
220void
221__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
222 struct jffs2_eraseblock *jeb)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100223{
224 struct jffs2_raw_node_ref *ref;
225 int i = 0;
226
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100227 JFFS2_DEBUG("Dump node_refs of the eraseblock %#08x\n", jeb->offset);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100228 if (!jeb->first_node) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100229 JFFS2_DEBUG("no nodes in the eraseblock %#08x\n", jeb->offset);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100230 return;
231 }
232
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100233 printk(JFFS2_DBG_LVL);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100234 for (ref = jeb->first_node; ; ref = ref->next_phys) {
235 printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
236 if (ref->next_phys)
237 printk("->");
238 else
239 break;
240 if (++i == 4) {
241 i = 0;
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100242 printk("\n" JFFS2_DBG_LVL);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100243 }
244 }
245 printk("\n");
246}
247
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100248/*
249 * Dump an eraseblock's space accounting.
250 */
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100251void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100252__jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100253{
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100254 spin_lock(&c->erase_completion_lock);
255 __jffs2_dbg_dump_jeb_nolock(jeb);
256 spin_unlock(&c->erase_completion_lock);
257}
258
259void
260__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
261{
262 if (!jeb)
263 return;
264
265 JFFS2_DEBUG("dump space accounting for the eraseblock at %#08x:\n",
266 jeb->offset);
267
268 printk(JFFS2_DBG_LVL "used_size: %#08x\n", jeb->used_size);
269 printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", jeb->dirty_size);
270 printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", jeb->wasted_size);
271 printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", jeb->unchecked_size);
272 printk(JFFS2_DBG_LVL "free_size: %#08x\n", jeb->free_size);
273}
274
275void
276__jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
277{
278 spin_lock(&c->erase_completion_lock);
279 __jffs2_dbg_dump_block_lists_nolock(c);
280 spin_unlock(&c->erase_completion_lock);
281}
282
283void
284__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
285{
286 JFFS2_DEBUG("dump JFFS2 blocks lists:\n");
287
288 printk(JFFS2_DBG_LVL "flash_size: %#08x\n", c->flash_size);
289 printk(JFFS2_DBG_LVL "used_size: %#08x\n", c->used_size);
290 printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", c->dirty_size);
291 printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", c->wasted_size);
292 printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", c->unchecked_size);
293 printk(JFFS2_DBG_LVL "free_size: %#08x\n", c->free_size);
294 printk(JFFS2_DBG_LVL "erasing_size: %#08x\n", c->erasing_size);
295 printk(JFFS2_DBG_LVL "bad_size: %#08x\n", c->bad_size);
296 printk(JFFS2_DBG_LVL "sector_size: %#08x\n", c->sector_size);
297 printk(JFFS2_DBG_LVL "jffs2_reserved_blocks size: %#08x\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100298 c->sector_size * c->resv_blocks_write);
299
300 if (c->nextblock)
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100301 printk(JFFS2_DBG_LVL "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
302 "unchecked %#08x, free %#08x)\n",
303 c->nextblock->offset, c->nextblock->used_size,
304 c->nextblock->dirty_size, c->nextblock->wasted_size,
305 c->nextblock->unchecked_size, c->nextblock->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100306 else
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100307 printk(JFFS2_DBG_LVL "nextblock: NULL\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100308
309 if (c->gcblock)
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100310 printk(JFFS2_DBG_LVL "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
311 "unchecked %#08x, free %#08x)\n",
312 c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
313 c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100314 else
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100315 printk(JFFS2_DBG_LVL "gcblock: NULL\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100316
317 if (list_empty(&c->clean_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100318 printk(JFFS2_DBG_LVL "clean_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100319 } else {
320 struct list_head *this;
321 int numblocks = 0;
322 uint32_t dirty = 0;
323
324 list_for_each(this, &c->clean_list) {
325 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
326 numblocks ++;
327 dirty += jeb->wasted_size;
328 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100329 printk(JFFS2_DBG_LVL "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
330 "unchecked %#08x, free %#08x)\n",
331 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
332 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100333 }
334 }
335
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100336 printk (JFFS2_DBG_LVL "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
337 numblocks, dirty, dirty / numblocks);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100338 }
339
340 if (list_empty(&c->very_dirty_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100341 printk(JFFS2_DBG_LVL "very_dirty_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100342 } else {
343 struct list_head *this;
344 int numblocks = 0;
345 uint32_t dirty = 0;
346
347 list_for_each(this, &c->very_dirty_list) {
348 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
349
350 numblocks ++;
351 dirty += jeb->dirty_size;
352 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100353 printk(JFFS2_DBG_LVL "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
354 "unchecked %#08x, free %#08x)\n",
355 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
356 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100357 }
358 }
359
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100360 printk (JFFS2_DBG_LVL "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
361 numblocks, dirty, dirty / numblocks);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100362 }
363
364 if (list_empty(&c->dirty_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100365 printk(JFFS2_DBG_LVL "dirty_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100366 } else {
367 struct list_head *this;
368 int numblocks = 0;
369 uint32_t dirty = 0;
370
371 list_for_each(this, &c->dirty_list) {
372 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
373
374 numblocks ++;
375 dirty += jeb->dirty_size;
376 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100377 printk(JFFS2_DBG_LVL "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
378 "unchecked %#08x, free %#08x)\n",
379 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
380 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100381 }
382 }
383
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100384 printk (JFFS2_DBG_LVL "contains %d blocks with total dirty size %u, average dirty size: %u\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100385 numblocks, dirty, dirty / numblocks);
386 }
387
388 if (list_empty(&c->erasable_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100389 printk(JFFS2_DBG_LVL "erasable_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100390 } else {
391 struct list_head *this;
392
393 list_for_each(this, &c->erasable_list) {
394 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
395
396 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100397 printk(JFFS2_DBG_LVL "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
398 "unchecked %#08x, free %#08x)\n",
399 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
400 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100401 }
402 }
403 }
404
405 if (list_empty(&c->erasing_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100406 printk(JFFS2_DBG_LVL "erasing_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100407 } else {
408 struct list_head *this;
409
410 list_for_each(this, &c->erasing_list) {
411 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
412
413 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100414 printk(JFFS2_DBG_LVL "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
415 "unchecked %#08x, free %#08x)\n",
416 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
417 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100418 }
419 }
420 }
421
422 if (list_empty(&c->erase_pending_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100423 printk(JFFS2_DBG_LVL "erase_pending_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100424 } else {
425 struct list_head *this;
426
427 list_for_each(this, &c->erase_pending_list) {
428 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
429
430 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100431 printk(JFFS2_DBG_LVL "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
432 "unchecked %#08x, free %#08x)\n",
433 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
434 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100435 }
436 }
437 }
438
439 if (list_empty(&c->erasable_pending_wbuf_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100440 printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100441 } else {
442 struct list_head *this;
443
444 list_for_each(this, &c->erasable_pending_wbuf_list) {
445 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
446
447 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100448 printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, "
449 "wasted %#08x, unchecked %#08x, free %#08x)\n",
450 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
451 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100452 }
453 }
454 }
455
456 if (list_empty(&c->free_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100457 printk(JFFS2_DBG_LVL "free_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100458 } else {
459 struct list_head *this;
460
461 list_for_each(this, &c->free_list) {
462 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
463
464 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100465 printk(JFFS2_DBG_LVL "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
466 "unchecked %#08x, free %#08x)\n",
467 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
468 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100469 }
470 }
471 }
472
473 if (list_empty(&c->bad_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100474 printk(JFFS2_DBG_LVL "bad_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100475 } else {
476 struct list_head *this;
477
478 list_for_each(this, &c->bad_list) {
479 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
480
481 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100482 printk(JFFS2_DBG_LVL "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
483 "unchecked %#08x, free %#08x)\n",
484 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
485 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100486 }
487 }
488 }
489
490 if (list_empty(&c->bad_used_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100491 printk(JFFS2_DBG_LVL "bad_used_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100492 } else {
493 struct list_head *this;
494
495 list_for_each(this, &c->bad_used_list) {
496 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
497
498 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100499 printk(JFFS2_DBG_LVL "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
500 "unchecked %#08x, free %#08x)\n",
501 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
502 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100503 }
504 }
505 }
506}
507
508void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100509__jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
510{
511 down(&f->sem);
512 jffs2_dbg_dump_fragtree_nolock(f);
513 up(&f->sem);
514}
515
516void
517__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100518{
519 struct jffs2_node_frag *this = frag_first(&f->fragtree);
520 uint32_t lastofs = 0;
521 int buggy = 0;
522
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100523 JFFS2_DEBUG("dump fragtree of ino #%u\n", f->inocache->ino);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100524 while(this) {
525 if (this->node)
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100526 printk(JFFS2_DBG_LVL "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), "
527 "right (%p), parent (%p)\n",
528 this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
529 ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
530 frag_parent(this));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100531 else
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100532 printk(JFFS2_DBG_LVL "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
533 this->ofs, this->ofs+this->size, this, frag_left(this),
534 frag_right(this), frag_parent(this));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100535 if (this->ofs != lastofs)
536 buggy = 1;
537 lastofs = this->ofs + this->size;
538 this = frag_next(this);
539 }
540
541 if (f->metadata)
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100542 printk(JFFS2_DBG_LVL "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100543
544 if (buggy) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100545 JFFS2_ERROR("frag tree got a hole in it.\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100546 BUG();
547 }
548}
549
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100550#define JFFS2_BUFDUMP_BYTES_PER_LINE 32
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100551void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100552__jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100553{
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100554 int skip;
555 int i;
556
557 JFFS2_DEBUG("dump from offset %#08x to offset %#08x (%x bytes).\n",
558 offs, offs + len, len);
559 i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
560 offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
561
562 if (skip != 0)
563 printk(JFFS2_DBG_LVL "%#08x: ", offs);
564
565 while (skip--)
566 printk(" ");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100567
568 while (i < len) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100569 if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
570 if (i != 0)
571 printk("\n");
572 offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
573 printk(JFFS2_DBG_LVL "%0#8x: ", offs);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100574 }
575
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100576 printk("%02x ", buf[i]);
577
578 i += 1;
579 }
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100580
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100581 printk("\n");
582}
583
584/*
585 * Dump a JFFS2 node.
586 */
587void
588__jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
589{
590 union jffs2_node_union node;
591 int len = sizeof(union jffs2_node_union);
592 size_t retlen;
593 uint32_t crc;
594 int ret;
595
596 JFFS2_DEBUG("dump node at offset %#08x.\n", ofs);
597
598 ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
599 if (ret || (retlen != len)) {
600 JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
601 len, ret, retlen);
602 return;
603 }
604
605 printk(JFFS2_DBG_LVL "magic:\t%#04x\n",
606 je16_to_cpu(node.u.magic));
607 printk(JFFS2_DBG_LVL "nodetype:\t%#04x\n",
608 je16_to_cpu(node.u.nodetype));
609 printk(JFFS2_DBG_LVL "totlen:\t%#08x\n",
610 je32_to_cpu(node.u.totlen));
611 printk(JFFS2_DBG_LVL "hdr_crc:\t%#08x\n",
612 je32_to_cpu(node.u.hdr_crc));
613
614 crc = crc32(0, &node.u, sizeof(node.u) - 4);
615 if (crc != je32_to_cpu(node.u.hdr_crc)) {
616 JFFS2_ERROR("wrong common header CRC.\n");
617 return;
618 }
619
620 if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
621 je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
622 {
623 JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
624 je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
625 return;
626 }
627
628 switch(je16_to_cpu(node.u.nodetype)) {
629
630 case JFFS2_NODETYPE_INODE:
631
632 printk(JFFS2_DBG_LVL "the node is inode node\n");
633 printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
634 je32_to_cpu(node.i.ino));
635 printk(JFFS2_DBG_LVL "version:\t%#08x\n",
636 je32_to_cpu(node.i.version));
637 printk(JFFS2_DBG_LVL "mode:\t%#08x\n",
638 node.i.mode.m);
639 printk(JFFS2_DBG_LVL "uid:\t%#04x\n",
640 je16_to_cpu(node.i.uid));
641 printk(JFFS2_DBG_LVL "gid:\t%#04x\n",
642 je16_to_cpu(node.i.gid));
643 printk(JFFS2_DBG_LVL "isize:\t%#08x\n",
644 je32_to_cpu(node.i.isize));
645 printk(JFFS2_DBG_LVL "atime:\t%#08x\n",
646 je32_to_cpu(node.i.atime));
647 printk(JFFS2_DBG_LVL "mtime:\t%#08x\n",
648 je32_to_cpu(node.i.mtime));
649 printk(JFFS2_DBG_LVL "ctime:\t%#08x\n",
650 je32_to_cpu(node.i.ctime));
651 printk(JFFS2_DBG_LVL "offset:\t%#08x\n",
652 je32_to_cpu(node.i.offset));
653 printk(JFFS2_DBG_LVL "csize:\t%#08x\n",
654 je32_to_cpu(node.i.csize));
655 printk(JFFS2_DBG_LVL "dsize:\t%#08x\n",
656 je32_to_cpu(node.i.dsize));
657 printk(JFFS2_DBG_LVL "compr:\t%#02x\n",
658 node.i.compr);
659 printk(JFFS2_DBG_LVL "usercompr:\t%#02x\n",
660 node.i.usercompr);
661 printk(JFFS2_DBG_LVL "flags:\t%#04x\n",
662 je16_to_cpu(node.i.flags));
663 printk(JFFS2_DBG_LVL "data_crc:\t%#08x\n",
664 je32_to_cpu(node.i.data_crc));
665 printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
666 je32_to_cpu(node.i.node_crc));
667 crc = crc32(0, &node.i, sizeof(node.i) - 8);
668 if (crc != je32_to_cpu(node.i.node_crc)) {
669 JFFS2_ERROR("wrong node header CRC.\n");
670 return;
671 }
672 break;
673
674 case JFFS2_NODETYPE_DIRENT:
675
676 printk(JFFS2_DBG_LVL "the node is dirent node\n");
677 printk(JFFS2_DBG_LVL "pino:\t%#08x\n",
678 je32_to_cpu(node.d.pino));
679 printk(JFFS2_DBG_LVL "version:\t%#08x\n",
680 je32_to_cpu(node.d.version));
681 printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
682 je32_to_cpu(node.d.ino));
683 printk(JFFS2_DBG_LVL "mctime:\t%#08x\n",
684 je32_to_cpu(node.d.mctime));
685 printk(JFFS2_DBG_LVL "nsize:\t%#02x\n",
686 node.d.nsize);
687 printk(JFFS2_DBG_LVL "type:\t%#02x\n",
688 node.d.type);
689 printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
690 je32_to_cpu(node.d.node_crc));
691 printk(JFFS2_DBG_LVL "name_crc:\t%#08x\n",
692 je32_to_cpu(node.d.name_crc));
693
694 node.d.name[node.d.nsize] = '\0';
695 printk(JFFS2_DBG_LVL "name:\t\"%s\"\n", node.d.name);
696
697 crc = crc32(0, &node.d, sizeof(node.d) - 8);
698 if (crc != je32_to_cpu(node.d.node_crc)) {
699 JFFS2_ERROR("wrong node header CRC.\n");
700 return;
701 }
702 break;
703
704 default:
705 printk(JFFS2_DBG_LVL "node type is unknown\n");
706 break;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100707 }
708}
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100709#endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */