]> err.no Git - linux-2.6/blob - fs/jffs2/debug.c
[JFFS2] Honour TEST_TOTLEN macro in debugging code. ref->__totlen is going!
[linux-2.6] / 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", ref_offset(ref));
404 #ifdef TEST_TOTLEN
405                 printk("(%x)", ref->__totlen);
406 #endif
407                 if (ref_next(ref))
408                         printk("->");
409                 else
410                         break;
411                 if (++i == 4) {
412                         i = 0;
413                         printk("\n" JFFS2_DBG);
414                 }
415         }
416         printk("\n");
417 }
418
419 /*
420  * Dump an eraseblock's space accounting.
421  */
422 void
423 __jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
424 {
425         spin_lock(&c->erase_completion_lock);
426         __jffs2_dbg_dump_jeb_nolock(jeb);
427         spin_unlock(&c->erase_completion_lock);
428 }
429
430 void
431 __jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
432 {
433         if (!jeb)
434                 return;
435
436         printk(JFFS2_DBG_MSG_PREFIX " dump space accounting for the eraseblock at %#08x:\n",
437                         jeb->offset);
438
439         printk(JFFS2_DBG "used_size: %#08x\n",          jeb->used_size);
440         printk(JFFS2_DBG "dirty_size: %#08x\n",         jeb->dirty_size);
441         printk(JFFS2_DBG "wasted_size: %#08x\n",        jeb->wasted_size);
442         printk(JFFS2_DBG "unchecked_size: %#08x\n",     jeb->unchecked_size);
443         printk(JFFS2_DBG "free_size: %#08x\n",          jeb->free_size);
444 }
445
446 void
447 __jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
448 {
449         spin_lock(&c->erase_completion_lock);
450         __jffs2_dbg_dump_block_lists_nolock(c);
451         spin_unlock(&c->erase_completion_lock);
452 }
453
454 void
455 __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
456 {
457         printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n");
458
459         printk(JFFS2_DBG "flash_size: %#08x\n",         c->flash_size);
460         printk(JFFS2_DBG "used_size: %#08x\n",          c->used_size);
461         printk(JFFS2_DBG "dirty_size: %#08x\n",         c->dirty_size);
462         printk(JFFS2_DBG "wasted_size: %#08x\n",        c->wasted_size);
463         printk(JFFS2_DBG "unchecked_size: %#08x\n",     c->unchecked_size);
464         printk(JFFS2_DBG "free_size: %#08x\n",          c->free_size);
465         printk(JFFS2_DBG "erasing_size: %#08x\n",       c->erasing_size);
466         printk(JFFS2_DBG "bad_size: %#08x\n",           c->bad_size);
467         printk(JFFS2_DBG "sector_size: %#08x\n",        c->sector_size);
468         printk(JFFS2_DBG "jffs2_reserved_blocks size: %#08x\n",
469                                 c->sector_size * c->resv_blocks_write);
470
471         if (c->nextblock)
472                 printk(JFFS2_DBG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
473                         c->nextblock->offset, c->nextblock->used_size,
474                         c->nextblock->dirty_size, c->nextblock->wasted_size,
475                         c->nextblock->unchecked_size, c->nextblock->free_size);
476         else
477                 printk(JFFS2_DBG "nextblock: NULL\n");
478
479         if (c->gcblock)
480                 printk(JFFS2_DBG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
481                         c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
482                         c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
483         else
484                 printk(JFFS2_DBG "gcblock: NULL\n");
485
486         if (list_empty(&c->clean_list)) {
487                 printk(JFFS2_DBG "clean_list: empty\n");
488         } else {
489                 struct list_head *this;
490                 int numblocks = 0;
491                 uint32_t dirty = 0;
492
493                 list_for_each(this, &c->clean_list) {
494                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
495                         numblocks ++;
496                         dirty += jeb->wasted_size;
497                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
498                                 printk(JFFS2_DBG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
499                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
500                                         jeb->unchecked_size, jeb->free_size);
501                         }
502                 }
503
504                 printk (JFFS2_DBG "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
505                         numblocks, dirty, dirty / numblocks);
506         }
507
508         if (list_empty(&c->very_dirty_list)) {
509                 printk(JFFS2_DBG "very_dirty_list: empty\n");
510         } else {
511                 struct list_head *this;
512                 int numblocks = 0;
513                 uint32_t dirty = 0;
514
515                 list_for_each(this, &c->very_dirty_list) {
516                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
517
518                         numblocks ++;
519                         dirty += jeb->dirty_size;
520                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
521                                 printk(JFFS2_DBG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
522                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
523                                         jeb->unchecked_size, jeb->free_size);
524                         }
525                 }
526
527                 printk (JFFS2_DBG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
528                         numblocks, dirty, dirty / numblocks);
529         }
530
531         if (list_empty(&c->dirty_list)) {
532                 printk(JFFS2_DBG "dirty_list: empty\n");
533         } else {
534                 struct list_head *this;
535                 int numblocks = 0;
536                 uint32_t dirty = 0;
537
538                 list_for_each(this, &c->dirty_list) {
539                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
540
541                         numblocks ++;
542                         dirty += jeb->dirty_size;
543                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
544                                 printk(JFFS2_DBG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
545                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
546                                         jeb->unchecked_size, jeb->free_size);
547                         }
548                 }
549
550                 printk (JFFS2_DBG "contains %d blocks with total dirty size %u, average dirty size: %u\n",
551                         numblocks, dirty, dirty / numblocks);
552         }
553
554         if (list_empty(&c->erasable_list)) {
555                 printk(JFFS2_DBG "erasable_list: empty\n");
556         } else {
557                 struct list_head *this;
558
559                 list_for_each(this, &c->erasable_list) {
560                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
561
562                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
563                                 printk(JFFS2_DBG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
564                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
565                                         jeb->unchecked_size, jeb->free_size);
566                         }
567                 }
568         }
569
570         if (list_empty(&c->erasing_list)) {
571                 printk(JFFS2_DBG "erasing_list: empty\n");
572         } else {
573                 struct list_head *this;
574
575                 list_for_each(this, &c->erasing_list) {
576                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
577
578                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
579                                 printk(JFFS2_DBG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
580                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
581                                         jeb->unchecked_size, jeb->free_size);
582                         }
583                 }
584         }
585
586         if (list_empty(&c->erase_pending_list)) {
587                 printk(JFFS2_DBG "erase_pending_list: empty\n");
588         } else {
589                 struct list_head *this;
590
591                 list_for_each(this, &c->erase_pending_list) {
592                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
593
594                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
595                                 printk(JFFS2_DBG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
596                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
597                                         jeb->unchecked_size, jeb->free_size);
598                         }
599                 }
600         }
601
602         if (list_empty(&c->erasable_pending_wbuf_list)) {
603                 printk(JFFS2_DBG "erasable_pending_wbuf_list: empty\n");
604         } else {
605                 struct list_head *this;
606
607                 list_for_each(this, &c->erasable_pending_wbuf_list) {
608                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
609
610                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
611                                 printk(JFFS2_DBG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
612                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
613                                         jeb->unchecked_size, jeb->free_size);
614                         }
615                 }
616         }
617
618         if (list_empty(&c->free_list)) {
619                 printk(JFFS2_DBG "free_list: empty\n");
620         } else {
621                 struct list_head *this;
622
623                 list_for_each(this, &c->free_list) {
624                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
625
626                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
627                                 printk(JFFS2_DBG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
628                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
629                                         jeb->unchecked_size, jeb->free_size);
630                         }
631                 }
632         }
633
634         if (list_empty(&c->bad_list)) {
635                 printk(JFFS2_DBG "bad_list: empty\n");
636         } else {
637                 struct list_head *this;
638
639                 list_for_each(this, &c->bad_list) {
640                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
641
642                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
643                                 printk(JFFS2_DBG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
644                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
645                                         jeb->unchecked_size, jeb->free_size);
646                         }
647                 }
648         }
649
650         if (list_empty(&c->bad_used_list)) {
651                 printk(JFFS2_DBG "bad_used_list: empty\n");
652         } else {
653                 struct list_head *this;
654
655                 list_for_each(this, &c->bad_used_list) {
656                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
657
658                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
659                                 printk(JFFS2_DBG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
660                                         jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
661                                         jeb->unchecked_size, jeb->free_size);
662                         }
663                 }
664         }
665 }
666
667 void
668 __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
669 {
670         mutex_lock(&f->sem);
671         jffs2_dbg_dump_fragtree_nolock(f);
672         mutex_unlock(&f->sem);
673 }
674
675 void
676 __jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
677 {
678         struct jffs2_node_frag *this = frag_first(&f->fragtree);
679         uint32_t lastofs = 0;
680         int buggy = 0;
681
682         printk(JFFS2_DBG_MSG_PREFIX " dump fragtree of ino #%u\n", f->inocache->ino);
683         while(this) {
684                 if (this->node)
685                         printk(JFFS2_DBG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), right (%p), parent (%p)\n",
686                                 this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
687                                 ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
688                                 frag_parent(this));
689                 else
690                         printk(JFFS2_DBG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
691                                 this->ofs, this->ofs+this->size, this, frag_left(this),
692                                 frag_right(this), frag_parent(this));
693                 if (this->ofs != lastofs)
694                         buggy = 1;
695                 lastofs = this->ofs + this->size;
696                 this = frag_next(this);
697         }
698
699         if (f->metadata)
700                 printk(JFFS2_DBG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
701
702         if (buggy) {
703                 JFFS2_ERROR("frag tree got a hole in it.\n");
704                 BUG();
705         }
706 }
707
708 #define JFFS2_BUFDUMP_BYTES_PER_LINE    32
709 void
710 __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
711 {
712         int skip;
713         int i;
714
715         printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n",
716                 offs, offs + len, len);
717         i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
718         offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
719
720         if (skip != 0)
721                 printk(JFFS2_DBG "%#08x: ", offs);
722
723         while (skip--)
724                 printk("   ");
725
726         while (i < len) {
727                 if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
728                         if (i != 0)
729                                 printk("\n");
730                         offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
731                         printk(JFFS2_DBG "%0#8x: ", offs);
732                 }
733
734                 printk("%02x ", buf[i]);
735
736                 i += 1;
737         }
738
739         printk("\n");
740 }
741
742 /*
743  * Dump a JFFS2 node.
744  */
745 void
746 __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
747 {
748         union jffs2_node_union node;
749         int len = sizeof(union jffs2_node_union);
750         size_t retlen;
751         uint32_t crc;
752         int ret;
753
754         printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs);
755
756         ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
757         if (ret || (retlen != len)) {
758                 JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
759                         len, ret, retlen);
760                 return;
761         }
762
763         printk(JFFS2_DBG "magic:\t%#04x\n", je16_to_cpu(node.u.magic));
764         printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype));
765         printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen));
766         printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc));
767
768         crc = crc32(0, &node.u, sizeof(node.u) - 4);
769         if (crc != je32_to_cpu(node.u.hdr_crc)) {
770                 JFFS2_ERROR("wrong common header CRC.\n");
771                 return;
772         }
773
774         if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
775                 je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
776         {
777                 JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
778                         je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
779                 return;
780         }
781
782         switch(je16_to_cpu(node.u.nodetype)) {
783
784         case JFFS2_NODETYPE_INODE:
785
786                 printk(JFFS2_DBG "the node is inode node\n");
787                 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.i.ino));
788                 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.i.version));
789                 printk(JFFS2_DBG "mode:\t%#08x\n", node.i.mode.m);
790                 printk(JFFS2_DBG "uid:\t%#04x\n", je16_to_cpu(node.i.uid));
791                 printk(JFFS2_DBG "gid:\t%#04x\n", je16_to_cpu(node.i.gid));
792                 printk(JFFS2_DBG "isize:\t%#08x\n", je32_to_cpu(node.i.isize));
793                 printk(JFFS2_DBG "atime:\t%#08x\n", je32_to_cpu(node.i.atime));
794                 printk(JFFS2_DBG "mtime:\t%#08x\n", je32_to_cpu(node.i.mtime));
795                 printk(JFFS2_DBG "ctime:\t%#08x\n", je32_to_cpu(node.i.ctime));
796                 printk(JFFS2_DBG "offset:\t%#08x\n", je32_to_cpu(node.i.offset));
797                 printk(JFFS2_DBG "csize:\t%#08x\n", je32_to_cpu(node.i.csize));
798                 printk(JFFS2_DBG "dsize:\t%#08x\n", je32_to_cpu(node.i.dsize));
799                 printk(JFFS2_DBG "compr:\t%#02x\n", node.i.compr);
800                 printk(JFFS2_DBG "usercompr:\t%#02x\n", node.i.usercompr);
801                 printk(JFFS2_DBG "flags:\t%#04x\n", je16_to_cpu(node.i.flags));
802                 printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc));
803                 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc));
804
805                 crc = crc32(0, &node.i, sizeof(node.i) - 8);
806                 if (crc != je32_to_cpu(node.i.node_crc)) {
807                         JFFS2_ERROR("wrong node header CRC.\n");
808                         return;
809                 }
810                 break;
811
812         case JFFS2_NODETYPE_DIRENT:
813
814                 printk(JFFS2_DBG "the node is dirent node\n");
815                 printk(JFFS2_DBG "pino:\t%#08x\n", je32_to_cpu(node.d.pino));
816                 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.d.version));
817                 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.d.ino));
818                 printk(JFFS2_DBG "mctime:\t%#08x\n", je32_to_cpu(node.d.mctime));
819                 printk(JFFS2_DBG "nsize:\t%#02x\n", node.d.nsize);
820                 printk(JFFS2_DBG "type:\t%#02x\n", node.d.type);
821                 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc));
822                 printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc));
823
824                 node.d.name[node.d.nsize] = '\0';
825                 printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name);
826
827                 crc = crc32(0, &node.d, sizeof(node.d) - 8);
828                 if (crc != je32_to_cpu(node.d.node_crc)) {
829                         JFFS2_ERROR("wrong node header CRC.\n");
830                         return;
831                 }
832                 break;
833
834         default:
835                 printk(JFFS2_DBG "node type is unknown\n");
836                 break;
837         }
838 }
839 #endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */