include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[linux-2.6-block.git] / fs / jffs2 / debug.c
CommitLineData
730554d9
AB
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
c00c310e 4 * Copyright © 2001-2007 Red Hat, Inc.
730554d9
AB
5 *
6 * Created by David Woodhouse <dwmw2@infradead.org>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
730554d9 10 */
c00c310e 11
730554d9 12#include <linux/kernel.h>
737b7661 13#include <linux/types.h>
730554d9 14#include <linux/pagemap.h>
e0c8e42f
AB
15#include <linux/crc32.h>
16#include <linux/jffs2.h>
733802d9 17#include <linux/mtd/mtd.h>
5a0e3ad6 18#include <linux/slab.h>
730554d9
AB
19#include "nodelist.h"
20#include "debug.h"
21
45ca1b50
AB
22#ifdef JFFS2_DBG_SANITY_CHECKS
23
24void
25__jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info *c,
26 struct jffs2_eraseblock *jeb)
27{
28 if (unlikely(jeb && jeb->used_size + jeb->dirty_size +
29 jeb->free_size + jeb->wasted_size +
30 jeb->unchecked_size != c->sector_size)) {
31 JFFS2_ERROR("eeep, space accounting for block at 0x%08x is screwed.\n", jeb->offset);
81e39cf0
AB
32 JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked %#08x != total %#08x.\n",
33 jeb->free_size, jeb->dirty_size, jeb->used_size,
45ca1b50
AB
34 jeb->wasted_size, jeb->unchecked_size, c->sector_size);
35 BUG();
36 }
37
38 if (unlikely(c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size
39 + c->wasted_size + c->unchecked_size != c->flash_size)) {
40 JFFS2_ERROR("eeep, space accounting superblock info is screwed.\n");
81e39cf0 41 JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + wasted %#08x + unchecked %#08x != total %#08x.\n",
45ca1b50
AB
42 c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size,
43 c->wasted_size, c->unchecked_size, c->flash_size);
44 BUG();
45 }
46}
47
48void
49__jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c,
50 struct jffs2_eraseblock *jeb)
51{
52 spin_lock(&c->erase_completion_lock);
53 jffs2_dbg_acct_sanity_check_nolock(c, jeb);
54 spin_unlock(&c->erase_completion_lock);
55}
56
57#endif /* JFFS2_DBG_SANITY_CHECKS */
58
730554d9 59#ifdef JFFS2_DBG_PARANOIA_CHECKS
e0c8e42f
AB
60/*
61 * Check the fragtree.
62 */
730554d9 63void
e0c8e42f
AB
64__jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
65{
ced22070 66 mutex_lock(&f->sem);
e0c8e42f 67 __jffs2_dbg_fragtree_paranoia_check_nolock(f);
ced22070 68 mutex_unlock(&f->sem);
e0c8e42f 69}
182ec4ee 70
e0c8e42f
AB
71void
72__jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f)
730554d9
AB
73{
74 struct jffs2_node_frag *frag;
75 int bitched = 0;
76
77 for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
78 struct jffs2_full_dnode *fn = frag->node;
79
80 if (!fn || !fn->raw)
81 continue;
82
83 if (ref_flags(fn->raw) == REF_PRISTINE) {
84 if (fn->frags > 1) {
e0c8e42f 85 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n",
81e39cf0 86 ref_offset(fn->raw), fn->frags);
730554d9
AB
87 bitched = 1;
88 }
89
90 /* A hole node which isn't multi-page should be garbage-collected
91 and merged anyway, so we just check for the frag size here,
92 rather than mucking around with actually reading the node
93 and checking the compression type, which is the real way
94 to tell a hole node. */
95 if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag)
96 && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
81e39cf0
AB
97 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag in the same page. Tell dwmw2.\n",
98 ref_offset(fn->raw));
730554d9
AB
99 bitched = 1;
100 }
101
102 if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag)
103 && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
81e39cf0
AB
104 JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following non-hole frag in the same page. Tell dwmw2.\n",
105 ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
730554d9
AB
106 bitched = 1;
107 }
108 }
109 }
110
111 if (bitched) {
e0c8e42f
AB
112 JFFS2_ERROR("fragtree is corrupted.\n");
113 __jffs2_dbg_dump_fragtree_nolock(f);
730554d9
AB
114 BUG();
115 }
116}
117
118/*
119 * Check if the flash contains all 0xFF before we start writing.
120 */
121void
e0c8e42f
AB
122__jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
123 uint32_t ofs, int len)
730554d9
AB
124{
125 size_t retlen;
126 int ret, i;
127 unsigned char *buf;
128
129 buf = kmalloc(len, GFP_KERNEL);
130 if (!buf)
131 return;
132
133 ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
134 if (ret || (retlen != len)) {
e0c8e42f
AB
135 JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n",
136 len, ret, retlen);
730554d9
AB
137 kfree(buf);
138 return;
139 }
140
141 ret = 0;
142 for (i = 0; i < len; i++)
143 if (buf[i] != 0xff)
144 ret = 1;
145
146 if (ret) {
81e39cf0
AB
147 JFFS2_ERROR("argh, about to write node to %#08x on flash, but there are data already there. The first corrupted byte is at %#08x offset.\n",
148 ofs, ofs + i);
e0c8e42f 149 __jffs2_dbg_dump_buffer(buf, len, ofs);
730554d9
AB
150 kfree(buf);
151 BUG();
152 }
153
154 kfree(buf);
155}
156
85a62db6
DW
157void __jffs2_dbg_superblock_counts(struct jffs2_sb_info *c)
158{
159 struct jffs2_eraseblock *jeb;
160 uint32_t free = 0, dirty = 0, used = 0, wasted = 0,
161 erasing = 0, bad = 0, unchecked = 0;
162 int nr_counted = 0;
163 int dump = 0;
164
165 if (c->gcblock) {
166 nr_counted++;
167 free += c->gcblock->free_size;
168 dirty += c->gcblock->dirty_size;
169 used += c->gcblock->used_size;
170 wasted += c->gcblock->wasted_size;
171 unchecked += c->gcblock->unchecked_size;
172 }
173 if (c->nextblock) {
174 nr_counted++;
175 free += c->nextblock->free_size;
176 dirty += c->nextblock->dirty_size;
177 used += c->nextblock->used_size;
178 wasted += c->nextblock->wasted_size;
179 unchecked += c->nextblock->unchecked_size;
180 }
181 list_for_each_entry(jeb, &c->clean_list, list) {
182 nr_counted++;
183 free += jeb->free_size;
184 dirty += jeb->dirty_size;
185 used += jeb->used_size;
186 wasted += jeb->wasted_size;
187 unchecked += jeb->unchecked_size;
188 }
189 list_for_each_entry(jeb, &c->very_dirty_list, list) {
190 nr_counted++;
191 free += jeb->free_size;
192 dirty += jeb->dirty_size;
193 used += jeb->used_size;
194 wasted += jeb->wasted_size;
195 unchecked += jeb->unchecked_size;
196 }
197 list_for_each_entry(jeb, &c->dirty_list, list) {
198 nr_counted++;
199 free += jeb->free_size;
200 dirty += jeb->dirty_size;
201 used += jeb->used_size;
202 wasted += jeb->wasted_size;
203 unchecked += jeb->unchecked_size;
204 }
205 list_for_each_entry(jeb, &c->erasable_list, list) {
206 nr_counted++;
207 free += jeb->free_size;
208 dirty += jeb->dirty_size;
209 used += jeb->used_size;
210 wasted += jeb->wasted_size;
211 unchecked += jeb->unchecked_size;
212 }
213 list_for_each_entry(jeb, &c->erasable_pending_wbuf_list, list) {
214 nr_counted++;
215 free += jeb->free_size;
216 dirty += jeb->dirty_size;
217 used += jeb->used_size;
218 wasted += jeb->wasted_size;
219 unchecked += jeb->unchecked_size;
220 }
221 list_for_each_entry(jeb, &c->erase_pending_list, list) {
222 nr_counted++;
223 free += jeb->free_size;
224 dirty += jeb->dirty_size;
225 used += jeb->used_size;
226 wasted += jeb->wasted_size;
227 unchecked += jeb->unchecked_size;
228 }
229 list_for_each_entry(jeb, &c->free_list, list) {
230 nr_counted++;
231 free += jeb->free_size;
232 dirty += jeb->dirty_size;
233 used += jeb->used_size;
234 wasted += jeb->wasted_size;
235 unchecked += jeb->unchecked_size;
236 }
237 list_for_each_entry(jeb, &c->bad_used_list, list) {
238 nr_counted++;
239 free += jeb->free_size;
240 dirty += jeb->dirty_size;
241 used += jeb->used_size;
242 wasted += jeb->wasted_size;
243 unchecked += jeb->unchecked_size;
244 }
245
246 list_for_each_entry(jeb, &c->erasing_list, list) {
247 nr_counted++;
248 erasing += c->sector_size;
249 }
e2bc322b
DW
250 list_for_each_entry(jeb, &c->erase_checking_list, list) {
251 nr_counted++;
252 erasing += c->sector_size;
253 }
85a62db6
DW
254 list_for_each_entry(jeb, &c->erase_complete_list, list) {
255 nr_counted++;
256 erasing += c->sector_size;
257 }
258 list_for_each_entry(jeb, &c->bad_list, list) {
259 nr_counted++;
260 bad += c->sector_size;
261 }
262
263#define check(sz) \
264 if (sz != c->sz##_size) { \
265 printk(KERN_WARNING #sz "_size mismatch counted 0x%x, c->" #sz "_size 0x%x\n", \
266 sz, c->sz##_size); \
267 dump = 1; \
268 }
269 check(free);
270 check(dirty);
271 check(used);
272 check(wasted);
273 check(unchecked);
274 check(bad);
275 check(erasing);
276#undef check
277
278 if (nr_counted != c->nr_blocks) {
279 printk(KERN_WARNING "%s counted only 0x%x blocks of 0x%x. Where are the others?\n",
280 __func__, nr_counted, c->nr_blocks);
281 dump = 1;
282 }
283
284 if (dump) {
285 __jffs2_dbg_dump_block_lists_nolock(c);
286 BUG();
287 }
288}
289
730554d9
AB
290/*
291 * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
292 */
293void
e0c8e42f
AB
294__jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
295 struct jffs2_eraseblock *jeb)
296{
297 spin_lock(&c->erase_completion_lock);
298 __jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
299 spin_unlock(&c->erase_completion_lock);
300}
182ec4ee 301
e0c8e42f
AB
302void
303__jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
304 struct jffs2_eraseblock *jeb)
730554d9
AB
305{
306 uint32_t my_used_size = 0;
307 uint32_t my_unchecked_size = 0;
308 uint32_t my_dirty_size = 0;
309 struct jffs2_raw_node_ref *ref2 = jeb->first_node;
310
311 while (ref2) {
312 uint32_t totlen = ref_totlen(c, jeb, ref2);
313
abb536e7
KP
314 if (ref_offset(ref2) < jeb->offset ||
315 ref_offset(ref2) > jeb->offset + c->sector_size) {
e0c8e42f 316 JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
730554d9 317 ref_offset(ref2), jeb->offset);
e0c8e42f 318 goto error;
730554d9
AB
319
320 }
321 if (ref_flags(ref2) == REF_UNCHECKED)
322 my_unchecked_size += totlen;
323 else if (!ref_obsolete(ref2))
324 my_used_size += totlen;
325 else
326 my_dirty_size += totlen;
327
99988f7b
DW
328 if ((!ref_next(ref2)) != (ref2 == jeb->last_node)) {
329 JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next at %#08x (mem %p), last_node is at %#08x (mem %p).\n",
330 ref_offset(ref2), ref2, ref_offset(ref_next(ref2)), ref_next(ref2),
331 ref_offset(jeb->last_node), jeb->last_node);
e0c8e42f 332 goto error;
730554d9 333 }
99988f7b 334 ref2 = ref_next(ref2);
730554d9
AB
335 }
336
337 if (my_used_size != jeb->used_size) {
e0c8e42f
AB
338 JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
339 my_used_size, jeb->used_size);
340 goto error;
730554d9
AB
341 }
342
343 if (my_unchecked_size != jeb->unchecked_size) {
e0c8e42f
AB
344 JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
345 my_unchecked_size, jeb->unchecked_size);
346 goto error;
730554d9
AB
347 }
348
e0c8e42f
AB
349#if 0
350 /* This should work when we implement ref->__totlen elemination */
730554d9 351 if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
e0c8e42f 352 JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
730554d9 353 my_dirty_size, jeb->dirty_size + jeb->wasted_size);
e0c8e42f 354 goto error;
730554d9
AB
355 }
356
357 if (jeb->free_size == 0
358 && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
e0c8e42f 359 JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
730554d9
AB
360 my_used_size + my_unchecked_size + my_dirty_size,
361 c->sector_size);
e0c8e42f 362 goto error;
730554d9 363 }
e0c8e42f
AB
364#endif
365
85a62db6
DW
366 if (!(c->flags & (JFFS2_SB_FLAG_BUILDING|JFFS2_SB_FLAG_SCANNING)))
367 __jffs2_dbg_superblock_counts(c);
368
e0c8e42f
AB
369 return;
370
371error:
372 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
373 __jffs2_dbg_dump_jeb_nolock(jeb);
374 __jffs2_dbg_dump_block_lists_nolock(c);
375 BUG();
182ec4ee 376
730554d9 377}
e0c8e42f 378#endif /* JFFS2_DBG_PARANOIA_CHECKS */
730554d9 379
e0c8e42f 380#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
730554d9
AB
381/*
382 * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
383 */
384void
e0c8e42f
AB
385__jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
386 struct jffs2_eraseblock *jeb)
387{
388 spin_lock(&c->erase_completion_lock);
389 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
390 spin_unlock(&c->erase_completion_lock);
391}
392
393void
394__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
395 struct jffs2_eraseblock *jeb)
730554d9
AB
396{
397 struct jffs2_raw_node_ref *ref;
398 int i = 0;
399
81e39cf0 400 printk(JFFS2_DBG_MSG_PREFIX " Dump node_refs of the eraseblock %#08x\n", jeb->offset);
730554d9 401 if (!jeb->first_node) {
81e39cf0 402 printk(JFFS2_DBG_MSG_PREFIX " no nodes in the eraseblock %#08x\n", jeb->offset);
730554d9
AB
403 return;
404 }
405
81e39cf0 406 printk(JFFS2_DBG);
99988f7b 407 for (ref = jeb->first_node; ; ref = ref_next(ref)) {
27e6b8e3
DW
408 printk("%#08x", ref_offset(ref));
409#ifdef TEST_TOTLEN
410 printk("(%x)", ref->__totlen);
411#endif
99988f7b 412 if (ref_next(ref))
730554d9
AB
413 printk("->");
414 else
415 break;
416 if (++i == 4) {
417 i = 0;
81e39cf0 418 printk("\n" JFFS2_DBG);
730554d9
AB
419 }
420 }
421 printk("\n");
422}
423
e0c8e42f
AB
424/*
425 * Dump an eraseblock's space accounting.
426 */
427void
428__jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
429{
430 spin_lock(&c->erase_completion_lock);
431 __jffs2_dbg_dump_jeb_nolock(jeb);
432 spin_unlock(&c->erase_completion_lock);
433}
434
730554d9 435void
e0c8e42f 436__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
730554d9 437{
e0c8e42f
AB
438 if (!jeb)
439 return;
440
81e39cf0 441 printk(JFFS2_DBG_MSG_PREFIX " dump space accounting for the eraseblock at %#08x:\n",
e0c8e42f
AB
442 jeb->offset);
443
81e39cf0
AB
444 printk(JFFS2_DBG "used_size: %#08x\n", jeb->used_size);
445 printk(JFFS2_DBG "dirty_size: %#08x\n", jeb->dirty_size);
446 printk(JFFS2_DBG "wasted_size: %#08x\n", jeb->wasted_size);
447 printk(JFFS2_DBG "unchecked_size: %#08x\n", jeb->unchecked_size);
448 printk(JFFS2_DBG "free_size: %#08x\n", jeb->free_size);
e0c8e42f
AB
449}
450
451void
452__jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
453{
454 spin_lock(&c->erase_completion_lock);
455 __jffs2_dbg_dump_block_lists_nolock(c);
456 spin_unlock(&c->erase_completion_lock);
457}
458
459void
460__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
461{
81e39cf0 462 printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n");
182ec4ee 463
81e39cf0
AB
464 printk(JFFS2_DBG "flash_size: %#08x\n", c->flash_size);
465 printk(JFFS2_DBG "used_size: %#08x\n", c->used_size);
466 printk(JFFS2_DBG "dirty_size: %#08x\n", c->dirty_size);
467 printk(JFFS2_DBG "wasted_size: %#08x\n", c->wasted_size);
468 printk(JFFS2_DBG "unchecked_size: %#08x\n", c->unchecked_size);
469 printk(JFFS2_DBG "free_size: %#08x\n", c->free_size);
470 printk(JFFS2_DBG "erasing_size: %#08x\n", c->erasing_size);
471 printk(JFFS2_DBG "bad_size: %#08x\n", c->bad_size);
472 printk(JFFS2_DBG "sector_size: %#08x\n", c->sector_size);
473 printk(JFFS2_DBG "jffs2_reserved_blocks size: %#08x\n",
730554d9
AB
474 c->sector_size * c->resv_blocks_write);
475
476 if (c->nextblock)
81e39cf0 477 printk(JFFS2_DBG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
478 c->nextblock->offset, c->nextblock->used_size,
479 c->nextblock->dirty_size, c->nextblock->wasted_size,
480 c->nextblock->unchecked_size, c->nextblock->free_size);
730554d9 481 else
81e39cf0 482 printk(JFFS2_DBG "nextblock: NULL\n");
730554d9
AB
483
484 if (c->gcblock)
81e39cf0 485 printk(JFFS2_DBG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
486 c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
487 c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
730554d9 488 else
81e39cf0 489 printk(JFFS2_DBG "gcblock: NULL\n");
730554d9
AB
490
491 if (list_empty(&c->clean_list)) {
81e39cf0 492 printk(JFFS2_DBG "clean_list: empty\n");
730554d9
AB
493 } else {
494 struct list_head *this;
495 int numblocks = 0;
496 uint32_t dirty = 0;
497
498 list_for_each(this, &c->clean_list) {
499 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
500 numblocks ++;
501 dirty += jeb->wasted_size;
502 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 503 printk(JFFS2_DBG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
504 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
505 jeb->unchecked_size, jeb->free_size);
730554d9
AB
506 }
507 }
508
81e39cf0 509 printk (JFFS2_DBG "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
e0c8e42f 510 numblocks, dirty, dirty / numblocks);
730554d9
AB
511 }
512
513 if (list_empty(&c->very_dirty_list)) {
81e39cf0 514 printk(JFFS2_DBG "very_dirty_list: empty\n");
730554d9
AB
515 } else {
516 struct list_head *this;
517 int numblocks = 0;
518 uint32_t dirty = 0;
519
520 list_for_each(this, &c->very_dirty_list) {
521 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
522
523 numblocks ++;
524 dirty += jeb->dirty_size;
525 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 526 printk(JFFS2_DBG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
527 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
528 jeb->unchecked_size, jeb->free_size);
730554d9
AB
529 }
530 }
531
81e39cf0 532 printk (JFFS2_DBG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
e0c8e42f 533 numblocks, dirty, dirty / numblocks);
730554d9
AB
534 }
535
536 if (list_empty(&c->dirty_list)) {
81e39cf0 537 printk(JFFS2_DBG "dirty_list: empty\n");
730554d9
AB
538 } else {
539 struct list_head *this;
540 int numblocks = 0;
541 uint32_t dirty = 0;
542
543 list_for_each(this, &c->dirty_list) {
544 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
545
546 numblocks ++;
547 dirty += jeb->dirty_size;
548 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 549 printk(JFFS2_DBG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
550 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
551 jeb->unchecked_size, jeb->free_size);
730554d9
AB
552 }
553 }
554
81e39cf0 555 printk (JFFS2_DBG "contains %d blocks with total dirty size %u, average dirty size: %u\n",
730554d9
AB
556 numblocks, dirty, dirty / numblocks);
557 }
558
559 if (list_empty(&c->erasable_list)) {
81e39cf0 560 printk(JFFS2_DBG "erasable_list: empty\n");
730554d9
AB
561 } else {
562 struct list_head *this;
563
564 list_for_each(this, &c->erasable_list) {
565 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
566
567 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 568 printk(JFFS2_DBG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
569 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
570 jeb->unchecked_size, jeb->free_size);
730554d9
AB
571 }
572 }
573 }
574
575 if (list_empty(&c->erasing_list)) {
81e39cf0 576 printk(JFFS2_DBG "erasing_list: empty\n");
730554d9
AB
577 } else {
578 struct list_head *this;
579
580 list_for_each(this, &c->erasing_list) {
581 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
582
583 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 584 printk(JFFS2_DBG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
585 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
586 jeb->unchecked_size, jeb->free_size);
730554d9
AB
587 }
588 }
589 }
e2bc322b
DW
590 if (list_empty(&c->erase_checking_list)) {
591 printk(JFFS2_DBG "erase_checking_list: empty\n");
592 } else {
593 struct list_head *this;
594
595 list_for_each(this, &c->erase_checking_list) {
596 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
597
598 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
599 printk(JFFS2_DBG "erase_checking_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
600 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
601 jeb->unchecked_size, jeb->free_size);
602 }
603 }
604 }
730554d9
AB
605
606 if (list_empty(&c->erase_pending_list)) {
81e39cf0 607 printk(JFFS2_DBG "erase_pending_list: empty\n");
730554d9
AB
608 } else {
609 struct list_head *this;
610
611 list_for_each(this, &c->erase_pending_list) {
612 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
613
614 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 615 printk(JFFS2_DBG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
616 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
617 jeb->unchecked_size, jeb->free_size);
730554d9
AB
618 }
619 }
620 }
621
622 if (list_empty(&c->erasable_pending_wbuf_list)) {
81e39cf0 623 printk(JFFS2_DBG "erasable_pending_wbuf_list: empty\n");
730554d9
AB
624 } else {
625 struct list_head *this;
626
627 list_for_each(this, &c->erasable_pending_wbuf_list) {
628 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
629
630 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 631 printk(JFFS2_DBG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
632 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
633 jeb->unchecked_size, jeb->free_size);
730554d9
AB
634 }
635 }
636 }
637
638 if (list_empty(&c->free_list)) {
81e39cf0 639 printk(JFFS2_DBG "free_list: empty\n");
730554d9
AB
640 } else {
641 struct list_head *this;
642
643 list_for_each(this, &c->free_list) {
644 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
645
646 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 647 printk(JFFS2_DBG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
648 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
649 jeb->unchecked_size, jeb->free_size);
730554d9
AB
650 }
651 }
652 }
653
654 if (list_empty(&c->bad_list)) {
81e39cf0 655 printk(JFFS2_DBG "bad_list: empty\n");
730554d9
AB
656 } else {
657 struct list_head *this;
658
659 list_for_each(this, &c->bad_list) {
660 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
661
662 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 663 printk(JFFS2_DBG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
664 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
665 jeb->unchecked_size, jeb->free_size);
730554d9
AB
666 }
667 }
668 }
669
670 if (list_empty(&c->bad_used_list)) {
81e39cf0 671 printk(JFFS2_DBG "bad_used_list: empty\n");
730554d9
AB
672 } else {
673 struct list_head *this;
674
675 list_for_each(this, &c->bad_used_list) {
676 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
677
678 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 679 printk(JFFS2_DBG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
680 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
681 jeb->unchecked_size, jeb->free_size);
730554d9
AB
682 }
683 }
684 }
685}
686
687void
e0c8e42f
AB
688__jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
689{
ced22070 690 mutex_lock(&f->sem);
e0c8e42f 691 jffs2_dbg_dump_fragtree_nolock(f);
ced22070 692 mutex_unlock(&f->sem);
e0c8e42f
AB
693}
694
695void
696__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
730554d9
AB
697{
698 struct jffs2_node_frag *this = frag_first(&f->fragtree);
699 uint32_t lastofs = 0;
700 int buggy = 0;
701
81e39cf0 702 printk(JFFS2_DBG_MSG_PREFIX " dump fragtree of ino #%u\n", f->inocache->ino);
730554d9
AB
703 while(this) {
704 if (this->node)
81e39cf0 705 printk(JFFS2_DBG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), right (%p), parent (%p)\n",
e0c8e42f
AB
706 this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
707 ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
708 frag_parent(this));
730554d9 709 else
81e39cf0 710 printk(JFFS2_DBG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
e0c8e42f
AB
711 this->ofs, this->ofs+this->size, this, frag_left(this),
712 frag_right(this), frag_parent(this));
730554d9
AB
713 if (this->ofs != lastofs)
714 buggy = 1;
715 lastofs = this->ofs + this->size;
716 this = frag_next(this);
717 }
718
719 if (f->metadata)
81e39cf0 720 printk(JFFS2_DBG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
730554d9
AB
721
722 if (buggy) {
e0c8e42f 723 JFFS2_ERROR("frag tree got a hole in it.\n");
730554d9
AB
724 BUG();
725 }
726}
727
e0c8e42f 728#define JFFS2_BUFDUMP_BYTES_PER_LINE 32
730554d9 729void
e0c8e42f 730__jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
730554d9 731{
e0c8e42f
AB
732 int skip;
733 int i;
182ec4ee 734
81e39cf0 735 printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n",
e0c8e42f
AB
736 offs, offs + len, len);
737 i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
738 offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
182ec4ee 739
e0c8e42f 740 if (skip != 0)
81e39cf0 741 printk(JFFS2_DBG "%#08x: ", offs);
182ec4ee 742
e0c8e42f
AB
743 while (skip--)
744 printk(" ");
730554d9
AB
745
746 while (i < len) {
e0c8e42f
AB
747 if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
748 if (i != 0)
749 printk("\n");
750 offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
81e39cf0 751 printk(JFFS2_DBG "%0#8x: ", offs);
730554d9
AB
752 }
753
e0c8e42f 754 printk("%02x ", buf[i]);
182ec4ee 755
e0c8e42f
AB
756 i += 1;
757 }
758
759 printk("\n");
760}
761
762/*
763 * Dump a JFFS2 node.
764 */
765void
766__jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
767{
768 union jffs2_node_union node;
769 int len = sizeof(union jffs2_node_union);
770 size_t retlen;
771 uint32_t crc;
772 int ret;
182ec4ee 773
81e39cf0 774 printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs);
e0c8e42f
AB
775
776 ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
777 if (ret || (retlen != len)) {
778 JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
779 len, ret, retlen);
780 return;
781 }
782
81e39cf0
AB
783 printk(JFFS2_DBG "magic:\t%#04x\n", je16_to_cpu(node.u.magic));
784 printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype));
785 printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen));
786 printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc));
182ec4ee 787
e0c8e42f
AB
788 crc = crc32(0, &node.u, sizeof(node.u) - 4);
789 if (crc != je32_to_cpu(node.u.hdr_crc)) {
790 JFFS2_ERROR("wrong common header CRC.\n");
791 return;
792 }
182ec4ee 793
e0c8e42f
AB
794 if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
795 je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
796 {
797 JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
798 je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
799 return;
800 }
801
802 switch(je16_to_cpu(node.u.nodetype)) {
803
804 case JFFS2_NODETYPE_INODE:
805
81e39cf0
AB
806 printk(JFFS2_DBG "the node is inode node\n");
807 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.i.ino));
808 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.i.version));
809 printk(JFFS2_DBG "mode:\t%#08x\n", node.i.mode.m);
810 printk(JFFS2_DBG "uid:\t%#04x\n", je16_to_cpu(node.i.uid));
811 printk(JFFS2_DBG "gid:\t%#04x\n", je16_to_cpu(node.i.gid));
812 printk(JFFS2_DBG "isize:\t%#08x\n", je32_to_cpu(node.i.isize));
813 printk(JFFS2_DBG "atime:\t%#08x\n", je32_to_cpu(node.i.atime));
814 printk(JFFS2_DBG "mtime:\t%#08x\n", je32_to_cpu(node.i.mtime));
815 printk(JFFS2_DBG "ctime:\t%#08x\n", je32_to_cpu(node.i.ctime));
816 printk(JFFS2_DBG "offset:\t%#08x\n", je32_to_cpu(node.i.offset));
817 printk(JFFS2_DBG "csize:\t%#08x\n", je32_to_cpu(node.i.csize));
818 printk(JFFS2_DBG "dsize:\t%#08x\n", je32_to_cpu(node.i.dsize));
819 printk(JFFS2_DBG "compr:\t%#02x\n", node.i.compr);
820 printk(JFFS2_DBG "usercompr:\t%#02x\n", node.i.usercompr);
821 printk(JFFS2_DBG "flags:\t%#04x\n", je16_to_cpu(node.i.flags));
822 printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc));
823 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc));
824
182ec4ee 825 crc = crc32(0, &node.i, sizeof(node.i) - 8);
e0c8e42f
AB
826 if (crc != je32_to_cpu(node.i.node_crc)) {
827 JFFS2_ERROR("wrong node header CRC.\n");
828 return;
829 }
830 break;
831
832 case JFFS2_NODETYPE_DIRENT:
833
81e39cf0
AB
834 printk(JFFS2_DBG "the node is dirent node\n");
835 printk(JFFS2_DBG "pino:\t%#08x\n", je32_to_cpu(node.d.pino));
836 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.d.version));
837 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.d.ino));
838 printk(JFFS2_DBG "mctime:\t%#08x\n", je32_to_cpu(node.d.mctime));
839 printk(JFFS2_DBG "nsize:\t%#02x\n", node.d.nsize);
840 printk(JFFS2_DBG "type:\t%#02x\n", node.d.type);
841 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc));
842 printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc));
182ec4ee 843
e0c8e42f 844 node.d.name[node.d.nsize] = '\0';
81e39cf0 845 printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name);
e0c8e42f 846
182ec4ee 847 crc = crc32(0, &node.d, sizeof(node.d) - 8);
e0c8e42f
AB
848 if (crc != je32_to_cpu(node.d.node_crc)) {
849 JFFS2_ERROR("wrong node header CRC.\n");
850 return;
730554d9 851 }
e0c8e42f 852 break;
730554d9 853
e0c8e42f 854 default:
81e39cf0 855 printk(JFFS2_DBG "node type is unknown\n");
e0c8e42f 856 break;
730554d9
AB
857 }
858}
e0c8e42f 859#endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */