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