1 /*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc.
5 *
6 * Created by David Woodhouse <[email protected]>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 * $Id: debug.c,v 1.1 2005/07/30 15:30:42 asl Exp $
11 *
12 */
13 #include <linux/kernel.h>
14 #include <linux/types.h>
15 #include <linux/pagemap.h>
16 #include <linux/crc32.h>
17 #include <linux/jffs2.h>
18 #include <linux/slab.h>
19 #include "nodelist.h"
20 #include "debug.h"
21
22 #ifdef JFFS2_DBG_PARANOIA_CHECKS
23 /*
24 * Check the fragtree.
25 */
26 void
__jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info * f)27 __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
28 {
29 down(&f->sem);
30 __jffs2_dbg_fragtree_paranoia_check_nolock(f);
31 up(&f->sem);
32 }
33
34 void
__jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info * f)35 __jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f)
36 {
37 struct jffs2_node_frag *frag;
38 int bitched = 0;
39
40 for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
41 struct jffs2_full_dnode *fn = frag->node;
42
43 if (!fn || !fn->raw)
44 continue;
45
46 if (ref_flags(fn->raw) == REF_PRISTINE) {
47 if (fn->frags > 1) {
48 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n",
49 ref_offset(fn->raw), fn->frags);
50 bitched = 1;
51 }
52
53 /* A hole node which isn't multi-page should be garbage-collected
54 and merged anyway, so we just check for the frag size here,
55 rather than mucking around with actually reading the node
56 and checking the compression type, which is the real way
57 to tell a hole node. */
58 if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag)
59 && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
60 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag "
61 "in the same page. Tell dwmw2.\n", ref_offset(fn->raw));
62 bitched = 1;
63 }
64
65 if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag)
66 && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
67 JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following "
68 "non-hole frag in the same page. Tell dwmw2.\n",
69 ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
70 bitched = 1;
71 }
72 }
73 }
74
75 if (bitched) {
76 JFFS2_ERROR("fragtree is corrupted.\n");
77 __jffs2_dbg_dump_fragtree_nolock(f);
78 BUG();
79 }
80 }
81
82 /*
83 * Check if the flash contains all 0xFF before we start writing.
84 */
85 void
__jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info * c,uint32_t ofs,int len)86 __jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
87 uint32_t ofs, int len)
88 {
89 size_t retlen;
90 int ret, i;
91 unsigned char *buf;
92
93 buf = kmalloc(len, GFP_KERNEL);
94 if (!buf)
95 return;
96
97 ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
98 if (ret || (retlen != len)) {
99 JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n",
100 len, ret, retlen);
101 kfree(buf);
102 return;
103 }
104
105 ret = 0;
106 for (i = 0; i < len; i++)
107 if (buf[i] != 0xff)
108 ret = 1;
109
110 if (ret) {
111 JFFS2_ERROR("argh, about to write node to %#08x on flash, but there are data "
112 "already there. The first corrupted byte is at %#08x offset.\n", ofs, ofs + i);
113 __jffs2_dbg_dump_buffer(buf, len, ofs);
114 kfree(buf);
115 BUG();
116 }
117
118 kfree(buf);
119 }
120
121 /*
122 * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
123 */
124 void
__jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)125 __jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
126 struct jffs2_eraseblock *jeb)
127 {
128 spin_lock(&c->erase_completion_lock);
129 __jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
130 spin_unlock(&c->erase_completion_lock);
131 }
132
133 void
__jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)134 __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
135 struct jffs2_eraseblock *jeb)
136 {
137 uint32_t my_used_size = 0;
138 uint32_t my_unchecked_size = 0;
139 uint32_t my_dirty_size = 0;
140 struct jffs2_raw_node_ref *ref2 = jeb->first_node;
141
142 while (ref2) {
143 uint32_t totlen = ref_totlen(c, jeb, ref2);
144
145 if (ref2->flash_offset < jeb->offset ||
146 ref2->flash_offset > jeb->offset + c->sector_size) {
147 JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
148 ref_offset(ref2), jeb->offset);
149 goto error;
150
151 }
152 if (ref_flags(ref2) == REF_UNCHECKED)
153 my_unchecked_size += totlen;
154 else if (!ref_obsolete(ref2))
155 my_used_size += totlen;
156 else
157 my_dirty_size += totlen;
158
159 if ((!ref2->next_phys) != (ref2 == jeb->last_node)) {
160 JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), "
161 "last_node is at %#08x (mem %p).\n",
162 ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys,
163 ref_offset(jeb->last_node), jeb->last_node);
164 goto error;
165 }
166 ref2 = ref2->next_phys;
167 }
168
169 if (my_used_size != jeb->used_size) {
170 JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
171 my_used_size, jeb->used_size);
172 goto error;
173 }
174
175 if (my_unchecked_size != jeb->unchecked_size) {
176 JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
177 my_unchecked_size, jeb->unchecked_size);
178 goto error;
179 }
180
181 #if 0
182 /* This should work when we implement ref->__totlen elemination */
183 if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
184 JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
185 my_dirty_size, jeb->dirty_size + jeb->wasted_size);
186 goto error;
187 }
188
189 if (jeb->free_size == 0
190 && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
191 JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
192 my_used_size + my_unchecked_size + my_dirty_size,
193 c->sector_size);
194 goto error;
195 }
196 #endif
197
198 return;
199
200 error:
201 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
202 __jffs2_dbg_dump_jeb_nolock(jeb);
203 __jffs2_dbg_dump_block_lists_nolock(c);
204 BUG();
205
206 }
207 #endif /* JFFS2_DBG_PARANOIA_CHECKS */
208
209 #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
210 /*
211 * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
212 */
213 void
__jffs2_dbg_dump_node_refs(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)214 __jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
215 struct jffs2_eraseblock *jeb)
216 {
217 spin_lock(&c->erase_completion_lock);
218 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
219 spin_unlock(&c->erase_completion_lock);
220 }
221
222 void
__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)223 __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
224 struct jffs2_eraseblock *jeb)
225 {
226 struct jffs2_raw_node_ref *ref;
227 int i = 0;
228
229 JFFS2_DEBUG("Dump node_refs of the eraseblock %#08x\n", jeb->offset);
230 if (!jeb->first_node) {
231 JFFS2_DEBUG("no nodes in the eraseblock %#08x\n", jeb->offset);
232 return;
233 }
234
235 printk(JFFS2_DBG_LVL);
236 for (ref = jeb->first_node; ; ref = ref->next_phys) {
237 printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
238 if (ref->next_phys)
239 printk("->");
240 else
241 break;
242 if (++i == 4) {
243 i = 0;
244 printk("\n" JFFS2_DBG_LVL);
245 }
246 }
247 printk("\n");
248 }
249
250 /*
251 * Dump an eraseblock's space accounting.
252 */
253 void
__jffs2_dbg_dump_jeb(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)254 __jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
255 {
256 spin_lock(&c->erase_completion_lock);
257 __jffs2_dbg_dump_jeb_nolock(jeb);
258 spin_unlock(&c->erase_completion_lock);
259 }
260
261 void
__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock * jeb)262 __jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
263 {
264 if (!jeb)
265 return;
266
267 JFFS2_DEBUG("dump space accounting for the eraseblock at %#08x:\n",
268 jeb->offset);
269
270 printk(JFFS2_DBG_LVL "used_size: %#08x\n", jeb->used_size);
271 printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", jeb->dirty_size);
272 printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", jeb->wasted_size);
273 printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", jeb->unchecked_size);
274 printk(JFFS2_DBG_LVL "free_size: %#08x\n", jeb->free_size);
275 }
276
277 void
__jffs2_dbg_dump_block_lists(struct jffs2_sb_info * c)278 __jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
279 {
280 spin_lock(&c->erase_completion_lock);
281 __jffs2_dbg_dump_block_lists_nolock(c);
282 spin_unlock(&c->erase_completion_lock);
283 }
284
285 void
__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info * c)286 __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
287 {
288 JFFS2_DEBUG("dump JFFS2 blocks lists:\n");
289
290 printk(JFFS2_DBG_LVL "flash_size: %#08x\n", c->flash_size);
291 printk(JFFS2_DBG_LVL "used_size: %#08x\n", c->used_size);
292 printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", c->dirty_size);
293 printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", c->wasted_size);
294 printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", c->unchecked_size);
295 printk(JFFS2_DBG_LVL "free_size: %#08x\n", c->free_size);
296 printk(JFFS2_DBG_LVL "erasing_size: %#08x\n", c->erasing_size);
297 printk(JFFS2_DBG_LVL "bad_size: %#08x\n", c->bad_size);
298 printk(JFFS2_DBG_LVL "sector_size: %#08x\n", c->sector_size);
299 printk(JFFS2_DBG_LVL "jffs2_reserved_blocks size: %#08x\n",
300 c->sector_size * c->resv_blocks_write);
301
302 if (c->nextblock)
303 printk(JFFS2_DBG_LVL "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
304 "unchecked %#08x, free %#08x)\n",
305 c->nextblock->offset, c->nextblock->used_size,
306 c->nextblock->dirty_size, c->nextblock->wasted_size,
307 c->nextblock->unchecked_size, c->nextblock->free_size);
308 else
309 printk(JFFS2_DBG_LVL "nextblock: NULL\n");
310
311 if (c->gcblock)
312 printk(JFFS2_DBG_LVL "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
313 "unchecked %#08x, free %#08x)\n",
314 c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
315 c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
316 else
317 printk(JFFS2_DBG_LVL "gcblock: NULL\n");
318
319 if (list_empty(&c->clean_list)) {
320 printk(JFFS2_DBG_LVL "clean_list: empty\n");
321 } else {
322 struct list_head *this;
323 int numblocks = 0;
324 uint32_t dirty = 0;
325
326 list_for_each(this, &c->clean_list) {
327 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
328 numblocks ++;
329 dirty += jeb->wasted_size;
330 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
331 printk(JFFS2_DBG_LVL "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
332 "unchecked %#08x, free %#08x)\n",
333 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
334 jeb->unchecked_size, jeb->free_size);
335 }
336 }
337
338 printk (JFFS2_DBG_LVL "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
339 numblocks, dirty, dirty / numblocks);
340 }
341
342 if (list_empty(&c->very_dirty_list)) {
343 printk(JFFS2_DBG_LVL "very_dirty_list: empty\n");
344 } else {
345 struct list_head *this;
346 int numblocks = 0;
347 uint32_t dirty = 0;
348
349 list_for_each(this, &c->very_dirty_list) {
350 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
351
352 numblocks ++;
353 dirty += jeb->dirty_size;
354 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
355 printk(JFFS2_DBG_LVL "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
356 "unchecked %#08x, free %#08x)\n",
357 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
358 jeb->unchecked_size, jeb->free_size);
359 }
360 }
361
362 printk (JFFS2_DBG_LVL "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
363 numblocks, dirty, dirty / numblocks);
364 }
365
366 if (list_empty(&c->dirty_list)) {
367 printk(JFFS2_DBG_LVL "dirty_list: empty\n");
368 } else {
369 struct list_head *this;
370 int numblocks = 0;
371 uint32_t dirty = 0;
372
373 list_for_each(this, &c->dirty_list) {
374 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
375
376 numblocks ++;
377 dirty += jeb->dirty_size;
378 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
379 printk(JFFS2_DBG_LVL "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
380 "unchecked %#08x, free %#08x)\n",
381 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
382 jeb->unchecked_size, jeb->free_size);
383 }
384 }
385
386 printk (JFFS2_DBG_LVL "contains %d blocks with total dirty size %u, average dirty size: %u\n",
387 numblocks, dirty, dirty / numblocks);
388 }
389
390 if (list_empty(&c->erasable_list)) {
391 printk(JFFS2_DBG_LVL "erasable_list: empty\n");
392 } else {
393 struct list_head *this;
394
395 list_for_each(this, &c->erasable_list) {
396 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
397
398 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
399 printk(JFFS2_DBG_LVL "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
400 "unchecked %#08x, free %#08x)\n",
401 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
402 jeb->unchecked_size, jeb->free_size);
403 }
404 }
405 }
406
407 if (list_empty(&c->erasing_list)) {
408 printk(JFFS2_DBG_LVL "erasing_list: empty\n");
409 } else {
410 struct list_head *this;
411
412 list_for_each(this, &c->erasing_list) {
413 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
414
415 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
416 printk(JFFS2_DBG_LVL "erasing_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);
420 }
421 }
422 }
423
424 if (list_empty(&c->erase_pending_list)) {
425 printk(JFFS2_DBG_LVL "erase_pending_list: empty\n");
426 } else {
427 struct list_head *this;
428
429 list_for_each(this, &c->erase_pending_list) {
430 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
431
432 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
433 printk(JFFS2_DBG_LVL "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
434 "unchecked %#08x, free %#08x)\n",
435 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
436 jeb->unchecked_size, jeb->free_size);
437 }
438 }
439 }
440
441 if (list_empty(&c->erasable_pending_wbuf_list)) {
442 printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: empty\n");
443 } else {
444 struct list_head *this;
445
446 list_for_each(this, &c->erasable_pending_wbuf_list) {
447 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
448
449 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
450 printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, "
451 "wasted %#08x, unchecked %#08x, free %#08x)\n",
452 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
453 jeb->unchecked_size, jeb->free_size);
454 }
455 }
456 }
457
458 if (list_empty(&c->free_list)) {
459 printk(JFFS2_DBG_LVL "free_list: empty\n");
460 } else {
461 struct list_head *this;
462
463 list_for_each(this, &c->free_list) {
464 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
465
466 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
467 printk(JFFS2_DBG_LVL "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
468 "unchecked %#08x, free %#08x)\n",
469 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
470 jeb->unchecked_size, jeb->free_size);
471 }
472 }
473 }
474
475 if (list_empty(&c->bad_list)) {
476 printk(JFFS2_DBG_LVL "bad_list: empty\n");
477 } else {
478 struct list_head *this;
479
480 list_for_each(this, &c->bad_list) {
481 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
482
483 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
484 printk(JFFS2_DBG_LVL "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
485 "unchecked %#08x, free %#08x)\n",
486 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
487 jeb->unchecked_size, jeb->free_size);
488 }
489 }
490 }
491
492 if (list_empty(&c->bad_used_list)) {
493 printk(JFFS2_DBG_LVL "bad_used_list: empty\n");
494 } else {
495 struct list_head *this;
496
497 list_for_each(this, &c->bad_used_list) {
498 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
499
500 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
501 printk(JFFS2_DBG_LVL "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
502 "unchecked %#08x, free %#08x)\n",
503 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
504 jeb->unchecked_size, jeb->free_size);
505 }
506 }
507 }
508 }
509
510 void
__jffs2_dbg_dump_fragtree(struct jffs2_inode_info * f)511 __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
512 {
513 down(&f->sem);
514 jffs2_dbg_dump_fragtree_nolock(f);
515 up(&f->sem);
516 }
517
518 void
__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info * f)519 __jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
520 {
521 struct jffs2_node_frag *this = frag_first(&f->fragtree);
522 uint32_t lastofs = 0;
523 int buggy = 0;
524
525 JFFS2_DEBUG("dump fragtree of ino #%u\n", f->inocache->ino);
526 while(this) {
527 if (this->node)
528 printk(JFFS2_DBG_LVL "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), "
529 "right (%p), parent (%p)\n",
530 this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
531 ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
532 frag_parent(this));
533 else
534 printk(JFFS2_DBG_LVL "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
535 this->ofs, this->ofs+this->size, this, frag_left(this),
536 frag_right(this), frag_parent(this));
537 if (this->ofs != lastofs)
538 buggy = 1;
539 lastofs = this->ofs + this->size;
540 this = frag_next(this);
541 }
542
543 if (f->metadata)
544 printk(JFFS2_DBG_LVL "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
545
546 if (buggy) {
547 JFFS2_ERROR("frag tree got a hole in it.\n");
548 BUG();
549 }
550 }
551
552 #define JFFS2_BUFDUMP_BYTES_PER_LINE 32
553 void
__jffs2_dbg_dump_buffer(unsigned char * buf,int len,uint32_t offs)554 __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
555 {
556 int skip;
557 int i;
558
559 JFFS2_DEBUG("dump from offset %#08x to offset %#08x (%x bytes).\n",
560 offs, offs + len, len);
561 i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
562 offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
563
564 if (skip != 0)
565 printk(JFFS2_DBG_LVL "%#08x: ", offs);
566
567 while (skip--)
568 printk(" ");
569
570 while (i < len) {
571 if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
572 if (i != 0)
573 printk("\n");
574 offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
575 printk(JFFS2_DBG_LVL "%0#8x: ", offs);
576 }
577
578 printk("%02x ", buf[i]);
579
580 i += 1;
581 }
582
583 printk("\n");
584 }
585
586 /*
587 * Dump a JFFS2 node.
588 */
589 void
__jffs2_dbg_dump_node(struct jffs2_sb_info * c,uint32_t ofs)590 __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
591 {
592 union jffs2_node_union node;
593 int len = sizeof(union jffs2_node_union);
594 size_t retlen;
595 uint32_t crc;
596 int ret;
597
598 JFFS2_DEBUG("dump node at offset %#08x.\n", ofs);
599
600 ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
601 if (ret || (retlen != len)) {
602 JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
603 len, ret, retlen);
604 return;
605 }
606
607 printk(JFFS2_DBG_LVL "magic:\t%#04x\n",
608 je16_to_cpu(node.u.magic));
609 printk(JFFS2_DBG_LVL "nodetype:\t%#04x\n",
610 je16_to_cpu(node.u.nodetype));
611 printk(JFFS2_DBG_LVL "totlen:\t%#08x\n",
612 je32_to_cpu(node.u.totlen));
613 printk(JFFS2_DBG_LVL "hdr_crc:\t%#08x\n",
614 je32_to_cpu(node.u.hdr_crc));
615
616 crc = crc32(0, &node.u, sizeof(node.u) - 4);
617 if (crc != je32_to_cpu(node.u.hdr_crc)) {
618 JFFS2_ERROR("wrong common header CRC.\n");
619 return;
620 }
621
622 if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
623 je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
624 {
625 JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
626 je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
627 return;
628 }
629
630 switch(je16_to_cpu(node.u.nodetype)) {
631
632 case JFFS2_NODETYPE_INODE:
633
634 printk(JFFS2_DBG_LVL "the node is inode node\n");
635 printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
636 je32_to_cpu(node.i.ino));
637 printk(JFFS2_DBG_LVL "version:\t%#08x\n",
638 je32_to_cpu(node.i.version));
639 printk(JFFS2_DBG_LVL "mode:\t%#08x\n",
640 node.i.mode.m);
641 printk(JFFS2_DBG_LVL "uid:\t%#04x\n",
642 je16_to_cpu(node.i.uid));
643 printk(JFFS2_DBG_LVL "gid:\t%#04x\n",
644 je16_to_cpu(node.i.gid));
645 printk(JFFS2_DBG_LVL "isize:\t%#08x\n",
646 je32_to_cpu(node.i.isize));
647 printk(JFFS2_DBG_LVL "atime:\t%#08x\n",
648 je32_to_cpu(node.i.atime));
649 printk(JFFS2_DBG_LVL "mtime:\t%#08x\n",
650 je32_to_cpu(node.i.mtime));
651 printk(JFFS2_DBG_LVL "ctime:\t%#08x\n",
652 je32_to_cpu(node.i.ctime));
653 printk(JFFS2_DBG_LVL "offset:\t%#08x\n",
654 je32_to_cpu(node.i.offset));
655 printk(JFFS2_DBG_LVL "csize:\t%#08x\n",
656 je32_to_cpu(node.i.csize));
657 printk(JFFS2_DBG_LVL "dsize:\t%#08x\n",
658 je32_to_cpu(node.i.dsize));
659 printk(JFFS2_DBG_LVL "compr:\t%#02x\n",
660 node.i.compr);
661 printk(JFFS2_DBG_LVL "usercompr:\t%#02x\n",
662 node.i.usercompr);
663 printk(JFFS2_DBG_LVL "flags:\t%#04x\n",
664 je16_to_cpu(node.i.flags));
665 printk(JFFS2_DBG_LVL "data_crc:\t%#08x\n",
666 je32_to_cpu(node.i.data_crc));
667 printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
668 je32_to_cpu(node.i.node_crc));
669 crc = crc32(0, &node.i, sizeof(node.i) - 8);
670 if (crc != je32_to_cpu(node.i.node_crc)) {
671 JFFS2_ERROR("wrong node header CRC.\n");
672 return;
673 }
674 break;
675
676 case JFFS2_NODETYPE_DIRENT:
677
678 printk(JFFS2_DBG_LVL "the node is dirent node\n");
679 printk(JFFS2_DBG_LVL "pino:\t%#08x\n",
680 je32_to_cpu(node.d.pino));
681 printk(JFFS2_DBG_LVL "version:\t%#08x\n",
682 je32_to_cpu(node.d.version));
683 printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
684 je32_to_cpu(node.d.ino));
685 printk(JFFS2_DBG_LVL "mctime:\t%#08x\n",
686 je32_to_cpu(node.d.mctime));
687 printk(JFFS2_DBG_LVL "nsize:\t%#02x\n",
688 node.d.nsize);
689 printk(JFFS2_DBG_LVL "type:\t%#02x\n",
690 node.d.type);
691 printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
692 je32_to_cpu(node.d.node_crc));
693 printk(JFFS2_DBG_LVL "name_crc:\t%#08x\n",
694 je32_to_cpu(node.d.name_crc));
695
696 node.d.name[node.d.nsize] = '\0';
697 printk(JFFS2_DBG_LVL "name:\t\"%s\"\n", node.d.name);
698
699 crc = crc32(0, &node.d, sizeof(node.d) - 8);
700 if (crc != je32_to_cpu(node.d.node_crc)) {
701 JFFS2_ERROR("wrong node header CRC.\n");
702 return;
703 }
704 break;
705
706 default:
707 printk(JFFS2_DBG_LVL "node type is unknown\n");
708 break;
709 }
710 }
711 #endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */
712