📄 intrep.c
字号:
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; f->deleted = raw_inode->deleted; } else if ((f->highest_version < node->version) || (node->version == 0)) { /* Insert at the end of the list. I.e. this node is the oldest 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; f->deleted = raw_inode->deleted; } 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; } if (raw_inode->deleted) { f->deleted = raw_inode->deleted; } } 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; } } } /* Perhaps update the name. */ if (raw_inode->nsize && update_name && name && *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); } if (f->deleted) { /* Mark all versions of the node as obsolete. */ jffs_possibly_delete_file(f); } else { if (node->data_size || node->removed_size) { jffs_update_file(f, node); } jffs_remove_redundant_nodes(f); }#ifdef USE_GC if (!c->fmc->no_call_gc) { jffs_garbage_collect(c); }#endif D3(printk("jffs_insert_node(): ---------------------------" "------------------------------------------- 2\n")); } return 0;} /* jffs_insert_node() *//* Unlink a jffs_node from the version list it is in. */static inline voidjffs_unlink_node_from_version_list(struct jffs_file *f, struct jffs_node *node){ if (node->version_prev) { node->version_prev->version_next = node->version_next; } else { f->version_head = node->version_next; } if (node->version_next) { node->version_next->version_prev = node->version_prev; } else { f->version_tail = node->version_prev; }}/* Unlink a jffs_node from the range list it is in. */static inline voidjffs_unlink_node_from_range_list(struct jffs_file *f, struct jffs_node *node){ if (node->range_prev) { node->range_prev->range_next = node->range_next; } else { f->range_head = node->range_next; } if (node->range_next) { node->range_next->range_prev = node->range_prev; } else { f->range_tail = node->range_prev; }}/* Function used by jffs_remove_redundant_nodes() below. This function classifies what kind of information a node adds to a file. */static inline __u8jffs_classify_node(struct jffs_node *node){ __u8 mod_type = JFFS_MODIFY_INODE; if (node->name_size) { mod_type |= JFFS_MODIFY_NAME; } if (node->data_size || node->removed_size) { mod_type |= JFFS_MODIFY_DATA; } return mod_type;}/* Remove redundant nodes from a file. Mark the on-flash memory as dirty. */intjffs_remove_redundant_nodes(struct jffs_file *f){ struct jffs_node *newest_node; struct jffs_node *cur; struct jffs_node *prev; __u8 newest_type; __u8 mod_type; __u8 node_with_name_later = 0; if (!(newest_node = f->version_tail)) { return 0; } /* What does the `newest_node' modify? */ newest_type = jffs_classify_node(newest_node); node_with_name_later = newest_type & JFFS_MODIFY_NAME; D3(printk("jffs_remove_redundant_nodes(): ino: %u, name: \"%s\", " "newest_type: %u\n", f->ino, (f->name ? f->name : ""), newest_type)); /* Traverse the file's nodes and determine which of them that are superfluous. Yeah, this might look very complex at first glance but it is actually very simple. */ for (cur = newest_node->version_prev; cur; cur = prev) { prev = cur->version_prev; mod_type = jffs_classify_node(cur); if ((mod_type <= JFFS_MODIFY_INODE) || ((newest_type & JFFS_MODIFY_NAME) && (mod_type <= (JFFS_MODIFY_INODE + JFFS_MODIFY_NAME))) || (cur->data_size == 0 && cur->removed_size && !cur->version_prev && node_with_name_later)) { /* Yes, this node is redundant. Remove it. */ D2(printk("jffs_remove_redundant_nodes(): " "Removing node: ino: %u, version: %u, " "mod_type: %u\n", cur->ino, cur->version, mod_type)); jffs_unlink_node_from_version_list(f, cur); jffs_fmfree(f->c->fmc, cur->fm, cur); kfree(cur); DJM(no_jffs_node--); } else { node_with_name_later |= (mod_type & JFFS_MODIFY_NAME); } } return 0;}/* Insert a file into the hash table. */intjffs_insert_file_into_hash(struct jffs_file *f){ int i = f->ino % f->c->hash_len; D3(printk("jffs_insert_file_into_hash(): f->ino: %u\n", f->ino)); f->hash_next = f->c->hash[i]; if (f->hash_next) { f->hash_next->hash_prev = f; } f->hash_prev = 0; f->c->hash[i] = f; return 0;}/* Insert a file into the file system tree. */intjffs_insert_file_into_tree(struct jffs_file *f){ struct jffs_file *parent; D3(printk("jffs_insert_file_into_tree(): name: \"%s\"\n", (f->name ? f->name : ""))); if (!(parent = jffs_find_file(f->c, f->pino))) { if (f->pino == 0) { f->c->root = f; f->parent = 0; f->sibling_prev = 0; f->sibling_next = 0; return 0; } else { D1(printk("jffs_insert_file_into_tree(): Found " "inode with no parent and pino == %u\n", f->pino)); return -1; } } f->parent = parent; f->sibling_next = parent->children; if (f->sibling_next) { f->sibling_next->sibling_prev = f; } f->sibling_prev = 0; parent->children = f; return 0;}/* Remove a file from the hash table. */intjffs_unlink_file_from_hash(struct jffs_file *f){ D3(printk("jffs_unlink_file_from_hash(): f: 0x%p, " "ino %u\n", f, f->ino)); if (f->hash_next) { f->hash_next->hash_prev = f->hash_prev; } if (f->hash_prev) { f->hash_prev->hash_next = f->hash_next; } else { f->c->hash[f->ino % f->c->hash_len] = f->hash_next; } return 0;}/* Just remove the file from the parent's children. Don't free any memory. */intjffs_unlink_file_from_tree(struct jffs_file *f){ D3(printk("jffs_unlink_file_from_tree(): ino: %d, name: " "\"%s\"\n", f->ino, (f->name ? f->name : ""))); if (f->sibling_prev) { f->sibling_prev->sibling_next = f->sibling_next; } else { f->parent->children = f->sibling_next; } if (f->sibling_next) { f->sibling_next->sibling_prev = f->sibling_prev; } return 0;}/* Find a file with its inode number. */struct jffs_file *jffs_find_file(struct jffs_control *c, __u32 ino){ struct jffs_file *f; int i = ino % c->hash_len; D3(printk("jffs_find_file(): ino: %u\n", ino)); for (f = c->hash[i]; f && (ino != f->ino); f = f->hash_next); D3(if (f) { printk("jffs_find_file(): Found file with ino " "%u. (name: \"%s\")\n", ino, (f->name ? f->name : "")); } else { printk("jffs_find_file(): Didn't find file " "with ino %u.\n", ino); }); return f;}/* Find a file in a directory. We are comparing the names. */struct jffs_file *jffs_find_child(struct jffs_file *dir, const char *name, int len){ struct jffs_file *f; D3(printk("jffs_find_child()\n")); for (f = dir->children; f; f = f->sibling_next) { if (f->name && !strncmp(f->name, name, len) && f->name[len] == '\0') { break; } } D3(if (f) { printk("jffs_find_child(): Found \"%s\".\n", f->name); } else { char *copy = (char *) kmalloc(len + 1, GFP_KERNEL); if (copy) { memcpy(copy, name, len); copy[len] = '\0'; } printk("jffs_find_child(): Didn't find the file \"%s\".\n", (copy ? copy : "")); if (copy) { kfree(copy); } }); return f;}#if !defined(JFFS_FLASH_SHORTCUT) || ! JFFS_FLASH_SHORTCUTstruct buffer_head *jffs_get_write_buffer(kdev_t dev, int block){ struct buffer_head *bh; D3(printk("jffs_get_write_buffer(): block = %u\n", block)); if (!(bh = bread(dev, block, BLOCK_SIZE))) { D(printk("jffs_get_write_buffer(): bread() failed. " "(block == %u)\n", block)); } D3(printk("jffs_get_write_buffer(): bh = 0x%08x\n", bh)); return bh;}voidjffs_put_write_buffer(struct buffer_head *bh){ D3(printk("jffs_put_write_buffer(): bh = 0x%08x\n", bh)); mark_buffer_dirty(bh, 1); ll_rw_block(WRITE, 1, &bh); wait_on_buffer(bh); brelse(bh);}/* Structure used by jffs_write_chunk() and jffs_write_node(). */struct jffs_write_task{ struct buffer_head *bh; __u32 block; __u32 block_offset;};/* Write a chunk of data to the flash memory. This is a helper routine to jffs_write_node(). */intjffs_write_chunk(struct jffs_control *c, struct jffs_write_task *wt, const unsigned char *data, __u32 size){ int write_len = 0; int len; int buf_pos = 0; D3(printk("jffs_write_chunk(): size = %u\n", size)); ASSERT(if (!wt) { printk("jffs_write_chunk(): wt == NULL\n"); return -1; }); if (size == 0) { return 0; } if (wt->block_offset == BLOCK_SIZE) { if (wt->bh) { jffs_put_write_buffer(wt->bh); wt->bh = 0; } wt->block++; wt->block_offset = 0; } if (!wt->bh && !(wt->bh = jffs_get_write_buffer(c->sb->s_dev, wt->block))) { return -1; } while (write_len < size) { len = jffs_min(size - write_len, BLOCK_SIZE - wt->block_offset); memcpy(&wt->bh->b_data[wt->block_offset], &data[buf_pos], len); write_len += len; wt->block_offset += len; D3(printk(" write_len: %u\n", write_len)); D3(printk(" len: %u\n", len)); D3(printk(" size: %u\n", size)); if (write_len < size) { jffs_put_write_buffer(wt->bh); wt->block++; wt->block_offset = 0; wt->bh = 0; if (!(wt->bh = jffs_get_write_buffer(c->sb->s_dev, wt->block))) { return write_len; } buf_pos += len; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -