📄 j_intrep.cpp
字号:
D2(printk("JFFS: Erase succeeded.\n"));
}
else {
/* XXX: Here we should allocate the memory
with jffs_fmalloced() in order to prevent
JFFS from using this area accidentally. */
return err;
}
}
#endif
/* Update the flash memory data structures. */
jffs_sync_erase(fmc, erase_size);
return erase_size;
}
/* Rewrite `size' bytes, and begin at `node'. */
int jffs_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;
unsigned char *pos;
unsigned char *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 : ""), 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 = f->nsize + JFFS_GET_PAD_BYTES(f->nsize);
total_data_size = size + JFFS_GET_PAD_BYTES(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;
if ((err = jffs_fmalloc(fmc, total_size, new_node, &fm)) < 0) {
D(printk("jffs_rewrite_data(): Failed to allocate fm.\n"));
kfree(new_node);
DJM(no_jffs_node--);
return err;
}
else if (!fm->nodes) {
/* The jffs_fm struct that we got is not good enough. */
if ((err = jffs_write_dummy_node(c, fm)) < 0) {
D(printk("jffs_rewrite_data(): "
"jffs_write_dummy_node() Failed!\n"));
kfree(fm);
DJM(no_jffs_fm--);
return err;
}
/* Get a new one. */
if ((err = jffs_fmalloc(fmc, total_size, node, &fm)) < 0) {
D(printk("jffs_rewrite_data(): Second "
"jffs_fmalloc(0x%p, %u) failed!\n",
fmc, total_size));
return err;
}
}
new_node->fm = fm;
ASSERT(if (new_node->fm->nodes == 0) {
printk("jffs_rewrite_data(): "
"new_node->fm->nodes == 0\n");
});
/* 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 = (unsigned char *) new_node->fm->offset;
pos_dchksum = &pos[JFFS_RAW_INODE_DCHKSUM_OFFSET];
D3(printk("jffs_rewrite_data(): Writing this raw inode "
"to pos 0x%p.\n", pos));
D3(jffs_print_raw_inode(&raw_inode));
if ((err = flash_safe_write(fmc->flash_part, pos,
(unsigned char *) &raw_inode,
sizeof(struct jffs_raw_inode)
- sizeof(__u32)
- sizeof(__u16) - sizeof(__u16))) < 0) {
/*printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during "
"rewrite. (raw inode)\n");*/
jffs_fmfree_partly(fmc, fm,
total_name_size + total_data_size);
return err;
}
pos += sizeof(struct jffs_raw_inode);
if( f->nsize==0 || (!f->name) )
D(printk("jffs_rewrite_data(): invalid name\n"));
/* Write the name to the flash memory. */
if (f->nsize) {
D3(printk("jffs_rewrite_data(): Writing name \"%s\" to "
"pos 0x%p.\n", f->name, pos));
if ((err = flash_safe_write(fmc->flash_part, pos,
(unsigned char *)f->name,
f->nsize)) < 0) {
/*printk(KERN_ERR "JFFS: jffs_rewrite_data: Write "
"error during rewrite. (name)\n");*/
jffs_fmfree_partly(fmc, fm, total_data_size);
return err;
}
pos += total_name_size;
raw_inode.nchksum = jffs_checksum(f->name, f->nsize);
}
/* Write the data. */
if (size) {
int r;
unsigned char page[256];
__u32 s; /*livefall@163.com 2005.01.09*/
__u32 offset = node->data_offset;
/*if (!(page = (unsigned char *)__get_free_page(GFP_KERNEL))) {
jffs_fmfree_partly(fmc, fm, 0);
return -1;
}*/
while (size) {
clearHW();
s = jffs_min(size, 256); /*livefall@163.com 2005.01.09*/
if ((r = jffs_read_data(f, (char *)page,
offset, s)) < s) {
/*printk(KERN_ERR "JFFS: jffs_rewrite_data: "
"jffs_read_data() "
"failed! (r = %d)\n", r);
free_page((unsigned long)page);*/
jffs_fmfree_partly(fmc, fm, 0);
return -1;
}
if ((err = flash_safe_write(fmc->flash_part,
pos, page, r)) < 0) {
/*printk(KERN_ERR "JFFS: jffs_rewrite_data: "
"Write error during rewrite. "
"(data)\n");
free_page((unsigned long)page);*/
jffs_fmfree_partly(fmc, fm, 0);
return err;
}
pos += r;
size -= r;
offset += r;
raw_inode.dchksum += jffs_checksum(page, r);
}
/*free_page((unsigned long)page);*/
}
raw_inode.accurate = 0;
raw_inode.chksum = jffs_checksum(&raw_inode,
sizeof(struct jffs_raw_inode)
- sizeof(__u16));
/* Add the checksum. */
if ((err
= flash_safe_write(fmc->flash_part, pos_dchksum,
&((unsigned char *)
&raw_inode)[JFFS_RAW_INODE_DCHKSUM_OFFSET],
sizeof(__u32) + sizeof(__u16)
+ sizeof(__u16))) < 0) {
/*printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during "
"rewrite. (checksum)\n");*/
jffs_fmfree_partly(fmc, fm, 0);
return err;
}
/* Now make the file system aware of the newly written node. */
jffs_insert_node(c, f, &raw_inode, f->name, new_node);
D3(printk("jffs_rewrite_data(): Leaving...\n"));
return 0;
} /* jffs_rewrite_data() */
/* jffs_garbage_collect_next implements one step in the garbage collect
process and is often called multiple times at each occasion of a
garbage collect. */
int jffs_garbage_collect_next(struct jffs_control *c)
{
struct jffs_fmcontrol *fmc = c->fmc;
struct jffs_node *node;
struct jffs_file *f;
int size;
int data_size;
int total_name_size;
int free_size = fmc->flash_size - (fmc->used_size + fmc->dirty_size);
__u32 free_chunk_size1 = jffs_free_size1(fmc);
D2(__u32 free_chunk_size2 = jffs_free_size2(fmc));
/* Get the oldest node in the flash. */
node = jffs_get_oldest_node(fmc);
ASSERT(if (!node) {
/*printk(KERN_ERR "JFFS: jffs_garbage_collect_next: "
"No oldest node found!\n");*/
return -1;
});
/* Find its corresponding file too. */
f = jffs_find_file(c, node->ino);
ASSERT(if (!f) {
/*printk(KERN_ERR "JFFS: jffs_garbage_collect_next: "
"No file to garbage collect! "
"(ino = 0x%08x)\n", node->ino);*/
return -1;
});
D1(printk("jffs_garbage_collect_next: \"%s\", "
"ino: %u, version: %u\n",
(f->name ? f->name : ""), node->ino, node->version));
//需保证node为range_head
/* Compute how much we want to rewrite at the moment. */
data_size = f->size - node->data_offset;
total_name_size = f->nsize + JFFS_GET_PAD_BYTES(f->nsize);
size = sizeof(struct jffs_raw_inode) + total_name_size
+ data_size + JFFS_GET_PAD_BYTES(data_size);
D2(printk(" total_name_size: %u\n", total_name_size));
D2(printk(" data_size: %u\n", data_size));
D2(printk(" size: %u\n", size));
D2(printk(" f->nsize: %u\n", f->nsize));
D2(printk(" f->size: %u\n", f->size));
D2(printk(" node->data_offset: %u\n", node->data_offset));
D2(printk(" free_chunk_size1: %u\n", free_chunk_size1));
D2(printk(" free_chunk_size2: %u\n", free_chunk_size2));
D2(printk(" node->fm->offset: 0x%08x\n", node->fm->offset));
if (size > fmc->max_chunk_size) {
size = fmc->max_chunk_size;
data_size = size - sizeof(struct jffs_raw_inode)
- total_name_size;
}
if (size > free_chunk_size1) {
if (free_chunk_size1 <
(sizeof(struct jffs_raw_inode) + f->nsize + BLOCK_SIZE)) {
/* The space left is too small to be of any
use really. */
struct jffs_fm *dirty_fm
= jffs_fmalloced(fmc,
fmc->tail->offset + fmc->tail->size,
free_chunk_size1, NULL);
if (!dirty_fm) {
/*printk(KERN_ERR "JFFS: "
"jffs_garbage_collect_next: "
"Failed to allocate `dirty' "
"flash memory!\n");*/
return -1;
}
jffs_write_dummy_node(c, dirty_fm);
goto jffs_garbage_collect_next_end;
}
size = free_chunk_size1;
data_size = size - sizeof(struct jffs_raw_inode)
- total_name_size;
}
D2(printk(" size: %u (again)\n", size));
if (free_size - size < fmc->sector_size) {
/* Just rewrite that node (or even less). */
jffs_rewrite_data(f, node,
jffs_min(node->data_size, data_size));
}
else {
//amine
int err = jffs_rewrite_data(f, node, data_size);
if(err < 0) return err;
}
jffs_garbage_collect_next_end:
D3(printk("jffs_garbage_collect_next: Leaving...\n"));
return 0;
} /* jffs_garbage_collect_next */
/* There are different criteria that should trigger a garbage collect:
1. There is too much dirt in the memory.
2. The free space is becoming small.
3. There are many versions of a node.
The garbage collect should always be done in a manner that guarantees
that future garbage collects cannot be locked. E.g. Rewritten chunks
should not be too large (span more than one sector in the flash memory
for exemple). Of course there is a limit on how intelligent this garbage
collection can be. */
int jffs_garbage_collect(struct jffs_control *c)
{
struct jffs_fmcontrol *fmc = c->fmc;
long erased_total = 0;
long erased;
int result = 0;
int i; /*livefall@163.com 2005.01.09*/
D1(int i = 1);
D2(printk("***jffs_garbage_collect(): fmc->dirty_size = %u\n",
fmc->dirty_size));
D2(jffs_print_fmcontrol(fmc));
c->fmc->no_call_gc = 1;
/* While there is too much dirt left and it is possible
to garbage collect, do so. */
//if(sys_init_done != 1)
// printf("fmc->dirty_size = %u\n", fmc->dirty_size);
i=1;
while (fmc->dirty_size >= fmc->sector_size) {
clearHW();
//printf("round #%u, fmc->dirty_size = %u\n",
// i++, fmc->dirty_size);
D2(jffs_print_fmcontrol(fmc));
/* At least one sector should be able to free now. */
if ((erased = jffs_try_to_erase(c)) < 0) {
/*printk(KERN_WARNING "JFFS: Error in "
"garbage collector.\n");*/
result = erased;
goto gc_end;
}
else if (erased == 0) {
__u32 free_size = fmc->flash_size
- (fmc->used_size
+ fmc->dirty_size);
if (free_size > 0) {
/* Let's dare to make a garbage collect. */
clearHW();
if ((result = jffs_garbage_collect_next(c))
< 0) {
/*printk(KERN_ERR "JFFS: Something "
"has gone seriously wrong "
"with a garbage collect.\n");*/
goto gc_end;
}
}
else {
/* What should we do here? */
D(printk(" jffs_garbage_collect(): "
"erased: %ld, free_size: %u\n",
erased, free_size));
result = -1;
goto gc_end;
}
}
D1(printk(" jffs_garbage_collect(): erased: %ld\n", erased));
erased_total += erased;
//DJM(jffs_print_memory_allocation_statistics());
}
gc_end:
c->fmc->no_call_gc = 0;
D3(printk(" jffs_garbage_collect(): Leaving...\n"));
D1(if (erased_total) {
printk("erased_total = %ld\n", erased_total);
jffs_print_fmcontrol(fmc);
});
return result;
}
/* This function adds a virtual root node to the in-RAM representation.
Called by jffs_build_fs(). */
static int jffs_add_virtual_root(struct jffs_control *c)
{
struct jffs_file *root;
struct jffs_node *node;
D2(printk("jffs_add_virtual_root(): "
"Creating a virtual root directory.\n"));
if (!(root = (struct jffs_file *)kmalloc(sizeof(struct jffs_file),
GFP_KERNEL))) {
D(printk("jffs_add_virtual_root(): root == 0\n"));
return -ENOMEM;
}
DJM(no_jffs_file++);
if (!(node = (struct jffs_node *)kmalloc(sizeof(struct jffs_node),
GFP_KERNEL))) {
D(printk("jffs_add_virtual_root(): node == 0\n"));
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);
I_FLASH.u.generic_ip = root;
I_FLASH.i_mode = S_IFDIR;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -