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