~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/jffs2/debug.c

Version: ~ [ linux-5.6-rc1 ] ~ [ linux-5.5.2 ] ~ [ linux-5.4.17 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.102 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.170 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.213 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.213 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.81 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp