* [PATCH] Adding eraseblock header support(revised version)
@ 2005-09-22 8:17 zhao forrest
2005-09-22 11:47 ` Artem B. Bityutskiy
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: zhao forrest @ 2005-09-22 8:17 UTC (permalink / raw)
To: dedekind, joern, havasi; +Cc: linux-mtd
[-- Attachment #1: Type: text/plain, Size: 763 bytes --]
Hi,
Here I send out the revised "eraseblock header" patch.
Two main changes compared with my first patch are made:
1 According to Joern's comment, we add 3 new fields into
struct jffs2_eraseblock_header for the compatibility purpose.
2 Add the code to support eraseblock summary, so that now EBH
can work with EBS. Fenenc, would you please help review this
part of code? Thanks.
According to the comments from mailing list, one problem is
still open:
Whether should we set the compat flag of eraseblock_header to
RWCOMPAT_DELETE or INCOMPAT?
Now in my patch I still set the compat flag of eraseblock_header
to INCOMPAT. After the final decision is made, I can modify
the patch accordingly.
Your comments for the revised patch are welcome :)
Thanks,
Forrest
[-- Attachment #2: eraseblock_header.patch --]
[-- Type: application/octet-stream, Size: 50929 bytes --]
diff -auNrp ./mtd/fs/jffs2/build.c ./mtd_EBH_EBS/fs/jffs2/build.c
--- ./mtd/fs/jffs2/build.c 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/build.c 2005-09-22 13:13:51.000000000 +0800
@@ -331,6 +331,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_EBH_EBS/fs/jffs2/debug.c
--- ./mtd/fs/jffs2/debug.c 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/debug.c 2005-09-22 13:13:51.000000000 +0800
@@ -648,6 +648,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 "the node is inode node\n");
printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.i.ino));
@@ -676,6 +677,7 @@ __jffs2_dbg_dump_node(struct jffs2_sb_in
break;
case JFFS2_NODETYPE_DIRENT:
+ case JFFS2_NODETYPE_DIRENT_EBH:
printk(JFFS2_DBG "the node is dirent node\n");
printk(JFFS2_DBG "pino:\t%#08x\n", je32_to_cpu(node.d.pino));
diff -auNrp ./mtd/fs/jffs2/dir.c ./mtd_EBH_EBS/fs/jffs2/dir.c
--- ./mtd/fs/jffs2/dir.c 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/dir.c 2005-09-22 13:13:51.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_EBH_EBS/fs/jffs2/erase.c
--- ./mtd/fs/jffs2/erase.c 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/erase.c 2005-09-22 13:13:51.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,17 @@ 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 = JFFS2_VERSION,
+ .compat_fset = JFFS2_EBH_COMPAT_FSET,
+ .incompat_fset = JFFS2_EBH_INCOMPAT_FSET,
+ .rocompat_fset = JFFS2_EBH_ROCOMPAT_FSET,
+ .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 +404,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 +425,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_EBH_EBS/fs/jffs2/file.c
--- ./mtd/fs/jffs2/file.c 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/file.c 2005-09-22 13:13:51.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_EBH_EBS/fs/jffs2/fs.c
--- ./mtd/fs/jffs2/fs.c 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/fs.c 2005-09-22 13:13:51.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_EBH_EBS/fs/jffs2/gc.c
--- ./mtd/fs/jffs2/gc.c 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/gc.c 2005-09-22 13:13:51.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_EBH_EBS/fs/jffs2/nodelist.h
--- ./mtd/fs/jffs2/nodelist.h 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/nodelist.h 2005-09-22 15:25:24.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)
@@ -404,7 +407,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_EBH_EBS/fs/jffs2/nodemgmt.c
--- ./mtd/fs/jffs2/nodemgmt.c 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/nodemgmt.c 2005-09-22 13:13:51.000000000 +0800
@@ -342,7 +342,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;
}
@@ -352,8 +355,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_EBH_EBS/fs/jffs2/os-linux.h
--- ./mtd/fs/jffs2/os-linux.h 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/os-linux.h 2005-09-22 13:13:51.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_EBH_EBS/fs/jffs2/readinode.c
--- ./mtd/fs/jffs2/readinode.c 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/readinode.c 2005-09-22 13:13:51.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_EBH_EBS/fs/jffs2/scan.c
--- ./mtd/fs/jffs2/scan.c 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/scan.c 2005-09-22 14:33:00.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, struct jffs2_summary *s);
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, s);
+ 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,57 @@ 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, struct jffs2_summary *s)
+{
+ 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_EBH_INCOMPAT_FSET | eh->incompat_fset) != JFFS2_EBH_INCOMPAT_FSET) {
+ printk(KERN_NOTICE "The incompat_fset of fs image EBH %d exceed the incompat_fset of JFFS2 module %d. Reject to mount.\n",
+ eh->incompat_fset, JFFS2_EBH_INCOMPAT_FSET);
+ return -EINVAL;
+ }
+ if ((JFFS2_EBH_ROCOMPAT_FSET | eh->rocompat_fset) != JFFS2_EBH_ROCOMPAT_FSET) {
+ printk(KERN_NOTICE "Read-only compatible EBH feature found at offset 0x%08x\n ", jeb->offset);
+ if (!(jffs2_is_readonly(c)))
+ return -EROFS;
+ }
+
+ 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)));
+ if (jffs2_sum_active()) {
+ jffs2_sum_add_ebh_mem(s, eh, ofs - jeb->offset);
+ }
+
+ return 0;
+}
+
static int count_list(struct list_head *l)
{
uint32_t count = 0;
diff -auNrp ./mtd/fs/jffs2/summary.c ./mtd_EBH_EBS/fs/jffs2/summary.c
--- ./mtd/fs/jffs2/summary.c 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/summary.c 2005-09-22 14:25:21.000000000 +0800
@@ -70,17 +70,25 @@ static int jffs2_sum_add_mem(struct jffs
switch (je16_to_cpu(item->u.nodetype)) {
case JFFS2_NODETYPE_INODE:
+ case JFFS2_NODETYPE_INODE_EBH:
s->sum_size += JFFS2_SUMMARY_INODE_SIZE;
s->sum_num++;
dbg_summary("inode (%u) added to summary\n",
je32_to_cpu(item->i.inode));
break;
case JFFS2_NODETYPE_DIRENT:
+ case JFFS2_NODETYPE_DIRENT_EBH:
s->sum_size += JFFS2_SUMMARY_DIRENT_SIZE(item->d.nsize);
s->sum_num++;
dbg_summary("dirent (%u) added to summary\n",
je32_to_cpu(item->d.ino));
break;
+ case JFFS2_NODETYPE_ERASEBLOCK_HEADER:
+ s->sum_size += JFFS2_SUMMARY_EBH_SIZE(je16_to_cpu(item->eh.dsize)*4);
+ s->sum_num++;
+ dbg_summary("eraseblock header (%x) added to summary\n",
+ je32_to_cpu(item->eh.offset));
+ break;
default:
JFFS2_WARNING("UNKNOWN node type %u\n",
je16_to_cpu(item->u.nodetype));
@@ -141,6 +149,29 @@ int jffs2_sum_add_dirent_mem(struct jffs
return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
}
+int jffs2_sum_add_ebh_mem(struct jffs2_summary *s, struct jffs2_eraseblock_header *eh, uint32_t ofs)
+{
+ struct jffs2_sum_ebh_mem *temp =
+ kmalloc(sizeof(struct jffs2_sum_ebh_mem) + je16_to_cpu(eh->dsize)*sizeof(uint32_t), GFP_KERNEL);
+ if (!temp)
+ return -ENOMEM;
+
+ temp->nodetype = eh->nodetype;
+ temp->totlen = eh->totlen;
+ temp->offset = cpu_to_je32(ofs);
+ temp->fs_version = eh->fs_version;
+ temp->compat_fset = eh->compat_fset;
+ temp->incompat_fset = eh->incompat_fset;
+ temp->rocompat_fset = eh->rocompat_fset;
+ temp->erase_count = eh->erase_count;
+ temp->dsize = eh->dsize;
+ temp->next = NULL;
+
+ memcpy(temp->data, eh->data, je16_to_cpu(eh->dsize)*sizeof(uint32_t));
+
+ return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
+}
+
/* Cleanup every collected summary information */
static void jffs2_sum_clean_collected(struct jffs2_summary *s)
@@ -209,7 +240,8 @@ int jffs2_sum_add_kvec(struct jffs2_sb_i
ofs -= jeb->offset;
switch (je16_to_cpu(node->u.nodetype)) {
- case JFFS2_NODETYPE_INODE: {
+ case JFFS2_NODETYPE_INODE:
+ case JFFS2_NODETYPE_INODE_EBH: {
struct jffs2_sum_inode_mem *temp =
kmalloc(sizeof(struct jffs2_sum_inode_mem), GFP_KERNEL);
@@ -226,7 +258,8 @@ int jffs2_sum_add_kvec(struct jffs2_sb_i
return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
}
- case JFFS2_NODETYPE_DIRENT: {
+ case JFFS2_NODETYPE_DIRENT:
+ case JFFS2_NODETYPE_DIRENT_EBH: {
struct jffs2_sum_dirent_mem *temp =
kmalloc(sizeof(struct jffs2_sum_dirent_mem) + node->d.nsize, GFP_KERNEL);
@@ -260,6 +293,36 @@ int jffs2_sum_add_kvec(struct jffs2_sb_i
return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
}
+ case JFFS2_NODETYPE_ERASEBLOCK_HEADER: {
+ struct jffs2_sum_ebh_mem *temp =
+ kmalloc(sizeof(struct jffs2_sum_ebh_mem) + je16_to_cpu(node->eh.dsize)*sizeof(uint32_t), GFP_KERNEL);
+ if (!temp)
+ goto no_mem;
+
+ temp->nodetype = node->eh.nodetype;
+ temp->totlen = node->eh.totlen;
+ temp->offset = cpu_to_je32(ofs);
+ temp->fs_version = node->eh.fs_version;
+ temp->compat_fset = node->eh.compat_fset;
+ temp->incompat_fset = node->eh.incompat_fset;
+ temp->rocompat_fset = node->eh.rocompat_fset;
+ temp->erase_count = node->eh.erase_count;
+ temp->dsize = node->eh.dsize;
+ temp->next = NULL;
+ switch (count) {
+ case 1:
+ memcpy(temp->data, node->eh.data, je16_to_cpu(node->eh.dsize)*sizeof(uint32_t));
+ break;
+ case 2:
+ memcpy(temp->data, invecs[1].iov_base, je16_to_cpu(node->eh.dsize)*sizeof(uint32_t));
+ break;
+ default:
+ BUG();
+ break;
+ }
+ return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
+ }
+
case JFFS2_NODETYPE_PADDING:
dbg_summary("node PADDING\n");
c->summary->sum_padded += je32_to_cpu(node->u.totlen);
@@ -306,7 +369,8 @@ static int jffs2_sum_process_sum_data(st
dbg_summary("processing summary index %d\n", i);
switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) {
- case JFFS2_NODETYPE_INODE: {
+ case JFFS2_NODETYPE_INODE:
+ case JFFS2_NODETYPE_INODE_EBH: {
struct jffs2_sum_inode_flash *spi;
spi = sp;
@@ -350,7 +414,8 @@ static int jffs2_sum_process_sum_data(st
break;
}
- case JFFS2_NODETYPE_DIRENT: {
+ case JFFS2_NODETYPE_DIRENT:
+ case JFFS2_NODETYPE_DIRENT_EBH: {
struct jffs2_sum_dirent_flash *spd;
spd = sp;
@@ -409,6 +474,60 @@ static int jffs2_sum_process_sum_data(st
break;
}
+ case JFFS2_NODETYPE_ERASEBLOCK_HEADER: {
+ struct jffs2_sum_ebh_flash *speh;
+ speh = sp;
+
+ dbg_summary("Eraseblock header at 0x%08x\n",
+ jeb->offset + je32_to_cpu(speh->offset));
+
+ if (je32_to_cpu(speh->offset) != 0) {
+ printk(KERN_NOTICE "Eraseblock header offset is %d\n", je32_to_cpu(speh->offset));
+ kfree(summary);
+ return -EINVAL;
+ }
+
+ if ((JFFS2_EBH_INCOMPAT_FSET | speh->incompat_fset) != JFFS2_EBH_INCOMPAT_FSET) {
+ printk(KERN_NOTICE "The incompat_fset of fs image EBH %d exceed the incompat_fset \
+ of JFFS2 module %d. Reject to mount.\n",
+ speh->incompat_fset, JFFS2_EBH_INCOMPAT_FSET);
+ kfree(summary);
+ return -EINVAL;
+ }
+ if ((JFFS2_EBH_ROCOMPAT_FSET | speh->rocompat_fset) != JFFS2_EBH_ROCOMPAT_FSET) {
+ printk(KERN_NOTICE "Read-only compatible EBH feature found at offset 0x%08x\n ",
+ jeb->offset);
+ if (!(jffs2_is_readonly(c))) {
+ kfree(summary);
+ return -EROFS;
+ }
+ }
+
+ raw = jffs2_alloc_raw_node_ref();
+ if (!raw) {
+ JFFS2_NOTICE("allocation of node reference failed\n");
+ kfree(summary);
+ return -ENOMEM;
+ }
+ jeb->has_eraseblock_header = 1;
+ jeb->erase_count = je32_to_cpu(speh->erase_count);
+ raw->next_in_ino = NULL;
+ raw->next_phys = NULL;
+ raw->flash_offset = (jeb->offset + je32_to_cpu(speh->offset)) | REF_NORMAL;
+ raw->__totlen = PAD(je32_to_cpu(speh->totlen));
+
+ if (!jeb->first_node)
+ jeb->first_node = raw;
+ if (jeb->last_node)
+ jeb->last_node->next_phys = raw;
+ jeb->last_node = raw;
+
+ USED_SPACE(PAD(je32_to_cpu(speh->totlen)));
+ sp += JFFS2_SUMMARY_EBH_SIZE(je16_to_cpu(speh->dsize)*sizeof(uint32_t));
+
+ break;
+ }
+
default : {
JFFS2_WARNING("Unsupported node type found in summary! Exiting...");
kfree(summary);
@@ -576,14 +695,15 @@ static int jffs2_sum_write_data(struct j
isum.totlen = cpu_to_je32(infosize);
isum.hdr_crc = cpu_to_je32(crc32(0, &isum, sizeof(struct jffs2_unknown_node) - 4));
isum.padded = cpu_to_je32(c->summary->sum_padded);
- isum.cln_mkr = cpu_to_je32(c->cleanmarker_size);
+ isum.cln_mkr = cpu_to_je32(0);
isum.sum_num = cpu_to_je32(c->summary->sum_num);
wpage = c->summary->sum_buf;
while (c->summary->sum_num) {
switch (je16_to_cpu(c->summary->sum_list_head->u.nodetype)) {
- case JFFS2_NODETYPE_INODE: {
+ case JFFS2_NODETYPE_INODE:
+ case JFFS2_NODETYPE_INODE_EBH: {
struct jffs2_sum_inode_flash *sino_ptr = wpage;
sino_ptr->nodetype = c->summary->sum_list_head->i.nodetype;
@@ -597,7 +717,8 @@ static int jffs2_sum_write_data(struct j
break;
}
- case JFFS2_NODETYPE_DIRENT: {
+ case JFFS2_NODETYPE_DIRENT:
+ case JFFS2_NODETYPE_DIRENT_EBH: {
struct jffs2_sum_dirent_flash *sdrnt_ptr = wpage;
sdrnt_ptr->nodetype = c->summary->sum_list_head->d.nodetype;
@@ -617,6 +738,26 @@ static int jffs2_sum_write_data(struct j
break;
}
+ case JFFS2_NODETYPE_ERASEBLOCK_HEADER: {
+ struct jffs2_sum_ebh_flash *sebh_ptr = wpage;
+
+ sebh_ptr->nodetype = c->summary->sum_list_head->eh.nodetype;
+ sebh_ptr->totlen = c->summary->sum_list_head->eh.totlen;
+ sebh_ptr->offset = c->summary->sum_list_head->eh.offset;
+ sebh_ptr->fs_version = c->summary->sum_list_head->eh.fs_version;
+ sebh_ptr->compat_fset = c->summary->sum_list_head->eh.compat_fset;
+ sebh_ptr->incompat_fset = c->summary->sum_list_head->eh.incompat_fset;
+ sebh_ptr->rocompat_fset = c->summary->sum_list_head->eh.rocompat_fset;
+ sebh_ptr->erase_count = c->summary->sum_list_head->eh.erase_count;
+ sebh_ptr->dsize = c->summary->sum_list_head->eh.dsize;
+
+ memcpy(sebh_ptr->data, c->summary->sum_list_head->eh.data,
+ je16_to_cpu(c->summary->sum_list_head->eh.dsize)*sizeof(uint32_t));
+ wpage += JFFS2_SUMMARY_EBH_SIZE(je16_to_cpu(c->summary->sum_list_head->eh.dsize)*sizeof(uint32_t));
+
+ break;
+ }
+
default : {
BUG(); /* unknown node in summary information */
}
diff -auNrp ./mtd/fs/jffs2/summary.h ./mtd_EBH_EBS/fs/jffs2/summary.h
--- ./mtd/fs/jffs2/summary.h 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/summary.h 2005-09-22 14:31:12.000000000 +0800
@@ -45,6 +45,7 @@
#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_EBH_SIZE(x) (sizeof(struct jffs2_sum_ebh_flash) + (x))
/* Summary structures used on flash */
@@ -75,11 +76,26 @@ struct jffs2_sum_dirent_flash
uint8_t name[0]; /* dirent name */
} __attribute__((packed));
+struct jffs2_sum_ebh_flash
+{
+ jint16_t nodetype;
+ jint32_t totlen;
+ jint32_t offset;
+ uint8_t fs_version;
+ uint8_t compat_fset;
+ uint8_t incompat_fset;
+ uint8_t rocompat_fset;
+ jint32_t erase_count;
+ jint16_t dsize;
+ jint32_t data[0];
+} __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_ebh_flash eh;
};
/* Summary structures used in the memory */
@@ -114,11 +130,27 @@ struct jffs2_sum_dirent_mem
uint8_t name[0]; /* dirent name */
} __attribute__((packed));
+struct jffs2_sum_ebh_mem
+{
+ union jffs2_sum_mem *next;
+ jint16_t nodetype;
+ jint32_t totlen;
+ jint32_t offset;
+ uint8_t fs_version;
+ uint8_t compat_fset;
+ uint8_t incompat_fset;
+ uint8_t rocompat_fset;
+ jint32_t erase_count;
+ jint16_t dsize;
+ jint32_t data[0];
+} __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_ebh_mem eh;
};
/* Summary related information stored in superblock */
@@ -159,6 +191,7 @@ int jffs2_sum_write_sumnode(struct jffs2
int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size);
int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, uint32_t ofs);
int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, uint32_t ofs);
+int jffs2_sum_add_ebh_mem(struct jffs2_summary *s, struct jffs2_eraseblock_header *eh, uint32_t ofs);
int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
uint32_t ofs, uint32_t *pseudo_random);
@@ -176,6 +209,7 @@ int jffs2_sum_scan_sumnode(struct jffs2_
#define jffs2_sum_add_padding_mem(a,b)
#define jffs2_sum_add_inode_mem(a,b,c)
#define jffs2_sum_add_dirent_mem(a,b,c)
+#define jffs2_sum_add_ebh_mem(a,b,c)
#define jffs2_sum_scan_sumnode(a,b,c,d) (0)
#endif /* CONFIG_JFFS2_SUMMARY */
diff -auNrp ./mtd/fs/jffs2/wbuf.c ./mtd_EBH_EBS/fs/jffs2/wbuf.c
--- ./mtd/fs/jffs2/wbuf.c 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/wbuf.c 2005-09-22 13:13:51.000000000 +0800
@@ -931,66 +931,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;
}
@@ -1000,86 +970,130 @@ 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;
- }
+ node_crc = crc32(0, &eh, sizeof(struct jffs2_eraseblock_header)-8);
+ if (node_crc != je32_to_cpu(eh.node_crc)) {
+ ret = 1;
+ goto out;
+ }
+
+ if ((JFFS2_EBH_INCOMPAT_FSET | eh.incompat_fset) != JFFS2_EBH_INCOMPAT_FSET) {
+ printk(KERN_NOTICE "The incompat_fset of fs image EBH %d execeed the incompat_fset \
+ of JFFS2 module %d. Reject to mount.\n", eh.incompat_fset, JFFS2_EBH_INCOMPAT_FSET);
+ ret = -EINVAL;
+ goto out;
+ }
+ if ((JFFS2_EBH_ROCOMPAT_FSET | eh.rocompat_fset) != JFFS2_EBH_ROCOMPAT_FSET) {
+ printk(KERN_NOTICE "Read-only compatible EBH feature found at offset 0x%08x\n ", jeb->offset);
+ if (!(jffs2_is_readonly(c))) {
+ ret = -EROFS;
+ goto out;
}
- 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");
- })
}
- offset += c->mtd->erasesize;
+
+ 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 = JFFS2_VERSION;
+ eh.compat_fset = JFFS2_EBH_COMPAT_FSET,
+ eh.incompat_fset = JFFS2_EBH_INCOMPAT_FSET,
+ eh.rocompat_fset = JFFS2_EBH_ROCOMPAT_FSET,
+ 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;
}
@@ -1132,6 +1146,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) {
@@ -1143,8 +1158,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) {
@@ -1164,6 +1177,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;
@@ -1178,6 +1206,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)
@@ -1220,6 +1253,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);
@@ -1240,6 +1274,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_EBH_EBS/fs/jffs2/write.c
--- ./mtd/fs/jffs2/write.c 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/fs/jffs2/write.c 2005-09-22 13:13:51.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_EBH_EBS/include/linux/jffs2_fs_sb.h
--- ./mtd/include/linux/jffs2_fs_sb.h 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/include/linux/jffs2_fs_sb.h 2005-09-22 13:13:51.000000000 +0800
@@ -115,6 +115,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_EBH_EBS/include/linux/jffs2.h
--- ./mtd/include/linux/jffs2.h 2005-09-22 11:08:47.000000000 +0800
+++ ./mtd_EBH_EBS/include/linux/jffs2.h 2005-09-22 13:13:51.000000000 +0800
@@ -28,6 +28,12 @@
#define JFFS2_EMPTY_BITMASK 0xffff
#define JFFS2_DIRTY_BITMASK 0x0000
+/* JFFS2 version number */
+#define JFFS2_VERSION 0x01
+#define JFFS2_EBH_COMPAT_FSET 0x00
+#define JFFS2_EBH_INCOMPAT_FSET 0x00
+#define JFFS2_EBH_ROCOMPAT_FSET 0x00
+
/* Summary node MAGIC marker */
#define JFFS2_SUM_MAGIC 0x02851885
@@ -63,7 +69,12 @@
#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 2 types are defined in order to let old JFFS2 code reject to mount new JFFS2 fs image for NAND flash,
+ these 2 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)
// Maybe later...
//#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
@@ -101,6 +112,23 @@ 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;
+ uint8_t fs_version; /* the version of this JFFS2 fs image */
+ uint8_t compat_fset;
+ uint8_t incompat_fset;
+ uint8_t rocompat_fset;
+ 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 +196,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] 8+ messages in thread* Re: [PATCH] Adding eraseblock header support(revised version)
2005-09-22 8:17 [PATCH] Adding eraseblock header support(revised version) zhao forrest
@ 2005-09-22 11:47 ` Artem B. Bityutskiy
2005-09-23 2:45 ` zhao forrest
2005-09-22 12:08 ` Artem B. Bityutskiy
2005-09-22 14:37 ` Artem B. Bityutskiy
2 siblings, 1 reply; 8+ messages in thread
From: Artem B. Bityutskiy @ 2005-09-22 11:47 UTC (permalink / raw)
To: zhao forrest; +Cc: linux-mtd
zhao forrest wrote:
> According to the comments from mailing list, one problem is
> still open:
> Whether should we set the compat flag of eraseblock_header to
> RWCOMPAT_DELETE or INCOMPAT? Now in my patch I still set the compat flag
> of eraseblock_header
> to INCOMPAT. After the final decision is made, I can modify
> the patch accordingly.
>
Well, this was discussed... But I still don't see any conclusion. My
opinion is below.
Terms:
1. New JFFS2 - recent JFFS2 where 1:1 was added.
2. Old JFFS2 - older JFFS2, before 1:1 was added.
3. New JFFS2 image - an image made for new JFFS2.
4. Old JFFS2 image - an image made for old JFFS2.
Q: are there any issues when an old JFFS2 image is mounted by new JFFS2
code?
A: yes, there are. Old JFFS2 did eraseblock concatenations and worked
with virtual eraseblocks. So, there are nodes which cross the eraseblock
boundary.
Q: why is this a problem?
A: because with 1:1 mapping we will have nodes which cross the
eraseblock boundary. JFFS2 will suffer hard.
Q: what to do?
A: either handle this or reject mounting old images in New JFFS2.
Thus, my answer is - yes, you must reject mounting old images.
But this has no relation to your parch. Could you implement that by a
distinct patch please? Or Ferenc, who actually committed the 1:1 patch
may do this :-) (please).
You may implement it like this. If you have met any clean marker during
scan - reject mounting JFFS2. No need to introduce messy
JFFS2_NODETYPE_INODE_EBH and the like.
--
Best Regards,
Artem B. Bityuckiy,
St.-Petersburg, Russia.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Adding eraseblock header support(revised version)
2005-09-22 11:47 ` Artem B. Bityutskiy
@ 2005-09-23 2:45 ` zhao forrest
2005-09-23 8:57 ` Jörn Engel
0 siblings, 1 reply; 8+ messages in thread
From: zhao forrest @ 2005-09-23 2:45 UTC (permalink / raw)
To: dedekind; +Cc: linux-mtd
>
>zhao forrest wrote:
> > According to the comments from mailing list, one problem is
> > still open:
> > Whether should we set the compat flag of eraseblock_header to
> > RWCOMPAT_DELETE or INCOMPAT? Now in my patch I still set the compat
flag
> > of eraseblock_header
> > to INCOMPAT. After the final decision is made, I can modify
> > the patch accordingly.
> >
>Well, this was discussed... But I still don't see any conclusion. My
>opinion is below.
>
>Terms:
>1. New JFFS2 - recent JFFS2 where 1:1 was added.
>2. Old JFFS2 - older JFFS2, before 1:1 was added.
>3. New JFFS2 image - an image made for new JFFS2.
>4. Old JFFS2 image - an image made for old JFFS2.
>
>Q: are there any issues when an old JFFS2 image is mounted by new JFFS2
>code?
>A: yes, there are. Old JFFS2 did eraseblock concatenations and worked
>with virtual eraseblocks. So, there are nodes which cross the eraseblock
>boundary.
>
>Q: why is this a problem?
>A: because with 1:1 mapping we will have nodes which cross the
>eraseblock boundary. JFFS2 will suffer hard.
>
>Q: what to do?
>A: either handle this or reject mounting old images in New JFFS2.
>
>Thus, my answer is - yes, you must reject mounting old images.
>
>But this has no relation to your parch. Could you implement that by a
>distinct patch please? Or Ferenc, who actually committed the 1:1 patch
>may do this :-) (please).
>
>You may implement it like this. If you have met any clean marker during
>scan - reject mounting JFFS2. No need to introduce messy
>JFFS2_NODETYPE_INODE_EBH and the like.
>
1 According to the later disscusion in "1:1 mapping" thread, we should
reject mounting when detect cross-boundary. In another word, we should
not reject mounting if we don't detect cross-boundary. Right? This is
just what my patch implemented :)
2 The reason why we introduce JFFS2_NODETYPE_INODE_EBH has nothing to
do with "when an old JFFS2 image is mounted by new JFFS2 code". It's
related with "when an new JFFS2 image is mounted by old JFFS2 code".
Your original design mail for eraseblock header has a clear description
of it.
So the problem is still open:
Whether should we set the compat flag of eraseblock_header to
RWCOMPAT_DELETE or INCOMPAT???
Thanks,
Forrest
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Adding eraseblock header support(revised version)
2005-09-23 2:45 ` zhao forrest
@ 2005-09-23 8:57 ` Jörn Engel
0 siblings, 0 replies; 8+ messages in thread
From: Jörn Engel @ 2005-09-23 8:57 UTC (permalink / raw)
To: zhao forrest; +Cc: dedekind, linux-mtd
On Fri, 23 September 2005 10:45:00 +0800, zhao forrest wrote:
> >
> 1 According to the later disscusion in "1:1 mapping" thread, we should
> reject mounting when detect cross-boundary. In another word, we should
> not reject mounting if we don't detect cross-boundary. Right? This is
> just what my patch implemented :)
>
> 2 The reason why we introduce JFFS2_NODETYPE_INODE_EBH has nothing to
> do with "when an old JFFS2 image is mounted by new JFFS2 code". It's
> related with "when an new JFFS2 image is mounted by old JFFS2 code".
> Your original design mail for eraseblock header has a clear description
> of it.
> So the problem is still open:
> Whether should we set the compat flag of eraseblock_header to
> RWCOMPAT_DELETE or INCOMPAT???
That's still a problem of the virtual mapping desaster. I refuse to
discuss it in the context of erase block headers. ;)
Jörn
--
ticks = jiffies;
while (ticks == jiffies);
ticks = jiffies;
-- /usr/src/linux/init/main.c
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Adding eraseblock header support(revised version)
2005-09-22 8:17 [PATCH] Adding eraseblock header support(revised version) zhao forrest
2005-09-22 11:47 ` Artem B. Bityutskiy
@ 2005-09-22 12:08 ` Artem B. Bityutskiy
2005-09-23 3:08 ` zhao forrest
2005-09-22 14:37 ` Artem B. Bityutskiy
2 siblings, 1 reply; 8+ messages in thread
From: Artem B. Bityutskiy @ 2005-09-22 12:08 UTC (permalink / raw)
To: zhao forrest; +Cc: linux-mtd
zhao forrest wrote:
> Your comments for the revised patch are welcome :)
It is supposed that you eliminated cleanmarkers completely, right?
Why then I still see functions like jffs2_check_nand_cleanmarker()?
--
Best Regards,
Artem B. Bityuckiy,
St.-Petersburg, Russia.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Adding eraseblock header support(revised version)
2005-09-22 12:08 ` Artem B. Bityutskiy
@ 2005-09-23 3:08 ` zhao forrest
2005-09-23 9:23 ` Artem B. Bityutskiy
0 siblings, 1 reply; 8+ messages in thread
From: zhao forrest @ 2005-09-23 3:08 UTC (permalink / raw)
To: dedekind; +Cc: linux-mtd
>
>zhao forrest wrote:
> > Your comments for the revised patch are welcome :)
>
>It is supposed that you eliminated cleanmarkers completely, right?
>Why then I still see functions like jffs2_check_nand_cleanmarker()?
>--
We'll allow mount old JFFS2 image if it used 1:1 mapping. So
during mount scan we need to scan both cleanmarker and eraseblock
header. So I don't change the name. Maybe a new name like
jffs2_check_nand_cleanmarker_ebh() is better.
Thanks,
Forrest
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Adding eraseblock header support(revised version)
2005-09-23 3:08 ` zhao forrest
@ 2005-09-23 9:23 ` Artem B. Bityutskiy
0 siblings, 0 replies; 8+ messages in thread
From: Artem B. Bityutskiy @ 2005-09-23 9:23 UTC (permalink / raw)
To: zhao forrest; +Cc: linux-mtd
zhao forrest wrote:
>> It is supposed that you eliminated cleanmarkers completely, right?
>> Why then I still see functions like jffs2_check_nand_cleanmarker()?
>
> We'll allow mount old JFFS2 image if it used 1:1 mapping. So
> during mount scan we need to scan both cleanmarker and eraseblock
> header. So I don't change the name. Maybe a new name like
> jffs2_check_nand_cleanmarker_ebh() is better.
>
Ah, pardon... Then OK, IMO, no need to rename.
--
Best Regards,
Artem B. Bityuckiy,
St.-Petersburg, Russia.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Adding eraseblock header support(revised version)
2005-09-22 8:17 [PATCH] Adding eraseblock header support(revised version) zhao forrest
2005-09-22 11:47 ` Artem B. Bityutskiy
2005-09-22 12:08 ` Artem B. Bityutskiy
@ 2005-09-22 14:37 ` Artem B. Bityutskiy
2 siblings, 0 replies; 8+ messages in thread
From: Artem B. Bityutskiy @ 2005-09-22 14:37 UTC (permalink / raw)
To: zhao forrest; +Cc: linux-mtd
zhao forrest wrote:
> Your comments for the revised patch are welcome :)
+ 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))
+ {
1. I would not use so looong lines. There is a 80 chars restriction. In
JFFS2 it is OK to use long lines for prints.
2. jeb->has_eraseblock_header - so looong name ... Why not to use
jeb->has_ebh ?
--
Best Regards,
Artem B. Bityuckiy,
St.-Petersburg, Russia.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2005-09-23 9:24 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-09-22 8:17 [PATCH] Adding eraseblock header support(revised version) zhao forrest
2005-09-22 11:47 ` Artem B. Bityutskiy
2005-09-23 2:45 ` zhao forrest
2005-09-23 8:57 ` Jörn Engel
2005-09-22 12:08 ` Artem B. Bityutskiy
2005-09-23 3:08 ` zhao forrest
2005-09-23 9:23 ` Artem B. Bityutskiy
2005-09-22 14:37 ` Artem B. Bityutskiy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox