]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - fs/jffs2/debug.c
[JFFS2] Add paranoia debugging for superblock counts
[linux-2.6-omap-h63xx.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_complete_list, list) {
250                 nr_counted++;
251                 erasing += c->sector_size;
252         }
253         list_for_each_entry(jeb, &c->bad_list, list) {
254                 nr_counted++;
255                 bad += c->sector_size;
256         }
257
258 #define check(sz) \
259         if (sz != c->sz##_size) {                       \
260                 printk(KERN_WARNING #sz "_size mismatch counted 0x%x, c->" #sz "_size 0x%x\n", \
261                        sz, c->sz##_size);               \
262                 dump = 1;                               \
263         }
264         check(free);
265         check(dirty);
266         check(used);
267         check(wasted);
268         check(unchecked);
269         check(bad);
270         check(erasing);
271 #undef check
272
273         if (nr_counted != c->nr_blocks) {
274                 printk(KERN_WARNING "%s counted only 0x%x blocks of 0x%x. Where are the others?\n",
275                        __func__, nr_counted, c->nr_blocks);
276                 dump = 1;
277         }
278
279         if (dump) {
280                 __jffs2_dbg_dump_block_lists_nolock(c);
281                 BUG();
282         }
283 }
284
285 /*
286  * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
287  */
288 void
289 __jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
290                                 struct jffs2_eraseblock *jeb)
291 {
292         spin_lock(&c->erase_completion_lock);
293         __jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
294         spin_unlock(&c->erase_completion_lock);
295 }
296
297 void
298 __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
299                                        struct jffs2_eraseblock *jeb)
300 {
301         uint32_t my_used_size = 0;
302         uint32_t my_unchecked_size = 0;
303         uint32_t my_dirty_size = 0;
304         struct jffs2_raw_node_ref *ref2 = jeb->first_node;
305
306         while (ref2) {
307                 uint32_t totlen = ref_totlen(c, jeb, ref2);
308
309                 if (ref_offset(ref2) < jeb->offset ||
310                                 ref_offset(ref2) > jeb->offset + c->sector_size) {
311                         JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
312                                 ref_offset(ref2), jeb->offset);
313                         goto error;
314
315                 }
316                 if (ref_flags(ref2) == REF_UNCHECKED)
317                         my_unchecked_size += totlen;
318                 else if (!ref_obsolete(ref2))
319                         my_used_size += totlen;
320                 else
321                         my_dirty_size += totlen;
322
323                 if ((!ref_next(ref2)) != (ref2 == jeb->last_node)) {
324                         JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next at %#08x (mem %p), last_node is at %#08x (mem %p).\n",
325                                     ref_offset(ref2), ref2, ref_offset(ref_next(ref2)), ref_next(ref2),
326                                     ref_offset(jeb->last_node), jeb->last_node);
327                         goto error;
328                 }
329                 ref2 = ref_next(ref2);
330         }
331
332         if (my_used_size != jeb->used_size) {
333                 JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
334                         my_used_size, jeb->used_size);
335                 goto error;
336         }
337
338         if (my_unchecked_size != jeb->unchecked_size) {
339                 JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
340                         my_unchecked_size, jeb->unchecked_size);
341                 goto error;
342         }
343
344 #if 0
345         /* This should work when we implement ref->__totlen elemination */
346         if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
347                 JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
348                         my_dirty_size, jeb->dirty_size + jeb->wasted_size);
349                 goto error;
350         }
351
352         if (jeb->free_size == 0
353                 && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
354                 JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
355                         my_used_size + my_unchecked_size + my_dirty_size,
356                         c->sector_size);
357                 goto error;
358         }
359 #endif
360
361         if (!(c->flags & (JFFS2_SB_FLAG_BUILDING|JFFS2_SB_FLAG_SCANNING)))
362                 __jffs2_dbg_superblock_counts(c);
363
364         return;
365
366 error:
367         __jffs2_dbg_dump_node_refs_nolock(c, jeb);
368         __jffs2_dbg_dump_jeb_nolock(jeb);
369         __jffs2_dbg_dump_block_lists_nolock(c);
370         BUG();
371
372 }
373 #endif /* JFFS2_DBG_PARANOIA_CHECKS */
374
375 #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
376 /*
377  * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
378  */
379 void
380 __jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
381                            struct jffs2_eraseblock *jeb)
382 {
383         spin_lock(&c->erase_completion_lock);
384         __jffs2_dbg_dump_node_refs_nolock(c, jeb);
385         spin_unlock(&c->erase_completion_lock);
386 }
387
388 void
389 __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
390                                   struct jffs2_eraseblock *jeb)
391 {
392         struct jffs2_raw_node_ref *ref;
393         int i = 0;
394
395         printk(JFFS2_DBG_MSG_PREFIX " Dump node_refs of the eraseblock %#08x\n", jeb->offset);
396         if (!jeb->first_node) {
397                 printk(JFFS2_DBG_MSG_PREFIX " no nodes in the eraseblock %#08x\n", jeb->offset);
398                 return;
399         }
400
401         printk(JFFS2_DBG);
402         for (ref = jeb->first_node; ; ref = ref_next(ref)) {
403                 printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
404                 if (ref_next(ref))
405                         printk("->");
406                 else
407                         break;
408                 if (++i == 4) {
409                         i = 0;
410                         printk("\n" JFFS2_DBG);
411                 }
412         }
413         printk("\n");
414 }
415
416 /*
417  * Dump an eraseblock's space accounting.
418  */
419 void
420 __jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
421 {
422         spin_lock(&c->erase_completion_lock);
423         __jffs2_dbg_dump_jeb_nolock(jeb);
424         spin_unlock(&c->erase_completion_lock);
425 }
426
427 void
428 __jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
429 {
430         if (!jeb)
431                 return;
432
433         printk(JFFS2_DBG_MSG_PREFIX " dump space accounting for the eraseblock at %#08x:\n",
434                         jeb->offset);
435
436         printk(JFFS2_DBG "used_size: %#08x\n",          jeb->used_size);
437         printk(JFFS2_DBG "dirty_size: %#08x\n",         jeb->dirty_size);
438         printk(JFFS2_DBG "wasted_size: %#08x\n",        jeb->wasted_size);
439         printk(JFFS2_DBG "unchecked_size: %#08x\n",     jeb->unchecked_size);
440         printk(JFFS2_DBG "free_size: %#08x\n",          jeb->free_size);
441 }
442
443 void
444 __jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
445 {
446         spin_lock(&c->erase_completion_lock);
447         __jffs2_dbg_dump_block_lists_nolock(c);
448         spin_unlock(&c->erase_completion_lock);
449 }
450
451 void
452 __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
453 {
454         printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n");
455
456         printk(JFFS2_DBG "flash_size: %#08x\n",         c->flash_size);
457         printk(JFFS2_DBG "used_size: %#08x\n",          c->used_size);
458         printk(JFFS2_DBG "dirty_size: %#08x\n",         c->dirty_size);
459         printk(JFFS2_DBG "wasted_size: %#08x\n",        c->wasted_size);
460         printk(JFFS2_DBG "unchecked_size: %#08x\n",     c->unchecked_size);
461         printk(JFFS2_DBG "free_size: %#08x\n",          c->free_size);
462         printk(JFFS2_DBG "erasing_size: %#08x\n",       c->erasing_size);
463         printk(JFFS2_DBG "bad_size: %#08x\n",           c->bad_size);
464         printk(JFFS2_DBG "sector_size: %#08x\n",        c->sector_size);
465         printk(JFFS2_DBG "jffs2_reserved_blocks size: %#08x\n",
466                                 c->sector_size * c->resv_blocks_write);
467
468         if (c->nextblock)
469                 printk(JFFS2_DBG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
470                         c->nextblock->offset, c->nextblock->used_size,
471                         c->nextblock->dirty_size, c->nextblock->wasted_size,
472                         c->nextblock->unchecked_size, c->nextblock->free_size);
473         else
474                 printk(JFFS2_DBG "nextblock: NULL\n");
475
476         if (c->gcblock)
477                 printk(JFFS2_DBG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
478                         c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
479                         c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
480         else
481                 printk(JFFS2_DBG "gcblock: NULL\n");
482
483         if (list_empty(&c->clean_list)) {
484                 printk(JFFS2_DBG "clean_list: empty\n");
485         } else {
486                 struct list_head *this;
487                 int numblocks = 0;
488                 uint32_t dirty = 0;
489
490                 list_for_each(this, &c->clean_list) {
491                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
492                         numblocks ++;
493                         dirty += jeb->wasted_size;
494                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
495                                 printk(JFFS2_DBG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
496                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
497                                         jeb->unchecked_size, jeb->free_size);
498                         }
499                 }
500
501                 printk (JFFS2_DBG "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
502                         numblocks, dirty, dirty / numblocks);
503         }
504
505         if (list_empty(&c->very_dirty_list)) {
506                 printk(JFFS2_DBG "very_dirty_list: empty\n");
507         } else {
508                 struct list_head *this;
509                 int numblocks = 0;
510                 uint32_t dirty = 0;
511
512                 list_for_each(this, &c->very_dirty_list) {
513                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
514
515                         numblocks ++;
516                         dirty += jeb->dirty_size;
517                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
518                                 printk(JFFS2_DBG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
519                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
520                                         jeb->unchecked_size, jeb->free_size);
521                         }
522                 }
523
524                 printk (JFFS2_DBG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
525                         numblocks, dirty, dirty / numblocks);
526         }
527
528         if (list_empty(&c->dirty_list)) {
529                 printk(JFFS2_DBG "dirty_list: empty\n");
530         } else {
531                 struct list_head *this;
532                 int numblocks = 0;
533                 uint32_t dirty = 0;
534
535                 list_for_each(this, &c->dirty_list) {
536                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
537
538                         numblocks ++;
539                         dirty += jeb->dirty_size;
540                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
541                                 printk(JFFS2_DBG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
542                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
543                                         jeb->unchecked_size, jeb->free_size);
544                         }
545                 }
546
547                 printk (JFFS2_DBG "contains %d blocks with total dirty size %u, average dirty size: %u\n",
548                         numblocks, dirty, dirty / numblocks);
549         }
550
551         if (list_empty(&c->erasable_list)) {
552                 printk(JFFS2_DBG "erasable_list: empty\n");
553         } else {
554                 struct list_head *this;
555
556                 list_for_each(this, &c->erasable_list) {
557                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
558
559                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
560                                 printk(JFFS2_DBG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
561                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
562                                         jeb->unchecked_size, jeb->free_size);
563                         }
564                 }
565         }
566
567         if (list_empty(&c->erasing_list)) {
568                 printk(JFFS2_DBG "erasing_list: empty\n");
569         } else {
570                 struct list_head *this;
571
572                 list_for_each(this, &c->erasing_list) {
573                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
574
575                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
576                                 printk(JFFS2_DBG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
577                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
578                                         jeb->unchecked_size, jeb->free_size);
579                         }
580                 }
581         }
582
583         if (list_empty(&c->erase_pending_list)) {
584                 printk(JFFS2_DBG "erase_pending_list: empty\n");
585         } else {
586                 struct list_head *this;
587
588                 list_for_each(this, &c->erase_pending_list) {
589                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
590
591                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
592                                 printk(JFFS2_DBG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
593                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
594                                         jeb->unchecked_size, jeb->free_size);
595                         }
596                 }
597         }
598
599         if (list_empty(&c->erasable_pending_wbuf_list)) {
600                 printk(JFFS2_DBG "erasable_pending_wbuf_list: empty\n");
601         } else {
602                 struct list_head *this;
603
604                 list_for_each(this, &c->erasable_pending_wbuf_list) {
605                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
606
607                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
608                                 printk(JFFS2_DBG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
609                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
610                                         jeb->unchecked_size, jeb->free_size);
611                         }
612                 }
613         }
614
615         if (list_empty(&c->free_list)) {
616                 printk(JFFS2_DBG "free_list: empty\n");
617         } else {
618                 struct list_head *this;
619
620                 list_for_each(this, &c->free_list) {
621                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
622
623                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
624                                 printk(JFFS2_DBG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
625                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
626                                         jeb->unchecked_size, jeb->free_size);
627                         }
628                 }
629         }
630
631         if (list_empty(&c->bad_list)) {
632                 printk(JFFS2_DBG "bad_list: empty\n");
633         } else {
634                 struct list_head *this;
635
636                 list_for_each(this, &c->bad_list) {
637                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
638
639                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
640                                 printk(JFFS2_DBG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
641                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
642                                         jeb->unchecked_size, jeb->free_size);
643                         }
644                 }
645         }
646
647         if (list_empty(&c->bad_used_list)) {
648                 printk(JFFS2_DBG "bad_used_list: empty\n");
649         } else {
650                 struct list_head *this;
651
652                 list_for_each(this, &c->bad_used_list) {
653                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
654
655                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
656                                 printk(JFFS2_DBG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
657                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
658                                         jeb->unchecked_size, jeb->free_size);
659                         }
660                 }
661         }
662 }
663
664 void
665 __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
666 {
667         mutex_lock(&f->sem);
668         jffs2_dbg_dump_fragtree_nolock(f);
669         mutex_unlock(&f->sem);
670 }
671
672 void
673 __jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
674 {
675         struct jffs2_node_frag *this = frag_first(&f->fragtree);
676         uint32_t lastofs = 0;
677         int buggy = 0;
678
679         printk(JFFS2_DBG_MSG_PREFIX " dump fragtree of ino #%u\n", f->inocache->ino);
680         while(this) {
681                 if (this->node)
682                         printk(JFFS2_DBG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), right (%p), parent (%p)\n",
683                                 this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
684                                 ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
685                                 frag_parent(this));
686                 else
687                         printk(JFFS2_DBG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
688                                 this->ofs, this->ofs+this->size, this, frag_left(this),
689                                 frag_right(this), frag_parent(this));
690                 if (this->ofs != lastofs)
691                         buggy = 1;
692                 lastofs = this->ofs + this->size;
693                 this = frag_next(this);
694         }
695
696         if (f->metadata)
697                 printk(JFFS2_DBG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
698
699         if (buggy) {
700                 JFFS2_ERROR("frag tree got a hole in it.\n");
701                 BUG();
702         }
703 }
704
705 #define JFFS2_BUFDUMP_BYTES_PER_LINE    32
706 void
707 __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
708 {
709         int skip;
710         int i;
711
712         printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n",
713                 offs, offs + len, len);
714         i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
715         offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
716
717         if (skip != 0)
718                 printk(JFFS2_DBG "%#08x: ", offs);
719
720         while (skip--)
721                 printk("   ");
722
723         while (i < len) {
724                 if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
725                         if (i != 0)
726                                 printk("\n");
727                         offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
728                         printk(JFFS2_DBG "%0#8x: ", offs);
729                 }
730
731                 printk("%02x ", buf[i]);
732
733                 i += 1;
734         }
735
736         printk("\n");
737 }
738
739 /*
740  * Dump a JFFS2 node.
741  */
742 void
743 __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
744 {
745         union jffs2_node_union node;
746         int len = sizeof(union jffs2_node_union);
747         size_t retlen;
748         uint32_t crc;
749         int ret;
750
751         printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs);
752
753         ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
754         if (ret || (retlen != len)) {
755                 JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
756                         len, ret, retlen);
757                 return;
758         }
759
760         printk(JFFS2_DBG "magic:\t%#04x\n", je16_to_cpu(node.u.magic));
761         printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype));
762         printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen));
763         printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc));
764
765         crc = crc32(0, &node.u, sizeof(node.u) - 4);
766         if (crc != je32_to_cpu(node.u.hdr_crc)) {
767                 JFFS2_ERROR("wrong common header CRC.\n");
768                 return;
769         }
770
771         if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
772                 je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
773         {
774                 JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
775                         je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
776                 return;
777         }
778
779         switch(je16_to_cpu(node.u.nodetype)) {
780
781         case JFFS2_NODETYPE_INODE:
782
783                 printk(JFFS2_DBG "the node is inode node\n");
784                 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.i.ino));
785                 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.i.version));
786                 printk(JFFS2_DBG "mode:\t%#08x\n", node.i.mode.m);
787                 printk(JFFS2_DBG "uid:\t%#04x\n", je16_to_cpu(node.i.uid));
788                 printk(JFFS2_DBG "gid:\t%#04x\n", je16_to_cpu(node.i.gid));
789                 printk(JFFS2_DBG "isize:\t%#08x\n", je32_to_cpu(node.i.isize));
790                 printk(JFFS2_DBG "atime:\t%#08x\n", je32_to_cpu(node.i.atime));
791                 printk(JFFS2_DBG "mtime:\t%#08x\n", je32_to_cpu(node.i.mtime));
792                 printk(JFFS2_DBG "ctime:\t%#08x\n", je32_to_cpu(node.i.ctime));
793                 printk(JFFS2_DBG "offset:\t%#08x\n", je32_to_cpu(node.i.offset));
794                 printk(JFFS2_DBG "csize:\t%#08x\n", je32_to_cpu(node.i.csize));
795                 printk(JFFS2_DBG "dsize:\t%#08x\n", je32_to_cpu(node.i.dsize));
796                 printk(JFFS2_DBG "compr:\t%#02x\n", node.i.compr);
797                 printk(JFFS2_DBG "usercompr:\t%#02x\n", node.i.usercompr);
798                 printk(JFFS2_DBG "flags:\t%#04x\n", je16_to_cpu(node.i.flags));
799                 printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc));
800                 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc));
801
802                 crc = crc32(0, &node.i, sizeof(node.i) - 8);
803                 if (crc != je32_to_cpu(node.i.node_crc)) {
804                         JFFS2_ERROR("wrong node header CRC.\n");
805                         return;
806                 }
807                 break;
808
809         case JFFS2_NODETYPE_DIRENT:
810
811                 printk(JFFS2_DBG "the node is dirent node\n");
812                 printk(JFFS2_DBG "pino:\t%#08x\n", je32_to_cpu(node.d.pino));
813                 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.d.version));
814                 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.d.ino));
815                 printk(JFFS2_DBG "mctime:\t%#08x\n", je32_to_cpu(node.d.mctime));
816                 printk(JFFS2_DBG "nsize:\t%#02x\n", node.d.nsize);
817                 printk(JFFS2_DBG "type:\t%#02x\n", node.d.type);
818                 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc));
819                 printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc));
820
821                 node.d.name[node.d.nsize] = '\0';
822                 printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name);
823
824                 crc = crc32(0, &node.d, sizeof(node.d) - 8);
825                 if (crc != je32_to_cpu(node.d.node_crc)) {
826                         JFFS2_ERROR("wrong node header CRC.\n");
827                         return;
828                 }
829                 break;
830
831         default:
832                 printk(JFFS2_DBG "node type is unknown\n");
833                 break;
834         }
835 }
836 #endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */