[JFFS2] Debug code clean up - step 1
[pandora-kernel.git] / fs / jffs2 / debug.c
1 /*
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  *
10  * $Id: debug.c,v 1.1 2005/07/17 06:56:20 dedekind Exp $
11  *
12  */
13 #include <linux/kernel.h>
14 #include <linux/pagemap.h>
15 #include "nodelist.h"
16 #include "debug.h"
17
18 #ifdef JFFS2_DBG_PARANOIA_CHECKS
19
20 void
21 jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
22 {
23         struct jffs2_node_frag *frag;
24         int bitched = 0;
25
26         for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
27                 struct jffs2_full_dnode *fn = frag->node;
28
29                 if (!fn || !fn->raw)
30                         continue;
31
32                 if (ref_flags(fn->raw) == REF_PRISTINE) {
33                         if (fn->frags > 1) {
34                                 printk(KERN_ERR "REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2\n",
35                                                 ref_offset(fn->raw), fn->frags);
36                                 bitched = 1;
37                         }
38
39                         /* A hole node which isn't multi-page should be garbage-collected
40                            and merged anyway, so we just check for the frag size here,
41                            rather than mucking around with actually reading the node
42                            and checking the compression type, which is the real way
43                            to tell a hole node. */
44                         if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag)
45                                         && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
46                                 printk(KERN_ERR "REF_PRISTINE node at 0x%08x had a previous non-hole frag "
47                                                 "in the same page. Tell dwmw2\n", ref_offset(fn->raw));
48                                 bitched = 1;
49                         }
50
51                         if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag)
52                                         && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
53                                 printk(KERN_ERR "REF_PRISTINE node at 0x%08x (%08x-%08x) had a following "
54                                                 "non-hole frag in the same page. Tell dwmw2\n",
55                                                ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
56                                 bitched = 1;
57                         }
58                 }
59         }
60
61         if (bitched) {
62                 printk(KERN_ERR "Fragtree is corrupted. Fragtree dump:\n");
63                 jffs2_dbg_dump_fragtree(f);
64                 BUG();
65         }
66 }
67
68 /*
69  * Check if the flash contains all 0xFF before we start writing.
70  */
71 void
72 jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, uint32_t ofs, int len)
73 {
74         size_t retlen;
75         int ret, i;
76         unsigned char *buf;
77
78         buf = kmalloc(len, GFP_KERNEL);
79         if (!buf)
80                 return;
81
82         ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
83         if (ret || (retlen != len)) {
84                 printk(KERN_WARNING "read %d bytes failed or short in %s(). ret %d, retlen %zd\n",
85                                 len, __FUNCTION__, ret, retlen);
86                 kfree(buf);
87                 return;
88         }
89
90         ret = 0;
91         for (i = 0; i < len; i++)
92                 if (buf[i] != 0xff)
93                         ret = 1;
94
95         if (ret) {
96                 printk(KERN_ERR "ARGH. About to write node to %#08x on flash, but there are data "
97                                 "already there. The first corrupted byte is at %#08x.\n", ofs, ofs + i);
98                 jffs2_dbg_dump_buffer(buf, len, ofs);
99                 kfree(buf);
100                 BUG();
101         }
102
103         kfree(buf);
104 }
105
106 /*
107  * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
108  */
109 void
110 jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
111 {
112         uint32_t my_used_size = 0;
113         uint32_t my_unchecked_size = 0;
114         uint32_t my_dirty_size = 0;
115         struct jffs2_raw_node_ref *ref2 = jeb->first_node;
116
117         while (ref2) {
118                 uint32_t totlen = ref_totlen(c, jeb, ref2);
119
120                 if (ref2->flash_offset < jeb->offset ||
121                                 ref2->flash_offset > jeb->offset + c->sector_size) {
122                         printk(KERN_ERR "node_ref %#08x shouldn't be in block at %#08x!\n",
123                                 ref_offset(ref2), jeb->offset);
124                         jffs2_dbg_dump_node_refs(c, jeb);
125                         jffs2_dbg_dump_block_lists(c);
126                         BUG();
127
128                 }
129                 if (ref_flags(ref2) == REF_UNCHECKED)
130                         my_unchecked_size += totlen;
131                 else if (!ref_obsolete(ref2))
132                         my_used_size += totlen;
133                 else
134                         my_dirty_size += totlen;
135
136                 if ((!ref2->next_phys) != (ref2 == jeb->last_node)) {
137                         printk(KERN_ERR "node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), "
138                                         "last_node is at %#08x (mem %p)\n",
139                                         ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys,
140                                         ref_offset(jeb->last_node), jeb->last_node);
141                         jffs2_dbg_dump_node_refs(c, jeb);
142                         jffs2_dbg_dump_block_lists(c);
143                         BUG();
144                 }
145                 ref2 = ref2->next_phys;
146         }
147
148         if (my_used_size != jeb->used_size) {
149                 printk(KERN_ERR "Calculated used size %#08x != stored used size %#08x\n",
150                                 my_used_size, jeb->used_size);
151                 jffs2_dbg_dump_node_refs(c, jeb);
152                 jffs2_dbg_dump_block_lists(c);
153                 BUG();
154         }
155
156         if (my_unchecked_size != jeb->unchecked_size) {
157                 printk(KERN_ERR "Calculated unchecked size %#08x != stored unchecked size %#08x\n",
158                                 my_unchecked_size, jeb->unchecked_size);
159                 jffs2_dbg_dump_node_refs(c, jeb);
160                 jffs2_dbg_dump_block_lists(c);
161                 BUG();
162         }
163
164         if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
165                 printk(KERN_ERR "Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
166                         my_dirty_size, jeb->dirty_size + jeb->wasted_size);
167                 jffs2_dbg_dump_node_refs(c, jeb);
168                 jffs2_dbg_dump_block_lists(c);
169                 BUG();
170         }
171
172         if (jeb->free_size == 0
173                 && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
174                 printk(KERN_ERR "The sum of all nodes in block (%#x) != size of block (%#x)\n",
175                         my_used_size + my_unchecked_size + my_dirty_size,
176                         c->sector_size);
177                 jffs2_dbg_dump_node_refs(c, jeb);
178                 jffs2_dbg_dump_block_lists(c);
179                 BUG();
180         }
181 }
182 #endif /* JFFS2_PARANOIA_CHECKS */
183
184 #if defined(JFFS2_PARANOIA_CHECKS) || (CONFIG_JFFS2_FS_DEBUG > 0)
185 /*
186  * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
187  */
188 void
189 jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
190 {
191         struct jffs2_raw_node_ref *ref;
192         int i = 0;
193
194         if (!jeb->first_node) {
195                 printk(KERN_DEBUG "no nodes in block %#08x\n", jeb->offset);
196                 return;
197         }
198
199         printk(KERN_DEBUG);
200         for (ref = jeb->first_node; ; ref = ref->next_phys) {
201                 printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
202                 if (ref->next_phys)
203                         printk("->");
204                 else
205                         break;
206                 if (++i == 4) {
207                         i = 0;
208                         printk("\n" KERN_DEBUG);
209                 }
210         }
211         printk("\n");
212 }
213
214 void
215 jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
216 {
217         printk(KERN_DEBUG "flash_size: %#08x\n",        c->flash_size);
218         printk(KERN_DEBUG "used_size: %#08x\n",         c->used_size);
219         printk(KERN_DEBUG "dirty_size: %#08x\n",        c->dirty_size);
220         printk(KERN_DEBUG "wasted_size: %#08x\n",       c->wasted_size);
221         printk(KERN_DEBUG "unchecked_size: %#08x\n",    c->unchecked_size);
222         printk(KERN_DEBUG "free_size: %#08x\n",         c->free_size);
223         printk(KERN_DEBUG "erasing_size: %#08x\n",      c->erasing_size);
224         printk(KERN_DEBUG "bad_size: %#08x\n",          c->bad_size);
225         printk(KERN_DEBUG "sector_size: %#08x\n",       c->sector_size);
226         printk(KERN_DEBUG "jffs2_reserved_blocks size: %#08x\n",
227                                 c->sector_size * c->resv_blocks_write);
228
229         if (c->nextblock)
230                 printk(KERN_DEBUG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
231                                 "unchecked %#08x, free %#08x)\n",
232                                 c->nextblock->offset, c->nextblock->used_size,
233                                 c->nextblock->dirty_size, c->nextblock->wasted_size,
234                                 c->nextblock->unchecked_size, c->nextblock->free_size);
235         else
236                 printk(KERN_DEBUG "nextblock: NULL\n");
237
238         if (c->gcblock)
239                 printk(KERN_DEBUG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
240                                 "unchecked %#08x, free %#08x)\n",
241                                 c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
242                                 c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
243         else
244                 printk(KERN_DEBUG "gcblock: NULL\n");
245
246         if (list_empty(&c->clean_list)) {
247                 printk(KERN_DEBUG "clean_list: empty\n");
248         } else {
249                 struct list_head *this;
250                 int numblocks = 0;
251                 uint32_t dirty = 0;
252
253                 list_for_each(this, &c->clean_list) {
254                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
255                         numblocks ++;
256                         dirty += jeb->wasted_size;
257                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
258                                 printk(KERN_DEBUG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
259                                                 "unchecked %#08x, free %#08x)\n",
260                                                 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
261                                                 jeb->unchecked_size, jeb->free_size);
262                         }
263                 }
264
265                 printk (KERN_DEBUG "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
266                                 numblocks, dirty, dirty / numblocks);
267         }
268
269         if (list_empty(&c->very_dirty_list)) {
270                 printk(KERN_DEBUG "very_dirty_list: empty\n");
271         } else {
272                 struct list_head *this;
273                 int numblocks = 0;
274                 uint32_t dirty = 0;
275
276                 list_for_each(this, &c->very_dirty_list) {
277                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
278
279                         numblocks ++;
280                         dirty += jeb->dirty_size;
281                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
282                                 printk(KERN_DEBUG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
283                                                 "unchecked %#08x, free %#08x)\n",
284                                                 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
285                                                 jeb->unchecked_size, jeb->free_size);
286                         }
287                 }
288
289                 printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
290                                 numblocks, dirty, dirty / numblocks);
291         }
292
293         if (list_empty(&c->dirty_list)) {
294                 printk(KERN_DEBUG "dirty_list: empty\n");
295         } else {
296                 struct list_head *this;
297                 int numblocks = 0;
298                 uint32_t dirty = 0;
299
300                 list_for_each(this, &c->dirty_list) {
301                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
302
303                         numblocks ++;
304                         dirty += jeb->dirty_size;
305                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
306                                 printk(KERN_DEBUG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
307                                                 "unchecked %#08x, free %#08x)\n",
308                                                 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
309                                                 jeb->unchecked_size, jeb->free_size);
310                         }
311                 }
312
313                 printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
314                         numblocks, dirty, dirty / numblocks);
315         }
316
317         if (list_empty(&c->erasable_list)) {
318                 printk(KERN_DEBUG "erasable_list: empty\n");
319         } else {
320                 struct list_head *this;
321
322                 list_for_each(this, &c->erasable_list) {
323                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
324
325                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
326                                 printk(KERN_DEBUG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
327                                                 "unchecked %#08x, free %#08x)\n",
328                                                 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
329                                                 jeb->unchecked_size, jeb->free_size);
330                         }
331                 }
332         }
333
334         if (list_empty(&c->erasing_list)) {
335                 printk(KERN_DEBUG "erasing_list: empty\n");
336         } else {
337                 struct list_head *this;
338
339                 list_for_each(this, &c->erasing_list) {
340                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
341
342                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
343                                 printk(KERN_DEBUG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
344                                                 "unchecked %#08x, free %#08x)\n",
345                                                 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
346                                                 jeb->unchecked_size, jeb->free_size);
347                         }
348                 }
349         }
350
351         if (list_empty(&c->erase_pending_list)) {
352                 printk(KERN_DEBUG "erase_pending_list: empty\n");
353         } else {
354                 struct list_head *this;
355
356                 list_for_each(this, &c->erase_pending_list) {
357                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
358
359                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
360                                 printk(KERN_DEBUG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
361                                                 "unchecked %#08x, free %#08x)\n",
362                                                 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
363                                                 jeb->unchecked_size, jeb->free_size);
364                         }
365                 }
366         }
367
368         if (list_empty(&c->erasable_pending_wbuf_list)) {
369                 printk(KERN_DEBUG "erasable_pending_wbuf_list: empty\n");
370         } else {
371                 struct list_head *this;
372
373                 list_for_each(this, &c->erasable_pending_wbuf_list) {
374                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
375
376                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
377                                 printk(KERN_DEBUG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, "
378                                                 "wasted %#08x, unchecked %#08x, free %#08x)\n",
379                                                 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
380                                                 jeb->unchecked_size, jeb->free_size);
381                         }
382                 }
383         }
384
385         if (list_empty(&c->free_list)) {
386                 printk(KERN_DEBUG "free_list: empty\n");
387         } else {
388                 struct list_head *this;
389
390                 list_for_each(this, &c->free_list) {
391                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
392
393                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
394                                 printk(KERN_DEBUG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
395                                                 "unchecked %#08x, free %#08x)\n",
396                                                 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
397                                                 jeb->unchecked_size, jeb->free_size);
398                         }
399                 }
400         }
401
402         if (list_empty(&c->bad_list)) {
403                 printk(KERN_DEBUG "bad_list: empty\n");
404         } else {
405                 struct list_head *this;
406
407                 list_for_each(this, &c->bad_list) {
408                         struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
409
410                         if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
411                                 printk(KERN_DEBUG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
412                                                 "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->bad_used_list)) {
420                 printk(KERN_DEBUG "bad_used_list: empty\n");
421         } else {
422                 struct list_head *this;
423
424                 list_for_each(this, &c->bad_used_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(KERN_DEBUG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
429                                                 "unchecked %#08x, free %#08x)\n",
430                                                 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
431                                                 jeb->unchecked_size, jeb->free_size);
432                         }
433                 }
434         }
435 }
436
437 void
438 jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
439 {
440         struct jffs2_node_frag *this = frag_first(&f->fragtree);
441         uint32_t lastofs = 0;
442         int buggy = 0;
443
444         printk(KERN_DEBUG "inode is ino #%u\n", f->inocache->ino);
445         while(this) {
446                 if (this->node)
447                         printk(KERN_DEBUG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), "
448                                         "right (%p), parent (%p)\n",
449                                         this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
450                                         ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
451                                         frag_parent(this));
452                 else
453                         printk(KERN_DEBUG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
454                                         this->ofs, this->ofs+this->size, this, frag_left(this),
455                                         frag_right(this), frag_parent(this));
456                 if (this->ofs != lastofs)
457                         buggy = 1;
458                 lastofs = this->ofs + this->size;
459                 this = frag_next(this);
460         }
461
462         if (f->metadata)
463                 printk(KERN_DEBUG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
464
465         if (buggy) {
466                 printk(KERN_ERR "Error! %s(): Frag tree got a hole in it\n", __FUNCTION__);
467                 BUG();
468         }
469 }
470
471 #define JFFS3_BUFDUMP_BYTES_PER_LINE    8
472 void
473 jffs2_dbg_dump_buffer(char *buf, int len, uint32_t offs)
474 {
475         int i = 0;
476         int skip = offs & ~(JFFS3_BUFDUMP_BYTES_PER_LINE - 1);
477
478         while (i < len) {
479                 int j = 0;
480
481                 printk(KERN_DEBUG "0x#x: \n");
482                 while (skip) {
483                         printk("   ");
484                         skip -= 1;
485                 }
486
487                 while (j < JFFS3_BUFDUMP_BYTES_PER_LINE) {
488                         if (i + j < len)
489                                 printk(" %#02x", buf[i + j++]);
490                 }
491
492                 i += JFFS3_BUFDUMP_BYTES_PER_LINE;
493         }
494 }
495 #endif /* JFFS2_PARANOIA_CHECKS || CONFIG_JFFS2_FS_DEBUG > 0 */