📄 scan.c
字号:
curofs += retlen&~3; } D1(printk(KERN_DEBUG "Empty flash detected from 0x%08x to 0x%08x\n", *startofs, curofs)); kfree(buf); *startofs = curofs; return 0;}static struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, __u32 ino){ struct jffs2_inode_cache *ic; ic = jffs2_get_ino_cache(c, ino); if (ic) return ic; ic = jffs2_alloc_inode_cache(); if (!ic) { printk(KERN_NOTICE "jffs2_scan_make_inode_cache(): allocation of inode cache failed\n"); return NULL; } memset(ic, 0, sizeof(*ic)); ic->scan = kmalloc(sizeof(struct jffs2_scan_info), GFP_KERNEL); if (!ic->scan) { printk(KERN_NOTICE "jffs2_scan_make_inode_cache(): allocation of scan info for inode cache failed\n"); jffs2_free_inode_cache(ic); return NULL; } memset(ic->scan, 0, sizeof(*ic->scan)); ic->ino = ino; ic->nodes = (void *)ic; jffs2_add_ino_cache(c, ic); if (ino == 1) ic->nlink=1; return ic;}static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, __u32 *ofs){ struct jffs2_raw_node_ref *raw; struct jffs2_full_dnode *fn; struct jffs2_tmp_dnode_info *tn, **tn_list; struct jffs2_inode_cache *ic; struct jffs2_raw_inode ri; __u32 crc; __u16 oldnodetype; int ret; ssize_t retlen; D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", *ofs)); ret = c->mtd->read(c->mtd, *ofs, sizeof(ri), &retlen, (char *)&ri); if (ret) { printk(KERN_NOTICE "jffs2_scan_inode_node(): Read error at 0x%08x: %d\n", *ofs, ret); return ret; } if (retlen != sizeof(ri)) { printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", retlen, *ofs, sizeof(ri)); return -EIO; } /* We sort of assume that the node was accurate when it was first written to the medium :) */ oldnodetype = ri.nodetype; ri.nodetype |= JFFS2_NODE_ACCURATE; crc = crc32(0, &ri, sizeof(ri)-8); ri.nodetype = oldnodetype; if(crc != ri.node_crc) { printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", *ofs, ri.node_crc, crc); /* FIXME: Why do we believe totlen? */ DIRTY_SPACE(4); *ofs += 4; return 0; } /* There was a bug where we wrote hole nodes out with csize/dsize swapped. Deal with it */ if (ri.compr == JFFS2_COMPR_ZERO && !ri.dsize && ri.csize) { ri.dsize = ri.csize; ri.csize = 0; } if (ri.csize) { /* Check data CRC too */ unsigned char *dbuf; __u32 crc; dbuf = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL); if (!dbuf) { printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of temporary data buffer for CRC check failed\n"); return -ENOMEM; } ret = c->mtd->read(c->mtd, *ofs+sizeof(ri), ri.csize, &retlen, dbuf); if (ret) { printk(KERN_NOTICE "jffs2_scan_inode_node(): Read error at 0x%08x: %d\n", *ofs+sizeof(ri), ret); kfree(dbuf); return ret; } if (retlen != ri.csize) { printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", retlen, *ofs+ sizeof(ri), ri.csize); kfree(dbuf); return -EIO; } crc = crc32(0, dbuf, ri.csize); kfree(dbuf); if (crc != ri.data_crc) { printk(KERN_NOTICE "jffs2_scan_inode_node(): Data CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", *ofs, ri.data_crc, crc); DIRTY_SPACE(PAD(ri.totlen)); *ofs += PAD(ri.totlen); return 0; } } /* Wheee. It worked */ raw = jffs2_alloc_raw_node_ref(); if (!raw) { printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n"); return -ENOMEM; } tn = jffs2_alloc_tmp_dnode_info(); if (!tn) { jffs2_free_raw_node_ref(raw); return -ENOMEM; } fn = jffs2_alloc_full_dnode(); if (!fn) { jffs2_free_tmp_dnode_info(tn); jffs2_free_raw_node_ref(raw); return -ENOMEM; } ic = jffs2_scan_make_ino_cache(c, ri.ino); if (!ic) { jffs2_free_full_dnode(fn); jffs2_free_tmp_dnode_info(tn); jffs2_free_raw_node_ref(raw); return -ENOMEM; } /* Build the data structures and file them for later */ raw->flash_offset = *ofs; raw->totlen = PAD(ri.totlen); raw->next_phys = NULL; raw->next_in_ino = ic->nodes; ic->nodes = raw; if (!jeb->first_node) jeb->first_node = raw; if (jeb->last_node) jeb->last_node->next_phys = raw; jeb->last_node = raw; D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", ri.ino, ri.version, ri.offset, ri.offset+ri.dsize)); pseudo_random += ri.version; for (tn_list = &ic->scan->tmpnodes; *tn_list; tn_list = &((*tn_list)->next)) { if ((*tn_list)->version < ri.version) continue; if ((*tn_list)->version > ri.version) break; /* Wheee. We've found another instance of the same version number. We should obsolete one of them. */ D1(printk(KERN_DEBUG "Duplicate version %d found in ino #%u. Previous one is at 0x%08x\n", ri.version, ic->ino, (*tn_list)->fn->raw->flash_offset &~3)); if (!jeb->used_size) { D1(printk(KERN_DEBUG "No valid nodes yet found in this eraseblock 0x%08x, so obsoleting the new instance at 0x%08x\n", jeb->offset, raw->flash_offset & ~3)); ri.nodetype &= ~JFFS2_NODE_ACCURATE; /* Perhaps we could also mark it as such on the medium. Maybe later */ } break; } if (ri.nodetype & JFFS2_NODE_ACCURATE) { memset(fn,0,sizeof(*fn)); fn->ofs = ri.offset; fn->size = ri.dsize; fn->frags = 0; fn->raw = raw; tn->next = NULL; tn->fn = fn; tn->version = ri.version; USED_SPACE(PAD(ri.totlen)); jffs2_add_tn_to_list(tn, &ic->scan->tmpnodes); /* Make sure the one we just added is the _last_ in the list with this version number, so the older ones get obsoleted */ while (tn->next && tn->next->version == tn->version) { D1(printk(KERN_DEBUG "Shifting new node at 0x%08x after other node at 0x%08x for version %d in list\n", fn->raw->flash_offset&~3, tn->next->fn->raw->flash_offset &~3, ri.version)); if(tn->fn != fn) BUG(); tn->fn = tn->next->fn; tn->next->fn = fn; tn = tn->next; } } else { jffs2_free_full_dnode(fn); jffs2_free_tmp_dnode_info(tn); raw->flash_offset |= 1; DIRTY_SPACE(PAD(ri.totlen)); } *ofs += PAD(ri.totlen); return 0;}static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, __u32 *ofs){ struct jffs2_raw_node_ref *raw; struct jffs2_full_dirent *fd; struct jffs2_inode_cache *ic; struct jffs2_raw_dirent rd; __u16 oldnodetype; int ret; __u32 crc; ssize_t retlen; D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", *ofs)); ret = c->mtd->read(c->mtd, *ofs, sizeof(rd), &retlen, (char *)&rd); if (ret) { printk(KERN_NOTICE "jffs2_scan_dirent_node(): Read error at 0x%08x: %d\n", *ofs, ret); return ret; } if (retlen != sizeof(rd)) { printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", retlen, *ofs, sizeof(rd)); return -EIO; } /* We sort of assume that the node was accurate when it was first written to the medium :) */ oldnodetype = rd.nodetype; rd.nodetype |= JFFS2_NODE_ACCURATE; crc = crc32(0, &rd, sizeof(rd)-8); rd.nodetype = oldnodetype; if (crc != rd.node_crc) { printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", *ofs, rd.node_crc, crc); /* FIXME: Why do we believe totlen? */ DIRTY_SPACE(4); *ofs += 4; return 0; } pseudo_random += rd.version; fd = jffs2_alloc_full_dirent(rd.nsize+1); if (!fd) { return -ENOMEM;} ret = c->mtd->read(c->mtd, *ofs + sizeof(rd), rd.nsize, &retlen, &fd->name[0]); if (ret) { jffs2_free_full_dirent(fd); printk(KERN_NOTICE "jffs2_scan_dirent_node(): Read error at 0x%08x: %d\n", *ofs + sizeof(rd), ret); return ret; } if (retlen != rd.nsize) { jffs2_free_full_dirent(fd); printk(KERN_NOTICE "Short read: 0x%x bytes at 0x%08x instead of requested %x\n", retlen, *ofs + sizeof(rd), rd.nsize); return -EIO; } crc = crc32(0, fd->name, rd.nsize); if (crc != rd.name_crc) { printk(KERN_NOTICE "jffs2_scan_dirent_node(): Name CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", *ofs, rd.name_crc, crc); fd->name[rd.nsize]=0; D1(printk(KERN_NOTICE "Name for which CRC failed is (now) '%s', ino #%d\n", fd->name, rd.ino)); jffs2_free_full_dirent(fd); /* FIXME: Why do we believe totlen? */ DIRTY_SPACE(PAD(rd.totlen)); *ofs += PAD(rd.totlen); return 0; } raw = jffs2_alloc_raw_node_ref(); if (!raw) { jffs2_free_full_dirent(fd); printk(KERN_NOTICE "jffs2_scan_dirent_node(): allocation of node reference failed\n"); return -ENOMEM; } ic = jffs2_scan_make_ino_cache(c, rd.pino); if (!ic) { jffs2_free_full_dirent(fd); jffs2_free_raw_node_ref(raw); return -ENOMEM; } raw->totlen = PAD(rd.totlen); raw->flash_offset = *ofs; raw->next_phys = NULL; raw->next_in_ino = ic->nodes; ic->nodes = raw; if (!jeb->first_node) jeb->first_node = raw; if (jeb->last_node) jeb->last_node->next_phys = raw; jeb->last_node = raw; if (rd.nodetype & JFFS2_NODE_ACCURATE) { fd->raw = raw; fd->next = NULL; fd->version = rd.version; fd->ino = rd.ino; fd->name[rd.nsize]=0; fd->nhash = full_name_hash(fd->name, rd.nsize); fd->type = rd.type; USED_SPACE(PAD(rd.totlen)); jffs2_add_fd_to_list(c, fd, &ic->scan->dents); } else { raw->flash_offset |= 1; jffs2_free_full_dirent(fd); DIRTY_SPACE(PAD(rd.totlen)); } *ofs += PAD(rd.totlen); return 0;}static int count_list(struct list_head *l){ uint32_t count = 0; struct list_head *tmp; list_for_each(tmp, l) { count++; } return count;}/* Note: This breaks if list_empty(head). I don't care. You might, if you copy this code and use it elsewhere :) */static void rotate_list(struct list_head *head, uint32_t count){ struct list_head *n = head->next; list_del(head); while(count--) n = n->next; list_add(head, n);}static void jffs2_rotate_lists(struct jffs2_sb_info *c){ uint32_t x; x = count_list(&c->clean_list); if (x) rotate_list((&c->clean_list), pseudo_random % x); x = count_list(&c->dirty_list); if (x) rotate_list((&c->dirty_list), pseudo_random % x); if (c->nr_erasing_blocks) rotate_list((&c->erase_pending_list), pseudo_random % c->nr_erasing_blocks); if (c->nr_free_blocks) /* Not that it should ever be zero */ rotate_list((&c->free_list), pseudo_random % c->nr_free_blocks);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -