1730554d9SArtem B. Bityutskiy /* 2730554d9SArtem B. Bityutskiy * JFFS2 -- Journalling Flash File System, Version 2. 3730554d9SArtem B. Bityutskiy * 4730554d9SArtem B. Bityutskiy * Copyright (C) 2001-2003 Red Hat, Inc. 5730554d9SArtem B. Bityutskiy * 6730554d9SArtem B. Bityutskiy * Created by David Woodhouse <dwmw2@infradead.org> 7730554d9SArtem B. Bityutskiy * 8730554d9SArtem B. Bityutskiy * For licensing information, see the file 'LICENCE' in this directory. 9730554d9SArtem B. Bityutskiy * 10*e0c8e42fSArtem B. Bityutskiy * $Id: debug.c,v 1.7 2005/07/24 15:14:14 dedekind Exp $ 11730554d9SArtem B. Bityutskiy * 12730554d9SArtem B. Bityutskiy */ 13730554d9SArtem B. Bityutskiy #include <linux/kernel.h> 14730554d9SArtem B. Bityutskiy #include <linux/pagemap.h> 15*e0c8e42fSArtem B. Bityutskiy #include <linux/crc32.h> 16*e0c8e42fSArtem B. Bityutskiy #include <linux/jffs2.h> 17730554d9SArtem B. Bityutskiy #include "nodelist.h" 18730554d9SArtem B. Bityutskiy #include "debug.h" 19730554d9SArtem B. Bityutskiy 20730554d9SArtem B. Bityutskiy #ifdef JFFS2_DBG_PARANOIA_CHECKS 21*e0c8e42fSArtem B. Bityutskiy /* 22*e0c8e42fSArtem B. Bityutskiy * Check the fragtree. 23*e0c8e42fSArtem B. Bityutskiy */ 24*e0c8e42fSArtem B. Bityutskiy void 25*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f) 26*e0c8e42fSArtem B. Bityutskiy { 27*e0c8e42fSArtem B. Bityutskiy down(&f->sem); 28*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_fragtree_paranoia_check_nolock(f); 29*e0c8e42fSArtem B. Bityutskiy up(&f->sem); 30*e0c8e42fSArtem B. Bityutskiy } 31730554d9SArtem B. Bityutskiy 32730554d9SArtem B. Bityutskiy void 33*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f) 34730554d9SArtem B. Bityutskiy { 35730554d9SArtem B. Bityutskiy struct jffs2_node_frag *frag; 36730554d9SArtem B. Bityutskiy int bitched = 0; 37730554d9SArtem B. Bityutskiy 38730554d9SArtem B. Bityutskiy for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) { 39730554d9SArtem B. Bityutskiy struct jffs2_full_dnode *fn = frag->node; 40730554d9SArtem B. Bityutskiy 41730554d9SArtem B. Bityutskiy if (!fn || !fn->raw) 42730554d9SArtem B. Bityutskiy continue; 43730554d9SArtem B. Bityutskiy 44730554d9SArtem B. Bityutskiy if (ref_flags(fn->raw) == REF_PRISTINE) { 45730554d9SArtem B. Bityutskiy if (fn->frags > 1) { 46*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n", 47730554d9SArtem B. Bityutskiy ref_offset(fn->raw), fn->frags); 48730554d9SArtem B. Bityutskiy bitched = 1; 49730554d9SArtem B. Bityutskiy } 50730554d9SArtem B. Bityutskiy 51730554d9SArtem B. Bityutskiy /* A hole node which isn't multi-page should be garbage-collected 52730554d9SArtem B. Bityutskiy and merged anyway, so we just check for the frag size here, 53730554d9SArtem B. Bityutskiy rather than mucking around with actually reading the node 54730554d9SArtem B. Bityutskiy and checking the compression type, which is the real way 55730554d9SArtem B. Bityutskiy to tell a hole node. */ 56730554d9SArtem B. Bityutskiy if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag) 57730554d9SArtem B. Bityutskiy && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) { 58*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag " 59*e0c8e42fSArtem B. Bityutskiy "in the same page. Tell dwmw2.\n", ref_offset(fn->raw)); 60730554d9SArtem B. Bityutskiy bitched = 1; 61730554d9SArtem B. Bityutskiy } 62730554d9SArtem B. Bityutskiy 63730554d9SArtem B. Bityutskiy if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag) 64730554d9SArtem B. Bityutskiy && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) { 65*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following " 66*e0c8e42fSArtem B. Bityutskiy "non-hole frag in the same page. Tell dwmw2.\n", 67730554d9SArtem B. Bityutskiy ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size); 68730554d9SArtem B. Bityutskiy bitched = 1; 69730554d9SArtem B. Bityutskiy } 70730554d9SArtem B. Bityutskiy } 71730554d9SArtem B. Bityutskiy } 72730554d9SArtem B. Bityutskiy 73730554d9SArtem B. Bityutskiy if (bitched) { 74*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("fragtree is corrupted.\n"); 75*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_fragtree_nolock(f); 76730554d9SArtem B. Bityutskiy BUG(); 77730554d9SArtem B. Bityutskiy } 78730554d9SArtem B. Bityutskiy } 79730554d9SArtem B. Bityutskiy 80730554d9SArtem B. Bityutskiy /* 81730554d9SArtem B. Bityutskiy * Check if the flash contains all 0xFF before we start writing. 82730554d9SArtem B. Bityutskiy */ 83730554d9SArtem B. Bityutskiy void 84*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, 85*e0c8e42fSArtem B. Bityutskiy uint32_t ofs, int len) 86730554d9SArtem B. Bityutskiy { 87730554d9SArtem B. Bityutskiy size_t retlen; 88730554d9SArtem B. Bityutskiy int ret, i; 89730554d9SArtem B. Bityutskiy unsigned char *buf; 90730554d9SArtem B. Bityutskiy 91730554d9SArtem B. Bityutskiy buf = kmalloc(len, GFP_KERNEL); 92730554d9SArtem B. Bityutskiy if (!buf) 93730554d9SArtem B. Bityutskiy return; 94730554d9SArtem B. Bityutskiy 95730554d9SArtem B. Bityutskiy ret = jffs2_flash_read(c, ofs, len, &retlen, buf); 96730554d9SArtem B. Bityutskiy if (ret || (retlen != len)) { 97*e0c8e42fSArtem B. Bityutskiy JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n", 98*e0c8e42fSArtem B. Bityutskiy len, ret, retlen); 99730554d9SArtem B. Bityutskiy kfree(buf); 100730554d9SArtem B. Bityutskiy return; 101730554d9SArtem B. Bityutskiy } 102730554d9SArtem B. Bityutskiy 103730554d9SArtem B. Bityutskiy ret = 0; 104730554d9SArtem B. Bityutskiy for (i = 0; i < len; i++) 105730554d9SArtem B. Bityutskiy if (buf[i] != 0xff) 106730554d9SArtem B. Bityutskiy ret = 1; 107730554d9SArtem B. Bityutskiy 108730554d9SArtem B. Bityutskiy if (ret) { 109*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("argh, about to write node to %#08x on flash, but there are data " 110*e0c8e42fSArtem B. Bityutskiy "already there. The first corrupted byte is at %#08x offset.\n", ofs, ofs + i); 111*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_buffer(buf, len, ofs); 112730554d9SArtem B. Bityutskiy kfree(buf); 113730554d9SArtem B. Bityutskiy BUG(); 114730554d9SArtem B. Bityutskiy } 115730554d9SArtem B. Bityutskiy 116730554d9SArtem B. Bityutskiy kfree(buf); 117730554d9SArtem B. Bityutskiy } 118730554d9SArtem B. Bityutskiy 119730554d9SArtem B. Bityutskiy /* 120730554d9SArtem B. Bityutskiy * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'. 121730554d9SArtem B. Bityutskiy */ 122730554d9SArtem B. Bityutskiy void 123*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, 124*e0c8e42fSArtem B. Bityutskiy struct jffs2_eraseblock *jeb) 125*e0c8e42fSArtem B. Bityutskiy { 126*e0c8e42fSArtem B. Bityutskiy spin_lock(&c->erase_completion_lock); 127*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_acct_paranoia_check_nolock(c, jeb); 128*e0c8e42fSArtem B. Bityutskiy spin_unlock(&c->erase_completion_lock); 129*e0c8e42fSArtem B. Bityutskiy } 130*e0c8e42fSArtem B. Bityutskiy 131*e0c8e42fSArtem B. Bityutskiy void 132*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c, 133*e0c8e42fSArtem B. Bityutskiy struct jffs2_eraseblock *jeb) 134730554d9SArtem B. Bityutskiy { 135730554d9SArtem B. Bityutskiy uint32_t my_used_size = 0; 136730554d9SArtem B. Bityutskiy uint32_t my_unchecked_size = 0; 137730554d9SArtem B. Bityutskiy uint32_t my_dirty_size = 0; 138730554d9SArtem B. Bityutskiy struct jffs2_raw_node_ref *ref2 = jeb->first_node; 139730554d9SArtem B. Bityutskiy 140730554d9SArtem B. Bityutskiy while (ref2) { 141730554d9SArtem B. Bityutskiy uint32_t totlen = ref_totlen(c, jeb, ref2); 142730554d9SArtem B. Bityutskiy 143730554d9SArtem B. Bityutskiy if (ref2->flash_offset < jeb->offset || 144730554d9SArtem B. Bityutskiy ref2->flash_offset > jeb->offset + c->sector_size) { 145*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n", 146730554d9SArtem B. Bityutskiy ref_offset(ref2), jeb->offset); 147*e0c8e42fSArtem B. Bityutskiy goto error; 148730554d9SArtem B. Bityutskiy 149730554d9SArtem B. Bityutskiy } 150730554d9SArtem B. Bityutskiy if (ref_flags(ref2) == REF_UNCHECKED) 151730554d9SArtem B. Bityutskiy my_unchecked_size += totlen; 152730554d9SArtem B. Bityutskiy else if (!ref_obsolete(ref2)) 153730554d9SArtem B. Bityutskiy my_used_size += totlen; 154730554d9SArtem B. Bityutskiy else 155730554d9SArtem B. Bityutskiy my_dirty_size += totlen; 156730554d9SArtem B. Bityutskiy 157730554d9SArtem B. Bityutskiy if ((!ref2->next_phys) != (ref2 == jeb->last_node)) { 158*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), " 159*e0c8e42fSArtem B. Bityutskiy "last_node is at %#08x (mem %p).\n", 160730554d9SArtem B. Bityutskiy ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys, 161730554d9SArtem B. Bityutskiy ref_offset(jeb->last_node), jeb->last_node); 162*e0c8e42fSArtem B. Bityutskiy goto error; 163730554d9SArtem B. Bityutskiy } 164730554d9SArtem B. Bityutskiy ref2 = ref2->next_phys; 165730554d9SArtem B. Bityutskiy } 166730554d9SArtem B. Bityutskiy 167730554d9SArtem B. Bityutskiy if (my_used_size != jeb->used_size) { 168*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n", 169730554d9SArtem B. Bityutskiy my_used_size, jeb->used_size); 170*e0c8e42fSArtem B. Bityutskiy goto error; 171730554d9SArtem B. Bityutskiy } 172730554d9SArtem B. Bityutskiy 173730554d9SArtem B. Bityutskiy if (my_unchecked_size != jeb->unchecked_size) { 174*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n", 175730554d9SArtem B. Bityutskiy my_unchecked_size, jeb->unchecked_size); 176*e0c8e42fSArtem B. Bityutskiy goto error; 177730554d9SArtem B. Bityutskiy } 178730554d9SArtem B. Bityutskiy 179*e0c8e42fSArtem B. Bityutskiy #if 0 180*e0c8e42fSArtem B. Bityutskiy /* This should work when we implement ref->__totlen elemination */ 181730554d9SArtem B. Bityutskiy if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) { 182*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n", 183730554d9SArtem B. Bityutskiy my_dirty_size, jeb->dirty_size + jeb->wasted_size); 184*e0c8e42fSArtem B. Bityutskiy goto error; 185730554d9SArtem B. Bityutskiy } 186730554d9SArtem B. Bityutskiy 187730554d9SArtem B. Bityutskiy if (jeb->free_size == 0 188730554d9SArtem B. Bityutskiy && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) { 189*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n", 190730554d9SArtem B. Bityutskiy my_used_size + my_unchecked_size + my_dirty_size, 191730554d9SArtem B. Bityutskiy c->sector_size); 192*e0c8e42fSArtem B. Bityutskiy goto error; 193730554d9SArtem B. Bityutskiy } 194*e0c8e42fSArtem B. Bityutskiy #endif 195730554d9SArtem B. Bityutskiy 196*e0c8e42fSArtem B. Bityutskiy return; 197*e0c8e42fSArtem B. Bityutskiy 198*e0c8e42fSArtem B. Bityutskiy error: 199*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_node_refs_nolock(c, jeb); 200*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_jeb_nolock(jeb); 201*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_block_lists_nolock(c); 202*e0c8e42fSArtem B. Bityutskiy BUG(); 203*e0c8e42fSArtem B. Bityutskiy 204*e0c8e42fSArtem B. Bityutskiy } 205*e0c8e42fSArtem B. Bityutskiy #endif /* JFFS2_DBG_PARANOIA_CHECKS */ 206*e0c8e42fSArtem B. Bityutskiy 207*e0c8e42fSArtem B. Bityutskiy #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS) 208730554d9SArtem B. Bityutskiy /* 209730554d9SArtem B. Bityutskiy * Dump the node_refs of the 'jeb' JFFS2 eraseblock. 210730554d9SArtem B. Bityutskiy */ 211730554d9SArtem B. Bityutskiy void 212*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c, 213*e0c8e42fSArtem B. Bityutskiy struct jffs2_eraseblock *jeb) 214*e0c8e42fSArtem B. Bityutskiy { 215*e0c8e42fSArtem B. Bityutskiy spin_lock(&c->erase_completion_lock); 216*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_node_refs_nolock(c, jeb); 217*e0c8e42fSArtem B. Bityutskiy spin_unlock(&c->erase_completion_lock); 218*e0c8e42fSArtem B. Bityutskiy } 219*e0c8e42fSArtem B. Bityutskiy 220*e0c8e42fSArtem B. Bityutskiy void 221*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c, 222*e0c8e42fSArtem B. Bityutskiy struct jffs2_eraseblock *jeb) 223730554d9SArtem B. Bityutskiy { 224730554d9SArtem B. Bityutskiy struct jffs2_raw_node_ref *ref; 225730554d9SArtem B. Bityutskiy int i = 0; 226730554d9SArtem B. Bityutskiy 227*e0c8e42fSArtem B. Bityutskiy JFFS2_DEBUG("Dump node_refs of the eraseblock %#08x\n", jeb->offset); 228730554d9SArtem B. Bityutskiy if (!jeb->first_node) { 229*e0c8e42fSArtem B. Bityutskiy JFFS2_DEBUG("no nodes in the eraseblock %#08x\n", jeb->offset); 230730554d9SArtem B. Bityutskiy return; 231730554d9SArtem B. Bityutskiy } 232730554d9SArtem B. Bityutskiy 233*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL); 234730554d9SArtem B. Bityutskiy for (ref = jeb->first_node; ; ref = ref->next_phys) { 235730554d9SArtem B. Bityutskiy printk("%#08x(%#x)", ref_offset(ref), ref->__totlen); 236730554d9SArtem B. Bityutskiy if (ref->next_phys) 237730554d9SArtem B. Bityutskiy printk("->"); 238730554d9SArtem B. Bityutskiy else 239730554d9SArtem B. Bityutskiy break; 240730554d9SArtem B. Bityutskiy if (++i == 4) { 241730554d9SArtem B. Bityutskiy i = 0; 242*e0c8e42fSArtem B. Bityutskiy printk("\n" JFFS2_DBG_LVL); 243730554d9SArtem B. Bityutskiy } 244730554d9SArtem B. Bityutskiy } 245730554d9SArtem B. Bityutskiy printk("\n"); 246730554d9SArtem B. Bityutskiy } 247730554d9SArtem B. Bityutskiy 248*e0c8e42fSArtem B. Bityutskiy /* 249*e0c8e42fSArtem B. Bityutskiy * Dump an eraseblock's space accounting. 250*e0c8e42fSArtem B. Bityutskiy */ 251730554d9SArtem B. Bityutskiy void 252*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 253730554d9SArtem B. Bityutskiy { 254*e0c8e42fSArtem B. Bityutskiy spin_lock(&c->erase_completion_lock); 255*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_jeb_nolock(jeb); 256*e0c8e42fSArtem B. Bityutskiy spin_unlock(&c->erase_completion_lock); 257*e0c8e42fSArtem B. Bityutskiy } 258*e0c8e42fSArtem B. Bityutskiy 259*e0c8e42fSArtem B. Bityutskiy void 260*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb) 261*e0c8e42fSArtem B. Bityutskiy { 262*e0c8e42fSArtem B. Bityutskiy if (!jeb) 263*e0c8e42fSArtem B. Bityutskiy return; 264*e0c8e42fSArtem B. Bityutskiy 265*e0c8e42fSArtem B. Bityutskiy JFFS2_DEBUG("dump space accounting for the eraseblock at %#08x:\n", 266*e0c8e42fSArtem B. Bityutskiy jeb->offset); 267*e0c8e42fSArtem B. Bityutskiy 268*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "used_size: %#08x\n", jeb->used_size); 269*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", jeb->dirty_size); 270*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", jeb->wasted_size); 271*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", jeb->unchecked_size); 272*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "free_size: %#08x\n", jeb->free_size); 273*e0c8e42fSArtem B. Bityutskiy } 274*e0c8e42fSArtem B. Bityutskiy 275*e0c8e42fSArtem B. Bityutskiy void 276*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) 277*e0c8e42fSArtem B. Bityutskiy { 278*e0c8e42fSArtem B. Bityutskiy spin_lock(&c->erase_completion_lock); 279*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_block_lists_nolock(c); 280*e0c8e42fSArtem B. Bityutskiy spin_unlock(&c->erase_completion_lock); 281*e0c8e42fSArtem B. Bityutskiy } 282*e0c8e42fSArtem B. Bityutskiy 283*e0c8e42fSArtem B. Bityutskiy void 284*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) 285*e0c8e42fSArtem B. Bityutskiy { 286*e0c8e42fSArtem B. Bityutskiy JFFS2_DEBUG("dump JFFS2 blocks lists:\n"); 287*e0c8e42fSArtem B. Bityutskiy 288*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "flash_size: %#08x\n", c->flash_size); 289*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "used_size: %#08x\n", c->used_size); 290*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", c->dirty_size); 291*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", c->wasted_size); 292*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", c->unchecked_size); 293*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "free_size: %#08x\n", c->free_size); 294*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "erasing_size: %#08x\n", c->erasing_size); 295*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "bad_size: %#08x\n", c->bad_size); 296*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "sector_size: %#08x\n", c->sector_size); 297*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "jffs2_reserved_blocks size: %#08x\n", 298730554d9SArtem B. Bityutskiy c->sector_size * c->resv_blocks_write); 299730554d9SArtem B. Bityutskiy 300730554d9SArtem B. Bityutskiy if (c->nextblock) 301*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, " 302730554d9SArtem B. Bityutskiy "unchecked %#08x, free %#08x)\n", 303730554d9SArtem B. Bityutskiy c->nextblock->offset, c->nextblock->used_size, 304730554d9SArtem B. Bityutskiy c->nextblock->dirty_size, c->nextblock->wasted_size, 305730554d9SArtem B. Bityutskiy c->nextblock->unchecked_size, c->nextblock->free_size); 306730554d9SArtem B. Bityutskiy else 307*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "nextblock: NULL\n"); 308730554d9SArtem B. Bityutskiy 309730554d9SArtem B. Bityutskiy if (c->gcblock) 310*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, " 311730554d9SArtem B. Bityutskiy "unchecked %#08x, free %#08x)\n", 312730554d9SArtem B. Bityutskiy c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, 313730554d9SArtem B. Bityutskiy c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size); 314730554d9SArtem B. Bityutskiy else 315*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "gcblock: NULL\n"); 316730554d9SArtem B. Bityutskiy 317730554d9SArtem B. Bityutskiy if (list_empty(&c->clean_list)) { 318*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "clean_list: empty\n"); 319730554d9SArtem B. Bityutskiy } else { 320730554d9SArtem B. Bityutskiy struct list_head *this; 321730554d9SArtem B. Bityutskiy int numblocks = 0; 322730554d9SArtem B. Bityutskiy uint32_t dirty = 0; 323730554d9SArtem B. Bityutskiy 324730554d9SArtem B. Bityutskiy list_for_each(this, &c->clean_list) { 325730554d9SArtem B. Bityutskiy struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 326730554d9SArtem B. Bityutskiy numblocks ++; 327730554d9SArtem B. Bityutskiy dirty += jeb->wasted_size; 328730554d9SArtem B. Bityutskiy if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 329*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " 330730554d9SArtem B. Bityutskiy "unchecked %#08x, free %#08x)\n", 331730554d9SArtem B. Bityutskiy jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 332730554d9SArtem B. Bityutskiy jeb->unchecked_size, jeb->free_size); 333730554d9SArtem B. Bityutskiy } 334730554d9SArtem B. Bityutskiy } 335730554d9SArtem B. Bityutskiy 336*e0c8e42fSArtem B. Bityutskiy printk (JFFS2_DBG_LVL "Contains %d blocks with total wasted size %u, average wasted size: %u\n", 337730554d9SArtem B. Bityutskiy numblocks, dirty, dirty / numblocks); 338730554d9SArtem B. Bityutskiy } 339730554d9SArtem B. Bityutskiy 340730554d9SArtem B. Bityutskiy if (list_empty(&c->very_dirty_list)) { 341*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "very_dirty_list: empty\n"); 342730554d9SArtem B. Bityutskiy } else { 343730554d9SArtem B. Bityutskiy struct list_head *this; 344730554d9SArtem B. Bityutskiy int numblocks = 0; 345730554d9SArtem B. Bityutskiy uint32_t dirty = 0; 346730554d9SArtem B. Bityutskiy 347730554d9SArtem B. Bityutskiy list_for_each(this, &c->very_dirty_list) { 348730554d9SArtem B. Bityutskiy struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 349730554d9SArtem B. Bityutskiy 350730554d9SArtem B. Bityutskiy numblocks ++; 351730554d9SArtem B. Bityutskiy dirty += jeb->dirty_size; 352730554d9SArtem B. Bityutskiy if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 353*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " 354730554d9SArtem B. Bityutskiy "unchecked %#08x, free %#08x)\n", 355730554d9SArtem B. Bityutskiy jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 356730554d9SArtem B. Bityutskiy jeb->unchecked_size, jeb->free_size); 357730554d9SArtem B. Bityutskiy } 358730554d9SArtem B. Bityutskiy } 359730554d9SArtem B. Bityutskiy 360*e0c8e42fSArtem B. Bityutskiy printk (JFFS2_DBG_LVL "Contains %d blocks with total dirty size %u, average dirty size: %u\n", 361730554d9SArtem B. Bityutskiy numblocks, dirty, dirty / numblocks); 362730554d9SArtem B. Bityutskiy } 363730554d9SArtem B. Bityutskiy 364730554d9SArtem B. Bityutskiy if (list_empty(&c->dirty_list)) { 365*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "dirty_list: empty\n"); 366730554d9SArtem B. Bityutskiy } else { 367730554d9SArtem B. Bityutskiy struct list_head *this; 368730554d9SArtem B. Bityutskiy int numblocks = 0; 369730554d9SArtem B. Bityutskiy uint32_t dirty = 0; 370730554d9SArtem B. Bityutskiy 371730554d9SArtem B. Bityutskiy list_for_each(this, &c->dirty_list) { 372730554d9SArtem B. Bityutskiy struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 373730554d9SArtem B. Bityutskiy 374730554d9SArtem B. Bityutskiy numblocks ++; 375730554d9SArtem B. Bityutskiy dirty += jeb->dirty_size; 376730554d9SArtem B. Bityutskiy if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 377*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " 378730554d9SArtem B. Bityutskiy "unchecked %#08x, free %#08x)\n", 379730554d9SArtem B. Bityutskiy jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 380730554d9SArtem B. Bityutskiy jeb->unchecked_size, jeb->free_size); 381730554d9SArtem B. Bityutskiy } 382730554d9SArtem B. Bityutskiy } 383730554d9SArtem B. Bityutskiy 384*e0c8e42fSArtem B. Bityutskiy printk (JFFS2_DBG_LVL "contains %d blocks with total dirty size %u, average dirty size: %u\n", 385730554d9SArtem B. Bityutskiy numblocks, dirty, dirty / numblocks); 386730554d9SArtem B. Bityutskiy } 387730554d9SArtem B. Bityutskiy 388730554d9SArtem B. Bityutskiy if (list_empty(&c->erasable_list)) { 389*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "erasable_list: empty\n"); 390730554d9SArtem B. Bityutskiy } else { 391730554d9SArtem B. Bityutskiy struct list_head *this; 392730554d9SArtem B. Bityutskiy 393730554d9SArtem B. Bityutskiy list_for_each(this, &c->erasable_list) { 394730554d9SArtem B. Bityutskiy struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 395730554d9SArtem B. Bityutskiy 396730554d9SArtem B. Bityutskiy if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 397*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " 398730554d9SArtem B. Bityutskiy "unchecked %#08x, free %#08x)\n", 399730554d9SArtem B. Bityutskiy jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 400730554d9SArtem B. Bityutskiy jeb->unchecked_size, jeb->free_size); 401730554d9SArtem B. Bityutskiy } 402730554d9SArtem B. Bityutskiy } 403730554d9SArtem B. Bityutskiy } 404730554d9SArtem B. Bityutskiy 405730554d9SArtem B. Bityutskiy if (list_empty(&c->erasing_list)) { 406*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "erasing_list: empty\n"); 407730554d9SArtem B. Bityutskiy } else { 408730554d9SArtem B. Bityutskiy struct list_head *this; 409730554d9SArtem B. Bityutskiy 410730554d9SArtem B. Bityutskiy list_for_each(this, &c->erasing_list) { 411730554d9SArtem B. Bityutskiy struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 412730554d9SArtem B. Bityutskiy 413730554d9SArtem B. Bityutskiy if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 414*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " 415730554d9SArtem B. Bityutskiy "unchecked %#08x, free %#08x)\n", 416730554d9SArtem B. Bityutskiy jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 417730554d9SArtem B. Bityutskiy jeb->unchecked_size, jeb->free_size); 418730554d9SArtem B. Bityutskiy } 419730554d9SArtem B. Bityutskiy } 420730554d9SArtem B. Bityutskiy } 421730554d9SArtem B. Bityutskiy 422730554d9SArtem B. Bityutskiy if (list_empty(&c->erase_pending_list)) { 423*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "erase_pending_list: empty\n"); 424730554d9SArtem B. Bityutskiy } else { 425730554d9SArtem B. Bityutskiy struct list_head *this; 426730554d9SArtem B. Bityutskiy 427730554d9SArtem B. Bityutskiy list_for_each(this, &c->erase_pending_list) { 428730554d9SArtem B. Bityutskiy struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 429730554d9SArtem B. Bityutskiy 430730554d9SArtem B. Bityutskiy if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 431*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " 432730554d9SArtem B. Bityutskiy "unchecked %#08x, free %#08x)\n", 433730554d9SArtem B. Bityutskiy jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 434730554d9SArtem B. Bityutskiy jeb->unchecked_size, jeb->free_size); 435730554d9SArtem B. Bityutskiy } 436730554d9SArtem B. Bityutskiy } 437730554d9SArtem B. Bityutskiy } 438730554d9SArtem B. Bityutskiy 439730554d9SArtem B. Bityutskiy if (list_empty(&c->erasable_pending_wbuf_list)) { 440*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: empty\n"); 441730554d9SArtem B. Bityutskiy } else { 442730554d9SArtem B. Bityutskiy struct list_head *this; 443730554d9SArtem B. Bityutskiy 444730554d9SArtem B. Bityutskiy list_for_each(this, &c->erasable_pending_wbuf_list) { 445730554d9SArtem B. Bityutskiy struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 446730554d9SArtem B. Bityutskiy 447730554d9SArtem B. Bityutskiy if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 448*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, " 449730554d9SArtem B. Bityutskiy "wasted %#08x, unchecked %#08x, free %#08x)\n", 450730554d9SArtem B. Bityutskiy jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 451730554d9SArtem B. Bityutskiy jeb->unchecked_size, jeb->free_size); 452730554d9SArtem B. Bityutskiy } 453730554d9SArtem B. Bityutskiy } 454730554d9SArtem B. Bityutskiy } 455730554d9SArtem B. Bityutskiy 456730554d9SArtem B. Bityutskiy if (list_empty(&c->free_list)) { 457*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "free_list: empty\n"); 458730554d9SArtem B. Bityutskiy } else { 459730554d9SArtem B. Bityutskiy struct list_head *this; 460730554d9SArtem B. Bityutskiy 461730554d9SArtem B. Bityutskiy list_for_each(this, &c->free_list) { 462730554d9SArtem B. Bityutskiy struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 463730554d9SArtem B. Bityutskiy 464730554d9SArtem B. Bityutskiy if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 465*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " 466730554d9SArtem B. Bityutskiy "unchecked %#08x, free %#08x)\n", 467730554d9SArtem B. Bityutskiy jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 468730554d9SArtem B. Bityutskiy jeb->unchecked_size, jeb->free_size); 469730554d9SArtem B. Bityutskiy } 470730554d9SArtem B. Bityutskiy } 471730554d9SArtem B. Bityutskiy } 472730554d9SArtem B. Bityutskiy 473730554d9SArtem B. Bityutskiy if (list_empty(&c->bad_list)) { 474*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "bad_list: empty\n"); 475730554d9SArtem B. Bityutskiy } else { 476730554d9SArtem B. Bityutskiy struct list_head *this; 477730554d9SArtem B. Bityutskiy 478730554d9SArtem B. Bityutskiy list_for_each(this, &c->bad_list) { 479730554d9SArtem B. Bityutskiy struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 480730554d9SArtem B. Bityutskiy 481730554d9SArtem B. Bityutskiy if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 482*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " 483730554d9SArtem B. Bityutskiy "unchecked %#08x, free %#08x)\n", 484730554d9SArtem B. Bityutskiy jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 485730554d9SArtem B. Bityutskiy jeb->unchecked_size, jeb->free_size); 486730554d9SArtem B. Bityutskiy } 487730554d9SArtem B. Bityutskiy } 488730554d9SArtem B. Bityutskiy } 489730554d9SArtem B. Bityutskiy 490730554d9SArtem B. Bityutskiy if (list_empty(&c->bad_used_list)) { 491*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "bad_used_list: empty\n"); 492730554d9SArtem B. Bityutskiy } else { 493730554d9SArtem B. Bityutskiy struct list_head *this; 494730554d9SArtem B. Bityutskiy 495730554d9SArtem B. Bityutskiy list_for_each(this, &c->bad_used_list) { 496730554d9SArtem B. Bityutskiy struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); 497730554d9SArtem B. Bityutskiy 498730554d9SArtem B. Bityutskiy if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { 499*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " 500730554d9SArtem B. Bityutskiy "unchecked %#08x, free %#08x)\n", 501730554d9SArtem B. Bityutskiy jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, 502730554d9SArtem B. Bityutskiy jeb->unchecked_size, jeb->free_size); 503730554d9SArtem B. Bityutskiy } 504730554d9SArtem B. Bityutskiy } 505730554d9SArtem B. Bityutskiy } 506730554d9SArtem B. Bityutskiy } 507730554d9SArtem B. Bityutskiy 508730554d9SArtem B. Bityutskiy void 509*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f) 510*e0c8e42fSArtem B. Bityutskiy { 511*e0c8e42fSArtem B. Bityutskiy down(&f->sem); 512*e0c8e42fSArtem B. Bityutskiy jffs2_dbg_dump_fragtree_nolock(f); 513*e0c8e42fSArtem B. Bityutskiy up(&f->sem); 514*e0c8e42fSArtem B. Bityutskiy } 515*e0c8e42fSArtem B. Bityutskiy 516*e0c8e42fSArtem B. Bityutskiy void 517*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f) 518730554d9SArtem B. Bityutskiy { 519730554d9SArtem B. Bityutskiy struct jffs2_node_frag *this = frag_first(&f->fragtree); 520730554d9SArtem B. Bityutskiy uint32_t lastofs = 0; 521730554d9SArtem B. Bityutskiy int buggy = 0; 522730554d9SArtem B. Bityutskiy 523*e0c8e42fSArtem B. Bityutskiy JFFS2_DEBUG("dump fragtree of ino #%u\n", f->inocache->ino); 524730554d9SArtem B. Bityutskiy while(this) { 525730554d9SArtem B. Bityutskiy if (this->node) 526*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), " 527730554d9SArtem B. Bityutskiy "right (%p), parent (%p)\n", 528730554d9SArtem B. Bityutskiy this->ofs, this->ofs+this->size, ref_offset(this->node->raw), 529730554d9SArtem B. Bityutskiy ref_flags(this->node->raw), this, frag_left(this), frag_right(this), 530730554d9SArtem B. Bityutskiy frag_parent(this)); 531730554d9SArtem B. Bityutskiy else 532*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n", 533730554d9SArtem B. Bityutskiy this->ofs, this->ofs+this->size, this, frag_left(this), 534730554d9SArtem B. Bityutskiy frag_right(this), frag_parent(this)); 535730554d9SArtem B. Bityutskiy if (this->ofs != lastofs) 536730554d9SArtem B. Bityutskiy buggy = 1; 537730554d9SArtem B. Bityutskiy lastofs = this->ofs + this->size; 538730554d9SArtem B. Bityutskiy this = frag_next(this); 539730554d9SArtem B. Bityutskiy } 540730554d9SArtem B. Bityutskiy 541730554d9SArtem B. Bityutskiy if (f->metadata) 542*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "metadata at 0x%08x\n", ref_offset(f->metadata->raw)); 543730554d9SArtem B. Bityutskiy 544730554d9SArtem B. Bityutskiy if (buggy) { 545*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("frag tree got a hole in it.\n"); 546730554d9SArtem B. Bityutskiy BUG(); 547730554d9SArtem B. Bityutskiy } 548730554d9SArtem B. Bityutskiy } 549730554d9SArtem B. Bityutskiy 550*e0c8e42fSArtem B. Bityutskiy #define JFFS2_BUFDUMP_BYTES_PER_LINE 32 551730554d9SArtem B. Bityutskiy void 552*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs) 553730554d9SArtem B. Bityutskiy { 554*e0c8e42fSArtem B. Bityutskiy int skip; 555*e0c8e42fSArtem B. Bityutskiy int i; 556*e0c8e42fSArtem B. Bityutskiy 557*e0c8e42fSArtem B. Bityutskiy JFFS2_DEBUG("dump from offset %#08x to offset %#08x (%x bytes).\n", 558*e0c8e42fSArtem B. Bityutskiy offs, offs + len, len); 559*e0c8e42fSArtem B. Bityutskiy i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE; 560*e0c8e42fSArtem B. Bityutskiy offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1); 561*e0c8e42fSArtem B. Bityutskiy 562*e0c8e42fSArtem B. Bityutskiy if (skip != 0) 563*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "%#08x: ", offs); 564*e0c8e42fSArtem B. Bityutskiy 565*e0c8e42fSArtem B. Bityutskiy while (skip--) 566*e0c8e42fSArtem B. Bityutskiy printk(" "); 567730554d9SArtem B. Bityutskiy 568730554d9SArtem B. Bityutskiy while (i < len) { 569*e0c8e42fSArtem B. Bityutskiy if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) { 570*e0c8e42fSArtem B. Bityutskiy if (i != 0) 571*e0c8e42fSArtem B. Bityutskiy printk("\n"); 572*e0c8e42fSArtem B. Bityutskiy offs += JFFS2_BUFDUMP_BYTES_PER_LINE; 573*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "%0#8x: ", offs); 574730554d9SArtem B. Bityutskiy } 575730554d9SArtem B. Bityutskiy 576*e0c8e42fSArtem B. Bityutskiy printk("%02x ", buf[i]); 577*e0c8e42fSArtem B. Bityutskiy 578*e0c8e42fSArtem B. Bityutskiy i += 1; 579730554d9SArtem B. Bityutskiy } 580730554d9SArtem B. Bityutskiy 581*e0c8e42fSArtem B. Bityutskiy printk("\n"); 582*e0c8e42fSArtem B. Bityutskiy } 583*e0c8e42fSArtem B. Bityutskiy 584*e0c8e42fSArtem B. Bityutskiy /* 585*e0c8e42fSArtem B. Bityutskiy * Dump a JFFS2 node. 586*e0c8e42fSArtem B. Bityutskiy */ 587*e0c8e42fSArtem B. Bityutskiy void 588*e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) 589*e0c8e42fSArtem B. Bityutskiy { 590*e0c8e42fSArtem B. Bityutskiy union jffs2_node_union node; 591*e0c8e42fSArtem B. Bityutskiy int len = sizeof(union jffs2_node_union); 592*e0c8e42fSArtem B. Bityutskiy size_t retlen; 593*e0c8e42fSArtem B. Bityutskiy uint32_t crc; 594*e0c8e42fSArtem B. Bityutskiy int ret; 595*e0c8e42fSArtem B. Bityutskiy 596*e0c8e42fSArtem B. Bityutskiy JFFS2_DEBUG("dump node at offset %#08x.\n", ofs); 597*e0c8e42fSArtem B. Bityutskiy 598*e0c8e42fSArtem B. Bityutskiy ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node); 599*e0c8e42fSArtem B. Bityutskiy if (ret || (retlen != len)) { 600*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n", 601*e0c8e42fSArtem B. Bityutskiy len, ret, retlen); 602*e0c8e42fSArtem B. Bityutskiy return; 603*e0c8e42fSArtem B. Bityutskiy } 604*e0c8e42fSArtem B. Bityutskiy 605*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "magic:\t%#04x\n", 606*e0c8e42fSArtem B. Bityutskiy je16_to_cpu(node.u.magic)); 607*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "nodetype:\t%#04x\n", 608*e0c8e42fSArtem B. Bityutskiy je16_to_cpu(node.u.nodetype)); 609*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "totlen:\t%#08x\n", 610*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.u.totlen)); 611*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "hdr_crc:\t%#08x\n", 612*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.u.hdr_crc)); 613*e0c8e42fSArtem B. Bityutskiy 614*e0c8e42fSArtem B. Bityutskiy crc = crc32(0, &node.u, sizeof(node.u) - 4); 615*e0c8e42fSArtem B. Bityutskiy if (crc != je32_to_cpu(node.u.hdr_crc)) { 616*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("wrong common header CRC.\n"); 617*e0c8e42fSArtem B. Bityutskiy return; 618*e0c8e42fSArtem B. Bityutskiy } 619*e0c8e42fSArtem B. Bityutskiy 620*e0c8e42fSArtem B. Bityutskiy if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK && 621*e0c8e42fSArtem B. Bityutskiy je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK) 622*e0c8e42fSArtem B. Bityutskiy { 623*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n", 624*e0c8e42fSArtem B. Bityutskiy je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK); 625*e0c8e42fSArtem B. Bityutskiy return; 626*e0c8e42fSArtem B. Bityutskiy } 627*e0c8e42fSArtem B. Bityutskiy 628*e0c8e42fSArtem B. Bityutskiy switch(je16_to_cpu(node.u.nodetype)) { 629*e0c8e42fSArtem B. Bityutskiy 630*e0c8e42fSArtem B. Bityutskiy case JFFS2_NODETYPE_INODE: 631*e0c8e42fSArtem B. Bityutskiy 632*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "the node is inode node\n"); 633*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "ino:\t%#08x\n", 634*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.i.ino)); 635*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "version:\t%#08x\n", 636*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.i.version)); 637*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "mode:\t%#08x\n", 638*e0c8e42fSArtem B. Bityutskiy node.i.mode.m); 639*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "uid:\t%#04x\n", 640*e0c8e42fSArtem B. Bityutskiy je16_to_cpu(node.i.uid)); 641*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "gid:\t%#04x\n", 642*e0c8e42fSArtem B. Bityutskiy je16_to_cpu(node.i.gid)); 643*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "isize:\t%#08x\n", 644*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.i.isize)); 645*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "atime:\t%#08x\n", 646*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.i.atime)); 647*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "mtime:\t%#08x\n", 648*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.i.mtime)); 649*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "ctime:\t%#08x\n", 650*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.i.ctime)); 651*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "offset:\t%#08x\n", 652*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.i.offset)); 653*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "csize:\t%#08x\n", 654*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.i.csize)); 655*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "dsize:\t%#08x\n", 656*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.i.dsize)); 657*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "compr:\t%#02x\n", 658*e0c8e42fSArtem B. Bityutskiy node.i.compr); 659*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "usercompr:\t%#02x\n", 660*e0c8e42fSArtem B. Bityutskiy node.i.usercompr); 661*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "flags:\t%#04x\n", 662*e0c8e42fSArtem B. Bityutskiy je16_to_cpu(node.i.flags)); 663*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "data_crc:\t%#08x\n", 664*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.i.data_crc)); 665*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n", 666*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.i.node_crc)); 667*e0c8e42fSArtem B. Bityutskiy crc = crc32(0, &node.i, sizeof(node.i) - 8); 668*e0c8e42fSArtem B. Bityutskiy if (crc != je32_to_cpu(node.i.node_crc)) { 669*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("wrong node header CRC.\n"); 670*e0c8e42fSArtem B. Bityutskiy return; 671*e0c8e42fSArtem B. Bityutskiy } 672*e0c8e42fSArtem B. Bityutskiy break; 673*e0c8e42fSArtem B. Bityutskiy 674*e0c8e42fSArtem B. Bityutskiy case JFFS2_NODETYPE_DIRENT: 675*e0c8e42fSArtem B. Bityutskiy 676*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "the node is dirent node\n"); 677*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "pino:\t%#08x\n", 678*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.d.pino)); 679*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "version:\t%#08x\n", 680*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.d.version)); 681*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "ino:\t%#08x\n", 682*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.d.ino)); 683*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "mctime:\t%#08x\n", 684*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.d.mctime)); 685*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "nsize:\t%#02x\n", 686*e0c8e42fSArtem B. Bityutskiy node.d.nsize); 687*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "type:\t%#02x\n", 688*e0c8e42fSArtem B. Bityutskiy node.d.type); 689*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n", 690*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.d.node_crc)); 691*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "name_crc:\t%#08x\n", 692*e0c8e42fSArtem B. Bityutskiy je32_to_cpu(node.d.name_crc)); 693*e0c8e42fSArtem B. Bityutskiy 694*e0c8e42fSArtem B. Bityutskiy node.d.name[node.d.nsize] = '\0'; 695*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "name:\t\"%s\"\n", node.d.name); 696*e0c8e42fSArtem B. Bityutskiy 697*e0c8e42fSArtem B. Bityutskiy crc = crc32(0, &node.d, sizeof(node.d) - 8); 698*e0c8e42fSArtem B. Bityutskiy if (crc != je32_to_cpu(node.d.node_crc)) { 699*e0c8e42fSArtem B. Bityutskiy JFFS2_ERROR("wrong node header CRC.\n"); 700*e0c8e42fSArtem B. Bityutskiy return; 701*e0c8e42fSArtem B. Bityutskiy } 702*e0c8e42fSArtem B. Bityutskiy break; 703*e0c8e42fSArtem B. Bityutskiy 704*e0c8e42fSArtem B. Bityutskiy default: 705*e0c8e42fSArtem B. Bityutskiy printk(JFFS2_DBG_LVL "node type is unknown\n"); 706*e0c8e42fSArtem B. Bityutskiy break; 707730554d9SArtem B. Bityutskiy } 708730554d9SArtem B. Bityutskiy } 709*e0c8e42fSArtem B. Bityutskiy #endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */ 710