📄 j_intrep.cpp
字号:
}
virtual_node->version_next = n;
break;
}
}
D1(jffs_print_node(virtual_node));
return 0;
}
/* Insert some data into a file. Prior to the call to this function,
jffs_delete_data should be called. */
static int jffs_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) {
D1(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("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)
{
//转为jffs_insert_virtual_data
}
D3(printk("jffs_insert_data(): f->size = %d\n", f->size));
return 0;
}
/* See if a file is deleted. If so, mark that file's nodes as obsolete. */
int jffs_possibly_delete_file(struct jffs_file *f)
{
struct jffs_node *n;
D3(printk("jffs_possibly_delete_file(): ino: %u\n", f->ino));
ASSERT(if (!f) {
/*printk(KERN_ERR "jffs_possibly_delete_file(): f == NULL\n");*/
return -1;
});
if (f->deleted) {
/* First try to remove all older versions. Commence with
the oldest node. */
for (n = f->version_head; n; n = n->version_next) {
if (!n->fm) {
continue;
}
if (jffs_fmfree(f->c->fmc, n->fm, n) < 0) {
break;
}
}
/* Unlink the file from the filesystem. */
if (!f->c->building_fs) {
jffs_unlink_file_from_tree(f);
}
jffs_unlink_file_from_hash(f);
jffs_free_node_list(f);
jffs_free_file(f);
}
return 0;
}
/* Function used by jffs_remove_redundant_nodes() below. This function
classifies what kind of information a node adds to a file. */
static __u8 jffs_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. */
int jffs_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);
free(cur);
DJM(no_jffs_node--);
}
else {
node_with_name_later |= (mod_type & JFFS_MODIFY_NAME);
}
}
return 0;
}
/* Build a control block for the file system. */
static struct jffs_control *jffs_create_control(kdev_t dev)
{
struct jffs_control *c;
register int s = sizeof(struct jffs_control);
D(char *t = 0);
D2(printk("jffs_create_control()\n"));
if (!(c = (struct jffs_control *)malloc(s))) {
D(printk("jffs_control(): c == 0\n"));
goto fail_control;
}
DJM(no_jffs_control++);
c->root = 0;
c->hash_len = JFFS_HASH_SIZE;
s = sizeof(struct jffs_file *) * c->hash_len;
if (!(c->hash = (struct jffs_file **)malloc(s))) {
D(printk("jffs_control(): c->hash == 0\n"));
goto fail_hash;
}
DJM(no_hash++);
memset(c->hash, 0, s);
if (!(c->fmc = jffs_build_begin(c, dev))) {
goto fail_fminit;
}
c->next_ino = JFFS_MIN_INO + 1;
c->rename_lock = 0;
/*-c->rename_wait = (struct wait_queue *) 0;*/
c->delete_list = (struct jffs_delete_list *) 0;
return c;
fail_fminit:
D(t = "c->fmc");
fail_hash:
free(c);
DJM(no_jffs_control--);
D(t = t ? t : "c->hash");
fail_control:
D(t = t ? t : "control");
D(printk("jffs_create_control(): Allocation failed: (%s)\n", t));
return (struct jffs_control *)0;
}
/* Clean up all data structures associated with the file system. */
void jffs_cleanup_control(struct jffs_control *c)
{
D2(printk("jffs_cleanup_control()\n"));
if (!c) {
D(printk("jffs_cleanup_control(): c == NULL !!!\n"));
return;
}
while (c->delete_list) {
struct jffs_delete_list *delete_list_element;
delete_list_element = c->delete_list;
c->delete_list = c->delete_list->next;
free(delete_list_element);
}
/* Free all files and nodes. */
if (c->hash) {
jffs_foreach_file(c, jffs_free_node_list);
jffs_foreach_file(c, jffs_free_file);
free(c->hash);
DJM(no_hash--);
}
jffs_cleanup_fmcontrol(c->fmc);
free(c);
DJM(no_jffs_control--);
D3(printk("jffs_cleanup_control(): Leaving...\n"));
}
/* Scan the whole flash memory in order to find all nodes in the
file systems. */
static int jffs_scan_flash(struct jffs_control *c)
{
int i;
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;
unsigned char *pos = (unsigned char *) fmc->flash_start;
unsigned char *start;
unsigned char *end = (unsigned char *)
(fmc->flash_start + fmc->flash_size);
void record_start_time(char *flag);
printf("Jffs scan flash...\n");
D1(printk("jffs_scan_flash(): start pos = 0x%p, end = 0x%p\n",
pos, end));
flash_safe_acquire(fmc->flash_part);
/* Start the scan. */
while (pos < end) {
deleted_file = 0;
clearHW(); //+
/* Remember the position from where we started this scan. */
start = pos;
switch (*(__u32 *)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%p.\n",
pos));
for (i=0; pos < end
&& JFFS_EMPTY_BITMASK == *(__u32 *)pos;
pos += 4){
if(i++ > 16000){ clearHW(); i=0;}
}
D1(printk("jffs_scan_flash(): 0xff ended at "
"pos 0x%p.\n", pos));
continue;
case JFFS_MAGIC_BITMASK:
/* We have probably found a new raw inode. */
break;
#if 0
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%p.\n",
pos));
for (; pos < end
&& JFFS_DIRTY_BITMASK == *(__u32 *)pos;
pos += 4);
D1(printk("jffs_scan_flash(): 0x00 ended at "
"pos 0x%p.\n", pos));
jffs_fmalloced(fmc, (__u32) start,
(__u32) (pos - start), 0);
continue;
#endif
default:
bad_inode:
//防止非法节点导致死循环
pos += 4;
/* 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%p, len = 128):\n",
pos));
D1(jffs_hexdump(pos, 128));
for (i=0; pos < end
&& JFFS_EMPTY_BITMASK != *(__u32 *)pos
&& JFFS_MAGIC_BITMASK != *(__u32 *)pos;
pos += 4){
if(i++ > 16000){ clearHW(); i=0;}
}
jffs_fmalloced(fmc, (__u32) start, (__u32) (pos - start), 0);
/*for (pos += 4; pos < end; pos += 4) {
switch (*(__u32 *)pos) {
case JFFS_MAGIC_BITMASK:
jffs_fmalloced(fmc, (__u32) start,
(__u32) (pos - start),
0);
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 *)
malloc(sizeof(struct jffs_node)))) {
D(printk("jffs_scan_flash(): node == 0\n"));
flash_safe_release(fmc->flash_part);
return -ENOMEM;
}
DJM(no_jffs_node++);
}
/* Read the next raw inode. */
memcpy(&raw_inode, pos, 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%p "
"on the flash:\n", 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 the unused jffs_node struct. */
continue;
}
/* Check the raw inode read so far. Start with the
maximum length of the filename. */
if (raw_inode.nsize > JFFS_MAX_NAME_LEN) {
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) {
if (raw_inode.dsize > (fmc->sector_size/2) ) {
printf("WARNING: bad inode for raw_inode.dsize\n");
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) {
memcpy(name, pos, 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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -