From 69dbebd1f70a983bede22ffb8be36fbf7eaa7d61 Mon Sep 17 00:00:00 2001 From: Petr Borsodi Date: Thu, 7 May 2020 12:25:56 +0200 Subject: [PATCH] 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 --- fs/jffs2/jffs2_1pass.c | 154 +++++++++++++++++++-------------------- fs/jffs2/jffs2_private.h | 5 ++ 2 files changed, 81 insertions(+), 78 deletions(-) diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index 68db8c3ba4..1115c8682e 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -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++; diff --git a/fs/jffs2/jffs2_private.h b/fs/jffs2/jffs2_private.h index 06b6ca2919..65d19a76f9 100644 --- a/fs/jffs2/jffs2_private.h +++ b/fs/jffs2/jffs2_private.h @@ -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 { -- 2.39.5