blob: 6cac7d6aad696de8c46f67f417af1f4992a025ff [file] [log] [blame]
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +01001/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
David Woodhousec00c3102007-04-25 14:16:47 +01004 * Copyright © 2001-2007 Red Hat, Inc.
David Woodhouse6088c052010-08-08 14:15:22 +01005 * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +01006 *
7 * Created by David Woodhouse <dwmw2@infradead.org>
8 *
9 * For licensing information, see the file 'LICENCE' in this directory.
10 *
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010011 */
David Woodhousec00c3102007-04-25 14:16:47 +010012
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010013#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. Bityutskiy733802d2005-09-22 12:25:00 +010018#include <linux/mtd/mtd.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090019#include <linux/slab.h>
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010020#include "nodelist.h"
21#include "debug.h"
22
Artem B. Bityutskiy45ca1b52005-08-05 12:43:47 +010023#ifdef JFFS2_DBG_SANITY_CHECKS
24
25void
26__jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info *c,
27 struct jffs2_eraseblock *jeb)
28{
29 if (unlikely(jeb && jeb->used_size + jeb->dirty_size +
30 jeb->free_size + jeb->wasted_size +
31 jeb->unchecked_size != c->sector_size)) {
32 JFFS2_ERROR("eeep, space accounting for block at 0x%08x is screwed.\n", jeb->offset);
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +010033 JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked %#08x != total %#08x.\n",
34 jeb->free_size, jeb->dirty_size, jeb->used_size,
Artem B. Bityutskiy45ca1b52005-08-05 12:43:47 +010035 jeb->wasted_size, jeb->unchecked_size, c->sector_size);
36 BUG();
37 }
38
39 if (unlikely(c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size
40 + c->wasted_size + c->unchecked_size != c->flash_size)) {
41 JFFS2_ERROR("eeep, space accounting superblock info is screwed.\n");
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +010042 JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + wasted %#08x + unchecked %#08x != total %#08x.\n",
Artem B. Bityutskiy45ca1b52005-08-05 12:43:47 +010043 c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size,
44 c->wasted_size, c->unchecked_size, c->flash_size);
45 BUG();
46 }
47}
48
49void
50__jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c,
51 struct jffs2_eraseblock *jeb)
52{
53 spin_lock(&c->erase_completion_lock);
54 jffs2_dbg_acct_sanity_check_nolock(c, jeb);
55 spin_unlock(&c->erase_completion_lock);
56}
57
58#endif /* JFFS2_DBG_SANITY_CHECKS */
59
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010060#ifdef JFFS2_DBG_PARANOIA_CHECKS
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010061/*
62 * Check the fragtree.
63 */
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010064void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010065__jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
66{
David Woodhouseced22072008-04-22 15:13:40 +010067 mutex_lock(&f->sem);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010068 __jffs2_dbg_fragtree_paranoia_check_nolock(f);
David Woodhouseced22072008-04-22 15:13:40 +010069 mutex_unlock(&f->sem);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010070}
Thomas Gleixner182ec4e2005-11-07 11:16:07 +000071
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010072void
73__jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010074{
75 struct jffs2_node_frag *frag;
76 int bitched = 0;
77
78 for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
79 struct jffs2_full_dnode *fn = frag->node;
80
81 if (!fn || !fn->raw)
82 continue;
83
84 if (ref_flags(fn->raw) == REF_PRISTINE) {
85 if (fn->frags > 1) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +010086 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n",
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +010087 ref_offset(fn->raw), fn->frags);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010088 bitched = 1;
89 }
90
91 /* A hole node which isn't multi-page should be garbage-collected
92 and merged anyway, so we just check for the frag size here,
93 rather than mucking around with actually reading the node
94 and checking the compression type, which is the real way
95 to tell a hole node. */
96 if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag)
97 && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +010098 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag in the same page. Tell dwmw2.\n",
99 ref_offset(fn->raw));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100100 bitched = 1;
101 }
102
103 if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag)
104 && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100105 JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following non-hole frag in the same page. Tell dwmw2.\n",
106 ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100107 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. Bityutskiy81e39cf2005-09-14 17:57:35 +0100148 JFFS2_ERROR("argh, about to write node to %#08x on flash, but there are data already there. The first corrupted byte is at %#08x offset.\n",
149 ofs, ofs + i);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100150 __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
David Woodhouse85a62db2008-04-23 01:17:51 +0100158void __jffs2_dbg_superblock_counts(struct jffs2_sb_info *c)
159{
160 struct jffs2_eraseblock *jeb;
161 uint32_t free = 0, dirty = 0, used = 0, wasted = 0,
162 erasing = 0, bad = 0, unchecked = 0;
163 int nr_counted = 0;
164 int dump = 0;
165
166 if (c->gcblock) {
167 nr_counted++;
168 free += c->gcblock->free_size;
169 dirty += c->gcblock->dirty_size;
170 used += c->gcblock->used_size;
171 wasted += c->gcblock->wasted_size;
172 unchecked += c->gcblock->unchecked_size;
173 }
174 if (c->nextblock) {
175 nr_counted++;
176 free += c->nextblock->free_size;
177 dirty += c->nextblock->dirty_size;
178 used += c->nextblock->used_size;
179 wasted += c->nextblock->wasted_size;
180 unchecked += c->nextblock->unchecked_size;
181 }
182 list_for_each_entry(jeb, &c->clean_list, list) {
183 nr_counted++;
184 free += jeb->free_size;
185 dirty += jeb->dirty_size;
186 used += jeb->used_size;
187 wasted += jeb->wasted_size;
188 unchecked += jeb->unchecked_size;
189 }
190 list_for_each_entry(jeb, &c->very_dirty_list, list) {
191 nr_counted++;
192 free += jeb->free_size;
193 dirty += jeb->dirty_size;
194 used += jeb->used_size;
195 wasted += jeb->wasted_size;
196 unchecked += jeb->unchecked_size;
197 }
198 list_for_each_entry(jeb, &c->dirty_list, list) {
199 nr_counted++;
200 free += jeb->free_size;
201 dirty += jeb->dirty_size;
202 used += jeb->used_size;
203 wasted += jeb->wasted_size;
204 unchecked += jeb->unchecked_size;
205 }
206 list_for_each_entry(jeb, &c->erasable_list, list) {
207 nr_counted++;
208 free += jeb->free_size;
209 dirty += jeb->dirty_size;
210 used += jeb->used_size;
211 wasted += jeb->wasted_size;
212 unchecked += jeb->unchecked_size;
213 }
214 list_for_each_entry(jeb, &c->erasable_pending_wbuf_list, list) {
215 nr_counted++;
216 free += jeb->free_size;
217 dirty += jeb->dirty_size;
218 used += jeb->used_size;
219 wasted += jeb->wasted_size;
220 unchecked += jeb->unchecked_size;
221 }
222 list_for_each_entry(jeb, &c->erase_pending_list, list) {
223 nr_counted++;
224 free += jeb->free_size;
225 dirty += jeb->dirty_size;
226 used += jeb->used_size;
227 wasted += jeb->wasted_size;
228 unchecked += jeb->unchecked_size;
229 }
230 list_for_each_entry(jeb, &c->free_list, list) {
231 nr_counted++;
232 free += jeb->free_size;
233 dirty += jeb->dirty_size;
234 used += jeb->used_size;
235 wasted += jeb->wasted_size;
236 unchecked += jeb->unchecked_size;
237 }
238 list_for_each_entry(jeb, &c->bad_used_list, list) {
239 nr_counted++;
240 free += jeb->free_size;
241 dirty += jeb->dirty_size;
242 used += jeb->used_size;
243 wasted += jeb->wasted_size;
244 unchecked += jeb->unchecked_size;
245 }
246
247 list_for_each_entry(jeb, &c->erasing_list, list) {
248 nr_counted++;
249 erasing += c->sector_size;
250 }
David Woodhousee2bc3222008-04-23 14:15:24 +0100251 list_for_each_entry(jeb, &c->erase_checking_list, list) {
252 nr_counted++;
253 erasing += c->sector_size;
254 }
David Woodhouse85a62db2008-04-23 01:17:51 +0100255 list_for_each_entry(jeb, &c->erase_complete_list, list) {
256 nr_counted++;
257 erasing += c->sector_size;
258 }
259 list_for_each_entry(jeb, &c->bad_list, list) {
260 nr_counted++;
261 bad += c->sector_size;
262 }
263
Joe Perchesda320f02012-02-15 15:56:44 -0800264#define check(sz) \
265do { \
266 if (sz != c->sz##_size) { \
267 pr_warn("%s_size mismatch counted 0x%x, c->%s_size 0x%x\n", \
268 #sz, #sz, sz, c->sz##_size); \
269 dump = 1; \
270 } \
271} while (0)
272
David Woodhouse85a62db2008-04-23 01:17:51 +0100273 check(free);
274 check(dirty);
275 check(used);
276 check(wasted);
277 check(unchecked);
278 check(bad);
279 check(erasing);
Joe Perchesda320f02012-02-15 15:56:44 -0800280
David Woodhouse85a62db2008-04-23 01:17:51 +0100281#undef check
282
283 if (nr_counted != c->nr_blocks) {
Joe Perchesda320f02012-02-15 15:56:44 -0800284 pr_warn("%s counted only 0x%x blocks of 0x%x. Where are the others?\n",
285 __func__, nr_counted, c->nr_blocks);
David Woodhouse85a62db2008-04-23 01:17:51 +0100286 dump = 1;
287 }
288
289 if (dump) {
290 __jffs2_dbg_dump_block_lists_nolock(c);
291 BUG();
292 }
293}
294
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100295/*
296 * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
297 */
298void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100299__jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
300 struct jffs2_eraseblock *jeb)
301{
302 spin_lock(&c->erase_completion_lock);
303 __jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
304 spin_unlock(&c->erase_completion_lock);
305}
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000306
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100307void
308__jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
309 struct jffs2_eraseblock *jeb)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100310{
311 uint32_t my_used_size = 0;
312 uint32_t my_unchecked_size = 0;
313 uint32_t my_dirty_size = 0;
314 struct jffs2_raw_node_ref *ref2 = jeb->first_node;
315
316 while (ref2) {
317 uint32_t totlen = ref_totlen(c, jeb, ref2);
318
Kyungmin Parkabb536e2006-12-22 16:39:30 +0900319 if (ref_offset(ref2) < jeb->offset ||
320 ref_offset(ref2) > jeb->offset + c->sector_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100321 JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100322 ref_offset(ref2), jeb->offset);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100323 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100324
325 }
326 if (ref_flags(ref2) == REF_UNCHECKED)
327 my_unchecked_size += totlen;
328 else if (!ref_obsolete(ref2))
329 my_used_size += totlen;
330 else
331 my_dirty_size += totlen;
332
David Woodhouse99988f72006-05-24 09:04:17 +0100333 if ((!ref_next(ref2)) != (ref2 == jeb->last_node)) {
334 JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next at %#08x (mem %p), last_node is at %#08x (mem %p).\n",
335 ref_offset(ref2), ref2, ref_offset(ref_next(ref2)), ref_next(ref2),
336 ref_offset(jeb->last_node), jeb->last_node);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100337 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100338 }
David Woodhouse99988f72006-05-24 09:04:17 +0100339 ref2 = ref_next(ref2);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100340 }
341
342 if (my_used_size != jeb->used_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100343 JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
344 my_used_size, jeb->used_size);
345 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100346 }
347
348 if (my_unchecked_size != jeb->unchecked_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100349 JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
350 my_unchecked_size, jeb->unchecked_size);
351 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100352 }
353
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100354#if 0
355 /* This should work when we implement ref->__totlen elemination */
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100356 if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100357 JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100358 my_dirty_size, jeb->dirty_size + jeb->wasted_size);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100359 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100360 }
361
362 if (jeb->free_size == 0
363 && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100364 JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100365 my_used_size + my_unchecked_size + my_dirty_size,
366 c->sector_size);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100367 goto error;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100368 }
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100369#endif
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100370
David Woodhouse85a62db2008-04-23 01:17:51 +0100371 if (!(c->flags & (JFFS2_SB_FLAG_BUILDING|JFFS2_SB_FLAG_SCANNING)))
372 __jffs2_dbg_superblock_counts(c);
373
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100374 return;
375
376error:
377 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
378 __jffs2_dbg_dump_jeb_nolock(jeb);
379 __jffs2_dbg_dump_block_lists_nolock(c);
380 BUG();
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000381
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100382}
383#endif /* JFFS2_DBG_PARANOIA_CHECKS */
384
385#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100386/*
387 * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
388 */
389void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100390__jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
391 struct jffs2_eraseblock *jeb)
392{
393 spin_lock(&c->erase_completion_lock);
394 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
395 spin_unlock(&c->erase_completion_lock);
396}
397
398void
399__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
400 struct jffs2_eraseblock *jeb)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100401{
402 struct jffs2_raw_node_ref *ref;
403 int i = 0;
404
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100405 printk(JFFS2_DBG_MSG_PREFIX " Dump node_refs of the eraseblock %#08x\n", jeb->offset);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100406 if (!jeb->first_node) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100407 printk(JFFS2_DBG_MSG_PREFIX " no nodes in the eraseblock %#08x\n", jeb->offset);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100408 return;
409 }
410
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100411 printk(JFFS2_DBG);
David Woodhouse99988f72006-05-24 09:04:17 +0100412 for (ref = jeb->first_node; ; ref = ref_next(ref)) {
David Woodhouse27e6b8e2008-04-23 01:25:33 +0100413 printk("%#08x", ref_offset(ref));
414#ifdef TEST_TOTLEN
415 printk("(%x)", ref->__totlen);
416#endif
David Woodhouse99988f72006-05-24 09:04:17 +0100417 if (ref_next(ref))
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100418 printk("->");
419 else
420 break;
421 if (++i == 4) {
422 i = 0;
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100423 printk("\n" JFFS2_DBG);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100424 }
425 }
426 printk("\n");
427}
428
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100429/*
430 * Dump an eraseblock's space accounting.
431 */
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100432void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100433__jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100434{
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100435 spin_lock(&c->erase_completion_lock);
436 __jffs2_dbg_dump_jeb_nolock(jeb);
437 spin_unlock(&c->erase_completion_lock);
438}
439
440void
441__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
442{
443 if (!jeb)
444 return;
445
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100446 printk(JFFS2_DBG_MSG_PREFIX " dump space accounting for the eraseblock at %#08x:\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100447 jeb->offset);
448
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100449 printk(JFFS2_DBG "used_size: %#08x\n", jeb->used_size);
450 printk(JFFS2_DBG "dirty_size: %#08x\n", jeb->dirty_size);
451 printk(JFFS2_DBG "wasted_size: %#08x\n", jeb->wasted_size);
452 printk(JFFS2_DBG "unchecked_size: %#08x\n", jeb->unchecked_size);
453 printk(JFFS2_DBG "free_size: %#08x\n", jeb->free_size);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100454}
455
456void
457__jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
458{
459 spin_lock(&c->erase_completion_lock);
460 __jffs2_dbg_dump_block_lists_nolock(c);
461 spin_unlock(&c->erase_completion_lock);
462}
463
464void
465__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
466{
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100467 printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n");
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000468
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100469 printk(JFFS2_DBG "flash_size: %#08x\n", c->flash_size);
470 printk(JFFS2_DBG "used_size: %#08x\n", c->used_size);
471 printk(JFFS2_DBG "dirty_size: %#08x\n", c->dirty_size);
472 printk(JFFS2_DBG "wasted_size: %#08x\n", c->wasted_size);
473 printk(JFFS2_DBG "unchecked_size: %#08x\n", c->unchecked_size);
474 printk(JFFS2_DBG "free_size: %#08x\n", c->free_size);
475 printk(JFFS2_DBG "erasing_size: %#08x\n", c->erasing_size);
476 printk(JFFS2_DBG "bad_size: %#08x\n", c->bad_size);
477 printk(JFFS2_DBG "sector_size: %#08x\n", c->sector_size);
478 printk(JFFS2_DBG "jffs2_reserved_blocks size: %#08x\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100479 c->sector_size * c->resv_blocks_write);
480
481 if (c->nextblock)
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100482 printk(JFFS2_DBG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100483 c->nextblock->offset, c->nextblock->used_size,
484 c->nextblock->dirty_size, c->nextblock->wasted_size,
485 c->nextblock->unchecked_size, c->nextblock->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100486 else
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100487 printk(JFFS2_DBG "nextblock: NULL\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100488
489 if (c->gcblock)
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100490 printk(JFFS2_DBG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100491 c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
492 c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100493 else
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100494 printk(JFFS2_DBG "gcblock: NULL\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100495
496 if (list_empty(&c->clean_list)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100497 printk(JFFS2_DBG "clean_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100498 } else {
499 struct list_head *this;
500 int numblocks = 0;
501 uint32_t dirty = 0;
502
503 list_for_each(this, &c->clean_list) {
504 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
505 numblocks ++;
506 dirty += jeb->wasted_size;
507 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100508 printk(JFFS2_DBG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100509 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
510 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100511 }
512 }
513
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100514 printk (JFFS2_DBG "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100515 numblocks, dirty, dirty / numblocks);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100516 }
517
518 if (list_empty(&c->very_dirty_list)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100519 printk(JFFS2_DBG "very_dirty_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100520 } else {
521 struct list_head *this;
522 int numblocks = 0;
523 uint32_t dirty = 0;
524
525 list_for_each(this, &c->very_dirty_list) {
526 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
527
528 numblocks ++;
529 dirty += jeb->dirty_size;
530 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100531 printk(JFFS2_DBG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100532 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
533 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100534 }
535 }
536
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100537 printk (JFFS2_DBG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100538 numblocks, dirty, dirty / numblocks);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100539 }
540
541 if (list_empty(&c->dirty_list)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100542 printk(JFFS2_DBG "dirty_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100543 } else {
544 struct list_head *this;
545 int numblocks = 0;
546 uint32_t dirty = 0;
547
548 list_for_each(this, &c->dirty_list) {
549 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
550
551 numblocks ++;
552 dirty += jeb->dirty_size;
553 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100554 printk(JFFS2_DBG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100555 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
556 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100557 }
558 }
559
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100560 printk (JFFS2_DBG "contains %d blocks with total dirty size %u, average dirty size: %u\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100561 numblocks, dirty, dirty / numblocks);
562 }
563
564 if (list_empty(&c->erasable_list)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100565 printk(JFFS2_DBG "erasable_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100566 } else {
567 struct list_head *this;
568
569 list_for_each(this, &c->erasable_list) {
570 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
571
572 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100573 printk(JFFS2_DBG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100574 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
575 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100576 }
577 }
578 }
579
580 if (list_empty(&c->erasing_list)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100581 printk(JFFS2_DBG "erasing_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100582 } else {
583 struct list_head *this;
584
585 list_for_each(this, &c->erasing_list) {
586 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
587
588 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100589 printk(JFFS2_DBG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100590 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
591 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100592 }
593 }
594 }
David Woodhousee2bc3222008-04-23 14:15:24 +0100595 if (list_empty(&c->erase_checking_list)) {
596 printk(JFFS2_DBG "erase_checking_list: empty\n");
597 } else {
598 struct list_head *this;
599
600 list_for_each(this, &c->erase_checking_list) {
601 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
602
603 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
604 printk(JFFS2_DBG "erase_checking_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
605 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
606 jeb->unchecked_size, jeb->free_size);
607 }
608 }
609 }
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100610
611 if (list_empty(&c->erase_pending_list)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100612 printk(JFFS2_DBG "erase_pending_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100613 } else {
614 struct list_head *this;
615
616 list_for_each(this, &c->erase_pending_list) {
617 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
618
619 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100620 printk(JFFS2_DBG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100621 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
622 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100623 }
624 }
625 }
626
627 if (list_empty(&c->erasable_pending_wbuf_list)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100628 printk(JFFS2_DBG "erasable_pending_wbuf_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100629 } else {
630 struct list_head *this;
631
632 list_for_each(this, &c->erasable_pending_wbuf_list) {
633 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
634
635 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100636 printk(JFFS2_DBG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100637 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
638 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100639 }
640 }
641 }
642
643 if (list_empty(&c->free_list)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100644 printk(JFFS2_DBG "free_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100645 } else {
646 struct list_head *this;
647
648 list_for_each(this, &c->free_list) {
649 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
650
651 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100652 printk(JFFS2_DBG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100653 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
654 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100655 }
656 }
657 }
658
659 if (list_empty(&c->bad_list)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100660 printk(JFFS2_DBG "bad_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100661 } else {
662 struct list_head *this;
663
664 list_for_each(this, &c->bad_list) {
665 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
666
667 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100668 printk(JFFS2_DBG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100669 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
670 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100671 }
672 }
673 }
674
675 if (list_empty(&c->bad_used_list)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100676 printk(JFFS2_DBG "bad_used_list: empty\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100677 } else {
678 struct list_head *this;
679
680 list_for_each(this, &c->bad_used_list) {
681 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
682
683 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100684 printk(JFFS2_DBG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100685 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
686 jeb->unchecked_size, jeb->free_size);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100687 }
688 }
689 }
690}
691
692void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100693__jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
694{
David Woodhouseced22072008-04-22 15:13:40 +0100695 mutex_lock(&f->sem);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100696 jffs2_dbg_dump_fragtree_nolock(f);
David Woodhouseced22072008-04-22 15:13:40 +0100697 mutex_unlock(&f->sem);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100698}
699
700void
701__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100702{
703 struct jffs2_node_frag *this = frag_first(&f->fragtree);
704 uint32_t lastofs = 0;
705 int buggy = 0;
706
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100707 printk(JFFS2_DBG_MSG_PREFIX " dump fragtree of ino #%u\n", f->inocache->ino);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100708 while(this) {
709 if (this->node)
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100710 printk(JFFS2_DBG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), right (%p), parent (%p)\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100711 this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
712 ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
713 frag_parent(this));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100714 else
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100715 printk(JFFS2_DBG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100716 this->ofs, this->ofs+this->size, this, frag_left(this),
717 frag_right(this), frag_parent(this));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100718 if (this->ofs != lastofs)
719 buggy = 1;
720 lastofs = this->ofs + this->size;
721 this = frag_next(this);
722 }
723
724 if (f->metadata)
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100725 printk(JFFS2_DBG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100726
727 if (buggy) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100728 JFFS2_ERROR("frag tree got a hole in it.\n");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100729 BUG();
730 }
731}
732
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100733#define JFFS2_BUFDUMP_BYTES_PER_LINE 32
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100734void
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100735__jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100736{
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100737 int skip;
738 int i;
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000739
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100740 printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n",
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100741 offs, offs + len, len);
742 i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
743 offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000744
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100745 if (skip != 0)
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100746 printk(JFFS2_DBG "%#08x: ", offs);
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000747
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100748 while (skip--)
749 printk(" ");
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100750
751 while (i < len) {
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100752 if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
753 if (i != 0)
754 printk("\n");
755 offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100756 printk(JFFS2_DBG "%0#8x: ", offs);
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100757 }
758
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100759 printk("%02x ", buf[i]);
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000760
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100761 i += 1;
762 }
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100763
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100764 printk("\n");
765}
766
767/*
768 * Dump a JFFS2 node.
769 */
770void
771__jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
772{
773 union jffs2_node_union node;
774 int len = sizeof(union jffs2_node_union);
775 size_t retlen;
776 uint32_t crc;
777 int ret;
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000778
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100779 printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100780
781 ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
782 if (ret || (retlen != len)) {
783 JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
784 len, ret, retlen);
785 return;
786 }
787
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100788 printk(JFFS2_DBG "magic:\t%#04x\n", je16_to_cpu(node.u.magic));
789 printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype));
790 printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen));
791 printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc));
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000792
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100793 crc = crc32(0, &node.u, sizeof(node.u) - 4);
794 if (crc != je32_to_cpu(node.u.hdr_crc)) {
795 JFFS2_ERROR("wrong common header CRC.\n");
796 return;
797 }
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000798
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100799 if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
800 je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
801 {
802 JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
803 je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
804 return;
805 }
806
807 switch(je16_to_cpu(node.u.nodetype)) {
808
809 case JFFS2_NODETYPE_INODE:
810
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100811 printk(JFFS2_DBG "the node is inode node\n");
812 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.i.ino));
813 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.i.version));
814 printk(JFFS2_DBG "mode:\t%#08x\n", node.i.mode.m);
815 printk(JFFS2_DBG "uid:\t%#04x\n", je16_to_cpu(node.i.uid));
816 printk(JFFS2_DBG "gid:\t%#04x\n", je16_to_cpu(node.i.gid));
817 printk(JFFS2_DBG "isize:\t%#08x\n", je32_to_cpu(node.i.isize));
818 printk(JFFS2_DBG "atime:\t%#08x\n", je32_to_cpu(node.i.atime));
819 printk(JFFS2_DBG "mtime:\t%#08x\n", je32_to_cpu(node.i.mtime));
820 printk(JFFS2_DBG "ctime:\t%#08x\n", je32_to_cpu(node.i.ctime));
821 printk(JFFS2_DBG "offset:\t%#08x\n", je32_to_cpu(node.i.offset));
822 printk(JFFS2_DBG "csize:\t%#08x\n", je32_to_cpu(node.i.csize));
823 printk(JFFS2_DBG "dsize:\t%#08x\n", je32_to_cpu(node.i.dsize));
824 printk(JFFS2_DBG "compr:\t%#02x\n", node.i.compr);
825 printk(JFFS2_DBG "usercompr:\t%#02x\n", node.i.usercompr);
826 printk(JFFS2_DBG "flags:\t%#04x\n", je16_to_cpu(node.i.flags));
827 printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc));
828 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc));
829
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000830 crc = crc32(0, &node.i, sizeof(node.i) - 8);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100831 if (crc != je32_to_cpu(node.i.node_crc)) {
832 JFFS2_ERROR("wrong node header CRC.\n");
833 return;
834 }
835 break;
836
837 case JFFS2_NODETYPE_DIRENT:
838
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100839 printk(JFFS2_DBG "the node is dirent node\n");
840 printk(JFFS2_DBG "pino:\t%#08x\n", je32_to_cpu(node.d.pino));
841 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.d.version));
842 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.d.ino));
843 printk(JFFS2_DBG "mctime:\t%#08x\n", je32_to_cpu(node.d.mctime));
844 printk(JFFS2_DBG "nsize:\t%#02x\n", node.d.nsize);
845 printk(JFFS2_DBG "type:\t%#02x\n", node.d.type);
846 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc));
847 printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc));
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000848
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100849 node.d.name[node.d.nsize] = '\0';
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100850 printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100851
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000852 crc = crc32(0, &node.d, sizeof(node.d) - 8);
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100853 if (crc != je32_to_cpu(node.d.node_crc)) {
854 JFFS2_ERROR("wrong node header CRC.\n");
855 return;
856 }
857 break;
858
859 default:
Artem B. Bityutskiy81e39cf2005-09-14 17:57:35 +0100860 printk(JFFS2_DBG "node type is unknown\n");
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100861 break;
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100862 }
863}
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100864#endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */