📄 j_intrep.cpp
字号:
if (f->name) {
free(f->name);
DJM(no_name--);
}
if (!(f->name = (char *) malloc(raw_inode->nsize + 1))) {
D(printk("jffs_insert_node(): f->name == 0\n"));
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() */
/* Read data from the node and write it to the buffer. 'node_offset'
is how much we have read from this particular node before and which
shouldn't be read again. 'max_size' is how much space there is in
the buffer. */
static int
jffs_get_node_data(struct jffs_file *f, struct jffs_node *node, char *buf,
__u32 node_offset, __u32 max_size, kdev_t dev)
{
struct jffs_fmcontrol *fmc = f->c->fmc;
__u32 pos = node->fm->offset + node->fm_offset + node_offset; /*???*/
__u32 avail = node->data_size - node_offset;
__u32 r;
D2(printk(" jffs_get_node_data(): file: \"%s\", ino: %u, "
"version: %u, node_offset: %u\n",
f->name, node->ino, node->version, node_offset));
r = jffs_min(avail, max_size);
flash_safe_read(fmc->flash_part, (unsigned char *) pos,
(unsigned char *)buf, r);
D3(printk(" jffs_get_node_data(): Read %u byte%s.\n",
r, (r == 1 ? "" : "s")));
return r;
}
/* Read data from the file's nodes. Write the data to the buffer
'buf'. 'read_offset' tells how much data we should skip. */
int jffs_read_data(struct jffs_file *f, char *buf, __u32 read_offset, __u32 size)
{
struct jffs_node *node;
__u32 read_data = 0; /* Total amount of read data. */
__u32 node_offset = 0;
__u32 pos = 0; /* Number of bytes traversed. */
D1(printk("jffs_read_data(): file = \"%s\", read_offset = %d, "
"size = %u\n",
(f->name ? f->name : ""), read_offset, size));
if (read_offset >= f->size) {
//!!!!!与FDK文件传送冲突
//D(printk(" f->size: %d\n", f->size));
return 0;
}
/* First find the node to read data from. */
node = f->range_head;
while (pos <= read_offset) {
node_offset = read_offset - pos;
if (node_offset >= node->data_size) {
pos += node->data_size;
node = node->range_next;
}
else {
break;
}
}
/* "Cats are living proof that not everything in nature
has to be useful."
- Garrison Keilor ('97) */
/* Fill the buffer. */
while (node && (read_data < size)) {
int r;
if (!node->fm) {
/* This node does not refer to real data. */
r = jffs_min(size - read_data,
node->data_size - node_offset);
memset(&buf[read_data], 0, r);
}
else if ((r = jffs_get_node_data(f, node, &buf[read_data],
node_offset,
size - read_data,
f->c->sb->s_dev)) < 0) {
return r;
}
read_data += r;
node_offset = 0;
node = node->range_next;
}
D3(printk(" jffs_read_data(): Read %u bytes.\n", read_data));
return read_data;
}
/* 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(): Couldn't find file "
"with ino %u.\n", ino);
});
return f;
}
/* Used for traversing all nodes in the hash table. */
int
jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *))
{
struct jffs_file *f;
struct jffs_file *next_f;
int pos;
int r;
int result = 0;
for (pos = 0; pos < c->hash_len; pos++) {
for (f = c->hash[pos]; f; f = next_f) {
/* We need a reference to the next file in the
list because `func' might remove the current
file `f'. */
next_f = f->hash_next;
if ((r = func(f)) < 0) {
return r;
}
result += r;
}
}
return result;
}
/* Build up a file's range list from scratch by going through the
version list. */
int jffs_build_file(struct jffs_file *f)
{
struct jffs_node *n;
D3(printk("jffs_build_file(): ino: %u, name: \"%s\"\n",
f->ino, (f->name ? f->name : "")));
for (n = f->version_head; n; n = n->version_next) {
jffs_update_file(f, n);
}
return 0;
}
/* A new node (with data) has been added to the file and now the range
list has to be modified. */
static int
jffs_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(node->data_offset > f->size){
if ((err = jffs_insert_virtual_data(f, node)) < 0) {
return err;
}
}
if ((err = jffs_delete_data(f, node)) < 0) {
return err;
}
if ((err = jffs_insert_data(f, node)) < 0) {
return err;
}
}
return 0;
}
/* Remove an amount of data from a file. If this amount of data is
zero, that could mean that a node should be split in two parts.
We remove or change the appropriate nodes in the lists.
Starting offset of area to be removed is node->data_offset,
and the length of the area is in node->removed_size. */
/*f表示被修改的文件, node传递删除数据的偏移和大小
只对RAM中的node进行修改, 不修改flash上的raw_inode, 除非已完全删除
在Flash上如何保存修改*/
static int jffs_delete_data(struct jffs_file *f, struct jffs_node *node)
{
struct jffs_node *n;
__u32 offset = node->data_offset;
__u32 remove_size = node->removed_size;
D3(printk("jffs_delete_data(): offset = %u, remove_size = %u\n",
offset, remove_size));
if (remove_size == 0) return 0;
if (remove_size == 0
&& f->range_tail
&& f->range_tail->data_offset + f->range_tail->data_size
== offset) {
/* A simple append; nothing to remove or no node to split. */
return 0;
}
/* Find the node where we should begin the removal. */
for (n = f->range_head; n; n = n->range_next) {
if (n->data_offset + n->data_size > offset) {
break;
}
}
if (!n) {
/* If there's no data in the file there's no data to
remove either. */
//????? D(printf("jffs_delete_data(): there's no data to remove\n"));
return 0;
}
if (n->data_offset > offset) {
/* XXX: Not implemented yet. */
D(printf("JFFS: An unexpected situation occurred in jffs_delete_data.\n"));
}
else if (n->data_offset < offset) {
/* See if the node has to be split into two parts. */
if (n->data_offset + n->data_size > offset + remove_size) {
/* Do the split. */
struct jffs_node *new_node;
D3(printk("jffs_delete_data(): Split node with "
"version number %u.\n", n->version));
if (!(new_node = (struct jffs_node *)
malloc(sizeof(struct jffs_node)))) {
D(printk("jffs_delete_data(): -ENOMEM\n"));
return -ENOMEM;
}
DJM(no_jffs_node++);
new_node->ino = n->ino;
new_node->version = n->version;
new_node->data_offset = offset;
new_node->data_size = n->data_size
- (remove_size
+ (offset - n->data_offset));
new_node->fm_offset = n->fm_offset
+ (remove_size
+ (offset - n->data_offset));
new_node->name_size = n->name_size;
new_node->fm = n->fm;
new_node->version_prev = n;
new_node->version_next = n->version_next;
if (new_node->version_next) {
new_node->version_next->version_prev
= new_node;
}
else {
f->version_tail = new_node;
}
n->version_next = new_node;
new_node->range_prev = n;
new_node->range_next = n->range_next;
if (new_node->range_next) {
new_node->range_next->range_prev = new_node;
}
else {
f->range_tail = new_node;
}
/* A very interesting can of worms. */
n->range_next = new_node;
n->data_size = offset - n->data_offset;
jffs_add_node(new_node);
n = new_node->range_next;
remove_size = 0;
}
else {
/* No. No need to split the node. Just remove
the end of the node. */
int r = jffs_min(n->data_offset + n->data_size
- offset, remove_size);
n->data_size -= r;
remove_size -= r;
n = n->range_next;
}
}
/* Remove as many nodes as necessary. */
while (n && remove_size) {
clearHW();
if (n->data_size <= remove_size) {
struct jffs_node *p = n;
remove_size -= n->data_size;
n = n->range_next;
//if(n->name_size == 0)//!!!有名称存在,不能删除
{
D3(printk("jffs_delete_data(): Removing node: "
"ino: %u, version: %u%s\n",
p->ino, p->version,
(p->fm ? "" : " (virtual)")));
if (p->fm) {
jffs_fmfree(f->c->fmc, p->fm, p);
}
jffs_unlink_node_from_range_list(f, p);
jffs_unlink_node_from_version_list(f, p);
free(p);
DJM(no_jffs_node--);
}/*if(n->name_size == 0)*/
}
else { /*最后一个node*/
n->data_size -= remove_size;
n->fm_offset += remove_size;
/*删除一段, offset应向前移动*/
n->data_offset -= (node->removed_size - remove_size);
n = n->range_next;
break;
}
}
/* Adjust the following nodes' information about offsets etc. */
/*调整后续节点的偏移地址.*/
while (n && node->removed_size) {
n->data_offset -= node->removed_size;
n = n->range_next;
}
f->size -= node->removed_size;
D3(printk("jffs_delete_data(): f->size = %d\n", f->size));
return 0;
} /* jffs_delete_data() */
static int jffs_insert_virtual_data(struct jffs_file *f, struct jffs_node *node)
{
/* 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 *)
malloc(sizeof(struct jffs_node)))) {
D(printk("jffs_insert_data(): virtual_node == 0\n"));
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, f->name = %s\n", f->size,f->name));
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -