public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH]Add JFFS2 eraseblock header support
@ 2005-09-20  7:45 zhao forrest
  2005-09-20 10:24 ` Jörn Engel
  2005-09-20 11:29 ` Artem B. Bityutskiy
  0 siblings, 2 replies; 13+ messages in thread
From: zhao forrest @ 2005-09-20  7:45 UTC (permalink / raw)
  To: dedekind, joern; +Cc: linux-mtd

[-- Attachment #1: Type: text/plain, Size: 1183 bytes --]

Hi,
This is the patch for eraseblock header, the high-level design
can be found at http://lists.infradead.org/pipermail/linux-mtd/
2005-August/013374.html.

This patch closely follows the high-level design. Here I list
some main implementation points:
1 eraseblock_header replaces clean marker, clean marker no
longer exists.
2 now eraseblock header carrys version and erase count, but the
length of eraseblock header is not constant and it allows further
extention.
3 for NAND flash, the eraseblock header is stored in OOB and it
may span several OOBs
4 old JFFS2 binaries reject mounting new JFFS2 images
5 change the type of dirent/inode nodes and adding INCOMPAT flag
there in order to make old JFFS2 binaries reject mounting new
JFFS2 images for NAND flash
6 new JFFS2 binary, when mounting an old JFFS2 image, will reject
mounting unless the old JFFS2 image doesn't use 1:N(N>1)mapping.
7 If JFFS2 finds that the version of the image is larger, it will
reject mounting the image
8 currently this patch doesn't take the "eraseblock summary" patch
into account. It's greatly appreciated if Ferenc can help to add
the missing part :)

Your comments are welcome.

Thanks,
Forrest


[-- Attachment #2: eraseblock_header.patch --]
[-- Type: application/octet-stream, Size: 39148 bytes --]

diff -auNrp ./mtd/fs/jffs2/build.c ./mtd_eraseblock_header/fs/jffs2/build.c
--- ./mtd/fs/jffs2/build.c	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/fs/jffs2/build.c	2005-09-20 14:33:03.000000000 +0800
@@ -337,6 +337,8 @@ int jffs2_do_mount_fs(struct jffs2_sb_in
 		c->blocks[i].first_node = NULL;
 		c->blocks[i].last_node = NULL;
 		c->blocks[i].bad_count = 0;
+		c->blocks[i].has_eraseblock_header = 0;
+		c->blocks[i].erase_count = 0;
 	}
 
 	INIT_LIST_HEAD(&c->clean_list);
diff -auNrp ./mtd/fs/jffs2/debug.c ./mtd_eraseblock_header/fs/jffs2/debug.c
--- ./mtd/fs/jffs2/debug.c	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/fs/jffs2/debug.c	2005-09-20 14:33:05.000000000 +0800
@@ -667,6 +667,7 @@ __jffs2_dbg_dump_node(struct jffs2_sb_in
 	switch(je16_to_cpu(node.u.nodetype)) {
 
 	case JFFS2_NODETYPE_INODE:
+	case JFFS2_NODETYPE_INODE_EBH:
 
 		printk(JFFS2_DBG_LVL "the node is inode node\n");
 		printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
@@ -711,6 +712,7 @@ __jffs2_dbg_dump_node(struct jffs2_sb_in
 		break;
 
 	case JFFS2_NODETYPE_DIRENT:
+	case JFFS2_NODETYPE_DIRENT_EBH:
 
 		printk(JFFS2_DBG_LVL "the node is dirent node\n");
 		printk(JFFS2_DBG_LVL "pino:\t%#08x\n",
diff -auNrp ./mtd/fs/jffs2/dir.c ./mtd_eraseblock_header/fs/jffs2/dir.c
--- ./mtd/fs/jffs2/dir.c	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/fs/jffs2/dir.c	2005-09-20 14:33:05.000000000 +0800
@@ -391,7 +391,7 @@ static int jffs2_symlink (struct inode *
 	down(&dir_f->sem);
 
 	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
+	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT_EBH);
 	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
 	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
 
@@ -521,7 +521,7 @@ static int jffs2_mkdir (struct inode *di
 	down(&dir_f->sem);
 
 	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
+	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT_EBH);
 	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
 	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
 
@@ -677,7 +677,7 @@ static int jffs2_mknod (struct inode *di
 	down(&dir_f->sem);
 
 	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
+	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT_EBH);
 	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
 	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
 
diff -auNrp ./mtd/fs/jffs2/erase.c ./mtd_eraseblock_header/fs/jffs2/erase.c
--- ./mtd/fs/jffs2/erase.c	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/fs/jffs2/erase.c	2005-09-20 14:40:26.000000000 +0800
@@ -210,6 +210,10 @@ static void jffs2_erase_callback(struct 
 	} else {
 		jffs2_erase_succeeded(priv->c, priv->jeb);
 	}	
+
+	if (!priv->jeb->has_eraseblock_header) {
+		priv->jeb->has_eraseblock_header = 1;
+	}
 	kfree(instr);
 }
 #endif /* !__ECOS */
@@ -362,16 +366,14 @@ static void jffs2_mark_erased_block(stru
 	}
 
 	/* Write the erase complete marker */	
-	D1(printk(KERN_DEBUG "Writing erased marker to block at 0x%08x\n", jeb->offset));
+	D1(printk(KERN_DEBUG "Writing eraseblock header to block at 0x%08x\n", jeb->offset));
 	bad_offset = jeb->offset;
 
 	/* Cleanmarker in oob area or no cleanmarker at all ? */
-	if (jffs2_cleanmarker_oob(c) || c->cleanmarker_size == 0) {
+	if (jffs2_cleanmarker_oob(c)) {
 
-		if (jffs2_cleanmarker_oob(c)) {
-			if (jffs2_write_nand_cleanmarker(c, jeb))
-				goto filebad;
-		}
+		if (jffs2_write_nand_cleanmarker(c, jeb))
+			goto filebad;
 
 		jeb->first_node = jeb->last_node = NULL;
 		jeb->free_size = c->sector_size;
@@ -382,10 +384,14 @@ static void jffs2_mark_erased_block(stru
 	} else {
 
 		struct kvec vecs[1];
-		struct jffs2_unknown_node marker = {
+		struct jffs2_eraseblock_header marker = {
 			.magic =	cpu_to_je16(JFFS2_MAGIC_BITMASK),
-			.nodetype =	cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER),
-			.totlen =	cpu_to_je32(c->cleanmarker_size)
+			.nodetype =	cpu_to_je16(JFFS2_NODETYPE_ERASEBLOCK_HEADER),
+			.totlen =	cpu_to_je32(PAD(c->eraseblock_header_size)),
+			.fs_version =   cpu_to_je32(JFFS2_VERSION),
+			.erase_count =  cpu_to_je32(jeb->erase_count),
+			.dsize =        cpu_to_je16(0),
+			.data_crc =     cpu_to_je32(0)
 		};
 
 		marker_ref = jffs2_alloc_raw_node_ref();
@@ -395,6 +401,7 @@ static void jffs2_mark_erased_block(stru
 		}
 
 		marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4));
+		marker.node_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_eraseblock_header)-8));
 
 		vecs[0].iov_base = (unsigned char *) ▮
 		vecs[0].iov_len = sizeof(marker);
@@ -415,12 +422,12 @@ static void jffs2_mark_erased_block(stru
 		marker_ref->next_in_ino = NULL;
 		marker_ref->next_phys = NULL;
 		marker_ref->flash_offset = jeb->offset | REF_NORMAL;
-		marker_ref->__totlen = c->cleanmarker_size;
+		marker_ref->__totlen = PAD(c->eraseblock_header_size);
 			
 		jeb->first_node = jeb->last_node = marker_ref;
 			
-		jeb->free_size = c->sector_size - c->cleanmarker_size;
-		jeb->used_size = c->cleanmarker_size;
+		jeb->free_size = c->sector_size - PAD(c->eraseblock_header_size);
+		jeb->used_size = PAD(c->eraseblock_header_size);
 		jeb->dirty_size = 0;
 		jeb->wasted_size = 0;
 	}
diff -auNrp ./mtd/fs/jffs2/file.c ./mtd_eraseblock_header/fs/jffs2/file.c
--- ./mtd/fs/jffs2/file.c	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/fs/jffs2/file.c	2005-09-20 14:33:06.000000000 +0800
@@ -146,7 +146,7 @@ static int jffs2_prepare_write (struct f
 		memset(&ri, 0, sizeof(ri));
 
 		ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-		ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
+		ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE_EBH);
 		ri.totlen = cpu_to_je32(sizeof(ri));
 		ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4));
 
