📄 j_intrep.cpp
字号:
(__u32) (pos - start), 0);
/* Reuse this unused jffs_node struct. */
continue;
}
if (pos >= end) {
goto check_node;
}
}
/* Read the data, if it exists, in order to be sure it
matches the checksum. */
if (raw_inode.dsize) {
if (raw_inode.rename) {
deleted_file = *(__u32 *)pos;
}
checksum = jffs_checksum(pos, raw_inode.dsize);
pos += raw_inode.dsize
+ JFFS_GET_PAD_BYTES(raw_inode.dsize);
if (checksum != raw_inode.dchksum) {
D1(printk("jffs_scan_flash(): Bad checksum: "
"checksum = %u, "
"raw_inode.dchksum = %u\n",
checksum, raw_inode.dchksum));
jffs_fmalloced(fmc, (__u32) start,
(__u32) (pos - start), 0);
/* Reuse this unused struct jffs_node. */
continue;
}
}
check_node:
/* Remember the highest inode number in the whole file
system. This information will be used when assigning
new files new inode numbers. */
if (c->next_ino <= raw_inode.ino) {
c->next_ino = raw_inode.ino + 1;
}
if (raw_inode.accurate) {
int err;
node->data_offset = raw_inode.offset;
node->data_size = raw_inode.dsize;
node->removed_size = raw_inode.rsize;
/* Compute the offset to the actual data in the
on-flash node. */
node->fm_offset
= sizeof(struct jffs_raw_inode)
+ raw_inode.nsize
+ JFFS_GET_PAD_BYTES(raw_inode.nsize);
node->fm = jffs_fmalloced(fmc, (__u32) start,
(__u32) (pos - start),
node);
if (!node->fm) {
D(printk("jffs_scan_flash(): !node->fm\n"));
free(node);
DJM(no_jffs_node--);
flash_safe_release(fmc->flash_part);
return -ENOMEM;
}
if ((err = jffs_insert_node(c, 0, &raw_inode,
name, node)) < 0) {
/*printk("JFFS: Failed to handle raw inode. "
"(err = %d)\n", err);*/
break;
}
if (raw_inode.rename) {
struct jffs_delete_list *dl
= (struct jffs_delete_list *)
malloc(sizeof(struct jffs_delete_list));
if (!dl) {
D(printk("jffs_scan_flash: !dl\n"));
free(node);
DJM(no_jffs_node--);
flash_safe_release(fmc->flash_part);
return -ENOMEM;
}
dl->ino = deleted_file;
dl->next = c->delete_list;
c->delete_list = dl;
node->data_size = 0;
}
D3(jffs_print_node(node));
node = 0; /* Don't free the node! */
}
else {
jffs_fmalloced(fmc, (__u32) start,
(__u32) (pos - start), 0);
D3(printk("jffs_scan_flash(): Just found an obsolete "
"raw_inode. Continuing the scan...\n"));
/* Reuse this unused struct jffs_node. */
}
}
if (node) {
free(node);
DJM(no_jffs_node--);
}
jffs_build_end(fmc);
D3(printk("jffs_scan_flash(): Leaving...\n"));
flash_safe_release(fmc->flash_part);
return 0;
} /*jffs_scan_flash*/
/* Create and initialize a new struct jffs_file. */
static struct jffs_file *jffs_create_file(struct jffs_control *c,
const struct jffs_raw_inode *raw_inode)
{
struct jffs_file *f;
if (!(f = (struct jffs_file *)malloc(sizeof(struct jffs_file)))) {
D(printk("jffs_create_file(): Failed!\n"));
return 0;
}
DJM(no_jffs_file++);
memset(f, 0, sizeof(struct jffs_file));
f->ino = raw_inode->ino;
f->pino = raw_inode->pino;
f->nlink = raw_inode->nlink;
f->deleted = raw_inode->deleted;
f->c = c;
return f;
}
/* Unlink a jffs_node from the version list it is in. */
static void jffs_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 void jffs_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;
}
}
/* Insert a file into the hash table. */
int
jffs_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. */
int jffs_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. */
int
jffs_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. */
int
jffs_unlink_file_from_tree(struct jffs_file *f)
{
D3(printk("jffs_unlink_file_from_tree(): ino: %d, pino: %d, name: "
"\"%s\"\n", f->ino, f->pino, (f->name ? f->name : "")));
if (f->sibling_prev) {
f->sibling_prev->sibling_next = f->sibling_next;
}
else if (f->parent) {
f->parent->children = f->sibling_next;
}
if (f->sibling_next) {
f->sibling_next->sibling_prev = f->sibling_prev;
}
return 0;
}
/* Free all nodes associated with a file. */
int
jffs_free_node_list(struct jffs_file *f)
{
struct jffs_node *node;
struct jffs_node *p;
D3(printk("jffs_free_node_list(): f #%u, \"%s\"\n",
f->ino, (f->name ? f->name : "")));
node = f->version_head;
while (node) {
p = node;
node = node->version_next;
free(p);
DJM(no_jffs_node--);
}
return 0;
}
/* Free a file and its name. */
int
jffs_free_file(struct jffs_file *f)
{
D3(printk("jffs_free_file: f #%u, \"%s\"\n",
f->ino, (f->name ? f->name : "")));
if (f->name) {
free(f->name);
DJM(no_name--);
}
free(f);
DJM(no_jffs_file--);
return 0;
}
/* This routine calculates checksums in JFFS. */
__u32
jffs_checksum(const void *data, int size)
{
__u32 sum = 0;
__u8 *ptr = (__u8 *)data;
D3(printk("#csum at 0x%p, {0x%08lx, 0x%08lx, ... }, size: %d",
data,
data ? *(long *)data : 0,
data ? *((long *)data + 1) : 0,
size));
while (size-- > 0) {
sum += *ptr++;
}
D3(printk(", result: 0x%08x\n", sum));
return sum;
}
int
jffs_min(int a, int b)
{
return (a < b ? a : b);
}
/* If an obsolete node is partly going to be erased due to garbage
collection, the part that isn't going to be erased must be filled
with zeroes so that the scan of the flash will work smoothly next
time. (The data in the file could for instance be a JFFS image
which could cause enormous confusion during a scan of the flash
device if we didn't do this.)
There are two phases in this procedure: First, the clearing of
the name and data parts of the node. Second, possibly also clearing
a part of the raw inode as well. If the box is power cycled during
the first phase, only the checksum of this node-to-be-cleared-at-
the-end will be wrong. If the box is power cycled during, or after,
the clearing of the raw inode, the information like the length of
the name and data parts are zeroed. The next time the box is
powered up, the scanning algorithm manages this faulty data too
because:
- The checksum is invalid and thus the raw inode must be discarded
in any case.
- If the lengths of the data part or the name part are zeroed, the
scanning just continues after the raw inode. But after the inode
the scanning procedure just finds zeroes which is the same as
dirt.
So, in the end, this could never fail. :-) Even if it does fail,
the scanning algorithm should manage that too. */
static int jffs_clear_end_of_node(struct jffs_control *c, __u32 erase_size)
{
struct jffs_fm *fm;
struct jffs_fmcontrol *fmc = c->fmc;
__u32 zero_offset;
__u32 zero_size;
__u32 zero_offset_data;
__u32 zero_size_data;
__u32 cutting_raw_inode = 0;
if (!(fm = jffs_cut_node(fmc, erase_size))) {
D3(printk("jffs_clear_end_of_node(): fm == NULL\n"));
return 0;
}
/* Where and how much shall we clear? */
zero_offset = fmc->head->offset + erase_size;
zero_size = fm->offset + fm->size - zero_offset;
/* Do we have to clear the raw_inode explicitly? */
if (fm->size - zero_size < sizeof(struct jffs_raw_inode)) {
cutting_raw_inode = sizeof(struct jffs_raw_inode)
- (fm->size - zero_size);
}
/* First, clear the name and data fields. */
zero_offset_data = zero_offset + cutting_raw_inode;
zero_size_data = zero_size - cutting_raw_inode;
flash_safe_acquire(fmc->flash_part);
flash_memset((unsigned char *) zero_offset_data, 0, zero_size_data);
flash_safe_release(fmc->flash_part);
/* Should we clear a part of the raw inode? */
if (cutting_raw_inode) {
/* I guess it is ok to clear the raw inode in this order. */
flash_safe_acquire(fmc->flash_part);
flash_memset((unsigned char *) zero_offset, 0,
cutting_raw_inode);
flash_safe_release(fmc->flash_part);
}
return 0;
} /* jffs_clear_end_of_node() */
/* Try to erase as much as possible of the dirt in the flash memory. */
long jffs_try_to_erase(struct jffs_control *c)
{
struct jffs_fmcontrol *fmc = c->fmc;
long erase_size;
int err;
__u32 offset;
D3(printk("jffs_try_to_erase()\n"));
erase_size = jffs_erasable_size(fmc);
D2(printk("jffs_try_to_erase(): erase_size = %ld\n", erase_size));
if (erase_size == 0) {
return 0;
}
else if (erase_size < 0) {
/*printk(KERN_ERR "JFFS: jffs_try_to_erase: "
"jffs_erasable_size returned %ld.\n", erase_size);*/
return erase_size;
}
if ((err = jffs_clear_end_of_node(c, erase_size)) < 0) {
/*printk(KERN_ERR "JFFS: jffs_try_to_erase: "
"Clearing of node failed.\n");*/
return err;
}
offset = fmc->head->offset - fmc->flash_start;
/* Now, let's try to do the erase. */
if ((err = flash_erase_region(c->sb->s_dev,
offset, erase_size)) < 0) {
/*printk(KERN_ERR "JFFS: Erase of flash failed. "
"offset = %u, erase_size = %ld\n",
offset, erase_size);*/
/* XXX: Here we should allocate this area as dirty
with jffs_fmalloced or something similar. Now
we just report the error. */
return err;
}
#if 0
/* Check if the erased sectors really got erased. */
{
__u32 pos;
__u32 end;
pos = (__u32)flash_get_direct_pointer(c->sb->s_dev, offset);
end = pos + erase_size;
D2(printk("JFFS: Checking erased sector(s)...\n"));
flash_safe_acquire(fmc->flash_part);
for (; pos < end; pos += 4) {
if (*(__u32 *)pos != JFFS_EMPTY_BITMASK) {
printk("JFFS: Erase failed! pos = 0x%p\n",
(unsigned char *)pos);
jffs_hexdump((unsigned char *)pos,
jffs_min(256, end - pos));
err = -1;
break;
}
}
flash_safe_release(fmc->flash_part);
if (!err) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -