📄 intrep.c
字号:
* collection. * * If this is the case, don't let f->size go negative. * Bad things would happen :) */ f->size = node->data_offset; } else { f->size -= node->removed_size; } D3(printk("jffs_delete_data(): f->size = %d\n", f->size)); return 0;} /* jffs_delete_data() *//* Insert some data into a file. Prior to the call to this function, jffs_delete_data should be called. */static intjffs_insert_data(struct jffs_file *f, struct jffs_node *node){ D3(printk("jffs_insert_data(): node->data_offset = %u, " "node->data_size = %u, f->size = %u\n", node->data_offset, node->data_size, f->size)); /* Find the position where we should insert data. */ retry: if (node->data_offset == f->size) { /* A simple append. This is the most common operation. */ node->range_next = 0; node->range_prev = f->range_tail; if (node->range_prev) { node->range_prev->range_next = node; } f->range_tail = node; f->size += node->data_size; if (!f->range_head) { f->range_head = node; } } else if (node->data_offset < f->size) { /* Trying to insert data into the middle of the file. This means no problem because jffs_delete_data() has already prepared the range list for us. */ struct jffs_node *n; /* Find the correct place for the insertion and then insert the node. */ for (n = f->range_head; n; n = n->range_next) { D2(printk("Cool stuff's happening!\n")); if (n->data_offset == node->data_offset) { node->range_prev = n->range_prev; if (node->range_prev) { node->range_prev->range_next = node; } else { f->range_head = node; } node->range_next = n; n->range_prev = node; break; } ASSERT(else if (n->data_offset + n->data_size > node->data_offset) { printk(KERN_ERR "jffs_insert_data(): " "Couldn't find a place to insert " "the data!\n"); return -1; }); } /* Adjust later nodes' offsets etc. */ n = node->range_next; while (n) { n->data_offset += node->data_size; n = n->range_next; } f->size += node->data_size; } else if (node->data_offset > f->size) { /* Okay. This is tricky. This means that we want to insert data at a place that is beyond the limits of the file as it is constructed right now. This is actually a common event that for instance could occur during the mounting of the file system if a large file have been truncated, rewritten and then only partially garbage collected. */ struct jffs_node *n; /* We need a place holder for the data that is missing in front of this insertion. This "virtual node" will not be associated with any space on the flash device. */ struct jffs_node *virtual_node; if (!(virtual_node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node), GFP_KERNEL))) { return -ENOMEM; } D(printk("jffs_insert_data: Inserting a virtual node.\n")); D(printk(" node->data_offset = %u\n", node->data_offset)); D(printk(" f->size = %u\n", f->size)); virtual_node->ino = node->ino; virtual_node->version = node->version; virtual_node->removed_size = 0; virtual_node->fm_offset = 0; virtual_node->name_size = 0; virtual_node->fm = 0; /* This is a virtual data holder. */ virtual_node->version_prev = 0; virtual_node->version_next = 0; virtual_node->range_next = 0; /* Are there any data at all in the file yet? */ if (f->range_head) { virtual_node->data_offset = f->range_tail->data_offset + f->range_tail->data_size; virtual_node->data_size = node->data_offset - virtual_node->data_offset; virtual_node->range_prev = f->range_tail; f->range_tail->range_next = virtual_node; } else { virtual_node->data_offset = 0; virtual_node->data_size = node->data_offset; virtual_node->range_prev = 0; f->range_head = virtual_node; } f->range_tail = virtual_node; f->size += virtual_node->data_size; /* Insert this virtual node in the version list as well. */ for (n = f->version_head; n ; n = n->version_next) { if (n->version == virtual_node->version) { virtual_node->version_prev = n->version_prev; n->version_prev = virtual_node; if (virtual_node->version_prev) { virtual_node->version_prev ->version_next = virtual_node; } else { f->version_head = virtual_node; } virtual_node->version_next = n; break; } } D(jffs_print_node(virtual_node)); /* Make a new try to insert the node. */ goto retry; } D3(printk("jffs_insert_data(): f->size = %d\n", f->size)); return 0;}/* A new node (with data) has been added to the file and now the range list has to be modified. */static intjffs_update_file(struct jffs_file *f, struct jffs_node *node){ int err; D3(printk("jffs_update_file(): ino: %u, version: %u\n", f->ino, node->version)); if (node->data_size == 0) { if (node->removed_size == 0) { /* data_offset == X */ /* data_size == 0 */ /* remove_size == 0 */ } else { /* data_offset == X */ /* data_size == 0 */ /* remove_size != 0 */ if ((err = jffs_delete_data(f, node)) < 0) { return err; } } } else { /* data_offset == X */ /* data_size != 0 */ /* remove_size == Y */ if ((err = jffs_delete_data(f, node)) < 0) { return err; } if ((err = jffs_insert_data(f, node)) < 0) { return err; } } return 0;}/* Print the contents of a node. */voidjffs_print_node(struct jffs_node *n){ D(printk("jffs_node: 0x%p\n", n)); D(printk("{\n")); D(printk(" 0x%08x, /* version */\n", n->version)); D(printk(" 0x%08x, /* data_offset */\n", n->data_offset)); D(printk(" 0x%08x, /* data_size */\n", n->data_size)); D(printk(" 0x%08x, /* removed_size */\n", n->removed_size)); D(printk(" 0x%08x, /* fm_offset */\n", n->fm_offset)); D(printk(" 0x%02x, /* name_size */\n", n->name_size)); D(printk(" 0x%p, /* fm, fm->offset: %u */\n", n->fm, (n->fm ? n->fm->offset : 0))); D(printk(" 0x%p, /* version_prev */\n", n->version_prev)); D(printk(" 0x%p, /* version_next */\n", n->version_next)); D(printk(" 0x%p, /* range_prev */\n", n->range_prev)); D(printk(" 0x%p, /* range_next */\n", n->range_next)); D(printk("}\n"));}/* Print the contents of a raw inode. */voidjffs_print_raw_inode(struct jffs_raw_inode *raw_inode){ D(printk("jffs_raw_inode: inode number: %u\n", raw_inode->ino)); D(printk("{\n")); D(printk(" 0x%08x, /* magic */\n", raw_inode->magic)); D(printk(" 0x%08x, /* ino */\n", raw_inode->ino)); D(printk(" 0x%08x, /* pino */\n", raw_inode->pino)); D(printk(" 0x%08x, /* version */\n", raw_inode->version)); D(printk(" 0x%08x, /* mode */\n", raw_inode->mode)); D(printk(" 0x%04x, /* uid */\n", raw_inode->uid)); D(printk(" 0x%04x, /* gid */\n", raw_inode->gid)); D(printk(" 0x%08x, /* atime */\n", raw_inode->atime)); D(printk(" 0x%08x, /* mtime */\n", raw_inode->mtime)); D(printk(" 0x%08x, /* ctime */\n", raw_inode->ctime)); D(printk(" 0x%08x, /* offset */\n", raw_inode->offset)); D(printk(" 0x%08x, /* dsize */\n", raw_inode->dsize)); D(printk(" 0x%08x, /* rsize */\n", raw_inode->rsize)); D(printk(" 0x%02x, /* nsize */\n", raw_inode->nsize)); D(printk(" 0x%02x, /* nlink */\n", raw_inode->nlink)); D(printk(" 0x%02x, /* spare */\n", raw_inode->spare)); D(printk(" %u, /* rename */\n", raw_inode->rename)); D(printk(" %u, /* deleted */\n", raw_inode->deleted)); D(printk(" 0x%02x, /* accurate */\n", raw_inode->accurate)); D(printk(" 0x%08x, /* dchksum */\n", raw_inode->dchksum)); D(printk(" 0x%04x, /* nchksum */\n", raw_inode->nchksum)); D(printk(" 0x%04x, /* chksum */\n", raw_inode->chksum)); D(printk("}\n"));}/* Print the contents of a file. */intjffs_print_file(struct jffs_file *f){ D(int i); D(printk("jffs_file: 0x%p\n", f)); D(printk("{\n")); D(printk(" 0x%08x, /* ino */\n", f->ino)); D(printk(" 0x%08x, /* pino */\n", f->pino)); D(printk(" 0x%08x, /* mode */\n", f->mode)); D(printk(" 0x%04x, /* uid */\n", f->uid)); D(printk(" 0x%04x, /* gid */\n", f->gid)); D(printk(" 0x%08x, /* atime */\n", f->atime)); D(printk(" 0x%08x, /* mtime */\n", f->mtime)); D(printk(" 0x%08x, /* ctime */\n", f->ctime)); D(printk(" 0x%02x, /* nsize */\n", f->nsize)); D(printk(" 0x%02x, /* nlink */\n", f->nlink)); D(printk(" 0x%02x, /* deleted */\n", f->deleted)); D(printk(" \"%s\", ", (f->name ? f->name : ""))); D(for (i = strlen(f->name ? f->name : ""); i < 8; ++i) { printk(" "); }); D(printk("/* name */\n")); D(printk(" 0x%08x, /* size */\n", f->size)); D(printk(" 0x%08x, /* highest_version */\n", f->highest_version)); D(printk(" 0x%p, /* c */\n", f->c)); D(printk(" 0x%p, /* parent */\n", f->parent)); D(printk(" 0x%p, /* children */\n", f->children)); D(printk(" 0x%p, /* sibling_prev */\n", f->sibling_prev)); D(printk(" 0x%p, /* sibling_next */\n", f->sibling_next)); D(printk(" 0x%p, /* hash_prev */\n", f->hash.prev)); D(printk(" 0x%p, /* hash_next */\n", f->hash.next)); D(printk(" 0x%p, /* range_head */\n", f->range_head)); D(printk(" 0x%p, /* range_tail */\n", f->range_tail)); D(printk(" 0x%p, /* version_head */\n", f->version_head)); D(printk(" 0x%p, /* version_tail */\n", f->version_tail)); D(printk("}\n")); return 0;}voidjffs_print_hash_table(struct jffs_control *c){ int i; printk("JFFS: Dumping the file system's hash table...\n"); for (i = 0; i < c->hash_len; i++) { struct list_head *p; for (p = c->hash[i].next; p != &c->hash[i]; p = p->next) { struct jffs_file *f=list_entry(p,struct jffs_file,hash); printk("*** c->hash[%u]: \"%s\" " "(ino: %u, pino: %u)\n", i, (f->name ? f->name : ""), f->ino, f->pino); } }}voidjffs_print_tree(struct jffs_file *first_file, int indent){ struct jffs_file *f; char *space; int dir; if (!first_file) { return; } if (!(space = (char *) kmalloc(indent + 1, GFP_KERNEL))) { printk("jffs_print_tree(): Out of memory!\n"); return; } memset(space, ' ', indent); space[indent] = '\0'; for (f = first_file; f; f = f->sibling_next) { dir = S_ISDIR(f->mode); printk("%s%s%s (ino: %u, highest_version: %u, size: %u)\n", space, (f->name ? f->name : ""), (dir ? "/" : ""), f->ino, f->highest_version, f->size); if (dir) { jffs_print_tree(f->children, indent + 2); } } kfree(space);}#if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUGvoidjffs_print_memory_allocation_statistics(void){ static long printout = 0; printk("________ Memory printout #%ld ________\n", ++printout); printk("no_jffs_file = %ld\n", no_jffs_file); printk("no_jffs_node = %ld\n", no_jffs_node); printk("no_jffs_control = %ld\n", no_jffs_control); printk("no_jffs_raw_inode = %ld\n", no_jffs_raw_inode); printk("no_jffs_node_ref = %ld\n", no_jffs_node_ref); printk("no_jffs_fm = %ld\n", no_jffs_fm); printk("no_jffs_fmcontrol = %ld\n", no_jffs_fmcontrol); printk("no_hash = %ld\n", no_hash); printk("no_name = %ld\n", no_name); printk("\n");}#endif/* Rewrite `size' bytes, and begin at `node'. */intjffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, int size){ struct jffs_control *c = f->c; struct jffs_fmcontrol *fmc = c->fmc; struct jffs_raw_inode raw_inode; struct jffs_node *new_node; struct jffs_fm *fm; __u32 pos; __u32 pos_dchksum; __u32 total_name_size; __u32 total_data_size; __u32 total_size; int err; D1(printk("***jffs_rewrite_data(): node: %u, name: \"%s\", size: %u\n", f->ino, (f->name ? f->name : "(null)"), size)); /* Create and initialize the new node. */ if (!(new_node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node), GFP_KERNEL))) { D(printk("jffs_rewrite_data(): " "Failed to allocate node.\n")); return -ENOMEM; } DJM(no_jffs_node++); new_node->data_offset = node->data_offset; new_node->removed_size = size; total_name_size = JFFS_PAD(f->nsize); total_data_size = JFFS_PAD(size); total_size = sizeof(struct jffs_raw_inode) + total_name_size + total_data_size; new_node->fm_offset = sizeof(struct jffs_raw_inode) + total_name_size; jffs_fm_write_lock(fmc); if ((err = jffs_fmalloc(fmc, total_size, new_node, &fm)) < 0) { DJM(no_jffs_node--); jffs_fm_write_unlock(fmc); D(printk("jffs_rewrite_data(): Failed to allocate fm.\n")); kfree(new_node); return err; } else if (!fm->nodes) { /* The jffs_fm struct that we got is not big enough. */ /* This should never happen, because we deal with this case in jffs_garbage_collect_next().*/ printk(KERN_WARNING "jffs_rewrite_data(): Allocated node is too small (%d bytes of %d)\n", fm->size, total_size); if ((err = jffs_write_dummy_node(c, fm)) < 0) { D(printk("jffs_rewrite_data(): " "jffs_write_dummy_node() Failed!\n")); } else { err = -ENOSPC; } DJM(no_jffs_fm--); jffs_fm_write_unlock(fmc); kfree(fm); return err; } new_node->fm = fm; /* Initialize the raw inode. */ raw_inode.magic = JFFS_MAGIC_BITMASK; raw_inode.ino = f->ino; raw_inode.pino = f->pino; raw_inode.version = f->highest_version + 1; raw_inode.mode = f->mode; raw_inode.uid = f->uid; raw_inode.gid = f->gid; raw_inode.atime = f->atime; raw_inode.mtime = f->mtime; raw_inode.ctime = f->ctime; raw_inode.offset = node->data_offset; raw_inode.dsize = size; raw_inode.rsize = size; raw_inode.nsize = f->nsize; raw_inode.nlink = f->nlink; raw_inode.spare = 0; raw_inode.rename = 0; raw_inode.deleted = 0; raw_inode.accurate = 0xff; raw_inode.dchksum = 0; raw_inode.nchksum = 0; pos = new_node->fm->offset; pos_dchksum = pos +JFFS_RAW_INODE_DCHKSUM_OFFSET; D3(printk("jffs_rewrite_data(): Writing this raw inode " "to pos 0x%ul.\n", pos)); D3(jffs_print_raw_inode(&raw_inode)); if ((err = flash_safe_write(fmc->mtd, pos, (u_char *) &raw_inode, sizeof(struct jffs_raw_inode) - sizeof(__u32) - sizeof(__u16) - sizeof(__u16))) < 0) { jffs_fmfree_partly(fmc, fm, total_name_size + total_data_size); jffs_fm_write_unlock(fmc); printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during " "rewrite. (raw inode)\n"); return err; } pos += sizeof(struct jffs_raw_inode); /* Write the name to the flash memory. */ if (f->nsize) { D3(printk("jffs_rewrite_data(): Writing name \"%s\" to " "pos 0x%ul.\n", f->name, (long)pos)); if ((err = flash_safe_write(fmc->mtd, pos, (u_char *)f->name, f->nsize)) < 0) { jffs_fmfree_partly(fmc, fm, total_data_size);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -