]> git.sur5r.net Git - u-boot/commitdiff
jffs2: summary support
authorIlya Yanok <yanok@emcraft.com>
Thu, 13 Nov 2008 16:49:35 +0000 (19:49 +0300)
committerWolfgang Denk <wd@denx.de>
Tue, 9 Dec 2008 22:39:59 +0000 (23:39 +0100)
This patch adds support for reading fs information from summary
node instead of scanning full eraseblock.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
fs/jffs2/jffs2_1pass.c
fs/jffs2/summary.h [new file with mode: 0644]
include/jffs2/jffs2.h

index 73d3ddc9e137fa7e68cc8e1855e9186d3fffeeaa..4e49a056694ec6b14a71eaadd0713e5ce3a0021b 100644 (file)
 # define DEBUGF(fmt,args...)
 #endif
 
+#include "summary.h"
+
 /* keeps pointer to currentlu processed partition */
 static struct part_info *current_part;
 
@@ -1214,6 +1216,132 @@ jffs2_1pass_rescan_needed(struct part_info *part)
        return 0;
 }
 
+#define dbg_summary(...) do {} while (0);
+/* Process the stored summary information - helper function for
+ * jffs2_sum_scan_sumnode()
+ */
+
+static int jffs2_sum_process_sum_data(struct part_info *part, uint32_t offset,
+                               struct jffs2_raw_summary *summary,
+                               struct b_lists *pL)
+{
+       void *sp;
+       int i;
+
+       sp = summary->sum;
+
+       for (i = 0; i < summary->sum_num; i++) {
+               dbg_summary("processing summary index %d\n", i);
+
+               switch (((struct jffs2_sum_unknown_flash *)sp)->nodetype) {
+                       case JFFS2_NODETYPE_INODE: {
+                               struct jffs2_sum_inode_flash *spi;
+                               spi = sp;
+
+                               dbg_summary("Inode at 0x%08x-0x%08x\n",
+                                           offset + spi->offset,
+                                           offset + spi->offset + spi->totlen);
+
+                               if (insert_node(&pL->frag, (u32) part->offset +
+                                               offset + spi->offset) == NULL)
+                                       return -1;
+
+                               sp += JFFS2_SUMMARY_INODE_SIZE;
+
+                               break;
+                       }
+
+                       case JFFS2_NODETYPE_DIRENT: {
+                               struct jffs2_sum_dirent_flash *spd;
+                               spd = sp;
+
+                               dbg_summary("Dirent at 0x%08x-0x%08x\n",
+                                           offset + spd->offset,
+                                           offset + spd->offset + spd->totlen);
+
+                               if (insert_node(&pL->dir, (u32) part->offset +
+                                               offset + spd->offset) == NULL)
+                                       return -1;
+
+                               sp += JFFS2_SUMMARY_DIRENT_SIZE(spd->nsize);
+
+                               break;
+                       }
+                       default : {
+                               uint16_t nodetype =
+                                       ((struct jffs2_sum_unknown_flash *)
+                                        sp)->nodetype;
+                               printf("Unsupported node type %x found in "
+                                               "summary!\n", nodetype);
+                               break;
+                       }
+               }
+       }
+       return 0;
+}
+
+/* Process the summary node - called from jffs2_scan_eraseblock() */
+int jffs2_sum_scan_sumnode(struct part_info *part, uint32_t offset,
+                          struct jffs2_raw_summary *summary, uint32_t sumsize,
+                          struct b_lists *pL)
+{
+       struct jffs2_unknown_node crcnode;
+       int ret, ofs;
+       uint32_t crc;
+
+       ofs = part->sector_size - sumsize;
+
+       dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n",
+                   offset, offset + ofs, sumsize);
+
+       /* OK, now check for node validity and CRC */
+       crcnode.magic = JFFS2_MAGIC_BITMASK;
+       crcnode.nodetype = JFFS2_NODETYPE_SUMMARY;
+       crcnode.totlen = summary->totlen;
+       crc = crc32_no_comp(0, (uchar *)&crcnode, sizeof(crcnode)-4);
+
+       if (summary->hdr_crc != crc) {
+               dbg_summary("Summary node header is corrupt (bad CRC or "
+                               "no summary at all)\n");
+               goto crc_err;
+       }
+
+       if (summary->totlen != sumsize) {
+               dbg_summary("Summary node is corrupt (wrong erasesize?)\n");
+               goto crc_err;
+       }
+
+       crc = crc32_no_comp(0, (uchar *)summary,
+                       sizeof(struct jffs2_raw_summary)-8);
+
+       if (summary->node_crc != crc) {
+               dbg_summary("Summary node is corrupt (bad CRC)\n");
+               goto crc_err;
+       }
+
+       crc = crc32_no_comp(0, (uchar *)summary->sum,
+                       sumsize - sizeof(struct jffs2_raw_summary));
+
+       if (summary->sum_crc != crc) {
+               dbg_summary("Summary node data is corrupt (bad CRC)\n");
+               goto crc_err;
+       }
+
+       if (summary->cln_mkr)
+               dbg_summary("Summary : CLEANMARKER node \n");
+
+       ret = jffs2_sum_process_sum_data(part, offset, summary, pL);
+       if (ret)
+               return ret;             /* real error */
+
+       return 1;
+
+crc_err:
+       putstr("Summary node crc error, skipping summary information.\n");
+
+       return 0;
+}
+
 #ifdef DEBUG_FRAGMENTS
 static void
 dump_fragments(struct b_lists *pL)
