📄 intrep.c
字号:
kfree(root); DJM(no_jffs_file--); return -ENOMEM; } DJM(no_jffs_node++); memset(node, 0, sizeof(struct jffs_node)); node->ino = JFFS_MIN_INO; memset(root, 0, sizeof(struct jffs_file)); root->ino = JFFS_MIN_INO; root->mode = S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; root->atime = root->mtime = root->ctime = CURRENT_TIME; root->nlink = 1; root->c = c; root->version_head = root->version_tail = node; jffs_insert_file_into_hash(root); return 0;}/* This is where the file system is built and initialized. */intjffs_build_fs(struct super_block *sb){ struct jffs_control *c; int err = 0; D2(printk("jffs_build_fs()\n")); if (!(c = jffs_create_control(sb->s_dev))) { return -ENOMEM; } c->building_fs = 1; c->sb = sb; if ((err = jffs_scan_flash(c)) < 0) { goto jffs_build_fs_fail; } /* Add a virtual root node if no one exists. */ if (!jffs_find_file(c, JFFS_MIN_INO)) { if ((err = jffs_add_virtual_root(c)) < 0) { goto jffs_build_fs_fail; } } while (c->delete_list) { struct jffs_file *f; struct jffs_delete_list *delete_list_element; if ((f = jffs_find_file(c, c->delete_list->ino))) { f->deleted = 1; } delete_list_element = c->delete_list; c->delete_list = c->delete_list->next; kfree(delete_list_element); } /* Remove deleted nodes. */ if ((err = jffs_foreach_file(c, jffs_possibly_delete_file)) < 0) { printk(KERN_ERR "JFFS: Failed to remove deleted nodes.\n"); goto jffs_build_fs_fail; } /* Remove redundant nodes. (We are not interested in the return value in this case.) */ jffs_foreach_file(c, jffs_remove_redundant_nodes); /* Try to build a tree from all the nodes. */ if ((err = jffs_foreach_file(c, jffs_insert_file_into_tree)) < 0) { printk("JFFS: Failed to build tree.\n"); goto jffs_build_fs_fail; } /* Compute the sizes of all files in the filesystem. Adjust if necessary. */ if ((err = jffs_foreach_file(c, jffs_build_file)) < 0) { printk("JFFS: Failed to build file system.\n"); goto jffs_build_fs_fail; } sb->u.generic_sbp = (void *)c; c->building_fs = 0; D1(jffs_print_hash_table(c)); D1(jffs_print_tree(c->root, 0)); return 0;jffs_build_fs_fail: jffs_cleanup_control(c); return err;} /* jffs_build_fs() *//* Scan the whole flash memory in order to find all nodes in the file systems. */static intjffs_scan_flash(struct jffs_control *c){ char name[JFFS_MAX_NAME_LEN + 2]; struct jffs_raw_inode raw_inode; struct jffs_node *node = 0; struct jffs_fmcontrol *fmc = c->fmc; __u32 checksum; __u8 tmp_accurate; __u16 tmp_chksum; __u32 deleted_file; loff_t pos = fmc->flash_start; loff_t start; loff_t end = fmc->flash_start + fmc->flash_size; __u8 *read_buf; int i, len, retlen; D1(printk("jffs_scan_flash(): start pos = 0x%lx, end = 0x%lx\n", (long)pos, (long)end)); flash_safe_acquire(fmc->mtd); /* Allocate read buffer */ read_buf = (__u8 *) kmalloc (sizeof(__u8) * 4096, GFP_KERNEL); /* Start the scan. */ while (pos < end) { deleted_file = 0; /* Remember the position from where we started this scan. */ start = pos; switch (flash_read_u32(fmc->mtd, pos)) { case JFFS_EMPTY_BITMASK: /* We have found 0xff at this position. We have to scan the rest of the flash till the end or till something else than 0xff is found. */ D1(printk("jffs_scan_flash(): 0xff at pos 0x%lx.\n", (long)pos)); len = end - pos < 4096 ? end - pos : 4096; retlen = flash_safe_read(fmc->mtd, pos, &read_buf[0], len); retlen &= ~3; for (i=0 ; i < retlen ; i+=4, pos += 4) { if(*((__u32 *) &read_buf[i]) != JFFS_EMPTY_BITMASK) break; } if (i == retlen) continue; D1(printk("jffs_scan_flash(): 0xff ended at " "pos 0x%lx.\n", (long)pos)); /* If some free space ends in the middle of a sector, treat it as dirty rather than clean. This is to handle the case where one thread allocated space for a node, but didn't get to actually _write_ it before power was lost, leaving a gap in the log. Shifting all node writes into a single kernel thread will fix the original problem. */ if ((__u32) pos % fmc->sector_size) { /* If there was free space in previous sectors, don't mark that dirty too - only from the beginning of this sector (or from start) */ if (start < (pos & ~(fmc->sector_size-1))) { D1(printk("Reducing start to 0x%x from 0x%x\n", pos & ~(fmc->sector_size-1), start)); start = pos & ~(fmc->sector_size-1); } D1(printk("Dirty space: 0x%x for 0x%x bytes\n", start, (pos - start))); jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0); } continue; case JFFS_DIRTY_BITMASK: /* We have found 0x00 at this position. Scan as far as possible to find out how much is dirty. */ D1(printk("jffs_scan_flash(): 0x00 at pos 0x%lx.\n", (long)pos)); for (; pos < end && JFFS_DIRTY_BITMASK == flash_read_u32(fmc->mtd, pos); pos += 4); D1(printk("jffs_scan_flash(): 0x00 ended at " "pos 0x%lx.\n", (long)pos)); jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0); continue; case JFFS_MAGIC_BITMASK: /* We have probably found a new raw inode. */ break; default: bad_inode: /* We're f*cked. This is not solved yet. We have to scan for the magic pattern. */ D1(printk("*************** Dirty flash memory or " "bad inode: " "hexdump(pos = 0x%lx, len = 128):\n", (long)pos)); D1(jffs_hexdump(fmc->mtd, pos, 128)); cont_dirty: for (pos += 4; pos < end; pos += 4) { switch (flash_read_u32(fmc->mtd, pos)) { case JFFS_MAGIC_BITMASK: jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0); goto cont_scan; case JFFS_EMPTY_BITMASK: /* First, mark as dirty the region which really does contain crap. */ jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0); /* Then, scan the region which looks free. Depending on how large it is, we may mark it dirty too. */ start = pos; for (; pos < end ; pos += 4) { switch (flash_read_u32(fmc->mtd, pos)) { case JFFS_MAGIC_BITMASK: if (pos - start < fmc->max_chunk_size) { /* Not much free space. Mark it dirty. */ jffs_fmalloced(fmc, (__u32)start, (__u32)pos-start, 0); } goto cont_scan; case JFFS_EMPTY_BITMASK: /* More empty space */ continue; default: /* i.e. more dirt */ if (pos - start < fmc->max_chunk_size) { /* There wasn't much before the dirt started again. Just mark it all dirty */ goto cont_dirty; } /* There was quite a lot of free space. Leave it free. */ goto cont_scan; } } default: break; } } cont_scan: continue; } /* We have found the beginning of an inode. Create a node for it unless there already is one available. */ if (!node) { if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node), GFP_KERNEL))) { /* Free read buffer */ kfree (read_buf); /* Release the flash device */ flash_safe_release(fmc->mtd); return -ENOMEM; } DJM(no_jffs_node++); } /* Read the next raw inode. */ flash_safe_read(fmc->mtd, pos, (u_char *) &raw_inode, sizeof(struct jffs_raw_inode)); /* When we compute the checksum for the inode, we never count the 'accurate' or the 'checksum' fields. */ tmp_accurate = raw_inode.accurate; tmp_chksum = raw_inode.chksum; raw_inode.accurate = 0; raw_inode.chksum = 0; checksum = jffs_checksum(&raw_inode, sizeof(struct jffs_raw_inode)); raw_inode.accurate = tmp_accurate; raw_inode.chksum = tmp_chksum; D3(printk("*** We have found this raw inode at pos 0x%lx " "on the flash:\n", (long)pos)); D3(jffs_print_raw_inode(&raw_inode)); if (checksum != raw_inode.chksum) { D1(printk("jffs_scan_flash(): Bad checksum: " "checksum = %u, " "raw_inode.chksum = %u\n", checksum, raw_inode.chksum)); pos += sizeof(struct jffs_raw_inode); jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0); /* Reuse this unused struct jffs_node. */ continue; } /* Check the raw inode read so far. Start with the maximum length of the filename. */ if (raw_inode.nsize > JFFS_MAX_NAME_LEN) { printk(KERN_WARNING "jffs_scan_flash: Found a " "JFFS node with name too large\n"); goto bad_inode; } if (raw_inode.rename && raw_inode.dsize != sizeof(__u32)) { printk(KERN_WARNING "jffs_scan_flash: Found a " "rename node with dsize %u.\n", raw_inode.dsize); jffs_print_raw_inode(&raw_inode); goto bad_inode; } /* The node's data segment should not exceed a certain length. */ if (raw_inode.dsize > fmc->max_chunk_size) { printk(KERN_WARNING "jffs_scan_flash: Found a " "JFFS node with dsize (0x%x) > max_chunk_size (0x%x)\n", raw_inode.dsize, fmc->max_chunk_size); goto bad_inode; } pos += sizeof(struct jffs_raw_inode); /* This shouldn't be necessary because a node that violates the flash boundaries shouldn't be written in the first place. */ if (pos >= end) { goto check_node; } /* Read the name. */ *name = 0; if (raw_inode.nsize) { flash_safe_read(fmc->mtd, pos, name, raw_inode.nsize); name[raw_inode.nsize] = '\0'; pos += raw_inode.nsize + JFFS_GET_PAD_BYTES(raw_inode.nsize); D3(printk("name == \"%s\"\n", name)); checksum = jffs_checksum(name, raw_inode.nsize); if (checksum != raw_inode.nchksum) { D1(printk("jffs_scan_flash(): Bad checksum: " "checksum = %u, " "raw_inode.nchksum = %u\n", checksum, raw_inode.nchksum)); jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0); /* Reuse this unused struct jffs_node. */ continue; } if (pos >= end) { goto check_node; } } /* Read the data, if it exists, in order to be sure it matches the checksum. */ if (raw_inode.dsize) { if (raw_inode.rename) { deleted_file = flash_read_u32(fmc->mtd, pos); } checksum = jffs_checksum_flash(fmc->mtd, pos, raw_inode.dsize); pos += raw_inode.dsize + JFFS_GET_PAD_BYTES(raw_inode.dsize); if (checksum != raw_inode.dchksum) { D1(printk("jffs_scan_flash(): Bad checksum: " "checksum = %u, " "raw_inode.dchksum = %u\n", checksum, raw_inode.dchksum)); jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0); /* Reuse this unused struct jffs_node. */ continue; } } check_node: /* Remember the highest inode number in the whole file system. This information will be used when assigning new files new inode numbers. */ if (c->next_ino <= raw_inode.ino) { c->next_ino = raw_inode.ino + 1; } if (raw_inode.accurate) { int err; node->data_offset = raw_inode.offset; node->data_size = raw_inode.dsize; node->removed_size = raw_inode.rsize; /* Compute the offset to the actual data in the on-flash node. */ node->fm_offset = sizeof(struct jffs_raw_inode) + raw_inode.nsize + JFFS_GET_PAD_BYTES(raw_inode.nsize); node->fm = jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), node); if (!node->fm) { D(printk("jffs_scan_flash(): !node->fm\n")); kfree(node); DJM(no_jffs_node--); /* Free read buffer */ kfree (read_buf); /* Release the flash device */ flash_safe_release(fmc->mtd); return -ENOMEM; } if ((err = jffs_insert_node(c, 0, &raw_inode, name, node)) < 0) { printk("JFFS: Failed to handle raw inode. " "(err = %d)\n", err); break; } if (raw_inode.rename) { struct jffs_delete_list *dl = (struct jffs_delete_list *) kmalloc(sizeof(struct jffs_delete_list), GFP_KERNEL); if (!dl) { D(printk("jffs_scan_flash: !dl\n")); kfree(node); DJM(no_jffs_node--); /* Release the flash device */ flash_safe_release(fmc->flash_part); /* Free read buffer */ kfree (read_buf); return -ENOMEM; } dl->ino = deleted_file; dl->next = c->delete_list; c->delete_list = dl; node->data_size = 0; } D3(jffs_print_node(node)); node = 0; /* Don't free the node! */ } else { jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0); D3(printk("jffs_scan_flash(): Just found an obsolete " "raw_inode. Continuing the scan...\n")); /* Reuse this unused struct jffs_node. */ } } if (node) { kfree(node); DJM(no_jffs_node--); } jffs_build_end(fmc); /* Free read buffer */ kfree (read_buf); /* Return happy */ D3(printk("jffs_scan_flash(): Leaving...\n")); flash_safe_release(fmc->mtd); return 0;} /* jffs_scan_flash() *//* Insert any kind of node into the file system. Take care of data insertions and deletions. Also remove redundant information. The memory allocated for the `name' is regarded as "given away" in the caller's perspective. */intjffs_insert_node(struct jffs_control *c, struct jffs_file *f, const struct jffs_raw_inode *raw_inode, const char *name, struct jffs_node *node){ int update_name = 0; int insert_into_tree = 0; D2(printk("jffs_insert_node(): ino = %u, version = %u, "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -