18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * JFFS2 -- Journalling Flash File System, Version 2. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright © 2001-2007 Red Hat, Inc. 58c2ecf20Sopenharmony_ci * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Created by David Woodhouse <dwmw2@infradead.org> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * For licensing information, see the file 'LICENCE' in this directory. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/kernel.h> 168c2ecf20Sopenharmony_ci#include <linux/types.h> 178c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 188c2ecf20Sopenharmony_ci#include <linux/crc32.h> 198c2ecf20Sopenharmony_ci#include <linux/jffs2.h> 208c2ecf20Sopenharmony_ci#include <linux/mtd/mtd.h> 218c2ecf20Sopenharmony_ci#include <linux/slab.h> 228c2ecf20Sopenharmony_ci#include "nodelist.h" 238c2ecf20Sopenharmony_ci#include "debug.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#ifdef JFFS2_DBG_SANITY_CHECKS 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_civoid 288c2ecf20Sopenharmony_ci__jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info *c, 298c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci if (unlikely(jeb && jeb->used_size + jeb->dirty_size + 328c2ecf20Sopenharmony_ci jeb->free_size + jeb->wasted_size + 338c2ecf20Sopenharmony_ci jeb->unchecked_size != c->sector_size)) { 348c2ecf20Sopenharmony_ci JFFS2_ERROR("eeep, space accounting for block at 0x%08x is screwed.\n", jeb->offset); 358c2ecf20Sopenharmony_ci JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked %#08x != total %#08x.\n", 368c2ecf20Sopenharmony_ci jeb->free_size, jeb->dirty_size, jeb->used_size, 378c2ecf20Sopenharmony_ci jeb->wasted_size, jeb->unchecked_size, c->sector_size); 388c2ecf20Sopenharmony_ci BUG(); 398c2ecf20Sopenharmony_ci } 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci if (unlikely(c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size 428c2ecf20Sopenharmony_ci + c->wasted_size + c->unchecked_size != c->flash_size)) { 438c2ecf20Sopenharmony_ci JFFS2_ERROR("eeep, space accounting superblock info is screwed.\n"); 448c2ecf20Sopenharmony_ci JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + wasted %#08x + unchecked %#08x != total %#08x.\n", 458c2ecf20Sopenharmony_ci c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, 468c2ecf20Sopenharmony_ci c->wasted_size, c->unchecked_size, c->flash_size); 478c2ecf20Sopenharmony_ci BUG(); 488c2ecf20Sopenharmony_ci } 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_civoid 528c2ecf20Sopenharmony_ci__jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c, 538c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 568c2ecf20Sopenharmony_ci jffs2_dbg_acct_sanity_check_nolock(c, jeb); 578c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#endif /* JFFS2_DBG_SANITY_CHECKS */ 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#ifdef JFFS2_DBG_PARANOIA_CHECKS 638c2ecf20Sopenharmony_ci/* 648c2ecf20Sopenharmony_ci * Check the fragtree. 658c2ecf20Sopenharmony_ci */ 668c2ecf20Sopenharmony_civoid 678c2ecf20Sopenharmony_ci__jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci mutex_lock(&f->sem); 708c2ecf20Sopenharmony_ci __jffs2_dbg_fragtree_paranoia_check_nolock(f); 718c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_civoid 758c2ecf20Sopenharmony_ci__jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci struct jffs2_node_frag *frag; 788c2ecf20Sopenharmony_ci int bitched = 0; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) { 818c2ecf20Sopenharmony_ci struct jffs2_full_dnode *fn = frag->node; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci if (!fn || !fn->raw) 848c2ecf20Sopenharmony_ci continue; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci if (ref_flags(fn->raw) == REF_PRISTINE) { 878c2ecf20Sopenharmony_ci if (fn->frags > 1) { 888c2ecf20Sopenharmony_ci JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n", 898c2ecf20Sopenharmony_ci ref_offset(fn->raw), fn->frags); 908c2ecf20Sopenharmony_ci bitched = 1; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* A hole node which isn't multi-page should be garbage-collected 948c2ecf20Sopenharmony_ci and merged anyway, so we just check for the frag size here, 958c2ecf20Sopenharmony_ci rather than mucking around with actually reading the node 968c2ecf20Sopenharmony_ci and checking the compression type, which is the real way 978c2ecf20Sopenharmony_ci to tell a hole node. */ 988c2ecf20Sopenharmony_ci if (frag->ofs & (PAGE_SIZE-1) && frag_prev(frag) 998c2ecf20Sopenharmony_ci && frag_prev(frag)->size < PAGE_SIZE && frag_prev(frag)->node) { 1008c2ecf20Sopenharmony_ci JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag in the same page. Tell dwmw2.\n", 1018c2ecf20Sopenharmony_ci ref_offset(fn->raw)); 1028c2ecf20Sopenharmony_ci bitched = 1; 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci if ((frag->ofs+frag->size) & (PAGE_SIZE-1) && frag_next(frag) 1068c2ecf20Sopenharmony_ci && frag_next(frag)->size < PAGE_SIZE && frag_next(frag)->node) { 1078c2ecf20Sopenharmony_ci JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following non-hole frag in the same page. Tell dwmw2.\n", 1088c2ecf20Sopenharmony_ci ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size); 1098c2ecf20Sopenharmony_ci bitched = 1; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci if (bitched) { 1158c2ecf20Sopenharmony_ci JFFS2_ERROR("fragtree is corrupted.\n"); 1168c2ecf20Sopenharmony_ci __jffs2_dbg_dump_fragtree_nolock(f); 1178c2ecf20Sopenharmony_ci BUG(); 1188c2ecf20Sopenharmony_ci } 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci/* 1228c2ecf20Sopenharmony_ci * Check if the flash contains all 0xFF before we start writing. 1238c2ecf20Sopenharmony_ci */ 1248c2ecf20Sopenharmony_civoid 1258c2ecf20Sopenharmony_ci__jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, 1268c2ecf20Sopenharmony_ci uint32_t ofs, int len) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci size_t retlen; 1298c2ecf20Sopenharmony_ci int ret, i; 1308c2ecf20Sopenharmony_ci unsigned char *buf; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci buf = kmalloc(len, GFP_KERNEL); 1338c2ecf20Sopenharmony_ci if (!buf) 1348c2ecf20Sopenharmony_ci return; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci ret = jffs2_flash_read(c, ofs, len, &retlen, buf); 1378c2ecf20Sopenharmony_ci if (ret || (retlen != len)) { 1388c2ecf20Sopenharmony_ci JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n", 1398c2ecf20Sopenharmony_ci len, ret, retlen); 1408c2ecf20Sopenharmony_ci kfree(buf); 1418c2ecf20Sopenharmony_ci return; 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci ret = 0; 1458c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) 1468c2ecf20Sopenharmony_ci if (buf[i] != 0xff) 1478c2ecf20Sopenharmony_ci ret = 1; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci if (ret) { 1508c2ecf20Sopenharmony_ci 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", 1518c2ecf20Sopenharmony_ci ofs, ofs + i); 1528c2ecf20Sopenharmony_ci __jffs2_dbg_dump_buffer(buf, len, ofs); 1538c2ecf20Sopenharmony_ci kfree(buf); 1548c2ecf20Sopenharmony_ci BUG(); 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci kfree(buf); 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_civoid __jffs2_dbg_superblock_counts(struct jffs2_sb_info *c) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb; 1638c2ecf20Sopenharmony_ci uint32_t free = 0, dirty = 0, used = 0, wasted = 0, 1648c2ecf20Sopenharmony_ci erasing = 0, bad = 0, unchecked = 0; 1658c2ecf20Sopenharmony_ci int nr_counted = 0; 1668c2ecf20Sopenharmony_ci int dump = 0; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci if (c->gcblock) { 1698c2ecf20Sopenharmony_ci nr_counted++; 1708c2ecf20Sopenharmony_ci free += c->gcblock->free_size; 1718c2ecf20Sopenharmony_ci dirty += c->gcblock->dirty_size; 1728c2ecf20Sopenharmony_ci used += c->gcblock->used_size; 1738c2ecf20Sopenharmony_ci wasted += c->gcblock->wasted_size; 1748c2ecf20Sopenharmony_ci unchecked += c->gcblock->unchecked_size; 1758c2ecf20Sopenharmony_ci } 1768c2ecf20Sopenharmony_ci if (c->nextblock) { 1778c2ecf20Sopenharmony_ci nr_counted++; 1788c2ecf20Sopenharmony_ci free += c->nextblock->free_size; 1798c2ecf20Sopenharmony_ci dirty += c->nextblock->dirty_size; 1808c2ecf20Sopenharmony_ci used += c->nextblock->used_size; 1818c2ecf20Sopenharmony_ci wasted += c->nextblock->wasted_size; 1828c2ecf20Sopenharmony_ci unchecked += c->nextblock->unchecked_size; 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci list_for_each_entry(jeb, &c->clean_list, list) { 1858c2ecf20Sopenharmony_ci nr_counted++; 1868c2ecf20Sopenharmony_ci free += jeb->free_size; 1878c2ecf20Sopenharmony_ci dirty += jeb->dirty_size; 1888c2ecf20Sopenharmony_ci used += jeb->used_size; 1898c2ecf20Sopenharmony_ci wasted += jeb->wasted_size; 1908c2ecf20Sopenharmony_ci unchecked += jeb->unchecked_size; 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci list_for_each_entry(jeb, &c->very_dirty_list, list) { 1938c2ecf20Sopenharmony_ci nr_counted++; 1948c2ecf20Sopenharmony_ci free += jeb->free_size; 1958c2ecf20Sopenharmony_ci dirty += jeb->dirty_size; 1968c2ecf20Sopenharmony_ci used += jeb->used_size; 1978c2ecf20Sopenharmony_ci wasted += jeb->wasted_size; 1988c2ecf20Sopenharmony_ci unchecked += jeb->unchecked_size; 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci list_for_each_entry(jeb, &c->dirty_list, list) { 2018c2ecf20Sopenharmony_ci nr_counted++; 2028c2ecf20Sopenharmony_ci free += jeb->free_size; 2038c2ecf20Sopenharmony_ci dirty += jeb->dirty_size; 2048c2ecf20Sopenharmony_ci used += jeb->used_size; 2058c2ecf20Sopenharmony_ci wasted += jeb->wasted_size; 2068c2ecf20Sopenharmony_ci unchecked += jeb->unchecked_size; 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci list_for_each_entry(jeb, &c->erasable_list, list) { 2098c2ecf20Sopenharmony_ci nr_counted++; 2108c2ecf20Sopenharmony_ci free += jeb->free_size; 2118c2ecf20Sopenharmony_ci dirty += jeb->dirty_size; 2128c2ecf20Sopenharmony_ci used += jeb->used_size; 2138c2ecf20Sopenharmony_ci wasted += jeb->wasted_size; 2148c2ecf20Sopenharmony_ci unchecked += jeb->unchecked_size; 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci list_for_each_entry(jeb, &c->erasable_pending_wbuf_list, list) { 2178c2ecf20Sopenharmony_ci nr_counted++; 2188c2ecf20Sopenharmony_ci free += jeb->free_size; 2198c2ecf20Sopenharmony_ci dirty += jeb->dirty_size; 2208c2ecf20Sopenharmony_ci used += jeb->used_size; 2218c2ecf20Sopenharmony_ci wasted += jeb->wasted_size; 2228c2ecf20Sopenharmony_ci unchecked += jeb->unchecked_size; 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci list_for_each_entry(jeb, &c->erase_pending_list, list) { 2258c2ecf20Sopenharmony_ci nr_counted++; 2268c2ecf20Sopenharmony_ci free += jeb->free_size; 2278c2ecf20Sopenharmony_ci dirty += jeb->dirty_size; 2288c2ecf20Sopenharmony_ci used += jeb->used_size; 2298c2ecf20Sopenharmony_ci wasted += jeb->wasted_size; 2308c2ecf20Sopenharmony_ci unchecked += jeb->unchecked_size; 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci list_for_each_entry(jeb, &c->free_list, list) { 2338c2ecf20Sopenharmony_ci nr_counted++; 2348c2ecf20Sopenharmony_ci free += jeb->free_size; 2358c2ecf20Sopenharmony_ci dirty += jeb->dirty_size; 2368c2ecf20Sopenharmony_ci used += jeb->used_size; 2378c2ecf20Sopenharmony_ci wasted += jeb->wasted_size; 2388c2ecf20Sopenharmony_ci unchecked += jeb->unchecked_size; 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci list_for_each_entry(jeb, &c->bad_used_list, list) { 2418c2ecf20Sopenharmony_ci nr_counted++; 2428c2ecf20Sopenharmony_ci free += jeb->free_size; 2438c2ecf20Sopenharmony_ci dirty += jeb->dirty_size; 2448c2ecf20Sopenharmony_ci used += jeb->used_size; 2458c2ecf20Sopenharmony_ci wasted += jeb->wasted_size; 2468c2ecf20Sopenharmony_ci unchecked += jeb->unchecked_size; 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci list_for_each_entry(jeb, &c->erasing_list, list) { 2508c2ecf20Sopenharmony_ci nr_counted++; 2518c2ecf20Sopenharmony_ci erasing += c->sector_size; 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci list_for_each_entry(jeb, &c->erase_checking_list, list) { 2548c2ecf20Sopenharmony_ci nr_counted++; 2558c2ecf20Sopenharmony_ci erasing += c->sector_size; 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci list_for_each_entry(jeb, &c->erase_complete_list, list) { 2588c2ecf20Sopenharmony_ci nr_counted++; 2598c2ecf20Sopenharmony_ci erasing += c->sector_size; 2608c2ecf20Sopenharmony_ci } 2618c2ecf20Sopenharmony_ci list_for_each_entry(jeb, &c->bad_list, list) { 2628c2ecf20Sopenharmony_ci nr_counted++; 2638c2ecf20Sopenharmony_ci bad += c->sector_size; 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci#define check(sz) \ 2678c2ecf20Sopenharmony_cido { \ 2688c2ecf20Sopenharmony_ci if (sz != c->sz##_size) { \ 2698c2ecf20Sopenharmony_ci pr_warn("%s_size mismatch counted 0x%x, c->%s_size 0x%x\n", \ 2708c2ecf20Sopenharmony_ci #sz, sz, #sz, c->sz##_size); \ 2718c2ecf20Sopenharmony_ci dump = 1; \ 2728c2ecf20Sopenharmony_ci } \ 2738c2ecf20Sopenharmony_ci} while (0) 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci check(free); 2768c2ecf20Sopenharmony_ci check(dirty); 2778c2ecf20Sopenharmony_ci check(used); 2788c2ecf20Sopenharmony_ci check(wasted); 2798c2ecf20Sopenharmony_ci check(unchecked); 2808c2ecf20Sopenharmony_ci check(bad); 2818c2ecf20Sopenharmony_ci check(erasing); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci#undef check 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci if (nr_counted != c->nr_blocks) { 2868c2ecf20Sopenharmony_ci pr_warn("%s counted only 0x%x blocks of 0x%x. Where are the others?\n", 2878c2ecf20Sopenharmony_ci __func__, nr_counted, c->nr_blocks); 2888c2ecf20Sopenharmony_ci dump = 1; 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci if (dump) { 2928c2ecf20Sopenharmony_ci __jffs2_dbg_dump_block_lists_nolock(c); 2938c2ecf20Sopenharmony_ci BUG(); 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci/* 2988c2ecf20Sopenharmony_ci * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'. 2998c2ecf20Sopenharmony_ci */ 3008c2ecf20Sopenharmony_civoid 3018c2ecf20Sopenharmony_ci__jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, 3028c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb) 3038c2ecf20Sopenharmony_ci{ 3048c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 3058c2ecf20Sopenharmony_ci __jffs2_dbg_acct_paranoia_check_nolock(c, jeb); 3068c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 3078c2ecf20Sopenharmony_ci} 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_civoid 3108c2ecf20Sopenharmony_ci__jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c, 3118c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci uint32_t my_used_size = 0; 3148c2ecf20Sopenharmony_ci uint32_t my_unchecked_size = 0; 3158c2ecf20Sopenharmony_ci uint32_t my_dirty_size = 0; 3168c2ecf20Sopenharmony_ci struct jffs2_raw_node_ref *ref2 = jeb->first_node; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci while (ref2) { 3198c2ecf20Sopenharmony_ci uint32_t totlen = ref_totlen(c, jeb, ref2); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci if (ref_offset(ref2) < jeb->offset || 3228c2ecf20Sopenharmony_ci ref_offset(ref2) > jeb->offset + c->sector_size) { 3238c2ecf20Sopenharmony_ci JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n", 3248c2ecf20Sopenharmony_ci ref_offset(ref2), jeb->offset); 3258c2ecf20Sopenharmony_ci goto error; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci } 3288c2ecf20Sopenharmony_ci if (ref_flags(ref2) == REF_UNCHECKED) 3298c2ecf20Sopenharmony_ci my_unchecked_size += totlen; 3308c2ecf20Sopenharmony_ci else if (!ref_obsolete(ref2)) 3318c2ecf20Sopenharmony_ci my_used_size += totlen; 3328c2ecf20Sopenharmony_ci else 3338c2ecf20Sopenharmony_ci my_dirty_size += totlen; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci if ((!ref_next(ref2)) != (ref2 == jeb->last_node)) { 3368c2ecf20Sopenharmony_ci JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next at %#08x (mem %p), last_node is at %#08x (mem %p).\n", 3378c2ecf20Sopenharmony_ci ref_offset(ref2), ref2, ref_offset(ref_next(ref2)), ref_next(ref2), 3388c2ecf20Sopenharmony_ci ref_offset(jeb->last_node), jeb->last_node); 3398c2ecf20Sopenharmony_ci goto error; 3408c2ecf20Sopenharmony_ci } 3418c2ecf20Sopenharmony_ci ref2 = ref_next(ref2); 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci if (my_used_size != jeb->used_size) { 3458c2ecf20Sopenharmony_ci JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n", 3468c2ecf20Sopenharmony_ci my_used_size, jeb->used_size); 3478c2ecf20Sopenharmony_ci goto error; 3488c2ecf20Sopenharmony_ci } 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci if (my_unchecked_size != jeb->unchecked_size) { 3518c2ecf20Sopenharmony_ci JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n", 3528c2ecf20Sopenharmony_ci my_unchecked_size, jeb->unchecked_size); 3538c2ecf20Sopenharmony_ci goto error; 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci#if 0 3578c2ecf20Sopenharmony_ci /* This should work when we implement ref->__totlen elemination */ 3588c2ecf20Sopenharmony_ci if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) { 3598c2ecf20Sopenharmony_ci JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n", 3608c2ecf20Sopenharmony_ci my_dirty_size, jeb->dirty_size + jeb->wasted_size); 3618c2ecf20Sopenharmony_ci goto error; 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci if (jeb->free_size == 0 3658c2ecf20Sopenharmony_ci && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) { 3668c2ecf20Sopenharmony_ci JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n", 3678c2ecf20Sopenharmony_ci my_used_size + my_unchecked_size + my_dirty_size, 3688c2ecf20Sopenharmony_ci c->sector_size); 3698c2ecf20Sopenharmony_ci goto error; 3708c2ecf20Sopenharmony_ci } 3718c2ecf20Sopenharmony_ci#endif 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci if (!(c->flags & (JFFS2_SB_FLAG_BUILDING|JFFS2_SB_FLAG_SCANNING))) 3748c2ecf20Sopenharmony_ci __jffs2_dbg_superblock_counts(c); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci return; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_cierror: 3798c2ecf20Sopenharmony_ci __jffs2_dbg_dump_node_refs_nolock(c, jeb); 3808c2ecf20Sopenharmony_ci __jffs2_dbg_dump_jeb_nolock(jeb); 3818c2ecf20Sopenharmony_ci __jffs2_dbg_dump_block_lists_nolock(c); 3828c2ecf20Sopenharmony_ci BUG(); 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci} 3858c2ecf20Sopenharmony_ci#endif /* JFFS2_DBG_PARANOIA_CHECKS */ 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS) 3888c2ecf20Sopenharmony_ci/* 3898c2ecf20Sopenharmony_ci * Dump the node_refs of the 'jeb' JFFS2 eraseblock. 3908c2ecf20Sopenharmony_ci */ 3918c2ecf20Sopenharmony_civoid 3928c2ecf20Sopenharmony_ci__jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c, 3938c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb) 3948c2ecf20Sopenharmony_ci{ 3958c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 3968c2ecf20Sopenharmony_ci __jffs2_dbg_dump_node_refs_nolock(c, jeb); 3978c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 3988c2ecf20Sopenharmony_ci} 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_civoid 4018c2ecf20Sopenharmony_ci__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c, 4028c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb) 4038c2ecf20Sopenharmony_ci{ 4048c2ecf20Sopenharmony_ci struct jffs2_raw_node_ref *ref; 4058c2ecf20Sopenharmony_ci int i = 0; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci printk(JFFS2_DBG_MSG_PREFIX " Dump node_refs of the eraseblock %#08x\n", jeb->offset); 4088c2ecf20Sopenharmony_ci if (!jeb->first_node) { 4098c2ecf20Sopenharmony_ci printk(JFFS2_DBG_MSG_PREFIX " no nodes in the eraseblock %#08x\n", jeb->offset); 4108c2ecf20Sopenharmony_ci return; 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci printk(JFFS2_DBG); 4148c2ecf20Sopenharmony_ci for (ref = jeb->first_node; ; ref = ref_next(ref)) { 4158c2ecf20Sopenharmony_ci printk("%#08x", ref_offset(ref)); 4168c2ecf20Sopenharmony_ci#ifdef TEST_TOTLEN 4178c2ecf20Sopenharmony_ci printk("(%x)", ref->__totlen); 4188c2ecf20Sopenharmony_ci#endif 4198c2ecf20Sopenharmony_ci if (ref_next(ref)) 4208c2ecf20Sopenharmony_ci printk("->"); 4218c2ecf20Sopenharmony_ci else 4228c2ecf20Sopenharmony_ci break; 4238c2ecf20Sopenharmony_ci if (++i == 4) { 4248c2ecf20Sopenharmony_ci i = 0; 4258c2ecf20Sopenharmony_ci printk("\n" JFFS2_DBG); 4268c2ecf20Sopenharmony_ci } 4278c2ecf20Sopenharmony_ci } 4288c2ecf20Sopenharmony_ci printk("\n"); 4298c2ecf20Sopenharmony_ci} 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci/* 4328c2ecf20Sopenharmony_ci * Dump an eraseblock's space accounting. 4338c2ecf20Sopenharmony_ci */ 4348c2ecf20Sopenharmony_civoid 4358c2ecf20Sopenharmony_ci__jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 4368c2ecf20Sopenharmony_ci{ 4378c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 4388c2ecf20Sopenharmony_ci __jffs2_dbg_dump_jeb_nolock(jeb); 4398c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 4408c2ecf20Sopenharmony_ci} 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_civoid 4438c2ecf20Sopenharmony_ci__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb) 4448c2ecf20Sopenharmony_ci{ 4458c2ecf20Sopenharmony_ci if (!jeb) 4468c2ecf20Sopenharmony_ci return; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci printk(JFFS2_DBG_MSG_PREFIX " dump space accounting for the eraseblock at %#08x:\n", 4498c2ecf20Sopenharmony_ci jeb->offset); 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci printk(JFFS2_DBG "used_size: %#08x\n", jeb->used_size); 4528c2ecf20Sopenharmony_ci printk(JFFS2_DBG "dirty_size: %#08x\n", jeb->dirty_size); 4538c2ecf20Sopenharmony_ci printk(JFFS2_DBG "wasted_size: %#08x\n", jeb->wasted_size); 4548c2ecf20Sopenharmony_ci printk(JFFS2_DBG "unchecked_size: %#08x\n", jeb->unchecked_size); 4558c2ecf20Sopenharmony_ci printk(JFFS2_DBG "free_size: %#08x\n", jeb->free_size); 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_civoid 4598c2ecf20Sopenharmony_ci__jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) 4608c2ecf20Sopenharmony_ci{ 4618c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 4628c2ecf20Sopenharmony_ci __jffs2_dbg_dump_block_lists_nolock(c); 4638c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 4648c2ecf20Sopenharmony_ci} 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_civoid 4678c2ecf20Sopenharmony_ci__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) 4688c2ecf20Sopenharmony_ci{ 4698c2ecf20Sopenharmony_ci printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n"); 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci printk(JFFS2_DBG "flash_size: %#08x\n", c->flash_size); 4728c2ecf20Sopenharmony_ci printk(JFFS2_DBG "used_size: %#08x\n", c->used_size); 4738c2ecf20Sopenharmony_ci printk(JFFS2_DBG "dirty_size: %#08x\n", c->dirty_size); 4748c2ecf20Sopenharmony_ci printk(JFFS2_DBG "wasted_size: %#08x\n", c->wasted_size); 4758c2ecf20Sopenharmony_ci printk(JFFS2_DBG "unchecked_size: %#08x\n", c->unchecked_size); 4768c2ecf20Sopenharmony_ci printk(JFFS2_DBG "free_size: %#08x\n", c->free_size); 4778c2ecf20Sopenharmony_ci printk(JFFS2_DBG "erasing_size: %#08x\n", c->erasing_size); 4788c2ecf20Sopenharmony_ci printk(JFFS2_DBG "bad_size: %#08x\n", c->bad_size); 4798c2ecf20Sopenharmony_ci printk(JFFS2_DBG "sector_size: %#08x\n", c->sector_size); 4808c2ecf20Sopenharmony_ci printk(JFFS2_DBG "jffs2_reserved_blocks size: %#08x\n", 4818c2ecf20Sopenharmony_ci c->sector_size * c->resv_blocks_write); 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci if (c->nextblock) 4848c2ecf20Sopenharmony_ci printk(JFFS2_DBG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", 4858c2ecf20Sopenharmony_ci c->nextblock->offset, c->nextblock->used_size, 4868c2ecf20Sopenharmony_ci c->nextblock->dirty_size, c->nextblock->wasted_size, 4878c2ecf20Sopenharmony_ci c->nextblock->unchecked_size, c->nextblock->free_size); 4888c2ecf20Sopenharmony_ci else 4898c2ecf20Sopenharmony_ci printk(JFFS2_DBG "nextblock: NULL\n"); 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci if (c->gcblock) 4928c2ecf20Sopenharmony_ci printk(JFFS2_DBG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", 4938c2ecf20Sopenharmony_ci c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, 4948c2ecf20Sopenharmony_ci c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size); 4958c2ecf20Sopenharmony_ci else 4968c2ecf20Sopenharmony_ci printk(JFFS2_DBG "gcblock: NULL\n"); 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci if (list_empty(&c->clean_list)) { 4998c2ecf20Sopenharmony_ci printk(JFFS2_DBG "clean_list: empty\n"); 5008c2ecf20Sopenharmony_ci } else { 5018c2ecf20Sopenharmony_ci struct list_head *this; 5028c2ecf20Sopenharmony_ci int numblocks = 0; 5038c2ecf20Sopenharmony_ci uint32_t dirty = 0; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci list_for_each(this, &c->clean_list) { 5068c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 5078c2ecf20Sopenharmony_ci numblocks ++; 5088c2ecf20Sopenharmony_ci dirty += jeb->wasted_size; 5098c2ecf20Sopenharmony_ci if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 5108c2ecf20Sopenharmony_ci printk(JFFS2_DBG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", 5118c2ecf20Sopenharmony_ci jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 5128c2ecf20Sopenharmony_ci jeb->unchecked_size, jeb->free_size); 5138c2ecf20Sopenharmony_ci } 5148c2ecf20Sopenharmony_ci } 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci printk (JFFS2_DBG "Contains %d blocks with total wasted size %u, average wasted size: %u\n", 5178c2ecf20Sopenharmony_ci numblocks, dirty, dirty / numblocks); 5188c2ecf20Sopenharmony_ci } 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci if (list_empty(&c->very_dirty_list)) { 5218c2ecf20Sopenharmony_ci printk(JFFS2_DBG "very_dirty_list: empty\n"); 5228c2ecf20Sopenharmony_ci } else { 5238c2ecf20Sopenharmony_ci struct list_head *this; 5248c2ecf20Sopenharmony_ci int numblocks = 0; 5258c2ecf20Sopenharmony_ci uint32_t dirty = 0; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci list_for_each(this, &c->very_dirty_list) { 5288c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci numblocks ++; 5318c2ecf20Sopenharmony_ci dirty += jeb->dirty_size; 5328c2ecf20Sopenharmony_ci if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 5338c2ecf20Sopenharmony_ci printk(JFFS2_DBG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", 5348c2ecf20Sopenharmony_ci jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 5358c2ecf20Sopenharmony_ci jeb->unchecked_size, jeb->free_size); 5368c2ecf20Sopenharmony_ci } 5378c2ecf20Sopenharmony_ci } 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci printk (JFFS2_DBG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", 5408c2ecf20Sopenharmony_ci numblocks, dirty, dirty / numblocks); 5418c2ecf20Sopenharmony_ci } 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci if (list_empty(&c->dirty_list)) { 5448c2ecf20Sopenharmony_ci printk(JFFS2_DBG "dirty_list: empty\n"); 5458c2ecf20Sopenharmony_ci } else { 5468c2ecf20Sopenharmony_ci struct list_head *this; 5478c2ecf20Sopenharmony_ci int numblocks = 0; 5488c2ecf20Sopenharmony_ci uint32_t dirty = 0; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci list_for_each(this, &c->dirty_list) { 5518c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci numblocks ++; 5548c2ecf20Sopenharmony_ci dirty += jeb->dirty_size; 5558c2ecf20Sopenharmony_ci if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 5568c2ecf20Sopenharmony_ci printk(JFFS2_DBG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", 5578c2ecf20Sopenharmony_ci jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 5588c2ecf20Sopenharmony_ci jeb->unchecked_size, jeb->free_size); 5598c2ecf20Sopenharmony_ci } 5608c2ecf20Sopenharmony_ci } 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci printk (JFFS2_DBG "contains %d blocks with total dirty size %u, average dirty size: %u\n", 5638c2ecf20Sopenharmony_ci numblocks, dirty, dirty / numblocks); 5648c2ecf20Sopenharmony_ci } 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci if (list_empty(&c->erasable_list)) { 5678c2ecf20Sopenharmony_ci printk(JFFS2_DBG "erasable_list: empty\n"); 5688c2ecf20Sopenharmony_ci } else { 5698c2ecf20Sopenharmony_ci struct list_head *this; 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci list_for_each(this, &c->erasable_list) { 5728c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 5758c2ecf20Sopenharmony_ci printk(JFFS2_DBG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", 5768c2ecf20Sopenharmony_ci jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 5778c2ecf20Sopenharmony_ci jeb->unchecked_size, jeb->free_size); 5788c2ecf20Sopenharmony_ci } 5798c2ecf20Sopenharmony_ci } 5808c2ecf20Sopenharmony_ci } 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci if (list_empty(&c->erasing_list)) { 5838c2ecf20Sopenharmony_ci printk(JFFS2_DBG "erasing_list: empty\n"); 5848c2ecf20Sopenharmony_ci } else { 5858c2ecf20Sopenharmony_ci struct list_head *this; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci list_for_each(this, &c->erasing_list) { 5888c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 5918c2ecf20Sopenharmony_ci printk(JFFS2_DBG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", 5928c2ecf20Sopenharmony_ci jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 5938c2ecf20Sopenharmony_ci jeb->unchecked_size, jeb->free_size); 5948c2ecf20Sopenharmony_ci } 5958c2ecf20Sopenharmony_ci } 5968c2ecf20Sopenharmony_ci } 5978c2ecf20Sopenharmony_ci if (list_empty(&c->erase_checking_list)) { 5988c2ecf20Sopenharmony_ci printk(JFFS2_DBG "erase_checking_list: empty\n"); 5998c2ecf20Sopenharmony_ci } else { 6008c2ecf20Sopenharmony_ci struct list_head *this; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci list_for_each(this, &c->erase_checking_list) { 6038c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 6068c2ecf20Sopenharmony_ci printk(JFFS2_DBG "erase_checking_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", 6078c2ecf20Sopenharmony_ci jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 6088c2ecf20Sopenharmony_ci jeb->unchecked_size, jeb->free_size); 6098c2ecf20Sopenharmony_ci } 6108c2ecf20Sopenharmony_ci } 6118c2ecf20Sopenharmony_ci } 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci if (list_empty(&c->erase_pending_list)) { 6148c2ecf20Sopenharmony_ci printk(JFFS2_DBG "erase_pending_list: empty\n"); 6158c2ecf20Sopenharmony_ci } else { 6168c2ecf20Sopenharmony_ci struct list_head *this; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci list_for_each(this, &c->erase_pending_list) { 6198c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 6228c2ecf20Sopenharmony_ci printk(JFFS2_DBG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", 6238c2ecf20Sopenharmony_ci jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 6248c2ecf20Sopenharmony_ci jeb->unchecked_size, jeb->free_size); 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci } 6278c2ecf20Sopenharmony_ci } 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci if (list_empty(&c->erasable_pending_wbuf_list)) { 6308c2ecf20Sopenharmony_ci printk(JFFS2_DBG "erasable_pending_wbuf_list: empty\n"); 6318c2ecf20Sopenharmony_ci } else { 6328c2ecf20Sopenharmony_ci struct list_head *this; 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci list_for_each(this, &c->erasable_pending_wbuf_list) { 6358c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 6388c2ecf20Sopenharmony_ci printk(JFFS2_DBG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", 6398c2ecf20Sopenharmony_ci jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 6408c2ecf20Sopenharmony_ci jeb->unchecked_size, jeb->free_size); 6418c2ecf20Sopenharmony_ci } 6428c2ecf20Sopenharmony_ci } 6438c2ecf20Sopenharmony_ci } 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci if (list_empty(&c->free_list)) { 6468c2ecf20Sopenharmony_ci printk(JFFS2_DBG "free_list: empty\n"); 6478c2ecf20Sopenharmony_ci } else { 6488c2ecf20Sopenharmony_ci struct list_head *this; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci list_for_each(this, &c->free_list) { 6518c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 6548c2ecf20Sopenharmony_ci printk(JFFS2_DBG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", 6558c2ecf20Sopenharmony_ci jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 6568c2ecf20Sopenharmony_ci jeb->unchecked_size, jeb->free_size); 6578c2ecf20Sopenharmony_ci } 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci } 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci if (list_empty(&c->bad_list)) { 6628c2ecf20Sopenharmony_ci printk(JFFS2_DBG "bad_list: empty\n"); 6638c2ecf20Sopenharmony_ci } else { 6648c2ecf20Sopenharmony_ci struct list_head *this; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci list_for_each(this, &c->bad_list) { 6678c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 6708c2ecf20Sopenharmony_ci printk(JFFS2_DBG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", 6718c2ecf20Sopenharmony_ci jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 6728c2ecf20Sopenharmony_ci jeb->unchecked_size, jeb->free_size); 6738c2ecf20Sopenharmony_ci } 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci if (list_empty(&c->bad_used_list)) { 6788c2ecf20Sopenharmony_ci printk(JFFS2_DBG "bad_used_list: empty\n"); 6798c2ecf20Sopenharmony_ci } else { 6808c2ecf20Sopenharmony_ci struct list_head *this; 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci list_for_each(this, &c->bad_used_list) { 6838c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 6868c2ecf20Sopenharmony_ci printk(JFFS2_DBG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", 6878c2ecf20Sopenharmony_ci jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 6888c2ecf20Sopenharmony_ci jeb->unchecked_size, jeb->free_size); 6898c2ecf20Sopenharmony_ci } 6908c2ecf20Sopenharmony_ci } 6918c2ecf20Sopenharmony_ci } 6928c2ecf20Sopenharmony_ci} 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_civoid 6958c2ecf20Sopenharmony_ci__jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f) 6968c2ecf20Sopenharmony_ci{ 6978c2ecf20Sopenharmony_ci mutex_lock(&f->sem); 6988c2ecf20Sopenharmony_ci jffs2_dbg_dump_fragtree_nolock(f); 6998c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 7008c2ecf20Sopenharmony_ci} 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_civoid 7038c2ecf20Sopenharmony_ci__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f) 7048c2ecf20Sopenharmony_ci{ 7058c2ecf20Sopenharmony_ci struct jffs2_node_frag *this = frag_first(&f->fragtree); 7068c2ecf20Sopenharmony_ci uint32_t lastofs = 0; 7078c2ecf20Sopenharmony_ci int buggy = 0; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci printk(JFFS2_DBG_MSG_PREFIX " dump fragtree of ino #%u\n", f->inocache->ino); 7108c2ecf20Sopenharmony_ci while(this) { 7118c2ecf20Sopenharmony_ci if (this->node) 7128c2ecf20Sopenharmony_ci printk(JFFS2_DBG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), right (%p), parent (%p)\n", 7138c2ecf20Sopenharmony_ci this->ofs, this->ofs+this->size, ref_offset(this->node->raw), 7148c2ecf20Sopenharmony_ci ref_flags(this->node->raw), this, frag_left(this), frag_right(this), 7158c2ecf20Sopenharmony_ci frag_parent(this)); 7168c2ecf20Sopenharmony_ci else 7178c2ecf20Sopenharmony_ci printk(JFFS2_DBG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n", 7188c2ecf20Sopenharmony_ci this->ofs, this->ofs+this->size, this, frag_left(this), 7198c2ecf20Sopenharmony_ci frag_right(this), frag_parent(this)); 7208c2ecf20Sopenharmony_ci if (this->ofs != lastofs) 7218c2ecf20Sopenharmony_ci buggy = 1; 7228c2ecf20Sopenharmony_ci lastofs = this->ofs + this->size; 7238c2ecf20Sopenharmony_ci this = frag_next(this); 7248c2ecf20Sopenharmony_ci } 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci if (f->metadata) 7278c2ecf20Sopenharmony_ci printk(JFFS2_DBG "metadata at 0x%08x\n", ref_offset(f->metadata->raw)); 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci if (buggy) { 7308c2ecf20Sopenharmony_ci JFFS2_ERROR("frag tree got a hole in it.\n"); 7318c2ecf20Sopenharmony_ci BUG(); 7328c2ecf20Sopenharmony_ci } 7338c2ecf20Sopenharmony_ci} 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci#define JFFS2_BUFDUMP_BYTES_PER_LINE 32 7368c2ecf20Sopenharmony_civoid 7378c2ecf20Sopenharmony_ci__jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs) 7388c2ecf20Sopenharmony_ci{ 7398c2ecf20Sopenharmony_ci int skip; 7408c2ecf20Sopenharmony_ci int i; 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n", 7438c2ecf20Sopenharmony_ci offs, offs + len, len); 7448c2ecf20Sopenharmony_ci i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE; 7458c2ecf20Sopenharmony_ci offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1); 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci if (skip != 0) 7488c2ecf20Sopenharmony_ci printk(JFFS2_DBG "%#08x: ", offs); 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci while (skip--) 7518c2ecf20Sopenharmony_ci printk(" "); 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci while (i < len) { 7548c2ecf20Sopenharmony_ci if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) { 7558c2ecf20Sopenharmony_ci if (i != 0) 7568c2ecf20Sopenharmony_ci printk("\n"); 7578c2ecf20Sopenharmony_ci offs += JFFS2_BUFDUMP_BYTES_PER_LINE; 7588c2ecf20Sopenharmony_ci printk(JFFS2_DBG "%0#8x: ", offs); 7598c2ecf20Sopenharmony_ci } 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci printk("%02x ", buf[i]); 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci i += 1; 7648c2ecf20Sopenharmony_ci } 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci printk("\n"); 7678c2ecf20Sopenharmony_ci} 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci/* 7708c2ecf20Sopenharmony_ci * Dump a JFFS2 node. 7718c2ecf20Sopenharmony_ci */ 7728c2ecf20Sopenharmony_civoid 7738c2ecf20Sopenharmony_ci__jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) 7748c2ecf20Sopenharmony_ci{ 7758c2ecf20Sopenharmony_ci union jffs2_node_union node; 7768c2ecf20Sopenharmony_ci int len = sizeof(union jffs2_node_union); 7778c2ecf20Sopenharmony_ci size_t retlen; 7788c2ecf20Sopenharmony_ci uint32_t crc; 7798c2ecf20Sopenharmony_ci int ret; 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs); 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node); 7848c2ecf20Sopenharmony_ci if (ret || (retlen != len)) { 7858c2ecf20Sopenharmony_ci JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n", 7868c2ecf20Sopenharmony_ci len, ret, retlen); 7878c2ecf20Sopenharmony_ci return; 7888c2ecf20Sopenharmony_ci } 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci printk(JFFS2_DBG "magic:\t%#04x\n", je16_to_cpu(node.u.magic)); 7918c2ecf20Sopenharmony_ci printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype)); 7928c2ecf20Sopenharmony_ci printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen)); 7938c2ecf20Sopenharmony_ci printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc)); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci crc = crc32(0, &node.u, sizeof(node.u) - 4); 7968c2ecf20Sopenharmony_ci if (crc != je32_to_cpu(node.u.hdr_crc)) { 7978c2ecf20Sopenharmony_ci JFFS2_ERROR("wrong common header CRC.\n"); 7988c2ecf20Sopenharmony_ci return; 7998c2ecf20Sopenharmony_ci } 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK && 8028c2ecf20Sopenharmony_ci je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK) 8038c2ecf20Sopenharmony_ci { 8048c2ecf20Sopenharmony_ci JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n", 8058c2ecf20Sopenharmony_ci je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK); 8068c2ecf20Sopenharmony_ci return; 8078c2ecf20Sopenharmony_ci } 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci switch(je16_to_cpu(node.u.nodetype)) { 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci case JFFS2_NODETYPE_INODE: 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci printk(JFFS2_DBG "the node is inode node\n"); 8148c2ecf20Sopenharmony_ci printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.i.ino)); 8158c2ecf20Sopenharmony_ci printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.i.version)); 8168c2ecf20Sopenharmony_ci printk(JFFS2_DBG "mode:\t%#08x\n", node.i.mode.m); 8178c2ecf20Sopenharmony_ci printk(JFFS2_DBG "uid:\t%#04x\n", je16_to_cpu(node.i.uid)); 8188c2ecf20Sopenharmony_ci printk(JFFS2_DBG "gid:\t%#04x\n", je16_to_cpu(node.i.gid)); 8198c2ecf20Sopenharmony_ci printk(JFFS2_DBG "isize:\t%#08x\n", je32_to_cpu(node.i.isize)); 8208c2ecf20Sopenharmony_ci printk(JFFS2_DBG "atime:\t%#08x\n", je32_to_cpu(node.i.atime)); 8218c2ecf20Sopenharmony_ci printk(JFFS2_DBG "mtime:\t%#08x\n", je32_to_cpu(node.i.mtime)); 8228c2ecf20Sopenharmony_ci printk(JFFS2_DBG "ctime:\t%#08x\n", je32_to_cpu(node.i.ctime)); 8238c2ecf20Sopenharmony_ci printk(JFFS2_DBG "offset:\t%#08x\n", je32_to_cpu(node.i.offset)); 8248c2ecf20Sopenharmony_ci printk(JFFS2_DBG "csize:\t%#08x\n", je32_to_cpu(node.i.csize)); 8258c2ecf20Sopenharmony_ci printk(JFFS2_DBG "dsize:\t%#08x\n", je32_to_cpu(node.i.dsize)); 8268c2ecf20Sopenharmony_ci printk(JFFS2_DBG "compr:\t%#02x\n", node.i.compr); 8278c2ecf20Sopenharmony_ci printk(JFFS2_DBG "usercompr:\t%#02x\n", node.i.usercompr); 8288c2ecf20Sopenharmony_ci printk(JFFS2_DBG "flags:\t%#04x\n", je16_to_cpu(node.i.flags)); 8298c2ecf20Sopenharmony_ci printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc)); 8308c2ecf20Sopenharmony_ci printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc)); 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci crc = crc32(0, &node.i, sizeof(node.i) - 8); 8338c2ecf20Sopenharmony_ci if (crc != je32_to_cpu(node.i.node_crc)) { 8348c2ecf20Sopenharmony_ci JFFS2_ERROR("wrong node header CRC.\n"); 8358c2ecf20Sopenharmony_ci return; 8368c2ecf20Sopenharmony_ci } 8378c2ecf20Sopenharmony_ci break; 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci case JFFS2_NODETYPE_DIRENT: 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci printk(JFFS2_DBG "the node is dirent node\n"); 8428c2ecf20Sopenharmony_ci printk(JFFS2_DBG "pino:\t%#08x\n", je32_to_cpu(node.d.pino)); 8438c2ecf20Sopenharmony_ci printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.d.version)); 8448c2ecf20Sopenharmony_ci printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.d.ino)); 8458c2ecf20Sopenharmony_ci printk(JFFS2_DBG "mctime:\t%#08x\n", je32_to_cpu(node.d.mctime)); 8468c2ecf20Sopenharmony_ci printk(JFFS2_DBG "nsize:\t%#02x\n", node.d.nsize); 8478c2ecf20Sopenharmony_ci printk(JFFS2_DBG "type:\t%#02x\n", node.d.type); 8488c2ecf20Sopenharmony_ci printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc)); 8498c2ecf20Sopenharmony_ci printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc)); 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci node.d.name[node.d.nsize] = '\0'; 8528c2ecf20Sopenharmony_ci printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name); 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci crc = crc32(0, &node.d, sizeof(node.d) - 8); 8558c2ecf20Sopenharmony_ci if (crc != je32_to_cpu(node.d.node_crc)) { 8568c2ecf20Sopenharmony_ci JFFS2_ERROR("wrong node header CRC.\n"); 8578c2ecf20Sopenharmony_ci return; 8588c2ecf20Sopenharmony_ci } 8598c2ecf20Sopenharmony_ci break; 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci default: 8628c2ecf20Sopenharmony_ci printk(JFFS2_DBG "node type is unknown\n"); 8638c2ecf20Sopenharmony_ci break; 8648c2ecf20Sopenharmony_ci } 8658c2ecf20Sopenharmony_ci} 8668c2ecf20Sopenharmony_ci#endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */ 867