fs: ext4: Fix alignment of cache buffers
[oweals/u-boot.git] / fs / jffs2 / jffs2_1pass.c
index c55d472047af4f07c4c17df3eb928abfae9f415c..5912cde83840f1b997cdb46251286f6912f8813f 100644 (file)
 #include <config.h>
 #include <malloc.h>
 #include <div64.h>
+#include <linux/compiler.h>
 #include <linux/stat.h>
 #include <linux/time.h>
+#include <u-boot/crc.h>
 #include <watchdog.h>
 #include <jffs2/jffs2.h>
 #include <jffs2/jffs2_1pass.h>
 #include <linux/compat.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
 
 #include "jffs2_private.h"
 
@@ -174,10 +176,15 @@ static u32 nand_cache_off = (u32)-1;
 static int read_nand_cached(u32 off, u32 size, u_char *buf)
 {
        struct mtdids *id = current_part->dev->id;
+       struct mtd_info *mtd;
        u32 bytes_read = 0;
        size_t retlen;
        int cpy_bytes;
 
+       mtd = get_nand_dev_by_index(id->num);
+       if (!mtd)
+               return -1;
+
        while (bytes_read < size) {
                if ((off + bytes_read < nand_cache_off) ||
                    (off + bytes_read >= nand_cache_off+NAND_CACHE_SIZE)) {
@@ -194,8 +201,8 @@ static int read_nand_cached(u32 off, u32 size, u_char *buf)
                        }
 
                        retlen = NAND_CACHE_SIZE;
-                       if (nand_read(&nand_info[id->num], nand_cache_off,
-                                               &retlen, nand_cache) != 0 ||
+                       if (nand_read(mtd, nand_cache_off,
+                                     &retlen, nand_cache) < 0 ||
                                        retlen != NAND_CACHE_SIZE) {
                                printf("read_nand_cached: error reading nand off %#x size %d bytes\n",
                                                nand_cache_off, NAND_CACHE_SIZE);
@@ -294,7 +301,7 @@ static int read_onenand_cached(u32 off, u32 size, u_char *buf)
 
                        retlen = ONENAND_CACHE_SIZE;
                        if (onenand_read(&onenand_mtd, onenand_cache_off, retlen,
-                                               &retlen, onenand_cache) != 0 ||
+                                               &retlen, onenand_cache) < 0 ||
                                        retlen != ONENAND_CACHE_SIZE) {
                                printf("read_onenand_cached: error reading nand off %#x size %d bytes\n",
                                        onenand_cache_off, ONENAND_CACHE_SIZE);
@@ -545,49 +552,19 @@ static struct b_node *
 insert_node(struct b_list *list, u32 offset)
 {
        struct b_node *new;
-#ifdef CONFIG_SYS_JFFS2_SORT_FRAGMENTS
-       struct b_node *b, *prev;
-#endif
 
        if (!(new = add_node(list))) {
                putstr("add_node failed!\r\n");
                return NULL;
        }
        new->offset = offset;
+       new->next = NULL;
 
-#ifdef CONFIG_SYS_JFFS2_SORT_FRAGMENTS
-       if (list->listTail != NULL && list->listCompare(new, list->listTail))
-               prev = list->listTail;
-       else if (list->listLast != NULL && list->listCompare(new, list->listLast))
-               prev = list->listLast;
+       if (list->listTail != NULL)
+               list->listTail->next = new;
        else
-               prev = NULL;
-
-       for (b = (prev ? prev->next : list->listHead);
-            b != NULL && list->listCompare(new, b);
-            prev = b, b = b->next) {
-               list->listLoops++;
-       }
-       if (b != NULL)
-               list->listLast = prev;
-
-       if (b != NULL) {
-               new->next = b;
-               if (prev != NULL)
-                       prev->next = new;
-               else
-                       list->listHead = new;
-       } else
-#endif
-       {
-               new->next = (struct b_node *) NULL;
-               if (list->listTail != NULL) {
-                       list->listTail->next = new;
-                       list->listTail = new;
-               } else {
-                       list->listTail = list->listHead = new;
-               }
-       }
+               list->listHead = new;
+       list->listTail = new;
 
        return new;
 }
@@ -1358,7 +1335,7 @@ int jffs2_sum_scan_sumnode(struct part_info *part, uint32_t offset,
                           struct b_lists *pL)
 {
        struct jffs2_unknown_node crcnode;
-       int ret, ofs;
+       int ret, __maybe_unused ofs;
        uint32_t crc;
 
        ofs = part->sector_size - sumsize;
@@ -1528,6 +1505,8 @@ jffs2_1pass_build_lists(struct part_info * part)
                uint32_t sumlen;
                int ret;
 #endif
+               /* Indicates a sector with a CLEANMARKER was found */
+               int clean_sector = 0;
 
                /* Set buf_size to maximum length */
                buf_size = DEFAULT_EMPTY_SCAN_SIZE;
@@ -1652,6 +1631,14 @@ jffs2_1pass_build_lists(struct part_info * part)
                                        ofs += 4;
                                }
                                /* Ran off end. */
+                               /*
+                                * If this sector had a clean marker at the
+                                * beginning, and immediately following this
+                                * have been a bunch of FF bytes, treat the
+                                * entire sector as empty.
+                                */
+                               if (clean_sector)
+                                       break;
 
                                /* See how much more there is to read in this
                                 * eraseblock...
@@ -1673,6 +1660,11 @@ jffs2_1pass_build_lists(struct part_info * part)
                                buf_ofs = ofs;
                                goto more_empty;
                        }
+                       /*
+                        * Found something not erased in the sector, so reset
+                        * the 'clean_sector' flag.
+                        */
+                       clean_sector = 0;
                        if (node->magic != JFFS2_MAGIC_BITMASK ||
                                        !hdr_crc(node)) {
                                ofs += 4;
@@ -1754,6 +1746,16 @@ jffs2_1pass_build_lists(struct part_info * part)
                                                "%d != %zu\n",
                                                node->totlen,
                                                sizeof(struct jffs2_unknown_node));
+                               if ((node->totlen ==
+                                    sizeof(struct jffs2_unknown_node)) &&
+                                   (ofs == sector_ofs)) {
+                                       /*
+                                        * Found a CLEANMARKER at the beginning
+                                        * of the sector. It's in the correct
+                                        * place with correct size and CRC.
+                                        */
+                                       clean_sector = 1;
+                               }
                                break;
                        case JFFS2_NODETYPE_PADDING:
                                if (node->totlen < sizeof(struct jffs2_unknown_node))
@@ -1775,6 +1777,13 @@ jffs2_1pass_build_lists(struct part_info * part)
        }
 
        free(buf);
+#if defined(CONFIG_SYS_JFFS2_SORT_FRAGMENTS)
+       /*
+        * Sort the lists.
+        */
+       sort_list(&pL->frag);
+       sort_list(&pL->dir);
+#endif
        putstr("\b\b done.\r\n");               /* close off the dots */
 
        /* We don't care if malloc failed - then each read operation will