2 * JFFS2 -- Journalling Flash File System, Version 2.
4 * Copyright (C) 2001-2003 Red Hat, Inc.
6 * Created by David Woodhouse <dwmw2@infradead.org>
8 * For licensing information, see the file 'LICENCE' in this directory.
10 * $Id: debug.c,v 1.1 2005/07/17 06:56:20 dedekind Exp $
13 #include <linux/kernel.h>
14 #include <linux/pagemap.h>
18 #ifdef JFFS2_DBG_PARANOIA_CHECKS
21 jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
23 struct jffs2_node_frag *frag;
26 for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
27 struct jffs2_full_dnode *fn = frag->node;
32 if (ref_flags(fn->raw) == REF_PRISTINE) {
34 printk(KERN_ERR "REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2\n",
35 ref_offset(fn->raw), fn->frags);
39 /* A hole node which isn't multi-page should be garbage-collected
40 and merged anyway, so we just check for the frag size here,
41 rather than mucking around with actually reading the node
42 and checking the compression type, which is the real way
43 to tell a hole node. */
44 if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag)
45 && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
46 printk(KERN_ERR "REF_PRISTINE node at 0x%08x had a previous non-hole frag "
47 "in the same page. Tell dwmw2\n", ref_offset(fn->raw));
51 if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag)
52 && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
53 printk(KERN_ERR "REF_PRISTINE node at 0x%08x (%08x-%08x) had a following "
54 "non-hole frag in the same page. Tell dwmw2\n",
55 ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
62 printk(KERN_ERR "Fragtree is corrupted. Fragtree dump:\n");
63 jffs2_dbg_dump_fragtree(f);
69 * Check if the flash contains all 0xFF before we start writing.
72 jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, uint32_t ofs, int len)
78 buf = kmalloc(len, GFP_KERNEL);
82 ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
83 if (ret || (retlen != len)) {
84 printk(KERN_WARNING "read %d bytes failed or short in %s(). ret %d, retlen %zd\n",
85 len, __FUNCTION__, ret, retlen);
91 for (i = 0; i < len; i++)
96 printk(KERN_ERR "ARGH. About to write node to %#08x on flash, but there are data "
97 "already there. The first corrupted byte is at %#08x.\n", ofs, ofs + i);
98 jffs2_dbg_dump_buffer(buf, len, ofs);
107 * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
110 jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
112 uint32_t my_used_size = 0;
113 uint32_t my_unchecked_size = 0;
114 uint32_t my_dirty_size = 0;
115 struct jffs2_raw_node_ref *ref2 = jeb->first_node;
118 uint32_t totlen = ref_totlen(c, jeb, ref2);
120 if (ref2->flash_offset < jeb->offset ||
121 ref2->flash_offset > jeb->offset + c->sector_size) {
122 printk(KERN_ERR "node_ref %#08x shouldn't be in block at %#08x!\n",
123 ref_offset(ref2), jeb->offset);
124 jffs2_dbg_dump_node_refs(c, jeb);
125 jffs2_dbg_dump_block_lists(c);
129 if (ref_flags(ref2) == REF_UNCHECKED)
130 my_unchecked_size += totlen;
131 else if (!ref_obsolete(ref2))
132 my_used_size += totlen;
134 my_dirty_size += totlen;
136 if ((!ref2->next_phys) != (ref2 == jeb->last_node)) {
137 printk(KERN_ERR "node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), "
138 "last_node is at %#08x (mem %p)\n",
139 ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys,
140 ref_offset(jeb->last_node), jeb->last_node);
141 jffs2_dbg_dump_node_refs(c, jeb);
142 jffs2_dbg_dump_block_lists(c);
145 ref2 = ref2->next_phys;
148 if (my_used_size != jeb->used_size) {
149 printk(KERN_ERR "Calculated used size %#08x != stored used size %#08x\n",
150 my_used_size, jeb->used_size);
151 jffs2_dbg_dump_node_refs(c, jeb);
152 jffs2_dbg_dump_block_lists(c);
156 if (my_unchecked_size != jeb->unchecked_size) {
157 printk(KERN_ERR "Calculated unchecked size %#08x != stored unchecked size %#08x\n",
158 my_unchecked_size, jeb->unchecked_size);
159 jffs2_dbg_dump_node_refs(c, jeb);
160 jffs2_dbg_dump_block_lists(c);
164 if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
165 printk(KERN_ERR "Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
166 my_dirty_size, jeb->dirty_size + jeb->wasted_size);
167 jffs2_dbg_dump_node_refs(c, jeb);
168 jffs2_dbg_dump_block_lists(c);
172 if (jeb->free_size == 0
173 && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
174 printk(KERN_ERR "The sum of all nodes in block (%#x) != size of block (%#x)\n",
175 my_used_size + my_unchecked_size + my_dirty_size,
177 jffs2_dbg_dump_node_refs(c, jeb);
178 jffs2_dbg_dump_block_lists(c);
182 #endif /* JFFS2_PARANOIA_CHECKS */
184 #if defined(JFFS2_PARANOIA_CHECKS) || (CONFIG_JFFS2_FS_DEBUG > 0)
186 * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
189 jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
191 struct jffs2_raw_node_ref *ref;
194 if (!jeb->first_node) {
195 printk(KERN_DEBUG "no nodes in block %#08x\n", jeb->offset);
200 for (ref = jeb->first_node; ; ref = ref->next_phys) {
201 printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
208 printk("\n" KERN_DEBUG);
215 jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
217 printk(KERN_DEBUG "flash_size: %#08x\n", c->flash_size);
218 printk(KERN_DEBUG "used_size: %#08x\n", c->used_size);
219 printk(KERN_DEBUG "dirty_size: %#08x\n", c->dirty_size);
220 printk(KERN_DEBUG "wasted_size: %#08x\n", c->wasted_size);
221 printk(KERN_DEBUG "unchecked_size: %#08x\n", c->unchecked_size);
222 printk(KERN_DEBUG "free_size: %#08x\n", c->free_size);
223 printk(KERN_DEBUG "erasing_size: %#08x\n", c->erasing_size);
224 printk(KERN_DEBUG "bad_size: %#08x\n", c->bad_size);
225 printk(KERN_DEBUG "sector_size: %#08x\n", c->sector_size);
226 printk(KERN_DEBUG "jffs2_reserved_blocks size: %#08x\n",
227 c->sector_size * c->resv_blocks_write);
230 printk(KERN_DEBUG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
231 "unchecked %#08x, free %#08x)\n",
232 c->nextblock->offset, c->nextblock->used_size,
233 c->nextblock->dirty_size, c->nextblock->wasted_size,
234 c->nextblock->unchecked_size, c->nextblock->free_size);
236 printk(KERN_DEBUG "nextblock: NULL\n");
239 printk(KERN_DEBUG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
240 "unchecked %#08x, free %#08x)\n",
241 c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
242 c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
244 printk(KERN_DEBUG "gcblock: NULL\n");
246 if (list_empty(&c->clean_list)) {
247 printk(KERN_DEBUG "clean_list: empty\n");
249 struct list_head *this;
253 list_for_each(this, &c->clean_list) {
254 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
256 dirty += jeb->wasted_size;
257 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
258 printk(KERN_DEBUG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
259 "unchecked %#08x, free %#08x)\n",
260 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
261 jeb->unchecked_size, jeb->free_size);
265 printk (KERN_DEBUG "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
266 numblocks, dirty, dirty / numblocks);
269 if (list_empty(&c->very_dirty_list)) {
270 printk(KERN_DEBUG "very_dirty_list: empty\n");
272 struct list_head *this;
276 list_for_each(this, &c->very_dirty_list) {
277 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
280 dirty += jeb->dirty_size;
281 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
282 printk(KERN_DEBUG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
283 "unchecked %#08x, free %#08x)\n",
284 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
285 jeb->unchecked_size, jeb->free_size);
289 printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
290 numblocks, dirty, dirty / numblocks);
293 if (list_empty(&c->dirty_list)) {
294 printk(KERN_DEBUG "dirty_list: empty\n");
296 struct list_head *this;
300 list_for_each(this, &c->dirty_list) {
301 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
304 dirty += jeb->dirty_size;
305 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
306 printk(KERN_DEBUG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
307 "unchecked %#08x, free %#08x)\n",
308 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
309 jeb->unchecked_size, jeb->free_size);
313 printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
314 numblocks, dirty, dirty / numblocks);
317 if (list_empty(&c->erasable_list)) {
318 printk(KERN_DEBUG "erasable_list: empty\n");
320 struct list_head *this;
322 list_for_each(this, &c->erasable_list) {
323 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
325 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
326 printk(KERN_DEBUG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
327 "unchecked %#08x, free %#08x)\n",
328 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
329 jeb->unchecked_size, jeb->free_size);
334 if (list_empty(&c->erasing_list)) {
335 printk(KERN_DEBUG "erasing_list: empty\n");
337 struct list_head *this;
339 list_for_each(this, &c->erasing_list) {
340 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
342 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
343 printk(KERN_DEBUG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
344 "unchecked %#08x, free %#08x)\n",
345 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
346 jeb->unchecked_size, jeb->free_size);
351 if (list_empty(&c->erase_pending_list)) {
352 printk(KERN_DEBUG "erase_pending_list: empty\n");
354 struct list_head *this;
356 list_for_each(this, &c->erase_pending_list) {
357 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
359 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
360 printk(KERN_DEBUG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
361 "unchecked %#08x, free %#08x)\n",
362 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
363 jeb->unchecked_size, jeb->free_size);
368 if (list_empty(&c->erasable_pending_wbuf_list)) {
369 printk(KERN_DEBUG "erasable_pending_wbuf_list: empty\n");
371 struct list_head *this;
373 list_for_each(this, &c->erasable_pending_wbuf_list) {
374 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
376 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
377 printk(KERN_DEBUG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, "
378 "wasted %#08x, unchecked %#08x, free %#08x)\n",
379 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
380 jeb->unchecked_size, jeb->free_size);
385 if (list_empty(&c->free_list)) {
386 printk(KERN_DEBUG "free_list: empty\n");
388 struct list_head *this;
390 list_for_each(this, &c->free_list) {
391 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
393 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
394 printk(KERN_DEBUG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
395 "unchecked %#08x, free %#08x)\n",
396 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
397 jeb->unchecked_size, jeb->free_size);
402 if (list_empty(&c->bad_list)) {
403 printk(KERN_DEBUG "bad_list: empty\n");
405 struct list_head *this;
407 list_for_each(this, &c->bad_list) {
408 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
410 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
411 printk(KERN_DEBUG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
412 "unchecked %#08x, free %#08x)\n",
413 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
414 jeb->unchecked_size, jeb->free_size);
419 if (list_empty(&c->bad_used_list)) {
420 printk(KERN_DEBUG "bad_used_list: empty\n");
422 struct list_head *this;
424 list_for_each(this, &c->bad_used_list) {
425 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
427 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
428 printk(KERN_DEBUG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
429 "unchecked %#08x, free %#08x)\n",
430 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
431 jeb->unchecked_size, jeb->free_size);
438 jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
440 struct jffs2_node_frag *this = frag_first(&f->fragtree);
441 uint32_t lastofs = 0;
444 printk(KERN_DEBUG "inode is ino #%u\n", f->inocache->ino);
447 printk(KERN_DEBUG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), "
448 "right (%p), parent (%p)\n",
449 this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
450 ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
453 printk(KERN_DEBUG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
454 this->ofs, this->ofs+this->size, this, frag_left(this),
455 frag_right(this), frag_parent(this));
456 if (this->ofs != lastofs)
458 lastofs = this->ofs + this->size;
459 this = frag_next(this);
463 printk(KERN_DEBUG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
466 printk(KERN_ERR "Error! %s(): Frag tree got a hole in it\n", __FUNCTION__);
471 #define JFFS3_BUFDUMP_BYTES_PER_LINE 8
473 jffs2_dbg_dump_buffer(char *buf, int len, uint32_t offs)
476 int skip = offs & ~(JFFS3_BUFDUMP_BYTES_PER_LINE - 1);
481 printk(KERN_DEBUG "0x#x: \n");
487 while (j < JFFS3_BUFDUMP_BYTES_PER_LINE) {
489 printk(" %#02x", buf[i + j++]);
492 i += JFFS3_BUFDUMP_BYTES_PER_LINE;
495 #endif /* JFFS2_PARANOIA_CHECKS || CONFIG_JFFS2_FS_DEBUG > 0 */