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