blob: 9b776b5a760460a7c520e9a52fe72032891620c1 [file] [log] [blame]
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +01001/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc.
5 *
6 * Created by David Woodhouse <dwmw2@infradead.org>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
Artem B. Bityutskiy45ca1b52005-08-05 12:43:47 +010010 * $Id: debug.c,v 1.9 2005/08/05 10:42:24 dedekind Exp $
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010011 *
12 */
13#include <linux/kernel.h>
Andrew Lunn737b7662005-07-30 16:29:30 +010014#include <linux/types.h>
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010015#include <linux/pagemap.h>
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010016#include <linux/crc32.h>
17#include <linux/jffs2.h>
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010018#include "nodelist.h"
19#include "debug.h"
20
Artem B. Bityutskiy45ca1b52005-08-05 12:43:47 +010021#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);
31 JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked "
32 "%#08x != total %#08x.\n", jeb->free_size, jeb->dirty_size, jeb->used_size,
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");
40 JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + "
41 "wasted %#08x + unchecked %#08x != total %#08x.\n",
42 c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size,
43 c->wasted_size, c->unchecked_size, c->flash_size);
44 BUG();
45 }
46}
47
48void
49__jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c,
50 struct jffs2_eraseblock *jeb)
51{
52 spin_lock(&c->erase_completion_lock);
53 jffs2_dbg_acct_sanity_check_nolock(c, jeb);
54 spin_unlock(&c->erase_completion_lock);
55}
56
57#endif /* JFFS2_DBG_SANITY_CHECKS */
58
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010059#ifdef JFFS2_DBG_PARANOIA_CHECKS
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010060/*
61 * Check the fragtree.
62 */
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010063void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010064__jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
65{
66 down(&f->sem);
67 __jffs2_dbg_fragtree_paranoia_check_nolock(f);
68 up(&f->sem);
69}
70
71void
72__jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010073{
74 struct jffs2_node_frag *frag;
75 int bitched = 0;
76
77 for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
78 struct jffs2_full_dnode *fn = frag->node;
79
80 if (!fn || !fn->raw)
81 continue;
82
83 if (ref_flags(fn->raw) == REF_PRISTINE) {
84 if (fn->frags > 1) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010085 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010086 ref_offset(fn->raw), fn->frags);
87 bitched = 1;
88 }
89
90 /* A hole node which isn't multi-page should be garbage-collected
91 and merged anyway, so we just check for the frag size here,
92 rather than mucking around with actually reading the node
93 and checking the compression type, which is the real way
94 to tell a hole node. */
95 if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag)
96 && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010097 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag "
98 "in the same page. Tell dwmw2.\n", ref_offset(fn->raw));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010099 bitched = 1;
100 }
101
102 if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag)
103 && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100104 JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following "
105 "non-hole frag in the same page. Tell dwmw2.\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100106 ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
107 bitched = 1;
108 }
109 }
110 }
111
112 if (bitched) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100113 JFFS2_ERROR("fragtree is corrupted.\n");
114 __jffs2_dbg_dump_fragtree_nolock(f);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100115 BUG();
116 }
117}
118
119/*
120 * Check if the flash contains all 0xFF before we start writing.
121 */
122void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100123__jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
124 uint32_t ofs, int len)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100125{
126 size_t retlen;
127 int ret, i;
128 unsigned char *buf;
129
130 buf = kmalloc(len, GFP_KERNEL);
131 if (!buf)
132 return;
133
134 ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
135 if (ret || (retlen != len)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100136 JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n",
137 len, ret, retlen);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100138 kfree(buf);
139 return;
140 }
141
142 ret = 0;
143 for (i = 0; i < len; i++)
144 if (buf[i] != 0xff)
145 ret = 1;
146
147 if (ret) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100148 JFFS2_ERROR("argh, about to write node to %#08x on flash, but there are data "
149 "already there. The first corrupted byte is at %#08x offset.\n", ofs, ofs + i);
150 __jffs2_dbg_dump_buffer(buf, len, ofs);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100151 kfree(buf);
152 BUG();
153 }
154
155 kfree(buf);
156}
157
158/*
159 * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
160 */
161void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100162__jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
163 struct jffs2_eraseblock *jeb)
164{
165 spin_lock(&c->erase_completion_lock);
166 __jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
167 spin_unlock(&c->erase_completion_lock);
168}
169
170void
171__jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
172 struct jffs2_eraseblock *jeb)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100173{
174 uint32_t my_used_size = 0;
175 uint32_t my_unchecked_size = 0;
176 uint32_t my_dirty_size = 0;
177 struct jffs2_raw_node_ref *ref2 = jeb->first_node;
178
179 while (ref2) {
180 uint32_t totlen = ref_totlen(c, jeb, ref2);
181
182 if (ref2->flash_offset < jeb->offset ||
183 ref2->flash_offset > jeb->offset + c->sector_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100184 JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100185 ref_offset(ref2), jeb->offset);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100186 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100187
188 }
189 if (ref_flags(ref2) == REF_UNCHECKED)
190 my_unchecked_size += totlen;
191 else if (!ref_obsolete(ref2))
192 my_used_size += totlen;
193 else
194 my_dirty_size += totlen;
195
196 if ((!ref2->next_phys) != (ref2 == jeb->last_node)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100197 JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), "
198 "last_node is at %#08x (mem %p).\n",
199 ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys,
200 ref_offset(jeb->last_node), jeb->last_node);
201 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100202 }
203 ref2 = ref2->next_phys;
204 }
205
206 if (my_used_size != jeb->used_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100207 JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
208 my_used_size, jeb->used_size);
209 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100210 }
211
212 if (my_unchecked_size != jeb->unchecked_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100213 JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
214 my_unchecked_size, jeb->unchecked_size);
215 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100216 }
217
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100218#if 0
219 /* This should work when we implement ref->__totlen elemination */
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100220 if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100221 JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100222 my_dirty_size, jeb->dirty_size + jeb->wasted_size);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100223 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100224 }
225
226 if (jeb->free_size == 0
227 && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100228 JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100229 my_used_size + my_unchecked_size + my_dirty_size,
230 c->sector_size);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100231 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100232 }
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100233#endif
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100234
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100235 return;
236
237error:
238 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
239 __jffs2_dbg_dump_jeb_nolock(jeb);
240 __jffs2_dbg_dump_block_lists_nolock(c);
241 BUG();
242
243}
244#endif /* JFFS2_DBG_PARANOIA_CHECKS */
245
246#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100247/*
248 * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
249 */
250void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100251__jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
252 struct jffs2_eraseblock *jeb)
253{
254 spin_lock(&c->erase_completion_lock);
255 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
256 spin_unlock(&c->erase_completion_lock);
257}
258
259void
260__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
261 struct jffs2_eraseblock *jeb)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100262{
263 struct jffs2_raw_node_ref *ref;
264 int i = 0;
265
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100266 JFFS2_DEBUG("Dump node_refs of the eraseblock %#08x\n", jeb->offset);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100267 if (!jeb->first_node) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100268 JFFS2_DEBUG("no nodes in the eraseblock %#08x\n", jeb->offset);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100269 return;
270 }
271
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100272 printk(JFFS2_DBG_LVL);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100273 for (ref = jeb->first_node; ; ref = ref->next_phys) {
274 printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
275 if (ref->next_phys)
276 printk("->");
277 else
278 break;
279 if (++i == 4) {
280 i = 0;
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100281 printk("\n" JFFS2_DBG_LVL);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100282 }
283 }
284 printk("\n");
285}
286
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100287/*
288 * Dump an eraseblock's space accounting.
289 */
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100290void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100291__jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100292{
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100293 spin_lock(&c->erase_completion_lock);
294 __jffs2_dbg_dump_jeb_nolock(jeb);
295 spin_unlock(&c->erase_completion_lock);
296}
297
298void
299__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
300{
301 if (!jeb)
302 return;
303
304 JFFS2_DEBUG("dump space accounting for the eraseblock at %#08x:\n",
305 jeb->offset);
306
307 printk(JFFS2_DBG_LVL "used_size: %#08x\n", jeb->used_size);
308 printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", jeb->dirty_size);
309 printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", jeb->wasted_size);
310 printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", jeb->unchecked_size);
311 printk(JFFS2_DBG_LVL "free_size: %#08x\n", jeb->free_size);
312}
313
314void
315__jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
316{
317 spin_lock(&c->erase_completion_lock);
318 __jffs2_dbg_dump_block_lists_nolock(c);
319 spin_unlock(&c->erase_completion_lock);
320}
321
322void
323__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
324{
325 JFFS2_DEBUG("dump JFFS2 blocks lists:\n");
326
327 printk(JFFS2_DBG_LVL "flash_size: %#08x\n", c->flash_size);
328 printk(JFFS2_DBG_LVL "used_size: %#08x\n", c->used_size);
329 printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", c->dirty_size);
330 printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", c->wasted_size);
331 printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", c->unchecked_size);
332 printk(JFFS2_DBG_LVL "free_size: %#08x\n", c->free_size);
333 printk(JFFS2_DBG_LVL "erasing_size: %#08x\n", c->erasing_size);
334 printk(JFFS2_DBG_LVL "bad_size: %#08x\n", c->bad_size);
335 printk(JFFS2_DBG_LVL "sector_size: %#08x\n", c->sector_size);
336 printk(JFFS2_DBG_LVL "jffs2_reserved_blocks size: %#08x\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100337 c->sector_size * c->resv_blocks_write);
338
339 if (c->nextblock)
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100340 printk(JFFS2_DBG_LVL "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
341 "unchecked %#08x, free %#08x)\n",
342 c->nextblock->offset, c->nextblock->used_size,
343 c->nextblock->dirty_size, c->nextblock->wasted_size,
344 c->nextblock->unchecked_size, c->nextblock->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100345 else
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100346 printk(JFFS2_DBG_LVL "nextblock: NULL\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100347
348 if (c->gcblock)
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100349 printk(JFFS2_DBG_LVL "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
350 "unchecked %#08x, free %#08x)\n",
351 c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
352 c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100353 else
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100354 printk(JFFS2_DBG_LVL "gcblock: NULL\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100355
356 if (list_empty(&c->clean_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100357 printk(JFFS2_DBG_LVL "clean_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100358 } else {
359 struct list_head *this;
360 int numblocks = 0;
361 uint32_t dirty = 0;
362
363 list_for_each(this, &c->clean_list) {
364 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
365 numblocks ++;
366 dirty += jeb->wasted_size;
367 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100368 printk(JFFS2_DBG_LVL "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
369 "unchecked %#08x, free %#08x)\n",
370 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
371 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100372 }
373 }
374
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100375 printk (JFFS2_DBG_LVL "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
376 numblocks, dirty, dirty / numblocks);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100377 }
378
379 if (list_empty(&c->very_dirty_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100380 printk(JFFS2_DBG_LVL "very_dirty_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100381 } else {
382 struct list_head *this;
383 int numblocks = 0;
384 uint32_t dirty = 0;
385
386 list_for_each(this, &c->very_dirty_list) {
387 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
388
389 numblocks ++;
390 dirty += jeb->dirty_size;
391 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100392 printk(JFFS2_DBG_LVL "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
393 "unchecked %#08x, free %#08x)\n",
394 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
395 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100396 }
397 }
398
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100399 printk (JFFS2_DBG_LVL "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
400 numblocks, dirty, dirty / numblocks);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100401 }
402
403 if (list_empty(&c->dirty_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100404 printk(JFFS2_DBG_LVL "dirty_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100405 } else {
406 struct list_head *this;
407 int numblocks = 0;
408 uint32_t dirty = 0;
409
410 list_for_each(this, &c->dirty_list) {
411 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
412
413 numblocks ++;
414 dirty += jeb->dirty_size;
415 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100416 printk(JFFS2_DBG_LVL "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
417 "unchecked %#08x, free %#08x)\n",
418 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
419 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100420 }
421 }
422
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100423 printk (JFFS2_DBG_LVL "contains %d blocks with total dirty size %u, average dirty size: %u\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100424 numblocks, dirty, dirty / numblocks);
425 }
426
427 if (list_empty(&c->erasable_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100428 printk(JFFS2_DBG_LVL "erasable_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100429 } else {
430 struct list_head *this;
431
432 list_for_each(this, &c->erasable_list) {
433 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
434
435 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100436 printk(JFFS2_DBG_LVL "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
437 "unchecked %#08x, free %#08x)\n",
438 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
439 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100440 }
441 }
442 }
443
444 if (list_empty(&c->erasing_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100445 printk(JFFS2_DBG_LVL "erasing_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100446 } else {
447 struct list_head *this;
448
449 list_for_each(this, &c->erasing_list) {
450 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
451
452 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100453 printk(JFFS2_DBG_LVL "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
454 "unchecked %#08x, free %#08x)\n",
455 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
456 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100457 }
458 }
459 }
460
461 if (list_empty(&c->erase_pending_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100462 printk(JFFS2_DBG_LVL "erase_pending_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100463 } else {
464 struct list_head *this;
465
466 list_for_each(this, &c->erase_pending_list) {
467 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
468
469 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100470 printk(JFFS2_DBG_LVL "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
471 "unchecked %#08x, free %#08x)\n",
472 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
473 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100474 }
475 }
476 }
477
478 if (list_empty(&c->erasable_pending_wbuf_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100479 printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100480 } else {
481 struct list_head *this;
482
483 list_for_each(this, &c->erasable_pending_wbuf_list) {
484 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
485
486 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100487 printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, "
488 "wasted %#08x, unchecked %#08x, free %#08x)\n",
489 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
490 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100491 }
492 }
493 }
494
495 if (list_empty(&c->free_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100496 printk(JFFS2_DBG_LVL "free_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100497 } else {
498 struct list_head *this;
499
500 list_for_each(this, &c->free_list) {
501 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
502
503 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100504 printk(JFFS2_DBG_LVL "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
505 "unchecked %#08x, free %#08x)\n",
506 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
507 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100508 }
509 }
510 }
511
512 if (list_empty(&c->bad_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100513 printk(JFFS2_DBG_LVL "bad_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100514 } else {
515 struct list_head *this;
516
517 list_for_each(this, &c->bad_list) {
518 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
519
520 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100521 printk(JFFS2_DBG_LVL "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
522 "unchecked %#08x, free %#08x)\n",
523 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
524 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100525 }
526 }
527 }
528
529 if (list_empty(&c->bad_used_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100530 printk(JFFS2_DBG_LVL "bad_used_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100531 } else {
532 struct list_head *this;
533
534 list_for_each(this, &c->bad_used_list) {
535 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
536
537 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100538 printk(JFFS2_DBG_LVL "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
539 "unchecked %#08x, free %#08x)\n",
540 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
541 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100542 }
543 }
544 }
545}
546
547void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100548__jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
549{
550 down(&f->sem);
551 jffs2_dbg_dump_fragtree_nolock(f);
552 up(&f->sem);
553}
554
555void
556__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100557{
558 struct jffs2_node_frag *this = frag_first(&f->fragtree);
559 uint32_t lastofs = 0;
560 int buggy = 0;
561
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100562 JFFS2_DEBUG("dump fragtree of ino #%u\n", f->inocache->ino);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100563 while(this) {
564 if (this->node)
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100565 printk(JFFS2_DBG_LVL "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), "
566 "right (%p), parent (%p)\n",
567 this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
568 ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
569 frag_parent(this));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100570 else
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100571 printk(JFFS2_DBG_LVL "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
572 this->ofs, this->ofs+this->size, this, frag_left(this),
573 frag_right(this), frag_parent(this));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100574 if (this->ofs != lastofs)
575 buggy = 1;
576 lastofs = this->ofs + this->size;
577 this = frag_next(this);
578 }
579
580 if (f->metadata)
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100581 printk(JFFS2_DBG_LVL "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100582
583 if (buggy) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100584 JFFS2_ERROR("frag tree got a hole in it.\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100585 BUG();
586 }
587}
588
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100589#define JFFS2_BUFDUMP_BYTES_PER_LINE 32
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100590void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100591__jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100592{
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100593 int skip;
594 int i;
595
596 JFFS2_DEBUG("dump from offset %#08x to offset %#08x (%x bytes).\n",
597 offs, offs + len, len);
598 i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
599 offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
600
601 if (skip != 0)
602 printk(JFFS2_DBG_LVL "%#08x: ", offs);
603
604 while (skip--)
605 printk(" ");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100606
607 while (i < len) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100608 if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
609 if (i != 0)
610 printk("\n");
611 offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
612 printk(JFFS2_DBG_LVL "%0#8x: ", offs);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100613 }
614
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100615 printk("%02x ", buf[i]);
616
617 i += 1;
618 }
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100619
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100620 printk("\n");
621}
622
623/*
624 * Dump a JFFS2 node.
625 */
626void
627__jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
628{
629 union jffs2_node_union node;
630 int len = sizeof(union jffs2_node_union);
631 size_t retlen;
632 uint32_t crc;
633 int ret;
634
635 JFFS2_DEBUG("dump node at offset %#08x.\n", ofs);
636
637 ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
638 if (ret || (retlen != len)) {
639 JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
640 len, ret, retlen);
641 return;
642 }
643
644 printk(JFFS2_DBG_LVL "magic:\t%#04x\n",
645 je16_to_cpu(node.u.magic));
646 printk(JFFS2_DBG_LVL "nodetype:\t%#04x\n",
647 je16_to_cpu(node.u.nodetype));
648 printk(JFFS2_DBG_LVL "totlen:\t%#08x\n",
649 je32_to_cpu(node.u.totlen));
650 printk(JFFS2_DBG_LVL "hdr_crc:\t%#08x\n",
651 je32_to_cpu(node.u.hdr_crc));
652
653 crc = crc32(0, &node.u, sizeof(node.u) - 4);
654 if (crc != je32_to_cpu(node.u.hdr_crc)) {
655 JFFS2_ERROR("wrong common header CRC.\n");
656 return;
657 }
658
659 if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
660 je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
661 {
662 JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
663 je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
664 return;
665 }
666
667 switch(je16_to_cpu(node.u.nodetype)) {
668
669 case JFFS2_NODETYPE_INODE:
670
671 printk(JFFS2_DBG_LVL "the node is inode node\n");
672 printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
673 je32_to_cpu(node.i.ino));
674 printk(JFFS2_DBG_LVL "version:\t%#08x\n",
675 je32_to_cpu(node.i.version));
676 printk(JFFS2_DBG_LVL "mode:\t%#08x\n",
677 node.i.mode.m);
678 printk(JFFS2_DBG_LVL "uid:\t%#04x\n",
679 je16_to_cpu(node.i.uid));
680 printk(JFFS2_DBG_LVL "gid:\t%#04x\n",
681 je16_to_cpu(node.i.gid));
682 printk(JFFS2_DBG_LVL "isize:\t%#08x\n",
683 je32_to_cpu(node.i.isize));
684 printk(JFFS2_DBG_LVL "atime:\t%#08x\n",
685 je32_to_cpu(node.i.atime));
686 printk(JFFS2_DBG_LVL "mtime:\t%#08x\n",
687 je32_to_cpu(node.i.mtime));
688 printk(JFFS2_DBG_LVL "ctime:\t%#08x\n",
689 je32_to_cpu(node.i.ctime));
690 printk(JFFS2_DBG_LVL "offset:\t%#08x\n",
691 je32_to_cpu(node.i.offset));
692 printk(JFFS2_DBG_LVL "csize:\t%#08x\n",
693 je32_to_cpu(node.i.csize));
694 printk(JFFS2_DBG_LVL "dsize:\t%#08x\n",
695 je32_to_cpu(node.i.dsize));
696 printk(JFFS2_DBG_LVL "compr:\t%#02x\n",
697 node.i.compr);
698 printk(JFFS2_DBG_LVL "usercompr:\t%#02x\n",
699 node.i.usercompr);
700 printk(JFFS2_DBG_LVL "flags:\t%#04x\n",
701 je16_to_cpu(node.i.flags));
702 printk(JFFS2_DBG_LVL "data_crc:\t%#08x\n",
703 je32_to_cpu(node.i.data_crc));
704 printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
705 je32_to_cpu(node.i.node_crc));
706 crc = crc32(0, &node.i, sizeof(node.i) - 8);
707 if (crc != je32_to_cpu(node.i.node_crc)) {
708 JFFS2_ERROR("wrong node header CRC.\n");
709 return;
710 }
711 break;
712
713 case JFFS2_NODETYPE_DIRENT:
714
715 printk(JFFS2_DBG_LVL "the node is dirent node\n");
716 printk(JFFS2_DBG_LVL "pino:\t%#08x\n",
717 je32_to_cpu(node.d.pino));
718 printk(JFFS2_DBG_LVL "version:\t%#08x\n",
719 je32_to_cpu(node.d.version));
720 printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
721 je32_to_cpu(node.d.ino));
722 printk(JFFS2_DBG_LVL "mctime:\t%#08x\n",
723 je32_to_cpu(node.d.mctime));
724 printk(JFFS2_DBG_LVL "nsize:\t%#02x\n",
725 node.d.nsize);
726 printk(JFFS2_DBG_LVL "type:\t%#02x\n",
727 node.d.type);
728 printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
729 je32_to_cpu(node.d.node_crc));
730 printk(JFFS2_DBG_LVL "name_crc:\t%#08x\n",
731 je32_to_cpu(node.d.name_crc));
732
733 node.d.name[node.d.nsize] = '\0';
734 printk(JFFS2_DBG_LVL "name:\t\"%s\"\n", node.d.name);
735
736 crc = crc32(0, &node.d, sizeof(node.d) - 8);
737 if (crc != je32_to_cpu(node.d.node_crc)) {
738 JFFS2_ERROR("wrong node header CRC.\n");
739 return;
740 }
741 break;
742
743 default:
744 printk(JFFS2_DBG_LVL "node type is unknown\n");
745 break;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100746 }
747}
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100748#endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */