]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - fs/jffs2/debug.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livep...
[mirror_ubuntu-artful-kernel.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.
6088c058 5 * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
730554d9
AB
6 *
7 * Created by David Woodhouse <dwmw2@infradead.org>
8 *
9 * For licensing information, see the file 'LICENCE' in this directory.
10 *
730554d9 11 */
c00c310e 12
5a528957
JP
13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14
730554d9 15#include <linux/kernel.h>
737b7661 16#include <linux/types.h>
730554d9 17#include <linux/pagemap.h>
e0c8e42f
AB
18#include <linux/crc32.h>
19#include <linux/jffs2.h>
733802d9 20#include <linux/mtd/mtd.h>
5a0e3ad6 21#include <linux/slab.h>
730554d9
AB
22#include "nodelist.h"
23#include "debug.h"
24
45ca1b50
AB
25#ifdef JFFS2_DBG_SANITY_CHECKS
26
27void
28__jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info *c,
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);
81e39cf0
AB
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,
45ca1b50
AB
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");
81e39cf0 44 JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + wasted %#08x + unchecked %#08x != total %#08x.\n",
45ca1b50
AB
45 c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size,
46 c->wasted_size, c->unchecked_size, c->flash_size);
47 BUG();
48 }
49}
50
51void
52__jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c,
53 struct jffs2_eraseblock *jeb)
54{
55 spin_lock(&c->erase_completion_lock);
56 jffs2_dbg_acct_sanity_check_nolock(c, jeb);
57 spin_unlock(&c->erase_completion_lock);
58}
59
60#endif /* JFFS2_DBG_SANITY_CHECKS */
61
730554d9 62#ifdef JFFS2_DBG_PARANOIA_CHECKS
e0c8e42f
AB
63/*
64 * Check the fragtree.
65 */
730554d9 66void
e0c8e42f
AB
67__jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
68{
ced22070 69 mutex_lock(&f->sem);
e0c8e42f 70 __jffs2_dbg_fragtree_paranoia_check_nolock(f);
ced22070 71 mutex_unlock(&f->sem);
e0c8e42f 72}
182ec4ee 73
e0c8e42f
AB
74void
75__jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f)
730554d9
AB
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) {
e0c8e42f 88 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n",
81e39cf0 89 ref_offset(fn->raw), fn->frags);
730554d9
AB
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. */
09cbfeaf
KS
98 if (frag->ofs & (PAGE_SIZE-1) && frag_prev(frag)
99 && frag_prev(frag)->size < PAGE_SIZE && frag_prev(frag)->node) {
81e39cf0
AB
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));
730554d9
AB
102 bitched = 1;
103 }
104
09cbfeaf
KS
105 if ((frag->ofs+frag->size) & (PAGE_SIZE-1) && frag_next(frag)
106 && frag_next(frag)->size < PAGE_SIZE && frag_next(frag)->node) {
81e39cf0
AB
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);
730554d9
AB
109 bitched = 1;
110 }
111 }
112 }
113
114 if (bitched) {
e0c8e42f
AB
115 JFFS2_ERROR("fragtree is corrupted.\n");
116 __jffs2_dbg_dump_fragtree_nolock(f);
730554d9
AB
117 BUG();
118 }
119}
120
121/*
122 * Check if the flash contains all 0xFF before we start writing.
123 */
124void
e0c8e42f
AB
125__jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
126 uint32_t ofs, int len)
730554d9
AB
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)) {
e0c8e42f
AB
138 JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n",
139 len, ret, retlen);
730554d9
AB
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) {
81e39cf0
AB
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);
e0c8e42f 152 __jffs2_dbg_dump_buffer(buf, len, ofs);
730554d9
AB
153 kfree(buf);
154 BUG();
155 }
156
157 kfree(buf);
158}
159
85a62db6
DW
160void __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 }
192 list_for_each_entry(jeb, &c->very_dirty_list, list) {
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 }
208 list_for_each_entry(jeb, &c->erasable_list, list) {
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 }
216 list_for_each_entry(jeb, &c->erasable_pending_wbuf_list, list) {
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 }
224 list_for_each_entry(jeb, &c->erase_pending_list, list) {
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 }
240 list_for_each_entry(jeb, &c->bad_used_list, list) {
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
249 list_for_each_entry(jeb, &c->erasing_list, list) {
250 nr_counted++;
251 erasing += c->sector_size;
252 }
e2bc322b
DW
253 list_for_each_entry(jeb, &c->erase_checking_list, list) {
254 nr_counted++;
255 erasing += c->sector_size;
256 }
85a62db6
DW
257 list_for_each_entry(jeb, &c->erase_complete_list, list) {
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
da320f05
JP
266#define check(sz) \
267do { \
268 if (sz != c->sz##_size) { \
269 pr_warn("%s_size mismatch counted 0x%x, c->%s_size 0x%x\n", \
9bbf29e4 270 #sz, sz, #sz, c->sz##_size); \
da320f05
JP
271 dump = 1; \
272 } \
273} while (0)
274
85a62db6
DW
275 check(free);
276 check(dirty);
277 check(used);
278 check(wasted);
279 check(unchecked);
280 check(bad);
281 check(erasing);
da320f05 282
85a62db6
DW
283#undef check
284
285 if (nr_counted != c->nr_blocks) {
da320f05
JP
286 pr_warn("%s counted only 0x%x blocks of 0x%x. Where are the others?\n",
287 __func__, nr_counted, c->nr_blocks);
85a62db6
DW
288 dump = 1;
289 }
290
291 if (dump) {
292 __jffs2_dbg_dump_block_lists_nolock(c);
293 BUG();
294 }
295}
296
730554d9
AB
297/*
298 * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
299 */
300void
e0c8e42f
AB
301__jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
302 struct jffs2_eraseblock *jeb)
303{
304 spin_lock(&c->erase_completion_lock);
305 __jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
306 spin_unlock(&c->erase_completion_lock);
307}
182ec4ee 308
e0c8e42f
AB
309void
310__jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
311 struct jffs2_eraseblock *jeb)
730554d9
AB
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
abb536e7
KP
321 if (ref_offset(ref2) < jeb->offset ||
322 ref_offset(ref2) > jeb->offset + c->sector_size) {
e0c8e42f 323 JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
730554d9 324 ref_offset(ref2), jeb->offset);
e0c8e42f 325 goto error;
730554d9
AB
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
99988f7b
DW
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);
e0c8e42f 339 goto error;
730554d9 340 }
99988f7b 341 ref2 = ref_next(ref2);
730554d9
AB
342 }
343
344 if (my_used_size != jeb->used_size) {
e0c8e42f
AB
345 JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
346 my_used_size, jeb->used_size);
347 goto error;
730554d9
AB
348 }
349
350 if (my_unchecked_size != jeb->unchecked_size) {
e0c8e42f
AB
351 JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
352 my_unchecked_size, jeb->unchecked_size);
353 goto error;
730554d9
AB
354 }
355
e0c8e42f
AB
356#if 0
357 /* This should work when we implement ref->__totlen elemination */
730554d9 358 if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
e0c8e42f 359 JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
730554d9 360 my_dirty_size, jeb->dirty_size + jeb->wasted_size);
e0c8e42f 361 goto error;
730554d9
AB
362 }
363
364 if (jeb->free_size == 0
365 && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
e0c8e42f 366 JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
730554d9
AB
367 my_used_size + my_unchecked_size + my_dirty_size,
368 c->sector_size);
e0c8e42f 369 goto error;
730554d9 370 }
e0c8e42f
AB
371#endif
372
85a62db6
DW
373 if (!(c->flags & (JFFS2_SB_FLAG_BUILDING|JFFS2_SB_FLAG_SCANNING)))
374 __jffs2_dbg_superblock_counts(c);
375
e0c8e42f
AB
376 return;
377
378error:
379 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
380 __jffs2_dbg_dump_jeb_nolock(jeb);
381 __jffs2_dbg_dump_block_lists_nolock(c);
382 BUG();
182ec4ee 383
730554d9 384}
e0c8e42f 385#endif /* JFFS2_DBG_PARANOIA_CHECKS */
730554d9 386
e0c8e42f 387#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
730554d9
AB
388/*
389 * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
390 */
391void
e0c8e42f
AB
392__jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
393 struct jffs2_eraseblock *jeb)
394{
395 spin_lock(&c->erase_completion_lock);
396 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
397 spin_unlock(&c->erase_completion_lock);
398}
399
400void
401__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
402 struct jffs2_eraseblock *jeb)
730554d9
AB
403{
404 struct jffs2_raw_node_ref *ref;
405 int i = 0;
406
81e39cf0 407 printk(JFFS2_DBG_MSG_PREFIX " Dump node_refs of the eraseblock %#08x\n", jeb->offset);
730554d9 408 if (!jeb->first_node) {
81e39cf0 409 printk(JFFS2_DBG_MSG_PREFIX " no nodes in the eraseblock %#08x\n", jeb->offset);
730554d9
AB
410 return;
411 }
412
81e39cf0 413 printk(JFFS2_DBG);
99988f7b 414 for (ref = jeb->first_node; ; ref = ref_next(ref)) {
27e6b8e3
DW
415 printk("%#08x", ref_offset(ref));
416#ifdef TEST_TOTLEN
417 printk("(%x)", ref->__totlen);
418#endif
99988f7b 419 if (ref_next(ref))
730554d9
AB
420 printk("->");
421 else
422 break;
423 if (++i == 4) {
424 i = 0;
81e39cf0 425 printk("\n" JFFS2_DBG);
730554d9
AB
426 }
427 }
428 printk("\n");
429}
430
e0c8e42f
AB
431/*
432 * Dump an eraseblock's space accounting.
433 */
434void
435__jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
436{
437 spin_lock(&c->erase_completion_lock);
438 __jffs2_dbg_dump_jeb_nolock(jeb);
439 spin_unlock(&c->erase_completion_lock);
440}
441
730554d9 442void
e0c8e42f 443__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
730554d9 444{
e0c8e42f
AB
445 if (!jeb)
446 return;
447
81e39cf0 448 printk(JFFS2_DBG_MSG_PREFIX " dump space accounting for the eraseblock at %#08x:\n",
e0c8e42f
AB
449 jeb->offset);
450
81e39cf0
AB
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);
e0c8e42f
AB
456}
457
458void
459__jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
460{
461 spin_lock(&c->erase_completion_lock);
462 __jffs2_dbg_dump_block_lists_nolock(c);
463 spin_unlock(&c->erase_completion_lock);
464}
465
466void
467__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
468{
81e39cf0 469 printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n");
182ec4ee 470
81e39cf0
AB
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",
730554d9
AB
481 c->sector_size * c->resv_blocks_write);
482
483 if (c->nextblock)
81e39cf0 484 printk(JFFS2_DBG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
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);
730554d9 488 else
81e39cf0 489 printk(JFFS2_DBG "nextblock: NULL\n");
730554d9
AB
490
491 if (c->gcblock)
81e39cf0 492 printk(JFFS2_DBG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
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);
730554d9 495 else
81e39cf0 496 printk(JFFS2_DBG "gcblock: NULL\n");
730554d9
AB
497
498 if (list_empty(&c->clean_list)) {
81e39cf0 499 printk(JFFS2_DBG "clean_list: empty\n");
730554d9
AB
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)) {
81e39cf0 510 printk(JFFS2_DBG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
511 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
512 jeb->unchecked_size, jeb->free_size);
730554d9
AB
513 }
514 }
515
81e39cf0 516 printk (JFFS2_DBG "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
e0c8e42f 517 numblocks, dirty, dirty / numblocks);
730554d9
AB
518 }
519
520 if (list_empty(&c->very_dirty_list)) {
81e39cf0 521 printk(JFFS2_DBG "very_dirty_list: empty\n");
730554d9
AB
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)) {
81e39cf0 533 printk(JFFS2_DBG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
534 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
535 jeb->unchecked_size, jeb->free_size);
730554d9
AB
536 }
537 }
538
81e39cf0 539 printk (JFFS2_DBG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
e0c8e42f 540 numblocks, dirty, dirty / numblocks);
730554d9
AB
541 }
542
543 if (list_empty(&c->dirty_list)) {
81e39cf0 544 printk(JFFS2_DBG "dirty_list: empty\n");
730554d9
AB
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)) {
81e39cf0 556 printk(JFFS2_DBG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
557 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
558 jeb->unchecked_size, jeb->free_size);
730554d9
AB
559 }
560 }
561
81e39cf0 562 printk (JFFS2_DBG "contains %d blocks with total dirty size %u, average dirty size: %u\n",
730554d9
AB
563 numblocks, dirty, dirty / numblocks);
564 }
565
566 if (list_empty(&c->erasable_list)) {
81e39cf0 567 printk(JFFS2_DBG "erasable_list: empty\n");
730554d9
AB
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)) {
81e39cf0 575 printk(JFFS2_DBG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
576 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
577 jeb->unchecked_size, jeb->free_size);
730554d9
AB
578 }
579 }
580 }
581
582 if (list_empty(&c->erasing_list)) {
81e39cf0 583 printk(JFFS2_DBG "erasing_list: empty\n");
730554d9
AB
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)) {
81e39cf0 591 printk(JFFS2_DBG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
592 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
593 jeb->unchecked_size, jeb->free_size);
730554d9
AB
594 }
595 }
596 }
e2bc322b
DW
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
602 list_for_each(this, &c->erase_checking_list) {
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 }
730554d9
AB
612
613 if (list_empty(&c->erase_pending_list)) {
81e39cf0 614 printk(JFFS2_DBG "erase_pending_list: empty\n");
730554d9
AB
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)) {
81e39cf0 622 printk(JFFS2_DBG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
623 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
624 jeb->unchecked_size, jeb->free_size);
730554d9
AB
625 }
626 }
627 }
628
629 if (list_empty(&c->erasable_pending_wbuf_list)) {
81e39cf0 630 printk(JFFS2_DBG "erasable_pending_wbuf_list: empty\n");
730554d9
AB
631 } else {
632 struct list_head *this;
633
634 list_for_each(this, &c->erasable_pending_wbuf_list) {
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)) {
81e39cf0 638 printk(JFFS2_DBG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
639 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
640 jeb->unchecked_size, jeb->free_size);
730554d9
AB
641 }
642 }
643 }
644
645 if (list_empty(&c->free_list)) {
81e39cf0 646 printk(JFFS2_DBG "free_list: empty\n");
730554d9
AB
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)) {
81e39cf0 654 printk(JFFS2_DBG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
655 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
656 jeb->unchecked_size, jeb->free_size);
730554d9
AB
657 }
658 }
659 }
660
661 if (list_empty(&c->bad_list)) {
81e39cf0 662 printk(JFFS2_DBG "bad_list: empty\n");
730554d9
AB
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)) {
81e39cf0 670 printk(JFFS2_DBG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
671 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
672 jeb->unchecked_size, jeb->free_size);
730554d9
AB
673 }
674 }
675 }
676
677 if (list_empty(&c->bad_used_list)) {
81e39cf0 678 printk(JFFS2_DBG "bad_used_list: empty\n");
730554d9
AB
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)) {
81e39cf0 686 printk(JFFS2_DBG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
687 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
688 jeb->unchecked_size, jeb->free_size);
730554d9
AB
689 }
690 }
691 }
692}
693
694void
e0c8e42f
AB
695__jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
696{
ced22070 697 mutex_lock(&f->sem);
e0c8e42f 698 jffs2_dbg_dump_fragtree_nolock(f);
ced22070 699 mutex_unlock(&f->sem);
e0c8e42f
AB
700}
701
702void
703__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
730554d9
AB
704{
705 struct jffs2_node_frag *this = frag_first(&f->fragtree);
706 uint32_t lastofs = 0;
707 int buggy = 0;
708
81e39cf0 709 printk(JFFS2_DBG_MSG_PREFIX " dump fragtree of ino #%u\n", f->inocache->ino);
730554d9
AB
710 while(this) {
711 if (this->node)
81e39cf0 712 printk(JFFS2_DBG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), right (%p), parent (%p)\n",
e0c8e42f
AB
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));
730554d9 716 else
81e39cf0 717 printk(JFFS2_DBG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
e0c8e42f
AB
718 this->ofs, this->ofs+this->size, this, frag_left(this),
719 frag_right(this), frag_parent(this));
730554d9
AB
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)
81e39cf0 727 printk(JFFS2_DBG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
730554d9
AB
728
729 if (buggy) {
e0c8e42f 730 JFFS2_ERROR("frag tree got a hole in it.\n");
730554d9
AB
731 BUG();
732 }
733}
734
e0c8e42f 735#define JFFS2_BUFDUMP_BYTES_PER_LINE 32
730554d9 736void
e0c8e42f 737__jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
730554d9 738{
e0c8e42f
AB
739 int skip;
740 int i;
182ec4ee 741
81e39cf0 742 printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n",
e0c8e42f
AB
743 offs, offs + len, len);
744 i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
745 offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
182ec4ee 746
e0c8e42f 747 if (skip != 0)
81e39cf0 748 printk(JFFS2_DBG "%#08x: ", offs);
182ec4ee 749
e0c8e42f
AB
750 while (skip--)
751 printk(" ");
730554d9
AB
752
753 while (i < len) {
e0c8e42f
AB
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;
81e39cf0 758 printk(JFFS2_DBG "%0#8x: ", offs);
730554d9
AB
759 }
760
e0c8e42f 761 printk("%02x ", buf[i]);
182ec4ee 762
e0c8e42f
AB
763 i += 1;
764 }
765
766 printk("\n");
767}
768
769/*
770 * Dump a JFFS2 node.
771 */
772void
773__jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
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;
182ec4ee 780
81e39cf0 781 printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs);
e0c8e42f
AB
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
81e39cf0
AB
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));
182ec4ee 794
e0c8e42f
AB
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 }
182ec4ee 800
e0c8e42f
AB
801 if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
802 je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
803 {
804 JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
805 je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
806 return;
807 }
808
809 switch(je16_to_cpu(node.u.nodetype)) {
810
811 case JFFS2_NODETYPE_INODE:
812
81e39cf0
AB
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
182ec4ee 832 crc = crc32(0, &node.i, sizeof(node.i) - 8);
e0c8e42f
AB
833 if (crc != je32_to_cpu(node.i.node_crc)) {
834 JFFS2_ERROR("wrong node header CRC.\n");
835 return;
836 }
837 break;
838
839 case JFFS2_NODETYPE_DIRENT:
840
81e39cf0
AB
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));
182ec4ee 850
e0c8e42f 851 node.d.name[node.d.nsize] = '\0';
81e39cf0 852 printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name);
e0c8e42f 853
182ec4ee 854 crc = crc32(0, &node.d, sizeof(node.d) - 8);
e0c8e42f
AB
855 if (crc != je32_to_cpu(node.d.node_crc)) {
856 JFFS2_ERROR("wrong node header CRC.\n");
857 return;
730554d9 858 }
e0c8e42f 859 break;
730554d9 860
e0c8e42f 861 default:
81e39cf0 862 printk(JFFS2_DBG "node type is unknown\n");
e0c8e42f 863 break;
730554d9
AB
864 }
865}
e0c8e42f 866#endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */