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