@@ -1321,10 +1449,65 @@ jffs2_1pass_build_lists(struct part_info * part)
        for (i = 0; i < nr_sectors; i++) {
                uint32_t sector_ofs = i * part->sector_size;
                uint32_t buf_ofs = sector_ofs;
-               uint32_t buf_len = EMPTY_SCAN_SIZE(part->sector_size);
+               uint32_t buf_len;
                uint32_t ofs, prevofs;
+               struct jffs2_sum_marker *sm;
+               void *sumptr = NULL;
+               uint32_t sumlen;
+               int ret;
 
                WATCHDOG_RESET();
+
+               buf_len = sizeof(*sm);
+
+               /* Read as much as we want into the _end_ of the preallocated
+                * buffer
+                */
+               get_fl_mem(part->offset + sector_ofs + part->sector_size -
+                               buf_len, buf_len, buf + buf_size - buf_len);
+
+               sm = (void *)buf + buf_size - sizeof(*sm);
+               if (sm->magic == JFFS2_SUM_MAGIC) {
+                       sumlen = part->sector_size - sm->offset;
+                       sumptr = buf + buf_size - sumlen;
+
+                       /* Now, make sure the summary itself is available */
+                       if (sumlen > buf_size) {
+                               /* Need to kmalloc for this. */
+                               sumptr = malloc(sumlen);
+                               if (!sumptr) {
+                                       putstr("Can't get memory for summary "
+                                                       "node!\n");
+                                       return 0;
+                               }
+                               memcpy(sumptr + sumlen - buf_len, buf +
+                                               buf_size - buf_len, buf_len);
+                       }
+                       if (buf_len < sumlen) {
+                               /* Need to read more so that the entire summary
+                                * node is present
+                                */
+                               get_fl_mem(part->offset + sector_ofs +
+                                               part->sector_size - sumlen,
+                                               sumlen - buf_len, sumptr);
+                       }
+               }
+
+               if (sumptr) {
+                       ret = jffs2_sum_scan_sumnode(part, sector_ofs, sumptr,
+                                       sumlen, pL);
+
+                       if (buf_size && sumlen > buf_size)
+                               free(sumptr);
+                       if (ret < 0)
+                               return 0;
+                       if (ret)
+                               continue;
+
+               }
+
+               buf_len = EMPTY_SCAN_SIZE(part->sector_size);
+
                get_fl_mem((u32)part->offset + buf_ofs, buf_len, buf);
 
                /* We temporarily use 'ofs' as a pointer into the buffer/jeb */
@@ -1477,6 +1660,8 @@ jffs2_1pass_build_lists(struct part_info * part)
                                                node->totlen,
                                                sizeof(struct jffs2_unknown_node));
                                break;