diff -auNrp ./mtd/fs/jffs2/fs.c ./mtd_eraseblock_header/fs/jffs2/fs.c
--- ./mtd/fs/jffs2/fs.c	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/fs/jffs2/fs.c	2005-09-20 14:33:06.000000000 +0800
@@ -86,7 +86,7 @@ static int jffs2_do_setattr (struct inod
 	ivalid = iattr->ia_valid;
 	
 	ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-	ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
+	ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE_EBH);
 	ri->totlen = cpu_to_je32(sizeof(*ri) + mdatalen);
 	ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
 
@@ -476,6 +476,7 @@ int jffs2_do_fill_super(struct super_blo
 	}
 
 	c->cleanmarker_size = sizeof(struct jffs2_unknown_node);
+	c->eraseblock_header_size = sizeof(struct jffs2_eraseblock_header);
 	/* Joern -- stick alignment for weird 8-byte-page flash here */
 
 	/* NAND (or other bizarre) flash... do setup accordingly */
diff -auNrp ./mtd/fs/jffs2/gc.c ./mtd_eraseblock_header/fs/jffs2/gc.c
--- ./mtd/fs/jffs2/gc.c	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/fs/jffs2/gc.c	2005-09-20 14:33:06.000000000 +0800
@@ -545,6 +545,7 @@ static int jffs2_garbage_collect_pristin
 
 	switch(je16_to_cpu(node->u.nodetype)) {
 	case JFFS2_NODETYPE_INODE:
+	case JFFS2_NODETYPE_INODE_EBH:
 		crc = crc32(0, node, sizeof(node->i)-8);
 		if (je32_to_cpu(node->i.node_crc) != crc) {
 			printk(KERN_WARNING "Node CRC failed on REF_PRISTINE data node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
@@ -563,6 +564,7 @@ static int jffs2_garbage_collect_pristin
 		break;
 
 	case JFFS2_NODETYPE_DIRENT:
+	case JFFS2_NODETYPE_DIRENT_EBH:
 		crc = crc32(0, node, sizeof(node->d)-8);
 		if (je32_to_cpu(node->d.node_crc) != crc) {
 			printk(KERN_WARNING "Node CRC failed on REF_PRISTINE dirent node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
@@ -724,7 +726,7 @@ static int jffs2_garbage_collect_metadat
 	
 	memset(&ri, 0, sizeof(ri));
 	ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-	ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
+	ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE_EBH);
 	ri.totlen = cpu_to_je32(sizeof(ri) + mdatalen);
 	ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4));
 
@@ -769,7 +771,7 @@ static int jffs2_garbage_collect_dirent(
 	int ret;
 
 	rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-	rd.nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
+	rd.nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT_EBH);
 	rd.nsize = strlen(fd->name);
 	rd.totlen = cpu_to_je32(sizeof(rd) + rd.nsize);
 	rd.hdr_crc = cpu_to_je32(crc32(0, &rd, sizeof(struct jffs2_unknown_node)-4));
@@ -864,7 +866,7 @@ static int jffs2_garbage_collect_deletio
 				continue;
 			}
 
-			if (je16_to_cpu(rd->nodetype) != JFFS2_NODETYPE_DIRENT)
+			if ((je16_to_cpu(rd->nodetype) != JFFS2_NODETYPE_DIRENT) && (je16_to_cpu(rd->nodetype) != JFFS2_NODETYPE_DIRENT_EBH))
 				continue;
 
 			/* If the name CRC doesn't match, skip */
@@ -940,7 +942,7 @@ static int jffs2_garbage_collect_hole(st
 			printk(KERN_WARNING "Node read failed in jffs2_garbage_collect_hole. Ret %d, retlen %zd. Data will be lost by writing new hole node\n", ret, readlen);
 			goto fill;
 		}
-		if (je16_to_cpu(ri.nodetype) != JFFS2_NODETYPE_INODE) {
+		if ((je16_to_cpu(ri.nodetype) != JFFS2_NODETYPE_INODE) && (je16_to_cpu(ri.nodetype) != JFFS2_NODETYPE_INODE_EBH)) {
 			printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had node type 0x%04x instead of JFFS2_NODETYPE_INODE(0x%04x)\n",
 			       ref_offset(fn->raw),
 			       je16_to_cpu(ri.nodetype), JFFS2_NODETYPE_INODE);
@@ -971,7 +973,7 @@ static int jffs2_garbage_collect_hole(st
 	} else {
 	fill:
 		ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-		ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
+		ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE_EBH);
 		ri.totlen = cpu_to_je32(sizeof(ri));
 		ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4));
 
@@ -1243,7 +1245,7 @@ static int jffs2_garbage_collect_dnode(s
 		comprtype = jffs2_compress(c, f, writebuf, &comprbuf, &datalen, &cdatalen);
 
 		ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-		ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
+		ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE_EBH);
 		ri.totlen = cpu_to_je32(sizeof(ri) + cdatalen);
 		ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4));
 
diff -auNrp ./mtd/fs/jffs2/nodelist.h ./mtd_eraseblock_header/fs/jffs2/nodelist.h
--- ./mtd/fs/jffs2/nodelist.h	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/fs/jffs2/nodelist.h	2005-09-20 15:07:29.000000000 +0800
@@ -196,6 +196,9 @@ struct jffs2_eraseblock
 	struct jffs2_raw_node_ref *last_node;
 
 	struct jffs2_raw_node_ref *gc_node;	/* Next node to be garbage collected */
+
+	uint8_t has_eraseblock_header;
+	uint32_t erase_count;
 };
 
 static inline int jffs2_blocks_use_vmalloc(struct jffs2_sb_info *c)
@@ -374,6 +377,8 @@ struct jffs2_node_frag *jffs2_alloc_node
 void jffs2_free_node_frag(struct jffs2_node_frag *);
 struct jffs2_inode_cache *jffs2_alloc_inode_cache(void);
 void jffs2_free_inode_cache(struct jffs2_inode_cache *);
+struct jffs2_eraseblock *jffs2_alloc_eraseblock(void);
+void jffs2_free_eraseblock(struct jffs2_eraseblock *);
 
 /* gc.c */
 int jffs2_garbage_collect_pass(struct jffs2_sb_info *c);
@@ -404,7 +409,7 @@ void jffs2_erase_pending_blocks(struct j
 /* wbuf.c */
 int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino);
 int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c);
-int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
+int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *data_len);
 int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
 #endif
 
