source: rtems/cpukit/libfs/src/jffs2/src/debug.c @ 6ac6a5c8

5
Last change on this file since 6ac6a5c8 was 6ac6a5c8, checked in by Sebastian Huber <sebastian.huber@…>, on 03/27/18 at 11:01:56

jffs2: Do not use command line defines

Update #3375.

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