[U-Boot] [PATCH] jffs2: summary support

Ilya Yanok yanok at emcraft.com
Mon Oct 13 07:53:50 CEST 2008


This patch adds support for reading fs information from summary
node instead of scanning full eraseblock.

Signed-off-by: Ilya Yanok <yanok at emcraft.com>
---
 fs/jffs2/jffs2_1pass.c |  187 +++++++++++++++++++++++++++++++++++++++++++++++-
 fs/jffs2/summary.h     |  163 +++++++++++++++++++++++++++++++++++++++++
 include/jffs2/jffs2.h  |   19 +++++
 3 files changed, 368 insertions(+), 1 deletions(-)
 create mode 100644 fs/jffs2/summary.h

diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c
index 61a0459..58298c0 100644
--- a/fs/jffs2/jffs2_1pass.c
+++ b/fs/jffs2/jffs2_1pass.c
@@ -138,6 +138,8 @@
 # define DEBUGF(fmt,args...)
 #endif
 
+#include "summary.h"
+
 /* keeps pointer to currentlu processed partition */
 static struct part_info *current_part;
 
@@ -1202,6 +1204,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)
@@ -1307,10 +1435,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 */
@@ -1459,6 +1642,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
index 0000000..834933c
--- /dev/null
+++ b/fs/jffs2/summary.h
@@ -0,0 +1,163 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright © 2004  Ferenc Havasi <havasi at inf.u-szeged.hu>,
+ *		     Zoltan Sogor <weth at inf.u-szeged.hu>,
+ *		     Patrik Kluba <pajko at 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 */
diff --git a/include/jffs2/jffs2.h b/include/jffs2/jffs2.h
index d142cd1..ed96bab 100644
--- a/include/jffs2/jffs2.h
+++ b/include/jffs2/jffs2.h
@@ -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));
 
-- 
1.5.6.1



More information about the U-Boot mailing list