diff -auNrp ./mtd/fs/jffs2/nodemgmt.c ./mtd_eraseblock_header/fs/jffs2/nodemgmt.c
--- ./mtd/fs/jffs2/nodemgmt.c	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/fs/jffs2/nodemgmt.c	2005-09-20 14:49:38.000000000 +0800
@@ -340,7 +340,10 @@ static int jffs2_do_reserve_space(struct
 
 		jeb = c->nextblock;
 
-		if (jeb->free_size != c->sector_size - c->cleanmarker_size) {
+		if ((!jeb->has_eraseblock_header && jeb->free_size != c->sector_size - c->cleanmarker_size) ||
+		    (jeb->has_eraseblock_header && c->eraseblock_header_size && jeb->free_size != c->sector_size - jeb->first_node->__totlen) ||
+		    (jeb->has_eraseblock_header && !c->eraseblock_header_size && jeb->free_size != c->sector_size))
+		{
 			printk(KERN_WARNING "Eep. Block 0x%08x taken from free_list had free_size of 0x%08x!!\n", jeb->offset, jeb->free_size);
 			goto restart;
 		}
@@ -350,8 +353,8 @@ static int jffs2_do_reserve_space(struct
 	*ofs = jeb->offset + (c->sector_size - jeb->free_size);
 	*len = jeb->free_size - reserved_size;
 
-	if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size &&
-	    !jeb->first_node->next_in_ino) {
+	if ((!jeb->has_eraseblock_header && c->cleanmarker_size && jeb->used_size == c->cleanmarker_size && !jeb->first_node->next_in_ino)
+	     || (jeb->has_eraseblock_header && c->eraseblock_header_size && jeb->used_size == jeb->first_node->__totlen && !jeb->first_node->next_in_ino)) {
 		/* Only node in it beforehand was a CLEANMARKER node (we think). 
 		   So mark it obsolete now that there's going to be another node
 		   in the block. This will reduce used_size to zero but We've 
diff -auNrp ./mtd/fs/jffs2/os-linux.h ./mtd_eraseblock_header/fs/jffs2/os-linux.h
--- ./mtd/fs/jffs2/os-linux.h	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/fs/jffs2/os-linux.h	2005-09-20 15:04:29.000000000 +0800
@@ -122,8 +122,8 @@ static inline void jffs2_init_inode_info
 int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino);
 int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf);
 int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, u_char *buf);
-int jffs2_check_oob_empty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,int mode);
-int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
+int jffs2_check_oob_empty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,uint32_t data_len);
+int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *data_len);
 int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
 int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset);
 void jffs2_wbuf_timeout(unsigned long data);
diff -auNrp ./mtd/fs/jffs2/readinode.c ./mtd_eraseblock_header/fs/jffs2/readinode.c
--- ./mtd/fs/jffs2/readinode.c	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/fs/jffs2/readinode.c	2005-09-20 14:33:08.000000000 +0800
@@ -552,6 +552,7 @@ static int jffs2_get_inode_nodes(struct 
 		switch (je16_to_cpu(node->u.nodetype)) {
 			
 		case JFFS2_NODETYPE_DIRENT:
+		case JFFS2_NODETYPE_DIRENT_EBH:
 
 			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) {
 				err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf, bufstart);
@@ -572,6 +573,7 @@ static int jffs2_get_inode_nodes(struct 
 			break;
 
 		case JFFS2_NODETYPE_INODE:
+		case JFFS2_NODETYPE_INODE_EBH:
 			
 			if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) {
 				err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf, bufstart);
diff -auNrp ./mtd/fs/jffs2/scan.c ./mtd_eraseblock_header/fs/jffs2/scan.c
--- ./mtd/fs/jffs2/scan.c	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/fs/jffs2/scan.c	2005-09-20 14:54:43.000000000 +0800
@@ -46,6 +46,8 @@ static int jffs2_scan_inode_node(struct 
 				 struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s);
 static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
 				 struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s);
+static int jffs2_scan_eraseblock_header(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
+				 struct jffs2_eraseblock_header *eh, uint32_t ofs);
 
 static inline int min_free(struct jffs2_sb_info *c)
 {
@@ -292,6 +294,11 @@ int jffs2_fill_scan_buf (struct jffs2_sb
 
 int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
 {
+	if (jeb->has_eraseblock_header && c->eraseblock_header_size) {
+		if (!jeb->first_node->next_phys && !jeb->dirty_size)
+			return BLK_STATE_CLEANMARKER;
+	}
+
 	if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size
 		&& (!jeb->first_node || !jeb->first_node->next_phys) )
 		return BLK_STATE_CLEANMARKER;
@@ -321,7 +328,7 @@ static int jffs2_scan_eraseblock (struct
 
 
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
-	int cleanmarkerfound = 0;
+	uint32_t data_len = 0;
 #endif
 
 	ofs = jeb->offset;
@@ -331,13 +338,13 @@ static int jffs2_scan_eraseblock (struct
 
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
 	if (jffs2_cleanmarker_oob(c)) {
-		int ret = jffs2_check_nand_cleanmarker(c, jeb);
+		int ret = jffs2_check_nand_cleanmarker(c, jeb, &data_len);
 		D2(printk(KERN_NOTICE "jffs_check_nand_cleanmarker returned %d\n",ret));
 		/* Even if it's not found, we still scan to see
 		   if the block is empty. We use this information
 		   to decide whether to erase it or not. */
 		switch (ret) {
-		case 0:		cleanmarkerfound = 1; break;
+		case 0:		break;
 		case 1: 	break;
 		case 2: 	return BLK_STATE_BADBLOCK;
 		case 3:		return BLK_STATE_ALLDIRTY; /* Block has failed to erase min. once */
@@ -403,10 +410,10 @@ static int jffs2_scan_eraseblock (struct
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
 		if (jffs2_cleanmarker_oob(c)) {
 			/* scan oob, take care of cleanmarker */
-			int ret = jffs2_check_oob_empty(c, jeb, cleanmarkerfound);
+			int ret = jffs2_check_oob_empty(c, jeb, data_len);
 			D2(printk(KERN_NOTICE "jffs2_check_oob_empty returned %d\n",ret));
 			switch (ret) {
-			case 0:		return cleanmarkerfound ? BLK_STATE_CLEANMARKER : BLK_STATE_ALLFF;
+			case 0:		return data_len ? BLK_STATE_CLEANMARKER : BLK_STATE_ALLFF;
 			case 1: 	return BLK_STATE_ALLDIRTY;
 			default: 	return ret;
 			}
@@ -502,6 +509,13 @@ scan_more:	
 				return BLK_STATE_CLEANMARKER;
 			}
 
+			if (jeb->has_eraseblock_header && c->eraseblock_header_size) {
+				if (!jeb->first_node->next_phys && !jeb->dirty_size) {
+					D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size)));
+					return BLK_STATE_CLEANMARKER;
+				}
+			}
+
 			/* See how much more there is to read in this eraseblock... */
 			buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
 			if (!buf_len) {
@@ -570,10 +584,8 @@ scan_more:	
 			/* Eep. Node goes over the end of the erase block. */
 			printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n",
 			       ofs, je32_to_cpu(node->totlen));
-			printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n");
-			DIRTY_SPACE(4);
-			ofs += 4;
-			continue;
+			printk(KERN_NOTICE "Perhaps the file system was created with the wrong erase size? Reject to mount.\n");
+			return -EINVAL;
 		}
 
 		if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) {
@@ -586,6 +598,7 @@ scan_more:	
 
 		switch(je16_to_cpu(node->nodetype)) {
 		case JFFS2_NODETYPE_INODE:
+		case JFFS2_NODETYPE_INODE_EBH:
 			if (buf_ofs + buf_len < ofs + sizeof(struct jffs2_raw_inode)) {
 				buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
 				D1(printk(KERN_DEBUG "Fewer than %zd bytes (inode node) left to end of buf. Reading 0x%x at 0x%08x\n",
@@ -602,6 +615,7 @@ scan_more:	
 			break;
 			
 		case JFFS2_NODETYPE_DIRENT:
+		case JFFS2_NODETYPE_DIRENT_EBH:
 			if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
 				buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
 				D1(printk(KERN_DEBUG "Fewer than %d bytes (dirent node) left to end of buf. Reading 0x%x at 0x%08x\n",
@@ -645,6 +659,26 @@ scan_more:	
 			}
 			break;
 
+		case JFFS2_NODETYPE_ERASEBLOCK_HEADER:
+			if (ofs != jeb->offset) {
+				printk(KERN_NOTICE "Eraseblock header found at 0x%08x is not at the beginning of block (0x%08x)\n", ofs, jeb->offset);
+				DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
+				ofs += PAD(je32_to_cpu(node->totlen));
+			} else {
+				if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
+					buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
+					err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
+					if (err)
+						return err;
+					buf_ofs = ofs;
+					node = (void *)buf;
+				}
+				err = jffs2_scan_eraseblock_header(c, jeb, (void *)node, ofs);
+				if (err) return err;
+				ofs += PAD(je32_to_cpu(node->totlen));
+			}
+			break;
+
 		case JFFS2_NODETYPE_PADDING:
 			if (jffs2_sum_active())
 				jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen));
@@ -888,6 +922,48 @@ static int jffs2_scan_dirent_node(struct
 	return 0;
 }
 
+static int jffs2_scan_eraseblock_header(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
+                                 struct jffs2_eraseblock_header *eh, uint32_t ofs)
+{
+	uint32_t crc, node_crc;
+	struct jffs2_raw_node_ref *raw;
+
+	D1(printk(KERN_DEBUG "jffs2_scan_eraseblock_header(): Node at 0x%08x\n", ofs));
+	crc = crc32(0, eh, sizeof(struct jffs2_eraseblock_header) - 8);
+	node_crc = je32_to_cpu(eh->node_crc);
+
+	if (crc != node_crc) {
+		printk(KERN_NOTICE "jffs2_scan_eraseblock_header(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
+			ofs, node_crc, crc);
+		DIRTY_SPACE(PAD(je32_to_cpu(eh->totlen)));
+		return 0;
+	}
+
+	if (JFFS2_VERSION < je32_to_cpu(eh->fs_version)) {
+		printk(KERN_NOTICE "The version of fs image %d > the version of JFFS2 module %d. Reject to mount.\n",
+			 je32_to_cpu(eh->fs_version), JFFS2_VERSION);
+		return -EINVAL;
+	}
+
+	raw = jffs2_alloc_raw_node_ref();
+	if (!raw) {
+		printk(KERN_NOTICE "jffs2_scan_eraseblock_header(): allocation of node reference failed.\n");
+		return -ENOMEM;
+	}
+
+	jeb->has_eraseblock_header = 1;
+	jeb->erase_count = je32_to_cpu(eh->erase_count);
+
+	raw->next_in_ino = NULL;
+	raw->next_phys = NULL;
+	raw->flash_offset = ofs | REF_NORMAL;
+	raw->__totlen = PAD(je32_to_cpu(eh->totlen));
+	jeb->first_node = jeb->last_node = raw;
+
+	USED_SPACE(PAD(je32_to_cpu(eh->totlen)));
+	return 0;
+}
+
 static int count_list(struct list_head *l)
 {
 	uint32_t count = 0;
diff -auNrp ./mtd/fs/jffs2/wbuf.c ./mtd_eraseblock_header/fs/jffs2/wbuf.c
--- ./mtd/fs/jffs2/wbuf.c	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/fs/jffs2/wbuf.c	2005-09-20 15:11:55.000000000 +0800
@@ -934,66 +934,36 @@ exit:
 /*
  *	Check, if the out of band area is empty
  */
-int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, int mode)
+
+int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t data_len)
 {
+	size_t offset, retlen;
+	uint32_t i = 0, j, oob_nr;
 	unsigned char *buf;
-	int 	ret = 0;
-	int	i,len,page;
-	size_t  retlen;
-	int	oob_size;
+	int oob_size, ret;
 
-	/* allocate a buffer for all oob data in this sector */
+	offset = jeb->offset;
 	oob_size = c->mtd->oobsize;
-	len = 4 * oob_size;
-	buf = kmalloc(len, GFP_KERNEL);
-	if (!buf) {
-		printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n");
-		return -ENOMEM;
-	}
-	/* 
-	 * if mode = 0, we scan for a total empty oob area, else we have
-	 * to take care of the cleanmarker in the first page of the block
-	*/
-	ret = jffs2_flash_read_oob(c, jeb->offset, len , &retlen, buf);
-	if (ret) {
-		D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB failed %d for block at %08x\n", ret, jeb->offset));
-		goto out;
-	}
-	
-	if (retlen < len) {
-		D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB return short read "
-			  "(%zd bytes not %d) for block at %08x\n", retlen, len, jeb->offset));
-		ret = -EIO;
-		goto out;
-	}
-	
-	/* Special check for first page */
-	for(i = 0; i < oob_size ; i++) {
-		/* Yeah, we know about the cleanmarker. */
-		if (mode && i >= c->fsdata_pos && 
-		    i < c->fsdata_pos + c->fsdata_len)
-			continue;
-
-		if (buf[i] != 0xFF) {
-			D2(printk(KERN_DEBUG "Found %02x at %x in OOB for %08x\n",
-				  buf[i], i, jeb->offset));
-			ret = 1; 
-			goto out;
-		}
-	}
-
-	/* we know, we are aligned :) */	
-	for (page = oob_size; page < len; page += sizeof(long)) {
-		unsigned long dat = *(unsigned long *)(&buf[page]);
-		if(dat != -1) {
-			ret = 1; 
-			goto out;
+	oob_nr = (data_len+c->fsdata_len-1)/c->fsdata_len;
+	if (oob_nr < 4) oob_nr = 4;
+	buf = kmalloc(oob_size * oob_nr, GFP_KERNEL);
+	ret = c->mtd->read_oob(c->mtd, offset, oob_size * oob_nr, &retlen, buf);
+
+	for (i=0; i<oob_nr; i++) {
+		for (j=0; j<oob_size; j++) {
+			if (data_len && j>=c->fsdata_pos && j<c->fsdata_pos + c->fsdata_len) {
+				data_len--;
+				continue;
+			}
+			if (buf[i*oob_size+j] != 0xFF) {
+				ret = 1;
+				goto out;
+			}
 		}
 	}
 
 out:
-	kfree(buf);	
-	
+	kfree(buf);
 	return ret;
 }
 
@@ -1003,86 +973,120 @@ out:
 *	only in the first page of the first physical block, but scan for bad blocks in all
 *	physical blocks
 */
-int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
+int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *data_len)
 {
-	struct jffs2_unknown_node n;
-	unsigned char buf[2 * NAND_MAX_OOBSIZE];
-	unsigned char *p;
-	int ret, i, cnt, retval = 0;
-	size_t retlen, offset;
+	size_t offset, retlen;
 	int oob_size;
+	uint32_t oob_nr, total_len;
+	unsigned char *buf;
+	int ret;
+	struct jffs2_unknown_node *n;
+	struct jffs2_eraseblock_header eh;
+	uint32_t read_in = 0, i = 0, copy_len, node_crc;
 
 	offset = jeb->offset;
+	*data_len = 0;
+
+	if (c->mtd->block_isbad (c->mtd, offset)) {
+		D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Bad block at %08x\n", jeb->offset));
+		return 2;
+	}
+
 	oob_size = c->mtd->oobsize;
+	oob_nr = (sizeof(struct jffs2_eraseblock_header)+c->fsdata_len-1)/c->fsdata_len;
+	total_len = oob_size * oob_nr;
 
-	/* Loop through the physical blocks */
-	for (cnt = 0; cnt < (c->sector_size / c->mtd->erasesize); cnt++) {
-		/* Check first if the block is bad. */
-		if (c->mtd->block_isbad (c->mtd, offset)) {
-			D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Bad block at %08x\n", jeb->offset));
-			return 2;
-		}
-		/*
-		   *    We read oob data from page 0 and 1 of the block.
-		   *    page 0 contains cleanmarker and badblock info
-		   *    page 1 contains failure count of this block
-		 */
-		ret = c->mtd->read_oob (c->mtd, offset, oob_size << 1, &retlen, buf);
+	buf = kmalloc(total_len, GFP_KERNEL);
+	if (!buf) {
+		return -ENOMEM;
+	}
+	ret = c->mtd->read_oob(c->mtd, offset, total_len, &retlen, buf);
+	if (ret) {
+		D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB failed %d for block at %08x\n", ret, jeb->offset));
+		goto out;
+	}
+	if (retlen < total_len) {
+		 D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB return short read (%zd bytes not %d) for block at %08x\n", retlen, total_len, jeb->offset));
+		ret = -EIO;
+		goto out;
+	}
 
-		if (ret) {
-			D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB failed %d for block at %08x\n", ret, jeb->offset));
-			return ret;
+	n = (struct jffs2_unknown_node *) &buf[c->fsdata_pos];
+	if (je16_to_cpu(n->magic) != JFFS2_MAGIC_BITMASK) {
+		D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): Cleanmarker node not detected in block at %08x\n", jeb->offset));
+		ret = 1;
+		goto out;
+	}
+
+	if (je16_to_cpu(n->nodetype) == JFFS2_NODETYPE_CLEANMARKER) {
+		if (je32_to_cpu(n->totlen) == 8) {
+			*data_len = 8;
+			ret = 0;
+		} else {
+			ret = 1;
 		}
-		if (retlen < (oob_size << 1)) {
-			D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB return short read (%zd bytes not %d) for block at %08x\n", retlen, oob_size << 1, jeb->offset));
-			return -EIO;
+		goto out;
+	}else if (je16_to_cpu(n->nodetype) == JFFS2_NODETYPE_ERASEBLOCK_HEADER) {
+		/* Read the scattered data(in buf[]) into struct jffs2_eraseblock_header */
+		while (read_in < sizeof(struct jffs2_eraseblock_header)) {
+			copy_len = min_t(uint32_t, c->fsdata_len, sizeof(struct jffs2_eraseblock_header) - read_in);
+			memcpy((unsigned char *)&eh + read_in, &buf[oob_size*i + c->fsdata_pos], copy_len);
+			read_in += copy_len;
+			i++;
 		}
 
-		/* Check cleanmarker only on the first physical block */
-		if (!cnt) {
-			n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
-			n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
-			n.totlen = cpu_to_je32 (8);
-			p = (unsigned char *) &n;
-
-			for (i = 0; i < c->fsdata_len; i++) {
-				if (buf[c->fsdata_pos + i] != p[i]) {
-					retval = 1;
-				}
-			}
-			D1(if (retval == 1) {
-				printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): Cleanmarker node not detected in block at %08x\n", jeb->offset);
-				printk(KERN_WARNING "OOB at %08x was ", offset);
-				for (i=0; i < oob_size; i++) {
-					printk("%02x ", buf[i]);
-				}
-				printk("\n");
-			})
+		node_crc = crc32(0, &eh, sizeof(struct jffs2_eraseblock_header)-8);
+		if (node_crc != je32_to_cpu(eh.node_crc)) {
+			ret = 1;
+			goto out;
 		}
-		offset += c->mtd->erasesize;
+
+		if (JFFS2_VERSION < je32_to_cpu(eh.fs_version)) {
+			printk(KERN_NOTICE "The version of fs image %d > the version of JFFS2 module %d. Reject to mount.\n",
+				je32_to_cpu(eh.fs_version), JFFS2_VERSION);
+			ret = -EINVAL;
+			goto out;
+		}
+
+		jeb->has_eraseblock_header = 1;
+		jeb->erase_count = je32_to_cpu(eh.erase_count);
+		*data_len = je32_to_cpu(eh.totlen);
+		ret = 0;
+	}else {
+		ret = 1;
 	}
-	return retval;
+out:
+	kfree(buf);
+	return ret;
 }
 
 int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
 {
-	struct 	jffs2_unknown_node n;
-	int 	ret;
-	size_t 	retlen;
-
-	n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-	n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
-	n.totlen = cpu_to_je32(8);
+	struct jffs2_eraseblock_header eh;
+	uint32_t i = 0, written = 0, write_len = 0;
+	int ret;
+	size_t  retlen;
 
-	ret = jffs2_flash_write_oob(c, jeb->offset + c->fsdata_pos, c->fsdata_len, &retlen, (unsigned char *)&n);
-	
-	if (ret) {
-		D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret));
-		return ret;
-	}
-	if (retlen != c->fsdata_len) {
-		D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Short write for block at %08x: %zd not %d\n", jeb->offset, retlen, c->fsdata_len));
-		return ret;
+	eh.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+	eh.nodetype = cpu_to_je16(JFFS2_NODETYPE_ERASEBLOCK_HEADER);
+	eh.fs_version = cpu_to_je32(JFFS2_VERSION);
+	eh.erase_count = cpu_to_je32(jeb->erase_count);
+	eh.dsize = cpu_to_je16(0);
+	eh.data_crc = cpu_to_je32(0);
+	eh.totlen = cpu_to_je32(sizeof(struct jffs2_eraseblock_header));
+
+	eh.hdr_crc = cpu_to_je32(crc32(0, &eh, sizeof(struct jffs2_unknown_node)-4));
+	eh.node_crc = cpu_to_je32(crc32(0, &eh, sizeof(struct jffs2_eraseblock_header)-8));
+
+	while (written < sizeof(struct jffs2_eraseblock_header)) {
+		write_len = min_t(uint32_t, c->fsdata_len, sizeof(struct jffs2_eraseblock_header) - written);
+		ret = jffs2_flash_write_oob(c, jeb->offset + c->mtd->oobblock*i + c->fsdata_pos, write_len,  &retlen, (unsigned char *)&eh + written);
+		if (ret || retlen != write_len) {
+			D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret));
+			return ret;
+		}
+		written += write_len;
+		i++;
 	}
 	return 0;
 }
@@ -1135,6 +1139,7 @@ static int jffs2_nand_set_oobinfo(struct
 	
 	/* Cleanmarker is out-of-band, so inline size zero */
 	c->cleanmarker_size = 0;
+	c->eraseblock_header_size = 0;
 
 	/* Should we use autoplacement ? */
 	if (oinfo && oinfo->useecc == MTD_NANDECC_AUTOPLACE) {
@@ -1146,8 +1151,6 @@ static int jffs2_nand_set_oobinfo(struct
 		}
 		c->fsdata_pos = oinfo->oobfree[0][0];
 		c->fsdata_len = oinfo->oobfree[0][1];
-		if (c->fsdata_len > 8)
-			c->fsdata_len = 8;
 	} else {
 		/* This is just a legacy fallback and should go away soon */
 		switch(c->mtd->ecctype) {
@@ -1167,6 +1170,21 @@ static int jffs2_nand_set_oobinfo(struct
 	return 0;
 }
 
+/* To check if the OOB area has enough space for eraseblock header */
+static int jffs2_nand_check_oobspace_for_ebh(struct jffs2_sb_info *c)
+{
+	uint32_t pages_per_eraseblock, available_oob_space;
+
+	pages_per_eraseblock = c->sector_size/c->mtd->oobblock;
+	available_oob_space = c->fsdata_len * pages_per_eraseblock;
+	if (available_oob_space < sizeof(struct jffs2_eraseblock_header)) {
+		printk(KERN_NOTICE "The OOB area(%d) is not big enough to hold eraseblock_header(%d), reject to mount.\n",
+			 available_oob_space, sizeof(struct jffs2_eraseblock_header));
+		return -EINVAL;
+	}
+	return 0;
+}
+
 int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
 {
 	int res;
@@ -1181,6 +1199,11 @@ int jffs2_nand_flash_setup(struct jffs2_
 		return -ENOMEM;
 
 	res = jffs2_nand_set_oobinfo(c);
+	if (res) {
+		return res;
+	}
+
+	res = jffs2_nand_check_oobspace_for_ebh(c);
 
 #ifdef BREAKME
 	if (!brokenbuf)
@@ -1223,6 +1246,7 @@ void jffs2_dataflash_cleanup(struct jffs
 int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) {
 	/* Cleanmarker is actually larger on the flashes */
 	c->cleanmarker_size = 16;
+	c->eraseblock_header_size = 40;
 
 	/* Initialize write buffer */
 	init_rwsem(&c->wbuf_sem);
@@ -1243,6 +1267,7 @@ void jffs2_nor_ecc_flash_cleanup(struct 
 int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) {
 	/* Cleanmarker currently occupies a whole programming region */
 	c->cleanmarker_size = MTD_PROGREGION_SIZE(c->mtd);
+	c->eraseblock_header_size = MTD_PROGREGION_SIZE(c->mtd);
 
 	/* Initialize write buffer */
 	init_rwsem(&c->wbuf_sem);
diff -auNrp ./mtd/fs/jffs2/write.c ./mtd_eraseblock_header/fs/jffs2/write.c
--- ./mtd/fs/jffs2/write.c	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/fs/jffs2/write.c	2005-09-20 14:33:10.000000000 +0800
@@ -43,7 +43,7 @@ int jffs2_do_new_inode(struct jffs2_sb_i
 	ri->ino = cpu_to_je32(f->inocache->ino);
 
 	ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-	ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
+	ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE_EBH);
 	ri->totlen = cpu_to_je32(PAD(sizeof(*ri)));
 	ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
 	ri->mode = cpu_to_jemode(mode);
@@ -379,7 +379,7 @@ int jffs2_write_inode_range(struct jffs2
 		comprtype = jffs2_compress(c, f, buf, &comprbuf, &datalen, &cdatalen);
 
 		ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-		ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
+		ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE_EBH);
 		ri->totlen = cpu_to_je32(sizeof(*ri) + cdatalen);
 		ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
 
@@ -503,7 +503,7 @@ int jffs2_do_create(struct jffs2_sb_info
 	down(&dir_f->sem);
 
 	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
+	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT_EBH);
 	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
 	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
 
@@ -567,7 +567,7 @@ int jffs2_do_unlink(struct jffs2_sb_info
 
 		/* Build a deletion node */
 		rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-		rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
+		rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT_EBH);
 		rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
 		rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
 		
@@ -677,7 +677,7 @@ int jffs2_do_link (struct jffs2_sb_info 
 
 	/* Build a deletion node */
 	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
+	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT_EBH);
 	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
 	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
 
diff -auNrp ./mtd/include/linux/jffs2_fs_sb.h ./mtd_eraseblock_header/include/linux/jffs2_fs_sb.h
--- ./mtd/include/linux/jffs2_fs_sb.h	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/include/linux/jffs2_fs_sb.h	2005-09-20 14:31:38.000000000 +0800
@@ -114,6 +114,8 @@ struct jffs2_sb_info {
 
 	struct jffs2_summary *summary;		/* Summary information */
 
+	uint32_t eraseblock_header_size;
+
 	/* OS-private pointer for getting back to master superblock info */
 	void *os_priv;
 };
diff -auNrp ./mtd/include/linux/jffs2.h ./mtd_eraseblock_header/include/linux/jffs2.h
--- ./mtd/include/linux/jffs2.h	2005-09-12 11:16:32.000000000 +0800
+++ ./mtd_eraseblock_header/include/linux/jffs2.h	2005-09-20 14:31:39.000000000 +0800
@@ -28,6 +28,9 @@
 #define JFFS2_EMPTY_BITMASK 0xffff
 #define JFFS2_DIRTY_BITMASK 0x0000
 
+/* JFFS2 version number */
+#define JFFS2_VERSION 0x01
+
 /* Summary node MAGIC marker */
 #define JFFS2_SUM_MAGIC	0x02851885
 
@@ -62,8 +65,13 @@
 #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_ERASEBLOCK_HEADER (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 5)
 #define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6)
+/* The 3 types are defined in order to let old JFFS2 code reject to mount new JFFS2 fs image for NAND flash, 
+  these 3 types are introduce together with eraseblock header and 1:1 mapping*/
+#define JFFS2_NODETYPE_DIRENT_EBH (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 7)
+#define JFFS2_NODETYPE_INODE_EBH (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 8)
+#define JFFS2_NODETYPE_SUMMARY_EBH (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 9)
 
 // Maybe later...
 //#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
@@ -101,6 +109,20 @@ struct jffs2_unknown_node
 	jint32_t hdr_crc;
 } __attribute__((packed));
 
+struct jffs2_eraseblock_header
+{
+	jint16_t magic;
+	jint16_t nodetype; /* == JFFS2_NODETYPE_ERASEBLOCK_HEADER */
+	jint32_t totlen;
+	jint32_t hdr_crc;
+	jint32_t fs_version; /* the version of this JFFS2 fs image */
+	jint32_t erase_count; /* the erase count of this erase block */
+	jint16_t dsize; /* the size of additional data behind node_crc */
+	jint32_t node_crc;
+	jint32_t data_crc;
+	jint32_t data[0];
+} __attribute__((packed));
+
 struct jffs2_raw_dirent
 {
 	jint16_t magic;
@@ -168,6 +190,7 @@ union jffs2_node_union {
 	struct jffs2_raw_inode i;
 	struct jffs2_raw_dirent d;
 	struct jffs2_unknown_node u;
+	struct jffs2_eraseblock_header eh;
 	struct jffs2_summary_node s;
 };
 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH]Add JFFS2 eraseblock header support
  2005-09-20  7:45 [PATCH]Add JFFS2 eraseblock header support zhao forrest
@ 2005-09-20 10:24 ` Jörn Engel
  2005-09-20 10:59   ` Artem B. Bityutskiy
  2005-09-20 11:29 ` Artem B. Bityutskiy
  1 sibling, 1 reply; 13+ messages in thread
From: Jörn Engel @ 2005-09-20 10:24 UTC (permalink / raw)
  To: zhao forrest; +Cc: linux-mtd

On Tue, 20 September 2005 15:45:37 +0800, zhao forrest wrote:
> 
> This is the patch for eraseblock header, the high-level design
> can be found at http://lists.infradead.org/pipermail/linux-mtd/
> 2005-August/013374.html.
> 
> This patch closely follows the high-level design. Here I list
> some main implementation points:
> 1 eraseblock_header replaces clean marker, clean marker no
> longer exists.
> 2 now eraseblock header carrys version and erase count, but the
> length of eraseblock header is not constant and it allows further
> extention.
> 3 for NAND flash, the eraseblock header is stored in OOB and it
> may span several OOBs
> 4 old JFFS2 binaries reject mounting new JFFS2 images

Why this?

> 5 change the type of dirent/inode nodes and adding INCOMPAT flag
> there in order to make old JFFS2 binaries reject mounting new
> JFFS2 images for NAND flash

Why?

> 6 new JFFS2 binary, when mounting an old JFFS2 image, will reject
> mounting unless the old JFFS2 image doesn't use 1:N(N>1)mapping.

I wouldn't waste code on this.

> 7 If JFFS2 finds that the version of the image is larger, it will
> reject mounting the image

Really bad idea.  Incompatible changes won't make users rejoice.  Have
a look at ext2:
	__le32	s_feature_compat; 	/* compatible feature set */
	__le32	s_feature_incompat; 	/* incompatible feature set */
	__le32	s_feature_ro_compat; 	/* readonly-compatible feature set */

The destinction between compatible, incompatible and ro-compatible
features is done for a reason.  If a new feature is harmless to
ignore, like EXT2_FEATURE_COMPAT_DIR_PREALLOC, there is no reason not
to mount the filesystem.  New feature is just a performance thing,
nothing more.

JFFS2 has the same for node types, you should know that.  Rationale is
the same.

So if we need a version (which I was always against, as you may
remember), we should at least express it as three sets of features.

> 8 currently this patch doesn't take the "eraseblock summary" patch
> into account. It's greatly appreciated if Ferenc can help to add
> the missing part :)

He can't.  It's against the rules of physics.

Jörn

-- 
People will accept your ideas much more readily if you tell them
that Benjamin Franklin said it first.
-- unknown

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH]Add JFFS2 eraseblock header support
  2005-09-20 10:24 ` Jörn Engel
@ 2005-09-20 10:59   ` Artem B. Bityutskiy
  2005-09-20 11:36     ` Jörn Engel
  2005-09-21  2:16     ` zhao forrest
  0 siblings, 2 replies; 13+ messages in thread
From: Artem B. Bityutskiy @ 2005-09-20 10:59 UTC (permalink / raw)
  To: Jörn Engel; +Cc: zhao forrest, linux-mtd

On Tue, 2005-09-20 at 12:24 +0200, Jörn Engel wrote:
> > 4 old JFFS2 binaries reject mounting new JFFS2 images
> 
> Why this?

Because he changed cleanmarker to the EB header (eraseblock header). Old
binaries got confused by this since there are working no compatibility
flags in cleanmarkers. 

Moreover, we are going to implement the 1:1 mapping at the same time.

If old binary mounts new image, it starts writing its cleanmarkers, use
1:N mapping etc. A "mixed" image appears. Afterwords, if this mixed
image is being mounted on new JFFS2 binary, what poor Zhao is supposed
to do? There will be too much ugliness in the code to handle that.

> > 5 change the type of dirent/inode nodes and adding INCOMPAT flag
> > there in order to make old JFFS2 binaries reject mounting new
> > JFFS2 images for NAND flash
> Why?
This is just a hacky ugly way to implement 4. In future, we will use the
version field in the EB header, or what you have offered below.

> 
> > 6 new JFFS2 binary, when mounting an old JFFS2 image, will reject
> > mounting unless the old JFFS2 image doesn't use 1:N(N>1)mapping.
> 
> I wouldn't waste code on this.
I would just reject mounting old images as well.

> > 7 If JFFS2 finds that the version of the image is larger, it will
> > reject mounting the image
> 
> Really bad idea.  Incompatible changes won't make users rejoice.  Have
> a look at ext2:
> 	__le32	s_feature_compat; 	/* compatible feature set */
> 	__le32	s_feature_incompat; 	/* incompatible feature set */
> 	__le32	s_feature_ro_compat; 	/* readonly-compatible feature set */
> 
> The destinction between compatible, incompatible and ro-compatible
> features is done for a reason.  If a new feature is harmless to
> ignore, like EXT2_FEATURE_COMPAT_DIR_PREALLOC, there is no reason not
> to mount the filesystem.  New feature is just a performance thing,
> nothing more.
> 
> JFFS2 has the same for node types, you should know that.  Rationale is
> the same.
> 
> So if we need a version (which I was always against, as you may
> remember), we should at least express it as three sets of features.
> 
Well, nice.

You may use the 1st 4 bytes for this 1 for version, 3 for
incompat/compat/RO-compat triplet.

Joern, why didn't you offer this earlier :-) ?

-- 
Best Regards,
Artem B. Bityuckiy,
St.-Petersburg, Russia.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH]Add JFFS2 eraseblock header support
  2005-09-20  7:45 [PATCH]Add JFFS2 eraseblock header support zhao forrest
  2005-09-20 10:24 ` Jörn Engel
@ 2005-09-20 11:29 ` Artem B. Bityutskiy
  2005-09-21  2:22   ` zhao forrest
  1 sibling, 1 reply; 13+ messages in thread
From: Artem B. Bityutskiy @ 2005-09-20 11:29 UTC (permalink / raw)
  To: zhao forrest; +Cc: linux-mtd

hmm,

zhao forrest wrote:
> Your comments are welcome.

+struct jffs2_eraseblock_header
+{
+       jint16_t magic;
+       jint16_t nodetype; /* == JFFS2_NODETYPE_ERASEBLOCK_HEADER */
+       jint32_t totlen;
+       jint32_t hdr_crc;
+       jint32_t fs_version; /* the version of this JFFS2 fs image */
Well, I assume we may have 3 fields here:
u8 version;
u8 compat_fset;
u8 incompat_fset;
u8 rocompat_fset;

+       jint32_t erase_count; /* the erase count of this erase block */
4 bytes enough?

+       jint16_t dsize; /* the size of additional data behind node_crc */
What for?

+       jint32_t node_crc;
+       jint32_t data_crc;
+       jint32_t data[0];
+} __attribute__((packed));
+


-- 
Best Regards,
Artem B. Bityuckiy,
St.-Petersburg, Russia.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH]Add JFFS2 eraseblock header support
  2005-09-20 10:59   ` Artem B. Bityutskiy
@ 2005-09-20 11:36     ` Jörn Engel
  2005-09-20 11:56       ` Artem B. Bityutskiy
  2005-09-21  2:57       ` zhao forrest
  2005-09-21  2:16     ` zhao forrest
  1 sibling, 2 replies; 13+ messages in thread
From: Jörn Engel @ 2005-09-20 11:36 UTC (permalink / raw)
  To: Artem B. Bityutskiy; +Cc: zhao forrest, linux-mtd

On Tue, 20 September 2005 14:59:43 +0400, Artem B. Bityutskiy wrote:
> On Tue, 2005-09-20 at 12:24 +0200, Jörn Engel wrote:
> > > 4 old JFFS2 binaries reject mounting new JFFS2 images
> > 
> > Why this?
> 
> Because he changed cleanmarker to the EB header (eraseblock header). Old
> binaries got confused by this since there are working no compatibility
> flags in cleanmarkers. 

WTF?  Old code can simply delete the EB.  You lost all the goodies
from EB, sure, but they are only optimization.  So who cares?

> Moreover, we are going to implement the 1:1 mapping at the same time.
> 
> If old binary mounts new image, it starts writing its cleanmarkers, use
> 1:N mapping etc. A "mixed" image appears. Afterwords, if this mixed
> image is being mounted on new JFFS2 binary, what poor Zhao is supposed
> to do? There will be too much ugliness in the code to handle that.

Please don't mix those two problems.  1:1 mapping has been dealt with.
If you don't like how it has been dealt with, complain in the context
of 1:1 mapping.

Jörn

-- 
When in doubt, use brute force.
-- Ken Thompson

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH]Add JFFS2 eraseblock header support
  2005-09-20 11:36     ` Jörn Engel
@ 2005-09-20 11:56       ` Artem B. Bityutskiy
  2005-09-20 12:27         ` Jörn Engel
  2005-09-21  2:57       ` zhao forrest
  1 sibling, 1 reply; 13+ messages in thread
From: Artem B. Bityutskiy @ 2005-09-20 11:56 UTC (permalink / raw)
  To: Jörn Engel; +Cc: zhao forrest, linux-mtd

On Tue, 2005-09-20 at 13:36 +0200, Jörn Engel wrote:
> > 
> > If old binary mounts new image, it starts writing its cleanmarkers, use
> > 1:N mapping etc. A "mixed" image appears. Afterwords, if this mixed
> > image is being mounted on new JFFS2 binary, what poor Zhao is supposed
> > to do? There will be too much ugliness in the code to handle that.
> 
> Please don't mix those two problems.  1:1 mapping has been dealt with.
> If you don't like how it has been dealt with, complain in the context
> of 1:1 mapping.
> 

Please, remember the original goal. It is new wear-levelling. This patch
may be considered as something independent, but it is not optimal. If we
follow this way, Zhao must:

1. Write code which understands both cleanmarkers and EB headers.
2. Test that old images are actually work well on new JFFS2.
3. Implement 1:1. Remove cleanmarkers support as they are not needed
anymore.

So, there is unneeded work. Does it make sense to regard these problems
coincidentally?

-- 
Best Regards,
Artem B. Bityuckiy,
St.-Petersburg, Russia.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH]Add JFFS2 eraseblock header support
  2005-09-20 11:56       ` Artem B. Bityutskiy
@ 2005-09-20 12:27         ` Jörn Engel
  2005-09-20 12:43           ` Jörn Engel
  0 siblings, 1 reply; 13+ messages in thread
From: Jörn Engel @ 2005-09-20 12:27 UTC (permalink / raw)
  To: Artem B. Bityutskiy; +Cc: zhao forrest, linux-mtd

On Tue, 20 September 2005 15:56:04 +0400, Artem B. Bityutskiy wrote:
> On Tue, 2005-09-20 at 13:36 +0200, Jörn Engel wrote:
> > > 
> > > If old binary mounts new image, it starts writing its cleanmarkers, use
> > > 1:N mapping etc. A "mixed" image appears. Afterwords, if this mixed
> > > image is being mounted on new JFFS2 binary, what poor Zhao is supposed
> > > to do? There will be too much ugliness in the code to handle that.
> > 
> > Please don't mix those two problems.  1:1 mapping has been dealt with.
> > If you don't like how it has been dealt with, complain in the context
> > of 1:1 mapping.
> 
> Please, remember the original goal. It is new wear-levelling. This patch
> may be considered as something independent, but it is not optimal. If we
> follow this way, Zhao must:
> 
> 1. Write code which understands both cleanmarkers and EB headers.
> 2. Test that old images are actually work well on new JFFS2.
> 3. Implement 1:1. Remove cleanmarkers support as they are not needed
> anymore.

Not quite.  He must:
1. Assume 1:1 mapping.  If people are not, that's a completely
   seperate problem.
2. Write robust code that does not depend on EBH.  If the header is
   missing, it should just create a new one and initialize its members
   as best it can - e.g. taking the average erase count.
3. Not emit clean markers anymore - they are not needed.

Going back to your list:

> 1. Write code which understands both cleanmarkers and EB headers.

Big deal.  Cleanmarker doesn't really matter, absence of EBH does.

> 2. Test that old images are actually work well on new JFFS2.

Sure!

> 3. Implement 1:1. Remove cleanmarkers support as they are not needed
> anymore.

Nope, why do you keep bringing it up?  1:1 is finished.  History.
Dealt with.  Old coffee.  Not a problem anymore.  Capisci?

Jörn

-- 
You ain't got no problem, Jules. I'm on the motherfucker. Go back in
there, chill them niggers out and wait for the Wolf, who should be
coming directly.
-- Marsellus Wallace

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH]Add JFFS2 eraseblock header support
  2005-09-20 12:27         ` Jörn Engel
@ 2005-09-20 12:43           ` Jörn Engel
  0 siblings, 0 replies; 13+ messages in thread
From: Jörn Engel @ 2005-09-20 12:43 UTC (permalink / raw)
  To: Artem B. Bityutskiy; +Cc: zhao forrest, linux-mtd

On Tue, 20 September 2005 14:27:47 +0200, Jörn Engel wrote:
> On Tue, 20 September 2005 15:56:04 +0400, Artem B. Bityutskiy wrote:
> > 
> > 1. Write code which understands both cleanmarkers and EB headers.
> > 2. Test that old images are actually work well on new JFFS2.
> > 3. Implement 1:1. Remove cleanmarkers support as they are not needed
> > anymore.
> 
> Not quite.  He must:
> 1. Assume 1:1 mapping.  If people are not, that's a completely
>    seperate problem.
> 2. Write robust code that does not depend on EBH.  If the header is
>    missing, it should just create a new one and initialize its members
>    as best it can - e.g. taking the average erase count.
> 3. Not emit clean markers anymore - they are not needed.

Btw, most of the complexity in Zhao's code comes from the attempt to
be future-proof and all that.  If he simply tried to implement better
wear levelling, it would be half the effort.

Jörn

-- 
The cheapest, fastest and most reliable components of a computer
system are those that aren't there.
-- Gordon Bell, DEC labratories

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH]Add JFFS2 eraseblock header support
  2005-09-20 10:59   ` Artem B. Bityutskiy
  2005-09-20 11:36     ` Jörn Engel
@ 2005-09-21  2:16     ` zhao forrest
  1 sibling, 0 replies; 13+ messages in thread
From: zhao forrest @ 2005-09-21  2:16 UTC (permalink / raw)
  To: dedekind, joern; +Cc: linux-mtd

> > > 6 new JFFS2 binary, when mounting an old JFFS2 image, will reject
> > > mounting unless the old JFFS2 image doesn't use 1:N(N>1)mapping.
> >
> > I wouldn't waste code on this.
>I would just reject mounting old images as well.
>
For trying to keep compatibility, I think there's no reason for new 
JFFS2 binary to reject mounting old JFFS2 image(with clean marker) if
this image use 1:1 mapping. So I'd insist on this. Does it make sense
to you?
In fact I didn't waste many code on this, it's only a little code
for it :)

Thanks,
Forrest

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH]Add JFFS2 eraseblock header support
  2005-09-20 11:29 ` Artem B. Bityutskiy
@ 2005-09-21  2:22   ` zhao forrest
  0 siblings, 0 replies; 13+ messages in thread
From: zhao forrest @ 2005-09-21  2:22 UTC (permalink / raw)
  To: dedekind; +Cc: linux-mtd

>
>+struct jffs2_eraseblock_header
>+{
>+       jint16_t magic;
>+       jint16_t nodetype; /* == JFFS2_NODETYPE_ERASEBLOCK_HEADER */
>+       jint32_t totlen;
>+       jint32_t hdr_crc;
>+       jint32_t fs_version; /* the version of this JFFS2 fs image */
>Well, I assume we may have 3 fields here:
>u8 version;
>u8 compat_fset;
>u8 incompat_fset;
>u8 rocompat_fset;

OK. I'll modify the patch to add support for these 3 new fields.

>
>+       jint32_t erase_count; /* the erase count of this erase block */
>4 bytes enough?
>

Yes. Now the erase cycles of flash erase block is about 100,000. So 4 
bytes is enough.

>+       jint16_t dsize; /* the size of additional data behind node_crc */
>What for?

This is for future extension. For example, if we decide to add more fields
into eraseblock_header in the future, they'll be appended to
eraseblock_header. dsize tells the data length of appended data; 
data_crc tells the crc of appended data.

>
>+       jint32_t node_crc;
>+       jint32_t data_crc;
>+       jint32_t data[0];
>+} __attribute__((packed));
>+
>
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH]Add JFFS2 eraseblock header support
  2005-09-20 11:36     ` Jörn Engel
  2005-09-20 11:56       ` Artem B. Bityutskiy
@ 2005-09-21  2:57       ` zhao forrest
  2005-09-21  7:10         ` Jörn Engel
  1 sibling, 1 reply; 13+ messages in thread
From: zhao forrest @ 2005-09-21  2:57 UTC (permalink / raw)
  To: joern, dedekind; +Cc: linux-mtd

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=gb2312; format=flowed, Size: 2106 bytes --]


> > On Tue, 2005-09-20 at 12:24 +0200, Jörn Engel wrote:
> > > > 4 old JFFS2 binaries reject mounting new JFFS2 images
> > >
> > > Why this?
> >
> > Because he changed cleanmarker to the EB header (eraseblock header). 
Old
> > binaries got confused by this since there are working no compatibility
> > flags in cleanmarkers.
>
>WTF?  Old code can simply delete the EB.  You lost all the goodies
>from EB, sure, but they are only optimization.  So who cares?
>
> > Moreover, we are going to implement the 1:1 mapping at the same time.
> >
> > If old binary mounts new image, it starts writing its cleanmarkers, use
> > 1:N mapping etc. A "mixed" image appears. Afterwords, if this mixed
> > image is being mounted on new JFFS2 binary, what poor Zhao is supposed
> > to do? There will be too much ugliness in the code to handle that.
>
>Please don't mix those two problems.  1:1 mapping has been dealt with.
>If you don't like how it has been dealt with, complain in the context
>of 1:1 mapping.
>

Let me give some my thoughts about the above two problems.
It's ture that 1:1 mapping was dealt with a few days ago. But we can't
assume 1:1 mapping when writing EBH patch. Because there still exist the
old JFFS2 code(the code without the recent 1:1 mapping patch) that use 1:N
mapping.So I can't set the comp_flag of eraseblock_header to JFFS2_FEATURE_
RWCOMPAT_DELETE. Otherwise the "mixed" image will appear for old JFFS2 code
(the code without the recent 1:1 mapping patch) as explained by Artem.

Joern,
I can understand your opinion. Your idea is that, since 1:1 mapping was 
handled recently, the comp_flag of eraseblock_header can be set to 
RWCOMPAT_
DELETE for the JFFS2 code with 1:1 mapping. But for the older JFFS2 code 
with
1:N mapping, the comp_flag of eraseblock_header have to be set to INCOMPAT.
IMHO I think 1:1 mapping and eraseblock_header should be added to JFFS2 at 
the same time. But the current situation is that 1:1 mapping patch was 
checked into CVS earlier than eraseblock_header. 
So I still agree that "old JFFS2 binaries reject mounting new JFFS2 
images".

Thanks,
Forrest

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH]Add JFFS2 eraseblock header support
  2005-09-21  2:57       ` zhao forrest
@ 2005-09-21  7:10         ` Jörn Engel
  2005-09-21 10:42           ` Ferenc Havasi
  0 siblings, 1 reply; 13+ messages in thread
From: Jörn Engel @ 2005-09-21  7:10 UTC (permalink / raw)
  To: zhao forrest; +Cc: linux-mtd

On Wed, 21 September 2005 10:57:40 +0800, zhao forrest wrote:
> 
> I can understand your opinion. Your idea is that, since 1:1 mapping was 
> handled recently, the comp_flag of eraseblock_header can be set to 
> RWCOMPAT_
> DELETE for the JFFS2 code with 1:1 mapping. But for the older JFFS2 code 
> with
> 1:N mapping, the comp_flag of eraseblock_header have to be set to INCOMPAT.
> IMHO I think 1:1 mapping and eraseblock_header should be added to JFFS2 at 
> the same time. But the current situation is that 1:1 mapping patch was 
> checked into CVS earlier than eraseblock_header. 
> So I still agree that "old JFFS2 binaries reject mounting new JFFS2 
> images".

Are you saying that the current way to handle 1:1 mapping is bullocks?

Jörn

-- 
/* Keep these two variables together */
int bar;

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH]Add JFFS2 eraseblock header support
  2005-09-21  7:10         ` Jörn Engel
@ 2005-09-21 10:42           ` Ferenc Havasi
  0 siblings, 0 replies; 13+ messages in thread
From: Ferenc Havasi @ 2005-09-21 10:42 UTC (permalink / raw)
  To: Jörn Engel; +Cc: zhao forrest, linux-mtd

Dear All,

I just would like to write my opinion about these topics.

I don't think that we should keep absolut monkey-safe compatibility. To
deal still with 1:N images makes the things unnecessary complicated
IMHO. The big warning (what Joern wrote to the list) should be enough
for every serious user. Or there is one more thing what we can do: if we
detect a cross-erase block node we reject mounting/set read-only flag.
Is there anything other (than cross erase block nodes) can be problem
with 1:N => 1:1?

I agree with Joern that erase block header now only a performance
improvement, so it should not be INCOMPAT. I think it would not even
solve the 1:N => 1:1 problem well. It only force the user than if he
uses new utils (mkfs.jffs2, ..) than use new JFFS2, tool; and if he used
a newer JFFS2 code, do not use an older one again. Nothing more. (Did I
misunderstand something?) I don't think that it is a real problem. But
if we afraid of it, I think we should introduce a distict new node type,
and not new types for inodes and dirents.

Bye,
Ferenc

P.S.: Zhao: If your patch reach the final state we will extend the
summary code to handle your node type correctly, too.

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2005-09-21 10:42 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-09-20  7:45 [PATCH]Add JFFS2 eraseblock header support zhao forrest
2005-09-20 10:24 ` Jörn Engel
2005-09-20 10:59   ` Artem B. Bityutskiy
2005-09-20 11:36     ` Jörn Engel
2005-09-20 11:56       ` Artem B. Bityutskiy
2005-09-20 12:27         ` Jörn Engel
2005-09-20 12:43           ` Jörn Engel
2005-09-21  2:57       ` zhao forrest
2005-09-21  7:10         ` Jörn Engel
2005-09-21 10:42           ` Ferenc Havasi
2005-09-21  2:16     ` zhao forrest
2005-09-20 11:29 ` Artem B. Bityutskiy
2005-09-21  2:22   ` zhao forrest

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox