📄 intrep.c
字号:
*/ num_free_space++; D1(printk("Free space accepted: Starting 0x%x for 0x%x bytes\n", (unsigned int) start, (unsigned int) (pos - start))); if (largest_hole < pos - start) { D3(printk("was hole = %x end_offset = %x\n", largest_hole, hole_end_offset)); if (fmc->head){ largest_hole = pos - start; hole_end_offset = pos; } D3(printk("now = %x end_offset = %x\n", largest_hole, hole_end_offset)); } }else{ num_free_spc_not_accp++; D1(printk("Free space (#%i) found but *Not* accepted: Starting " "0x%x for 0x%x bytes\n", num_free_spc_not_accp, (unsigned int) start, (unsigned int) (pos - start))); /* Mark this space as dirty. We already have our free space. */ D1(printk("Dirty space: Starting 0x%x for 0x%x bytes\n", (unsigned int) start, (unsigned int) (pos - start))); jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0); } } if(num_free_space > NUMFREEALLOWED){ printk(KERN_WARNING "jffs_scan_flash(): Found free space " "number %i. Only %i free space is allowed.\n", num_free_space, NUMFREEALLOWED); } continue; case JFFS_DIRTY_BITMASK: /* We have found 0x00000000 at this position. Scan as far as possible to find out how much is dirty. */ D1(printk("jffs_scan_flash(): 0x00000000 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 = %d):\n", (long)pos, end - pos > 128 ? 128 : end - pos)); D1(jffs_hexdump(fmc->mtd, pos, end - pos > 128 ? 128 : end - pos)); for (pos += 4; pos < end; pos += 4) { switch (flash_read_u32(fmc->mtd, pos)) { case JFFS_MAGIC_BITMASK: case JFFS_EMPTY_BITMASK: /* handle these in the main switch() loop */ goto cont_scan; default: break; } } cont_scan: /* First, mark as dirty the region which really does contain crap. */ jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0); continue; }/* switch */ /* We have found the beginning of an inode. Create a node for it unless there already is one available. */ if (!node) { if (!(node = jffs_alloc_node())) { /* 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); } if (jffs_checksum_flash(fmc->mtd, pos, raw_inode.dsize, &checksum)) { printk("jffs_checksum_flash() failed to calculate a checksum\n"); jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0); /* Reuse this unused struct jffs_node. */ continue; } 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")); jffs_free_node(node); DJM(no_jffs_node--); /* Free read buffer */ kfree (read_buf); /* Release the flash device */ flash_safe_release(fmc->mtd); return -ENOMEM; } 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")); jffs_free_node(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; } if ((err = jffs_insert_node(c, 0, &raw_inode, name, node)) < 0) { printk("JFFS: Failed to handle raw inode. " "(err = %d)\n", err); break; } 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) { jffs_free_node(node); DJM(no_jffs_node--); } if (fmc->head && fmc->tail_extra && fmc->head->offset + fmc->flash_size - fmc->tail_extra->offset - fmc->tail_extra->size > largest_hole) { head_offset = fmc->head->offset; } else { head_offset = hole_end_offset; } if (jffs_build_end(fmc, head_offset) < 0) { D(printk("jffs_build_end() failed\n")); return -ENOMEM; } /* Free read buffer */ kfree (read_buf); if(!num_free_space){ printk(KERN_WARNING "jffs_scan_flash(): Did not find even a single " "chunk of free space. This is BAD!\n"); } /* Return happy */ D3(printk("jffs_scan_flash(): Leaving...\n")); flash_safe_release(fmc->mtd); /* This is to trap the "free size accounting screwed error. */ free_chunk_size1 = jffs_free_size1(fmc); free_chunk_size2 = jffs_free_size2(fmc); if (free_chunk_size1 + free_chunk_size2 != fmc->free_size) { printk(KERN_WARNING "jffs_scan_falsh():Free size accounting screwed\n"); printk(KERN_WARNING "jfffs_scan_flash():free_chunk_size1 == 0x%x, " "free_chunk_size2 == 0x%x, fmc->free_size == 0x%x\n", free_chunk_size1, free_chunk_size2, fmc->free_size); return -1; /* Do NOT mount f/s so that we can inspect what happened. Mounting this screwed up f/s will screw us up anyway. */ } return 0; /* as far as we are concerned, we are happy! */} /* 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, " "name = \"%s\", deleted = %d\n", raw_inode->ino, raw_inode->version, ((name && *name) ? name : ""), raw_inode->deleted)); /* If there doesn't exist an associated jffs_file, then create, initialize and insert one into the file system. */ if (!f && !(f = jffs_find_file(c, raw_inode->ino))) { if (!(f = jffs_create_file(c, raw_inode))) { return -ENOMEM; } jffs_insert_file_into_hash(f); insert_into_tree = 1; } node->ino = raw_inode->ino; node->version = raw_inode->version; node->data_size = raw_inode->dsize; node->fm_offset = sizeof(struct jffs_raw_inode) + raw_inode->nsize + JFFS_GET_PAD_BYTES(raw_inode->nsize); node->name_size = raw_inode->nsize; /* Now insert the node at the correct position into the file's version list. */ if (!f->version_head) { /* This is the first node. */ f->version_head = node; f->version_tail = node; node->version_prev = 0; node->version_next = 0; f->highest_version = node->version; update_name = 1; f->mode = raw_inode->mode; f->uid = raw_inode->uid; f->gid = raw_inode->gid; f->atime = raw_inode->atime; f->mtime = raw_inode->mtime; f->ctime = raw_inode->ctime; } else if ((f->highest_version < node->version) || (node->version == 0)) { /* Insert at the end of the list. I.e. this node is the newest one so far. */ node->version_prev = f->version_tail; node->version_next = 0; f->version_tail->version_next = node; f->version_tail = node; f->highest_version = node->version; update_name = 1; f->pino = raw_inode->pino; f->mode = raw_inode->mode; f->uid = raw_inode->uid; f->gid = raw_inode->gid; f->atime = raw_inode->atime; f->mtime = raw_inode->mtime; f->ctime = raw_inode->ctime; } else if (f->version_head->version > node->version) { /* Insert at the bottom of the list. */ node->version_prev = 0; node->version_next = f->version_head; f->version_head->version_prev = node; f->version_head = node; if (!f->name) { update_name = 1; } } else { struct jffs_node *n; int newer_name = 0; /* Search for the insertion position starting from the tail (newest node). */ for (n = f->version_tail; n; n = n->version_prev) { if (n->version < node->version) { node->version_prev = n; node->version_next = n->version_next; node->version_next->version_prev = node; n->version_next = node; if (!newer_name) { update_name = 1; } break; } if (n->name_size) { newer_name = 1; } } } /* Deletion is irreversible. If any 'deleted' node is ever written, the file is deleted */ if (raw_inode->deleted) f->deleted = raw_inode->deleted; /* Perhaps update the name. */ if (raw_inode->nsize && update_name && name && *name && (name != f->name)) { if (f->name) { kfree(f->name); DJM(no_name--); } if (!(f->name = (char *) kmalloc(raw_inode->nsize + 1, GFP_KERNEL))) { return -ENOMEM; } DJM(no_name++); memcpy(f->name, name, raw_inode->nsize); f->name[raw_inode->nsize] = '\0'; f->nsize = raw_inode->nsize; D3(printk("jffs_insert_node(): Updated the name of " "the file to \"%s\".\n", name)); } if (!c->building_fs) { D3(printk("jffs_insert_node(): ---------------------------" "------------------------------------------- 1\n")); if (insert_into_tree) { jffs_insert_file_into_tree(f); } /* Once upon a time, we would call jffs_possibly_delete_file() here. That causes an oops if someone's still got the file open, so now we only do it in jffs_delete_inode() -- dwmw2 */ if (node->data_size || node->removed_size) { jffs_update_file(f, node);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -