JFFS2: Add useful fields into lists

The inode list uses version and ino, the dirent list uses version and pino.
This information is collected during scanning, reducing accesses to flash
and significantly speeding up ls and read.

Signed-off-by: Petr Borsodi <petr.borsodi@i.cz>
This commit is contained in:
Petr Borsodi 2020-05-07 12:25:56 +02:00 committed by Tom Rini
parent 25ec2282eb
commit 69dbebd1f7
2 changed files with 81 additions and 78 deletions

View file

@ -549,7 +549,7 @@ add_node(struct b_list *list)
}
static struct b_node *
insert_node(struct b_list *list, u32 offset)
insert_node(struct b_list *list)
{
struct b_node *new;
@ -557,7 +557,6 @@ insert_node(struct b_list *list, u32 offset)
putstr("add_node failed!\r\n");
return NULL;
}
new->offset = offset;
new->next = NULL;
if (list->listTail != NULL)
@ -575,18 +574,7 @@ insert_node(struct b_list *list, u32 offset)
*/
static int compare_inodes(struct b_node *new, struct b_node *old)
{
/*
* Only read in the version info from flash, not the entire inode.
* This can make a big difference to speed if flash is slow.
*/
u32 new_version;
u32 old_version;
get_fl_mem(new->offset + offsetof(struct jffs2_raw_inode, version),
sizeof(new_version), &new_version);
get_fl_mem(old->offset + offsetof(struct jffs2_raw_inode, version),
sizeof(old_version), &old_version);
return new_version > old_version;
return new->version > old->version;
}
/* Sort directory entries so all entries in the same directory
@ -683,7 +671,7 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)
uchar *src;
int i;
u32 counter = 0;
#ifdef CONFIG_SYS_JFFS2_SORT_FRAGMENTS
/* Find file size before loading any data, so fragments that
* start past the end of file can be ignored. A fragment
* that is partially in the file is loaded, so extra data may
@ -691,35 +679,40 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)
* This shouldn't cause trouble when loading kernel images, so
* we will live with it.
*/
int latestOffset = -1;
for (b = pL->frag.listHead; b != NULL; b = b->next) {
jNode = (struct jffs2_raw_inode *) get_fl_mem(b->offset,
sizeof(struct jffs2_raw_inode), pL->readbuf);
if ((inode == jNode->ino)) {
if (inode == b->ino) {
/* get actual file length from the newest node */
if (jNode->version >= latestVersion) {
totalSize = jNode->isize;
latestVersion = jNode->version;
if (b->version >= latestVersion) {
latestVersion = b->version;
latestOffset = b->offset;
}
}
}
if (latestOffset >= 0) {
jNode = (struct jffs2_raw_inode *)get_fl_mem(latestOffset,
sizeof(struct jffs2_raw_inode), pL->readbuf);
totalSize = jNode->isize;
put_fl_mem(jNode, pL->readbuf);
}
/*
* If no destination is provided, we are done.
* Just return the total size.
*/
if (!dest)
return totalSize;
#endif
for (b = pL->frag.listHead; b != NULL; b = b->next) {
/*
* Copy just the node and not the data at this point,
* since we don't yet know if we need this data.
*/
jNode = (struct jffs2_raw_inode *)get_fl_mem(b->offset,
sizeof(struct jffs2_raw_inode),
pL->readbuf);
if (inode == jNode->ino) {
if (inode == b->ino) {
/*
* Copy just the node and not the data at this point,
* since we don't yet know if we need this data.
*/
jNode = (struct jffs2_raw_inode *)get_fl_mem(b->offset,
sizeof(struct jffs2_raw_inode),
pL->readbuf);
#if 0
putLabeledWord("\r\n\r\nread_inode: totlen = ", jNode->totlen);
putLabeledWord("read_inode: inode = ", jNode->ino);
@ -733,14 +726,6 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)
putLabeledWord("read_inode: flags = ", jNode->flags);
#endif
#ifndef CONFIG_SYS_JFFS2_SORT_FRAGMENTS
/* get actual file length from the newest node */
if (jNode->version >= latestVersion) {
totalSize = jNode->isize;
latestVersion = jNode->version;
}
#endif
if(dest) {
/*
* Now that the inode has been checked,
@ -804,9 +789,9 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)
#if 0
putLabeledWord("read_inode: totalSize = ", totalSize);
#endif
put_fl_mem(jNode, pL->readbuf);
}
counter++;
put_fl_mem(jNode, pL->readbuf);
}
#if 0
@ -953,13 +938,14 @@ jffs2_1pass_list_inodes(struct b_lists * pL, u32 pino)
struct jffs2_raw_dirent *jDir;
for (b = pL->dir.listHead; b; b = b->next) {
jDir = (struct jffs2_raw_dirent *) get_node_mem(b->offset,
pL->readbuf);
if (pino == jDir->pino) {
if (pino == b->pino) {
u32 i_version = 0;
struct jffs2_raw_inode *jNode, *i = NULL;
int i_offset = -1;
struct jffs2_raw_inode *jNode = NULL;
struct b_node *b2;
jDir = (struct jffs2_raw_dirent *)
get_node_mem(b->offset, pL->readbuf);
#ifdef CONFIG_SYS_JFFS2_SORT_FRAGMENTS
/* Check for more recent versions of this file */
int match;
@ -991,30 +977,27 @@ jffs2_1pass_list_inodes(struct b_lists * pL, u32 pino)
}
for (b2 = pL->frag.listHead; b2; b2 = b2->next) {
jNode = (struct jffs2_raw_inode *)
get_fl_mem(b2->offset, sizeof(*jNode),
NULL);
if (jNode->ino == jDir->ino &&
jNode->version >= i_version) {
i_version = jNode->version;
if (i)
put_fl_mem(i, NULL);
if (jDir->type == DT_LNK)
i = get_node_mem(b2->offset,
NULL);
else
i = get_fl_mem(b2->offset,
sizeof(*i),
NULL);
if (b2->ino == jDir->ino &&
b2->version >= i_version) {
i_version = b2->version;
i_offset = b2->offset;
}
put_fl_mem(jNode, NULL);
}
dump_inode(pL, jDir, i);
put_fl_mem(i, NULL);
if (i_version >= 0) {
if (jDir->type == DT_LNK)
jNode = get_node_mem(i_offset, NULL);
else
jNode = get_fl_mem(i_offset,
sizeof(*jNode),
NULL);
}
dump_inode(pL, jDir, jNode);
put_fl_mem(jNode, NULL);
put_fl_mem(jDir, pL->readbuf);
}
put_fl_mem(jDir, pL->readbuf);
}
return pino;
}
@ -1266,7 +1249,7 @@ static int jffs2_sum_process_sum_data(struct part_info *part, uint32_t offset,
{
void *sp;
int i, pass;
void *ret;
struct b_node *b;
for (pass = 0; pass < 2; pass++) {
sp = summary->sum;
@ -1281,13 +1264,17 @@ static int jffs2_sum_process_sum_data(struct part_info *part, uint32_t offset,
if (pass) {
spi = sp;
ret = insert_node(&pL->frag,
(u32)part->offset +
b = insert_node(&pL->frag);
if (!b)
return -1;
b->offset = (u32)part->offset +
offset +
sum_get_unaligned32(
&spi->offset));
if (ret == NULL)
return -1;
&spi->offset);
b->version = sum_get_unaligned32(
&spi->version);
b->ino = sum_get_unaligned32(
&spi->inode);
}
sp += JFFS2_SUMMARY_INODE_SIZE;
@ -1298,13 +1285,17 @@ static int jffs2_sum_process_sum_data(struct part_info *part, uint32_t offset,
struct jffs2_sum_dirent_flash *spd;
spd = sp;
if (pass) {
ret = insert_node(&pL->dir,
(u32) part->offset +
b = insert_node(&pL->dir);
if (!b)
return -1;
b->offset = (u32)part->offset +
offset +
sum_get_unaligned32(
&spd->offset));
if (ret == NULL)
return -1;
&spd->offset);
b->version = sum_get_unaligned32(
&spd->version);
b->pino = sum_get_unaligned32(
&spd->pino);
}
sp += JFFS2_SUMMARY_DIRENT_SIZE(
@ -1508,6 +1499,7 @@ jffs2_1pass_build_lists(struct part_info * part)
/* Indicates a sector with a CLEANMARKER was found */
int clean_sector = 0;
struct jffs2_unknown_node crcnode;
struct b_node *b;
/* Set buf_size to maximum length */
buf_size = DEFAULT_EMPTY_SCAN_SIZE;
@ -1715,12 +1707,15 @@ jffs2_1pass_build_lists(struct part_info * part)
if (!inode_crc((struct jffs2_raw_inode *)node))
break;
if (insert_node(&pL->frag, (u32) part->offset +
ofs) == NULL) {
b = insert_node(&pL->frag);
if (!b) {
free(buf);
jffs2_free_cache(part);
return 0;
}
b->offset = (u32)part->offset + ofs;
b->version = node->i.version;
b->ino = node->i.ino;
if (max_totlen < node->u.totlen)
max_totlen = node->u.totlen;
break;
@ -1750,12 +1745,15 @@ jffs2_1pass_build_lists(struct part_info * part)
break;
if (! (counterN%100))
puts ("\b\b. ");
if (insert_node(&pL->dir, (u32) part->offset +
ofs) == NULL) {
b = insert_node(&pL->dir);
if (!b) {
free(buf);
jffs2_free_cache(part);
return 0;
}
b->offset = (u32)part->offset + ofs;
b->version = node->d.version;
b->pino = node->d.pino;
if (max_totlen < node->u.totlen)
max_totlen = node->u.totlen;
counterN++;

View file

@ -8,6 +8,11 @@ struct b_node {
u32 offset;
struct b_node *next;
enum { CRC_UNKNOWN = 0, CRC_OK, CRC_BAD } datacrc;
u32 version;
union {
u32 ino; /* for inodes */
u32 pino; /* for dirents */
};
};
struct b_list {