Merge git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
[linux-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{
65 down(&f->sem);
66 __jffs2_dbg_fragtree_paranoia_check_nolock(f);
67 up(&f->sem);
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
156/*
157 * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
158 */
159void
e0c8e42f
AB
160__jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
161 struct jffs2_eraseblock *jeb)
162{
163 spin_lock(&c->erase_completion_lock);
164 __jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
165 spin_unlock(&c->erase_completion_lock);
166}
182ec4ee 167
e0c8e42f
AB
168void
169__jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
170 struct jffs2_eraseblock *jeb)
730554d9
AB
171{
172 uint32_t my_used_size = 0;
173 uint32_t my_unchecked_size = 0;
174 uint32_t my_dirty_size = 0;
175 struct jffs2_raw_node_ref *ref2 = jeb->first_node;
176
177 while (ref2) {
178 uint32_t totlen = ref_totlen(c, jeb, ref2);
179
abb536e7
KP
180 if (ref_offset(ref2) < jeb->offset ||
181 ref_offset(ref2) > jeb->offset + c->sector_size) {
e0c8e42f 182 JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
730554d9 183 ref_offset(ref2), jeb->offset);
e0c8e42f 184 goto error;
730554d9
AB
185
186 }
187 if (ref_flags(ref2) == REF_UNCHECKED)
188 my_unchecked_size += totlen;
189 else if (!ref_obsolete(ref2))
190 my_used_size += totlen;
191 else
192 my_dirty_size += totlen;
193
99988f7b
DW
194 if ((!ref_next(ref2)) != (ref2 == jeb->last_node)) {
195 JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next at %#08x (mem %p), last_node is at %#08x (mem %p).\n",
196 ref_offset(ref2), ref2, ref_offset(ref_next(ref2)), ref_next(ref2),
197 ref_offset(jeb->last_node), jeb->last_node);
e0c8e42f 198 goto error;
730554d9 199 }
99988f7b 200 ref2 = ref_next(ref2);
730554d9
AB
201 }
202
203 if (my_used_size != jeb->used_size) {
e0c8e42f
AB
204 JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
205 my_used_size, jeb->used_size);
206 goto error;
730554d9
AB
207 }
208
209 if (my_unchecked_size != jeb->unchecked_size) {
e0c8e42f
AB
210 JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
211 my_unchecked_size, jeb->unchecked_size);
212 goto error;
730554d9
AB
213 }
214
e0c8e42f
AB
215#if 0
216 /* This should work when we implement ref->__totlen elemination */
730554d9 217 if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
e0c8e42f 218 JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
730554d9 219 my_dirty_size, jeb->dirty_size + jeb->wasted_size);
e0c8e42f 220 goto error;
730554d9
AB
221 }
222
223 if (jeb->free_size == 0
224 && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
e0c8e42f 225 JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
730554d9
AB
226 my_used_size + my_unchecked_size + my_dirty_size,
227 c->sector_size);
e0c8e42f 228 goto error;
730554d9 229 }
e0c8e42f
AB
230#endif
231
232 return;
233
234error:
235 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
236 __jffs2_dbg_dump_jeb_nolock(jeb);
237 __jffs2_dbg_dump_block_lists_nolock(c);
238 BUG();
182ec4ee 239
730554d9 240}
e0c8e42f 241#endif /* JFFS2_DBG_PARANOIA_CHECKS */
730554d9 242
e0c8e42f 243#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
730554d9
AB
244/*
245 * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
246 */
247void
e0c8e42f
AB
248__jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
249 struct jffs2_eraseblock *jeb)
250{
251 spin_lock(&c->erase_completion_lock);
252 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
253 spin_unlock(&c->erase_completion_lock);
254}
255
256void
257__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
258 struct jffs2_eraseblock *jeb)
730554d9
AB
259{
260 struct jffs2_raw_node_ref *ref;
261 int i = 0;
262
81e39cf0 263 printk(JFFS2_DBG_MSG_PREFIX " Dump node_refs of the eraseblock %#08x\n", jeb->offset);
730554d9 264 if (!jeb->first_node) {
81e39cf0 265 printk(JFFS2_DBG_MSG_PREFIX " no nodes in the eraseblock %#08x\n", jeb->offset);
730554d9
AB
266 return;
267 }
268
81e39cf0 269 printk(JFFS2_DBG);
99988f7b 270 for (ref = jeb->first_node; ; ref = ref_next(ref)) {
730554d9 271 printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
99988f7b 272 if (ref_next(ref))
730554d9
AB
273 printk("->");
274 else
275 break;
276 if (++i == 4) {
277 i = 0;
81e39cf0 278 printk("\n" JFFS2_DBG);
730554d9
AB
279 }
280 }
281 printk("\n");
282}
283
e0c8e42f
AB
284/*
285 * Dump an eraseblock's space accounting.
286 */
287void
288__jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
289{
290 spin_lock(&c->erase_completion_lock);
291 __jffs2_dbg_dump_jeb_nolock(jeb);
292 spin_unlock(&c->erase_completion_lock);
293}
294
730554d9 295void
e0c8e42f 296__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
730554d9 297{
e0c8e42f
AB
298 if (!jeb)
299 return;
300
81e39cf0 301 printk(JFFS2_DBG_MSG_PREFIX " dump space accounting for the eraseblock at %#08x:\n",
e0c8e42f
AB
302 jeb->offset);
303
81e39cf0
AB
304 printk(JFFS2_DBG "used_size: %#08x\n", jeb->used_size);
305 printk(JFFS2_DBG "dirty_size: %#08x\n", jeb->dirty_size);
306 printk(JFFS2_DBG "wasted_size: %#08x\n", jeb->wasted_size);
307 printk(JFFS2_DBG "unchecked_size: %#08x\n", jeb->unchecked_size);
308 printk(JFFS2_DBG "free_size: %#08x\n", jeb->free_size);
e0c8e42f
AB
309}
310
311void
312__jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
313{
314 spin_lock(&c->erase_completion_lock);
315 __jffs2_dbg_dump_block_lists_nolock(c);
316 spin_unlock(&c->erase_completion_lock);
317}
318
319void
320__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
321{
81e39cf0 322 printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n");
182ec4ee 323
81e39cf0
AB
324 printk(JFFS2_DBG "flash_size: %#08x\n", c->flash_size);
325 printk(JFFS2_DBG "used_size: %#08x\n", c->used_size);
326 printk(JFFS2_DBG "dirty_size: %#08x\n", c->dirty_size);
327 printk(JFFS2_DBG "wasted_size: %#08x\n", c->wasted_size);
328 printk(JFFS2_DBG "unchecked_size: %#08x\n", c->unchecked_size);
329 printk(JFFS2_DBG "free_size: %#08x\n", c->free_size);
330 printk(JFFS2_DBG "erasing_size: %#08x\n", c->erasing_size);
331 printk(JFFS2_DBG "bad_size: %#08x\n", c->bad_size);
332 printk(JFFS2_DBG "sector_size: %#08x\n", c->sector_size);
333 printk(JFFS2_DBG "jffs2_reserved_blocks size: %#08x\n",
730554d9
AB
334 c->sector_size * c->resv_blocks_write);
335
336 if (c->nextblock)
81e39cf0 337 printk(JFFS2_DBG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
338 c->nextblock->offset, c->nextblock->used_size,
339 c->nextblock->dirty_size, c->nextblock->wasted_size,
340 c->nextblock->unchecked_size, c->nextblock->free_size);
730554d9 341 else
81e39cf0 342 printk(JFFS2_DBG "nextblock: NULL\n");
730554d9
AB
343
344 if (c->gcblock)
81e39cf0 345 printk(JFFS2_DBG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
346 c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
347 c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
730554d9 348 else
81e39cf0 349 printk(JFFS2_DBG "gcblock: NULL\n");
730554d9
AB
350
351 if (list_empty(&c->clean_list)) {
81e39cf0 352 printk(JFFS2_DBG "clean_list: empty\n");
730554d9
AB
353 } else {
354 struct list_head *this;
355 int numblocks = 0;
356 uint32_t dirty = 0;
357
358 list_for_each(this, &c->clean_list) {
359 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
360 numblocks ++;
361 dirty += jeb->wasted_size;
362 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 363 printk(JFFS2_DBG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
364 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
365 jeb->unchecked_size, jeb->free_size);
730554d9
AB
366 }
367 }
368
81e39cf0 369 printk (JFFS2_DBG "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
e0c8e42f 370 numblocks, dirty, dirty / numblocks);
730554d9
AB
371 }
372
373 if (list_empty(&c->very_dirty_list)) {
81e39cf0 374 printk(JFFS2_DBG "very_dirty_list: empty\n");
730554d9
AB
375 } else {
376 struct list_head *this;
377 int numblocks = 0;
378 uint32_t dirty = 0;
379
380 list_for_each(this, &c->very_dirty_list) {
381 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
382
383 numblocks ++;
384 dirty += jeb->dirty_size;
385 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 386 printk(JFFS2_DBG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
387 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
388 jeb->unchecked_size, jeb->free_size);
730554d9
AB
389 }
390 }
391
81e39cf0 392 printk (JFFS2_DBG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
e0c8e42f 393 numblocks, dirty, dirty / numblocks);
730554d9
AB
394 }
395
396 if (list_empty(&c->dirty_list)) {
81e39cf0 397 printk(JFFS2_DBG "dirty_list: empty\n");
730554d9
AB
398 } else {
399 struct list_head *this;
400 int numblocks = 0;
401 uint32_t dirty = 0;
402
403 list_for_each(this, &c->dirty_list) {
404 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
405
406 numblocks ++;
407 dirty += jeb->dirty_size;
408 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 409 printk(JFFS2_DBG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
410 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
411 jeb->unchecked_size, jeb->free_size);
730554d9
AB
412 }
413 }
414
81e39cf0 415 printk (JFFS2_DBG "contains %d blocks with total dirty size %u, average dirty size: %u\n",
730554d9
AB
416 numblocks, dirty, dirty / numblocks);
417 }
418
419 if (list_empty(&c->erasable_list)) {
81e39cf0 420 printk(JFFS2_DBG "erasable_list: empty\n");
730554d9
AB
421 } else {
422 struct list_head *this;
423
424 list_for_each(this, &c->erasable_list) {
425 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
426
427 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 428 printk(JFFS2_DBG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
429 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
430 jeb->unchecked_size, jeb->free_size);
730554d9
AB
431 }
432 }
433 }
434
435 if (list_empty(&c->erasing_list)) {
81e39cf0 436 printk(JFFS2_DBG "erasing_list: empty\n");
730554d9
AB
437 } else {
438 struct list_head *this;
439
440 list_for_each(this, &c->erasing_list) {
441 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
442
443 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 444 printk(JFFS2_DBG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
445 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
446 jeb->unchecked_size, jeb->free_size);
730554d9
AB
447 }
448 }
449 }
450
451 if (list_empty(&c->erase_pending_list)) {
81e39cf0 452 printk(JFFS2_DBG "erase_pending_list: empty\n");
730554d9
AB
453 } else {
454 struct list_head *this;
455
456 list_for_each(this, &c->erase_pending_list) {
457 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
458
459 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 460 printk(JFFS2_DBG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
461 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
462 jeb->unchecked_size, jeb->free_size);
730554d9
AB
463 }
464 }
465 }
466
467 if (list_empty(&c->erasable_pending_wbuf_list)) {
81e39cf0 468 printk(JFFS2_DBG "erasable_pending_wbuf_list: empty\n");
730554d9
AB
469 } else {
470 struct list_head *this;
471
472 list_for_each(this, &c->erasable_pending_wbuf_list) {
473 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
474
475 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 476 printk(JFFS2_DBG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
477 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
478 jeb->unchecked_size, jeb->free_size);
730554d9
AB
479 }
480 }
481 }
482
483 if (list_empty(&c->free_list)) {
81e39cf0 484 printk(JFFS2_DBG "free_list: empty\n");
730554d9
AB
485 } else {
486 struct list_head *this;
487
488 list_for_each(this, &c->free_list) {
489 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
490
491 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 492 printk(JFFS2_DBG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
493 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
494 jeb->unchecked_size, jeb->free_size);
730554d9
AB
495 }
496 }
497 }
498
499 if (list_empty(&c->bad_list)) {
81e39cf0 500 printk(JFFS2_DBG "bad_list: empty\n");
730554d9
AB
501 } else {
502 struct list_head *this;
503
504 list_for_each(this, &c->bad_list) {
505 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
506
507 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 508 printk(JFFS2_DBG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
509 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
510 jeb->unchecked_size, jeb->free_size);
730554d9
AB
511 }
512 }
513 }
514
515 if (list_empty(&c->bad_used_list)) {
81e39cf0 516 printk(JFFS2_DBG "bad_used_list: empty\n");
730554d9
AB
517 } else {
518 struct list_head *this;
519
520 list_for_each(this, &c->bad_used_list) {
521 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
522
523 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
81e39cf0 524 printk(JFFS2_DBG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
e0c8e42f
AB
525 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
526 jeb->unchecked_size, jeb->free_size);
730554d9
AB
527 }
528 }
529 }
530}
531
532void
e0c8e42f
AB
533__jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
534{
535 down(&f->sem);
536 jffs2_dbg_dump_fragtree_nolock(f);
537 up(&f->sem);
538}
539
540void
541__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
730554d9
AB
542{
543 struct jffs2_node_frag *this = frag_first(&f->fragtree);
544 uint32_t lastofs = 0;
545 int buggy = 0;
546
81e39cf0 547 printk(JFFS2_DBG_MSG_PREFIX " dump fragtree of ino #%u\n", f->inocache->ino);
730554d9
AB
548 while(this) {
549 if (this->node)
81e39cf0 550 printk(JFFS2_DBG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), right (%p), parent (%p)\n",
e0c8e42f
AB
551 this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
552 ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
553 frag_parent(this));
730554d9 554 else
81e39cf0 555 printk(JFFS2_DBG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
e0c8e42f
AB
556 this->ofs, this->ofs+this->size, this, frag_left(this),
557 frag_right(this), frag_parent(this));
730554d9
AB
558 if (this->ofs != lastofs)
559 buggy = 1;
560 lastofs = this->ofs + this->size;
561 this = frag_next(this);
562 }
563
564 if (f->metadata)
81e39cf0 565 printk(JFFS2_DBG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
730554d9
AB
566
567 if (buggy) {
e0c8e42f 568 JFFS2_ERROR("frag tree got a hole in it.\n");
730554d9
AB
569 BUG();
570 }
571}
572
e0c8e42f 573#define JFFS2_BUFDUMP_BYTES_PER_LINE 32
730554d9 574void
e0c8e42f 575__jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
730554d9 576{
e0c8e42f
AB
577 int skip;
578 int i;
182ec4ee 579
81e39cf0 580 printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n",
e0c8e42f
AB
581 offs, offs + len, len);
582 i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
583 offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
182ec4ee 584
e0c8e42f 585 if (skip != 0)
81e39cf0 586 printk(JFFS2_DBG "%#08x: ", offs);
182ec4ee 587
e0c8e42f
AB
588 while (skip--)
589 printk(" ");
730554d9
AB
590
591 while (i < len) {
e0c8e42f
AB
592 if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
593 if (i != 0)
594 printk("\n");
595 offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
81e39cf0 596 printk(JFFS2_DBG "%0#8x: ", offs);
730554d9
AB
597 }
598
e0c8e42f 599 printk("%02x ", buf[i]);
182ec4ee 600
e0c8e42f
AB
601 i += 1;
602 }
603
604 printk("\n");
605}
606
607/*
608 * Dump a JFFS2 node.
609 */
610void
611__jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
612{
613 union jffs2_node_union node;
614 int len = sizeof(union jffs2_node_union);
615 size_t retlen;
616 uint32_t crc;
617 int ret;
182ec4ee 618
81e39cf0 619 printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs);
e0c8e42f
AB
620
621 ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
622 if (ret || (retlen != len)) {
623 JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
624 len, ret, retlen);
625 return;
626 }
627
81e39cf0
AB
628 printk(JFFS2_DBG "magic:\t%#04x\n", je16_to_cpu(node.u.magic));
629 printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype));
630 printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen));
631 printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc));
182ec4ee 632
e0c8e42f
AB
633 crc = crc32(0, &node.u, sizeof(node.u) - 4);
634 if (crc != je32_to_cpu(node.u.hdr_crc)) {
635 JFFS2_ERROR("wrong common header CRC.\n");
636 return;
637 }
182ec4ee 638
e0c8e42f
AB
639 if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
640 je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
641 {
642 JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
643 je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
644 return;
645 }
646
647 switch(je16_to_cpu(node.u.nodetype)) {
648
649 case JFFS2_NODETYPE_INODE:
650
81e39cf0
AB
651 printk(JFFS2_DBG "the node is inode node\n");
652 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.i.ino));
653 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.i.version));
654 printk(JFFS2_DBG "mode:\t%#08x\n", node.i.mode.m);
655 printk(JFFS2_DBG "uid:\t%#04x\n", je16_to_cpu(node.i.uid));
656 printk(JFFS2_DBG "gid:\t%#04x\n", je16_to_cpu(node.i.gid));
657 printk(JFFS2_DBG "isize:\t%#08x\n", je32_to_cpu(node.i.isize));
658 printk(JFFS2_DBG "atime:\t%#08x\n", je32_to_cpu(node.i.atime));
659 printk(JFFS2_DBG "mtime:\t%#08x\n", je32_to_cpu(node.i.mtime));
660 printk(JFFS2_DBG "ctime:\t%#08x\n", je32_to_cpu(node.i.ctime));
661 printk(JFFS2_DBG "offset:\t%#08x\n", je32_to_cpu(node.i.offset));
662 printk(JFFS2_DBG "csize:\t%#08x\n", je32_to_cpu(node.i.csize));
663 printk(JFFS2_DBG "dsize:\t%#08x\n", je32_to_cpu(node.i.dsize));
664 printk(JFFS2_DBG "compr:\t%#02x\n", node.i.compr);
665 printk(JFFS2_DBG "usercompr:\t%#02x\n", node.i.usercompr);
666 printk(JFFS2_DBG "flags:\t%#04x\n", je16_to_cpu(node.i.flags));
667 printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc));
668 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc));
669
182ec4ee 670 crc = crc32(0, &node.i, sizeof(node.i) - 8);
e0c8e42f
AB
671 if (crc != je32_to_cpu(node.i.node_crc)) {
672 JFFS2_ERROR("wrong node header CRC.\n");
673 return;
674 }
675 break;
676
677 case JFFS2_NODETYPE_DIRENT:
678
81e39cf0
AB
679 printk(JFFS2_DBG "the node is dirent node\n");
680 printk(JFFS2_DBG "pino:\t%#08x\n", je32_to_cpu(node.d.pino));
681 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.d.version));
682 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.d.ino));
683 printk(JFFS2_DBG "mctime:\t%#08x\n", je32_to_cpu(node.d.mctime));
684 printk(JFFS2_DBG "nsize:\t%#02x\n", node.d.nsize);
685 printk(JFFS2_DBG "type:\t%#02x\n", node.d.type);
686 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc));
687 printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc));
182ec4ee 688
e0c8e42f 689 node.d.name[node.d.nsize] = '\0';
81e39cf0 690 printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name);
e0c8e42f 691
182ec4ee 692 crc = crc32(0, &node.d, sizeof(node.d) - 8);
e0c8e42f
AB
693 if (crc != je32_to_cpu(node.d.node_crc)) {
694 JFFS2_ERROR("wrong node header CRC.\n");
695 return;
730554d9 696 }
e0c8e42f 697 break;
730554d9 698
e0c8e42f 699 default:
81e39cf0 700 printk(JFFS2_DBG "node type is unknown\n");
e0c8e42f 701 break;
730554d9
AB
702 }
703}
e0c8e42f 704#endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */