blob: 80ac9b6514bfdab12ff6a1de59d1c4225922bce6 [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 *
Andrew Lunn737b7662005-07-30 16:29:30 +010010 * $Id: debug.c,v 1.8 2005/07/30 15:27:05 lunn 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
21#ifdef JFFS2_DBG_PARANOIA_CHECKS
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010022/*
23 * Check the fragtree.
24 */
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010025void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010026__jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
27{
28 down(&f->sem);
29 __jffs2_dbg_fragtree_paranoia_check_nolock(f);
30 up(&f->sem);
31}
32
33void
34__jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010035{
36 struct jffs2_node_frag *frag;
37 int bitched = 0;
38
39 for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
40 struct jffs2_full_dnode *fn = frag->node;
41
42 if (!fn || !fn->raw)
43 continue;
44
45 if (ref_flags(fn->raw) == REF_PRISTINE) {
46 if (fn->frags > 1) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010047 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010048 ref_offset(fn->raw), fn->frags);
49 bitched = 1;
50 }
51
52 /* A hole node which isn't multi-page should be garbage-collected
53 and merged anyway, so we just check for the frag size here,
54 rather than mucking around with actually reading the node
55 and checking the compression type, which is the real way
56 to tell a hole node. */
57 if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag)
58 && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010059 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag "
60 "in the same page. Tell dwmw2.\n", ref_offset(fn->raw));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010061 bitched = 1;
62 }
63
64 if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag)
65 && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010066 JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following "
67 "non-hole frag in the same page. Tell dwmw2.\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010068 ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
69 bitched = 1;
70 }
71 }
72 }
73
74 if (bitched) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010075 JFFS2_ERROR("fragtree is corrupted.\n");
76 __jffs2_dbg_dump_fragtree_nolock(f);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010077 BUG();
78 }
79}
80
81/*
82 * Check if the flash contains all 0xFF before we start writing.
83 */
84void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010085__jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
86 uint32_t ofs, int len)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010087{
88 size_t retlen;
89 int ret, i;
90 unsigned char *buf;
91
92 buf = kmalloc(len, GFP_KERNEL);
93 if (!buf)
94 return;
95
96 ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
97 if (ret || (retlen != len)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010098 JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n",
99 len, ret, retlen);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100100 kfree(buf);
101 return;
102 }
103
104 ret = 0;
105 for (i = 0; i < len; i++)
106 if (buf[i] != 0xff)
107 ret = 1;
108
109 if (ret) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100110 JFFS2_ERROR("argh, about to write node to %#08x on flash, but there are data "
111 "already there. The first corrupted byte is at %#08x offset.\n", ofs, ofs + i);
112 __jffs2_dbg_dump_buffer(buf, len, ofs);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100113 kfree(buf);
114 BUG();
115 }
116
117 kfree(buf);
118}
119
120/*
121 * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
122 */
123void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100124__jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
125 struct jffs2_eraseblock *jeb)
126{
127 spin_lock(&c->erase_completion_lock);
128 __jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
129 spin_unlock(&c->erase_completion_lock);
130}
131
132void
133__jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
134 struct jffs2_eraseblock *jeb)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100135{
136 uint32_t my_used_size = 0;
137 uint32_t my_unchecked_size = 0;
138 uint32_t my_dirty_size = 0;
139 struct jffs2_raw_node_ref *ref2 = jeb->first_node;
140
141 while (ref2) {
142 uint32_t totlen = ref_totlen(c, jeb, ref2);
143
144 if (ref2->flash_offset < jeb->offset ||
145 ref2->flash_offset > jeb->offset + c->sector_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100146 JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100147 ref_offset(ref2), jeb->offset);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100148 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100149
150 }
151 if (ref_flags(ref2) == REF_UNCHECKED)
152 my_unchecked_size += totlen;
153 else if (!ref_obsolete(ref2))
154 my_used_size += totlen;
155 else
156 my_dirty_size += totlen;
157
158 if ((!ref2->next_phys) != (ref2 == jeb->last_node)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100159 JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), "
160 "last_node is at %#08x (mem %p).\n",
161 ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys,
162 ref_offset(jeb->last_node), jeb->last_node);
163 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100164 }
165 ref2 = ref2->next_phys;
166 }
167
168 if (my_used_size != jeb->used_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100169 JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
170 my_used_size, jeb->used_size);
171 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100172 }
173
174 if (my_unchecked_size != jeb->unchecked_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100175 JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
176 my_unchecked_size, jeb->unchecked_size);
177 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100178 }
179
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100180#if 0
181 /* This should work when we implement ref->__totlen elemination */
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100182 if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100183 JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100184 my_dirty_size, jeb->dirty_size + jeb->wasted_size);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100185 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100186 }
187
188 if (jeb->free_size == 0
189 && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100190 JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100191 my_used_size + my_unchecked_size + my_dirty_size,
192 c->sector_size);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100193 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100194 }
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100195#endif
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100196
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100197 return;
198
199error:
200 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
201 __jffs2_dbg_dump_jeb_nolock(jeb);
202 __jffs2_dbg_dump_block_lists_nolock(c);
203 BUG();
204
205}
206#endif /* JFFS2_DBG_PARANOIA_CHECKS */
207
208#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100209/*
210 * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
211 */
212void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100213__jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
214 struct jffs2_eraseblock *jeb)
215{
216 spin_lock(&c->erase_completion_lock);
217 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
218 spin_unlock(&c->erase_completion_lock);
219}
220
221void
222__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
223 struct jffs2_eraseblock *jeb)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100224{
225 struct jffs2_raw_node_ref *ref;
226 int i = 0;
227
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100228 JFFS2_DEBUG("Dump node_refs of the eraseblock %#08x\n", jeb->offset);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100229 if (!jeb->first_node) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100230 JFFS2_DEBUG("no nodes in the eraseblock %#08x\n", jeb->offset);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100231 return;
232 }
233
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100234 printk(JFFS2_DBG_LVL);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100235 for (ref = jeb->first_node; ; ref = ref->next_phys) {
236 printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
237 if (ref->next_phys)
238 printk("->");
239 else
240 break;
241 if (++i == 4) {
242 i = 0;
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100243 printk("\n" JFFS2_DBG_LVL);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100244 }
245 }
246 printk("\n");
247}
248
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100249/*
250 * Dump an eraseblock's space accounting.
251 */
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100252void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100253__jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100254{
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100255 spin_lock(&c->erase_completion_lock);
256 __jffs2_dbg_dump_jeb_nolock(jeb);
257 spin_unlock(&c->erase_completion_lock);
258}
259
260void
261__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
262{
263 if (!jeb)
264 return;
265
266 JFFS2_DEBUG("dump space accounting for the eraseblock at %#08x:\n",
267 jeb->offset);
268
269 printk(JFFS2_DBG_LVL "used_size: %#08x\n", jeb->used_size);
270 printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", jeb->dirty_size);
271 printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", jeb->wasted_size);
272 printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", jeb->unchecked_size);
273 printk(JFFS2_DBG_LVL "free_size: %#08x\n", jeb->free_size);
274}
275
276void
277__jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
278{
279 spin_lock(&c->erase_completion_lock);
280 __jffs2_dbg_dump_block_lists_nolock(c);
281 spin_unlock(&c->erase_completion_lock);
282}
283
284void
285__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
286{
287 JFFS2_DEBUG("dump JFFS2 blocks lists:\n");
288
289 printk(JFFS2_DBG_LVL "flash_size: %#08x\n", c->flash_size);
290 printk(JFFS2_DBG_LVL "used_size: %#08x\n", c->used_size);
291 printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", c->dirty_size);
292 printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", c->wasted_size);
293 printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", c->unchecked_size);
294 printk(JFFS2_DBG_LVL "free_size: %#08x\n", c->free_size);
295 printk(JFFS2_DBG_LVL "erasing_size: %#08x\n", c->erasing_size);
296 printk(JFFS2_DBG_LVL "bad_size: %#08x\n", c->bad_size);
297 printk(JFFS2_DBG_LVL "sector_size: %#08x\n", c->sector_size);
298 printk(JFFS2_DBG_LVL "jffs2_reserved_blocks size: %#08x\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100299 c->sector_size * c->resv_blocks_write);
300
301 if (c->nextblock)
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100302 printk(JFFS2_DBG_LVL "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
303 "unchecked %#08x, free %#08x)\n",
304 c->nextblock->offset, c->nextblock->used_size,
305 c->nextblock->dirty_size, c->nextblock->wasted_size,
306 c->nextblock->unchecked_size, c->nextblock->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100307 else
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100308 printk(JFFS2_DBG_LVL "nextblock: NULL\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100309
310 if (c->gcblock)
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100311 printk(JFFS2_DBG_LVL "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
312 "unchecked %#08x, free %#08x)\n",
313 c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
314 c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100315 else
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100316 printk(JFFS2_DBG_LVL "gcblock: NULL\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100317
318 if (list_empty(&c->clean_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100319 printk(JFFS2_DBG_LVL "clean_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100320 } else {
321 struct list_head *this;
322 int numblocks = 0;
323 uint32_t dirty = 0;
324
325 list_for_each(this, &c->clean_list) {
326 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
327 numblocks ++;
328 dirty += jeb->wasted_size;
329 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100330 printk(JFFS2_DBG_LVL "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
331 "unchecked %#08x, free %#08x)\n",
332 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
333 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100334 }
335 }
336
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100337 printk (JFFS2_DBG_LVL "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
338 numblocks, dirty, dirty / numblocks);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100339 }
340
341 if (list_empty(&c->very_dirty_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100342 printk(JFFS2_DBG_LVL "very_dirty_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100343 } else {
344 struct list_head *this;
345 int numblocks = 0;
346 uint32_t dirty = 0;
347
348 list_for_each(this, &c->very_dirty_list) {
349 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
350
351 numblocks ++;
352 dirty += jeb->dirty_size;
353 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100354 printk(JFFS2_DBG_LVL "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
355 "unchecked %#08x, free %#08x)\n",
356 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
357 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100358 }
359 }
360
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100361 printk (JFFS2_DBG_LVL "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
362 numblocks, dirty, dirty / numblocks);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100363 }
364
365 if (list_empty(&c->dirty_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100366 printk(JFFS2_DBG_LVL "dirty_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100367 } else {
368 struct list_head *this;
369 int numblocks = 0;
370 uint32_t dirty = 0;
371
372 list_for_each(this, &c->dirty_list) {
373 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
374
375 numblocks ++;
376 dirty += jeb->dirty_size;
377 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100378 printk(JFFS2_DBG_LVL "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
379 "unchecked %#08x, free %#08x)\n",
380 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
381 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100382 }
383 }
384
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100385 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 +0100386 numblocks, dirty, dirty / numblocks);
387 }
388
389 if (list_empty(&c->erasable_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100390 printk(JFFS2_DBG_LVL "erasable_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100391 } else {
392 struct list_head *this;
393
394 list_for_each(this, &c->erasable_list) {
395 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
396
397 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100398 printk(JFFS2_DBG_LVL "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
399 "unchecked %#08x, free %#08x)\n",
400 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
401 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100402 }
403 }
404 }
405
406 if (list_empty(&c->erasing_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100407 printk(JFFS2_DBG_LVL "erasing_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100408 } else {
409 struct list_head *this;
410
411 list_for_each(this, &c->erasing_list) {
412 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
413
414 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100415 printk(JFFS2_DBG_LVL "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
416 "unchecked %#08x, free %#08x)\n",
417 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
418 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100419 }
420 }
421 }
422
423 if (list_empty(&c->erase_pending_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100424 printk(JFFS2_DBG_LVL "erase_pending_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100425 } else {
426 struct list_head *this;
427
428 list_for_each(this, &c->erase_pending_list) {
429 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
430
431 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100432 printk(JFFS2_DBG_LVL "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
433 "unchecked %#08x, free %#08x)\n",
434 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
435 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100436 }
437 }
438 }
439
440 if (list_empty(&c->erasable_pending_wbuf_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100441 printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100442 } else {
443 struct list_head *this;
444
445 list_for_each(this, &c->erasable_pending_wbuf_list) {
446 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
447
448 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100449 printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, "
450 "wasted %#08x, unchecked %#08x, free %#08x)\n",
451 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
452 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100453 }
454 }
455 }
456
457 if (list_empty(&c->free_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100458 printk(JFFS2_DBG_LVL "free_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100459 } else {
460 struct list_head *this;
461
462 list_for_each(this, &c->free_list) {
463 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
464
465 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100466 printk(JFFS2_DBG_LVL "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
467 "unchecked %#08x, free %#08x)\n",
468 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
469 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100470 }
471 }
472 }
473
474 if (list_empty(&c->bad_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100475 printk(JFFS2_DBG_LVL "bad_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100476 } else {
477 struct list_head *this;
478
479 list_for_each(this, &c->bad_list) {
480 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
481
482 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100483 printk(JFFS2_DBG_LVL "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
484 "unchecked %#08x, free %#08x)\n",
485 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
486 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100487 }
488 }
489 }
490
491 if (list_empty(&c->bad_used_list)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100492 printk(JFFS2_DBG_LVL "bad_used_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100493 } else {
494 struct list_head *this;
495
496 list_for_each(this, &c->bad_used_list) {
497 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
498
499 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100500 printk(JFFS2_DBG_LVL "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
501 "unchecked %#08x, free %#08x)\n",
502 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
503 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100504 }
505 }
506 }
507}
508
509void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100510__jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
511{
512 down(&f->sem);
513 jffs2_dbg_dump_fragtree_nolock(f);
514 up(&f->sem);
515}
516
517void
518__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100519{
520 struct jffs2_node_frag *this = frag_first(&f->fragtree);
521 uint32_t lastofs = 0;
522 int buggy = 0;
523
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100524 JFFS2_DEBUG("dump fragtree of ino #%u\n", f->inocache->ino);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100525 while(this) {
526 if (this->node)
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100527 printk(JFFS2_DBG_LVL "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), "
528 "right (%p), parent (%p)\n",
529 this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
530 ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
531 frag_parent(this));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100532 else
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100533 printk(JFFS2_DBG_LVL "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
534 this->ofs, this->ofs+this->size, this, frag_left(this),
535 frag_right(this), frag_parent(this));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100536 if (this->ofs != lastofs)
537 buggy = 1;
538 lastofs = this->ofs + this->size;
539 this = frag_next(this);
540 }
541
542 if (f->metadata)
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100543 printk(JFFS2_DBG_LVL "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100544
545 if (buggy) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100546 JFFS2_ERROR("frag tree got a hole in it.\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100547 BUG();
548 }
549}
550
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100551#define JFFS2_BUFDUMP_BYTES_PER_LINE 32
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100552void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100553__jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100554{
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100555 int skip;
556 int i;
557
558 JFFS2_DEBUG("dump from offset %#08x to offset %#08x (%x bytes).\n",
559 offs, offs + len, len);
560 i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
561 offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
562
563 if (skip != 0)
564 printk(JFFS2_DBG_LVL "%#08x: ", offs);
565
566 while (skip--)
567 printk(" ");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100568
569 while (i < len) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100570 if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
571 if (i != 0)
572 printk("\n");
573 offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
574 printk(JFFS2_DBG_LVL "%0#8x: ", offs);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100575 }
576
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100577 printk("%02x ", buf[i]);
578
579 i += 1;
580 }
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100581
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100582 printk("\n");
583}
584
585/*
586 * Dump a JFFS2 node.
587 */
588void
589__jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
590{
591 union jffs2_node_union node;
592 int len = sizeof(union jffs2_node_union);
593 size_t retlen;
594 uint32_t crc;
595 int ret;
596
597 JFFS2_DEBUG("dump node at offset %#08x.\n", ofs);
598
599 ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
600 if (ret || (retlen != len)) {
601 JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
602 len, ret, retlen);
603 return;
604 }
605
606 printk(JFFS2_DBG_LVL "magic:\t%#04x\n",
607 je16_to_cpu(node.u.magic));
608 printk(JFFS2_DBG_LVL "nodetype:\t%#04x\n",
609 je16_to_cpu(node.u.nodetype));
610 printk(JFFS2_DBG_LVL "totlen:\t%#08x\n",
611 je32_to_cpu(node.u.totlen));
612 printk(JFFS2_DBG_LVL "hdr_crc:\t%#08x\n",
613 je32_to_cpu(node.u.hdr_crc));
614
615 crc = crc32(0, &node.u, sizeof(node.u) - 4);
616 if (crc != je32_to_cpu(node.u.hdr_crc)) {
617 JFFS2_ERROR("wrong common header CRC.\n");
618 return;
619 }
620
621 if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
622 je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
623 {
624 JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
625 je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
626 return;
627 }
628
629 switch(je16_to_cpu(node.u.nodetype)) {
630
631 case JFFS2_NODETYPE_INODE:
632
633 printk(JFFS2_DBG_LVL "the node is inode node\n");
634 printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
635 je32_to_cpu(node.i.ino));
636 printk(JFFS2_DBG_LVL "version:\t%#08x\n",
637 je32_to_cpu(node.i.version));
638 printk(JFFS2_DBG_LVL "mode:\t%#08x\n",
639 node.i.mode.m);
640 printk(JFFS2_DBG_LVL "uid:\t%#04x\n",
641 je16_to_cpu(node.i.uid));
642 printk(JFFS2_DBG_LVL "gid:\t%#04x\n",
643 je16_to_cpu(node.i.gid));
644 printk(JFFS2_DBG_LVL "isize:\t%#08x\n",
645 je32_to_cpu(node.i.isize));
646 printk(JFFS2_DBG_LVL "atime:\t%#08x\n",
647 je32_to_cpu(node.i.atime));
648 printk(JFFS2_DBG_LVL "mtime:\t%#08x\n",
649 je32_to_cpu(node.i.mtime));
650 printk(JFFS2_DBG_LVL "ctime:\t%#08x\n",
651 je32_to_cpu(node.i.ctime));
652 printk(JFFS2_DBG_LVL "offset:\t%#08x\n",
653 je32_to_cpu(node.i.offset));
654 printk(JFFS2_DBG_LVL "csize:\t%#08x\n",
655 je32_to_cpu(node.i.csize));
656 printk(JFFS2_DBG_LVL "dsize:\t%#08x\n",
657 je32_to_cpu(node.i.dsize));
658 printk(JFFS2_DBG_LVL "compr:\t%#02x\n",
659 node.i.compr);
660 printk(JFFS2_DBG_LVL "usercompr:\t%#02x\n",
661 node.i.usercompr);
662 printk(JFFS2_DBG_LVL "flags:\t%#04x\n",
663 je16_to_cpu(node.i.flags));
664 printk(JFFS2_DBG_LVL "data_crc:\t%#08x\n",
665 je32_to_cpu(node.i.data_crc));
666 printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
667 je32_to_cpu(node.i.node_crc));
668 crc = crc32(0, &node.i, sizeof(node.i) - 8);
669 if (crc != je32_to_cpu(node.i.node_crc)) {
670 JFFS2_ERROR("wrong node header CRC.\n");
671 return;
672 }
673 break;
674
675 case JFFS2_NODETYPE_DIRENT:
676
677 printk(JFFS2_DBG_LVL "the node is dirent node\n");
678 printk(JFFS2_DBG_LVL "pino:\t%#08x\n",
679 je32_to_cpu(node.d.pino));
680 printk(JFFS2_DBG_LVL "version:\t%#08x\n",
681 je32_to_cpu(node.d.version));
682 printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
683 je32_to_cpu(node.d.ino));
684 printk(JFFS2_DBG_LVL "mctime:\t%#08x\n",
685 je32_to_cpu(node.d.mctime));
686 printk(JFFS2_DBG_LVL "nsize:\t%#02x\n",
687 node.d.nsize);
688 printk(JFFS2_DBG_LVL "type:\t%#02x\n",
689 node.d.type);
690 printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
691 je32_to_cpu(node.d.node_crc));
692 printk(JFFS2_DBG_LVL "name_crc:\t%#08x\n",
693 je32_to_cpu(node.d.name_crc));
694
695 node.d.name[node.d.nsize] = '\0';
696 printk(JFFS2_DBG_LVL "name:\t\"%s\"\n", node.d.name);
697
698 crc = crc32(0, &node.d, sizeof(node.d) - 8);
699 if (crc != je32_to_cpu(node.d.node_crc)) {
700 JFFS2_ERROR("wrong node header CRC.\n");
701 return;
702 }
703 break;
704
705 default:
706 printk(JFFS2_DBG_LVL "node type is unknown\n");
707 break;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100708 }
709}
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100710#endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */