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