]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - fs/jffs2/jffs2_1pass.c
JFFS2: Improve speed reading flash files
[karo-tx-uboot.git] / fs / jffs2 / jffs2_1pass.c
index aaeb522a31b88d8c4b86ccfcf051d5ec35680bf2..e58e7d25cff128b248db26b99b0f50a73428a9bf 100644 (file)
@@ -735,8 +735,13 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)
 #endif
 
        for (b = pL->frag.listHead; b != NULL; b = b->next) {
-               jNode = (struct jffs2_raw_inode *) get_node_mem(b->offset,
-                                                               pL->readbuf);
+               /*
+                * 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 0
                        putLabeledWord("\r\n\r\nread_inode: totlen = ", jNode->totlen);
@@ -760,7 +765,15 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)
 #endif
 
                        if(dest) {
-                               src = ((uchar *) jNode) + sizeof(struct jffs2_raw_inode);
+                               /*
+                                * Now that the inode has been checked,
+                                * read the entire inode, including data.
+                                */
+                               put_fl_mem(jNode, pL->readbuf);
+                               jNode = (struct jffs2_raw_inode *)
+                                       get_node_mem(b->offset, pL->readbuf);
+                               src = ((uchar *)jNode) +
+                                       sizeof(struct jffs2_raw_inode);
                                /* ignore data behind latest known EOF */
                                if (jNode->offset > totalSize) {
                                        put_fl_mem(jNode, pL->readbuf);
@@ -845,7 +858,6 @@ jffs2_1pass_find_inode(struct b_lists * pL, const char *name, u32 pino)
                jDir = (struct jffs2_raw_dirent *) get_node_mem(b->offset,
                                                                pL->readbuf);
                if ((pino == jDir->pino) && (len == jDir->nsize) &&
-                   (jDir->ino) &&      /* 0 for unlink */
                    (!strncmp((char *)jDir->name, name, len))) {        /* a match */
                        if (jDir->version < version) {
                                put_fl_mem(jDir, pL->readbuf);
@@ -966,16 +978,47 @@ jffs2_1pass_list_inodes(struct b_lists * pL, u32 pino)
        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) && (jDir->ino)) { /* ino=0 -> unlink */
+               if (pino == jDir->pino) {
                        u32 i_version = 0;
-                       struct jffs2_raw_inode ojNode;
                        struct jffs2_raw_inode *jNode, *i = NULL;
-                       struct b_node *b2 = pL->frag.listHead;
+                       struct b_node *b2;
+
+#ifdef CONFIG_SYS_JFFS2_SORT_FRAGMENTS
+                       /* Check for more recent versions of this file */
+                       int match;
+                       do {
+                               struct b_node *next = b->next;
+                               struct jffs2_raw_dirent *jDirNext;
+                               if (!next)
+                                       break;
+                               jDirNext = (struct jffs2_raw_dirent *)
+                                       get_node_mem(next->offset, NULL);
+                               match = jDirNext->pino == jDir->pino &&
+                                       jDirNext->nsize == jDir->nsize &&
+                                       strncmp((char *)jDirNext->name,
+                                               (char *)jDir->name,
+                                               jDir->nsize) == 0;
+                               if (match) {
+                                       /* Use next. It is more recent */
+                                       b = next;
+                                       /* Update buffer with the new info */
+                                       *jDir = *jDirNext;
+                               }
+                               put_fl_mem(jDirNext, NULL);
+                       } while (match);
+#endif
+                       if (jDir->ino == 0) {
+                               /* Deleted file */
+                               put_fl_mem(jDir, pL->readbuf);
+                               continue;
+                       }
 
-                       while (b2) {
+                       for (b2 = pL->frag.listHead; b2; b2 = b2->next) {
                                jNode = (struct jffs2_raw_inode *)
-                                       get_fl_mem(b2->offset, sizeof(ojNode), &ojNode);
-                               if (jNode->ino == jDir->ino && jNode->version >= i_version) {
+                                       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);
@@ -988,7 +1031,7 @@ jffs2_1pass_list_inodes(struct b_lists * pL, u32 pino)
                                                               sizeof(*i),
                                                               NULL);
                                }
-                               b2 = b2->next;
+                               put_fl_mem(jNode, NULL);
                        }
 
                        dump_inode(pL, jDir, i);