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