root/fs/jffs2/debug.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __jffs2_dbg_acct_sanity_check_nolock
  2. __jffs2_dbg_acct_sanity_check
  3. __jffs2_dbg_fragtree_paranoia_check
  4. __jffs2_dbg_fragtree_paranoia_check_nolock
  5. __jffs2_dbg_prewrite_paranoia_check
  6. __jffs2_dbg_superblock_counts
  7. __jffs2_dbg_acct_paranoia_check
  8. __jffs2_dbg_acct_paranoia_check_nolock
  9. __jffs2_dbg_dump_node_refs
  10. __jffs2_dbg_dump_node_refs_nolock
  11. __jffs2_dbg_dump_jeb
  12. __jffs2_dbg_dump_jeb_nolock
  13. __jffs2_dbg_dump_block_lists
  14. __jffs2_dbg_dump_block_lists_nolock
  15. __jffs2_dbg_dump_fragtree
  16. __jffs2_dbg_dump_fragtree_nolock
  17. __jffs2_dbg_dump_buffer
  18. __jffs2_dbg_dump_node

   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_SIZE-1) && frag_prev(frag)
  99                                         && frag_prev(frag)->size < PAGE_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_SIZE-1) && frag_next(frag)
 106                                         && frag_next(frag)->size < PAGE_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 */

/* [<][>][^][v][top][bottom][index][help] */