+                       case JFFS2_NODETYPE_SUMMARY:
+                               break;
                        default:
                                printf("Unknown node type: %x len %d offset 0x%x\n",
                                        node->nodetype,
diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h
new file mode 100644 (file)
index 0000000..834933c
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright © 2004  Ferenc Havasi <havasi@inf.u-szeged.hu>,
+ *                  Zoltan Sogor <weth@inf.u-szeged.hu>,
+ *                  Patrik Kluba <pajko@halom.u-szeged.hu>,
+ *                  University of Szeged, Hungary
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+
+#ifndef JFFS2_SUMMARY_H
+#define JFFS2_SUMMARY_H
+
+#define BLK_STATE_ALLFF                0
+#define BLK_STATE_CLEAN                1
+#define BLK_STATE_PARTDIRTY    2
+#define BLK_STATE_CLEANMARKER  3
+#define BLK_STATE_ALLDIRTY     4
+#define BLK_STATE_BADBLOCK     5
+
+#define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff
+#define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash))
+#define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x))
+#define JFFS2_SUMMARY_XATTR_SIZE (sizeof(struct jffs2_sum_xattr_flash))
+#define JFFS2_SUMMARY_XREF_SIZE (sizeof(struct jffs2_sum_xref_flash))
+
+/* Summary structures used on flash */
+
+struct jffs2_sum_unknown_flash
+{
+       __u16 nodetype; /* node type */
+};
+
+struct jffs2_sum_inode_flash
+{
+       __u16 nodetype; /* node type */
+       __u32 inode;            /* inode number */
+       __u32 version;  /* inode version */
+       __u32 offset;   /* offset on jeb */
+       __u32 totlen;   /* record length */
+} __attribute__((packed));
+
+struct jffs2_sum_dirent_flash
+{
+       __u16 nodetype; /* == JFFS_NODETYPE_DIRENT */
+       __u32 totlen;   /* record length */
+       __u32 offset;   /* offset on jeb */
+       __u32 pino;             /* parent inode */
+       __u32 version;  /* dirent version */
+       __u32 ino;              /* == zero for unlink */
+       uint8_t nsize;          /* dirent name size */
+       uint8_t type;           /* dirent type */
+       uint8_t name[0];        /* dirent name */
+} __attribute__((packed));
+
+struct jffs2_sum_xattr_flash
+{
+       __u16 nodetype; /* == JFFS2_NODETYPE_XATR */
+       __u32 xid;              /* xattr identifier */
+       __u32 version;  /* version number */
+       __u32 offset;   /* offset on jeb */
+       __u32 totlen;   /* node length */
+} __attribute__((packed));
+
+struct jffs2_sum_xref_flash
+{
+       __u16 nodetype; /* == JFFS2_NODETYPE_XREF */
+       __u32 offset;   /* offset on jeb */
+} __attribute__((packed));
+
+union jffs2_sum_flash
+{
+       struct jffs2_sum_unknown_flash u;
+       struct jffs2_sum_inode_flash i;
+       struct jffs2_sum_dirent_flash d;
+       struct jffs2_sum_xattr_flash x;
+       struct jffs2_sum_xref_flash r;
+};
+
+/* Summary structures used in the memory */
+
+struct jffs2_sum_unknown_mem
+{
+       union jffs2_sum_mem *next;
+       __u16 nodetype; /* node type */
+};
+
+struct jffs2_sum_inode_mem
+{
+       union jffs2_sum_mem *next;
+       __u16 nodetype; /* node type */
+       __u32 inode;            /* inode number */
+       __u32 version;  /* inode version */
+       __u32 offset;   /* offset on jeb */
+       __u32 totlen;   /* record length */
+} __attribute__((packed));
+
+struct jffs2_sum_dirent_mem
+{
+       union jffs2_sum_mem *next;
+       __u16 nodetype; /* == JFFS_NODETYPE_DIRENT */
+       __u32 totlen;   /* record length */
+       __u32 offset;   /* ofset on jeb */
+       __u32 pino;             /* parent inode */
+       __u32 version;  /* dirent version */
+       __u32 ino;              /* == zero for unlink */
+       uint8_t nsize;          /* dirent name size */
+       uint8_t type;           /* dirent type */
+       uint8_t name[0];        /* dirent name */
+} __attribute__((packed));
+
+struct jffs2_sum_xattr_mem
+{
+       union jffs2_sum_mem *next;
+       __u16 nodetype;
+       __u32 xid;
+       __u32 version;
+       __u32 offset;
+       __u32 totlen;
+} __attribute__((packed));
+
+struct jffs2_sum_xref_mem
+{
+       union jffs2_sum_mem *next;
+       __u16 nodetype;
+       __u32 offset;
+} __attribute__((packed));
+
+union jffs2_sum_mem
+{
+       struct jffs2_sum_unknown_mem u;
+       struct jffs2_sum_inode_mem i;
+       struct jffs2_sum_dirent_mem d;
+       struct jffs2_sum_xattr_mem x;
+       struct jffs2_sum_xref_mem r;
+};
+
+/* Summary related information stored in superblock */
+
+struct jffs2_summary
+{
+       uint32_t sum_size;      /* collected summary information for nextblock */
+       uint32_t sum_num;
+       uint32_t sum_padded;
+       union jffs2_sum_mem *sum_list_head;
+       union jffs2_sum_mem *sum_list_tail;
+
+       __u32 *sum_buf; /* buffer for writing out summary */
+};
+
+/* Summary marker is stored at the end of every sumarized erase block */
+
+struct jffs2_sum_marker
+{
+       __u32 offset;   /* offset of the summary node in the jeb */
+       __u32 magic;    /* == JFFS2_SUM_MAGIC */
+};
+
+#define JFFS2_SUMMARY_FRAME_SIZE (sizeof(struct jffs2_raw_summary) + sizeof(struct jffs2_sum_marker))
+
+#endif /* JFFS2_SUMMARY_H */
index d142cd1bce76de62ae2487fc41811fcbf9716ed3..ed96babf610967cf2cedf3bf9c90167861b5976d 100644 (file)
@@ -50,6 +50,9 @@
 #define JFFS2_EMPTY_BITMASK 0xffff
 #define JFFS2_DIRTY_BITMASK 0x0000
 
+/* Summary node MAGIC marker */
+#define JFFS2_SUM_MAGIC        0x02851885
+
 /* We only allow a single char for length, and 0xFF is empty flash so
    we don't want it confused with a real length. Hence max 254.
 */
@@ -89,6 +92,7 @@
 #define JFFS2_NODETYPE_INODE (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 2)
 #define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
 #define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4)
+#define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6)
 
 /* Maybe later... */
 /*#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) */
@@ -166,9 +170,24 @@ struct jffs2_raw_inode
 /*     __u8 data[dsize]; */
 } __attribute__((packed));
 
+struct jffs2_raw_summary
+{
+       __u16 magic;
+       __u16 nodetype;         /* = JFFS2_NODETYPE_SUMMARY */
+       __u32 totlen;
+       __u32 hdr_crc;
+       __u32 sum_num;  /* number of sum entries*/
+       __u32 cln_mkr;  /* clean marker size, 0 = no cleanmarker */
+       __u32 padded;   /* sum of the size of padding nodes */
+       __u32 sum_crc;  /* summary information crc */
+       __u32 node_crc;         /* node crc */
+       __u32 sum[0];   /* inode summary info */
+};
+
 union jffs2_node_union {
        struct jffs2_raw_inode i;
        struct jffs2_raw_dirent d;
+       struct jffs2_raw_summary s;
        struct jffs2_unknown_node u;
 } __attribute__((packed));