From 7c96b7a146eb81d13be738709c36752c20abe4fc Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 2 May 2007 08:36:21 +0100 Subject: [JFFS2] Remove dead file histo_mips.h Its contents were subsumed into compr_rubin.c in a previous commit, but I forgot to git-rm it. Signed-off-by: David Woodhouse --- fs/jffs2/histo_mips.h | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 fs/jffs2/histo_mips.h (limited to 'fs/jffs2') diff --git a/fs/jffs2/histo_mips.h b/fs/jffs2/histo_mips.h deleted file mode 100644 index fa3dac19a10..00000000000 --- a/fs/jffs2/histo_mips.h +++ /dev/null @@ -1,2 +0,0 @@ -#define BIT_DIVIDER_MIPS 1043 -static int bits_mips[8] = { 277,249,290,267,229,341,212,241}; /* mips32 */ -- cgit v1.2.3 From 3fddb6c985e3823c991399840d2d5ef5940e1b60 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 5 May 2007 09:52:49 +0100 Subject: [JFFS2] Don't advance c->wbuf_ofs to next eraseblock after wbuf flush After flushing the last page of an eraseblock, don't leave the wbuf 'offset' field pointing at the start of the next physical eraseblock. This was causing a BUG() on NOR-ECC (Sibley) flash, where we start writing a little further in, after the cleanmarker. Debugged by Alexander Belyakov Signed-off-by: David Woodhouse --- fs/jffs2/wbuf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'fs/jffs2') diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index c556e85a565..91d1d0f1c66 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -637,7 +637,10 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) memset(c->wbuf,0xff,c->wbuf_pagesize); /* adjust write buffer offset, else we get a non contiguous write bug */ - c->wbuf_ofs += c->wbuf_pagesize; + if (SECTOR_ADDR(c->wbuf_ofs) == SECTOR_ADDR(c->wbuf_ofs+c->wbuf_pagesize)) + c->wbuf_ofs += c->wbuf_pagesize; + else + c->wbuf_ofs = 0xffffffff; c->wbuf_len = 0; return 0; } -- cgit v1.2.3 From 1123e2a85941c7f506bd42c91c7e9ab74fc42d79 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 5 May 2007 16:29:34 +0100 Subject: [JFFS2] Remember to calculate overlap on nodes which replace older nodes This fixes a problem Artem found with the integck test tool -- we weren't correctly keeping track of the 'overlap' flag in some cases, which led to the nodes being played back in an incorrect order and file corruption. Signed-off-by: David Woodhouse --- fs/jffs2/readinode.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'fs/jffs2') diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 6aff38930b5..b0645ac7769 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -276,10 +276,9 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, /* Who cares if the new one is good; keep it for now anyway. */ rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); /* Same overlapping from in front and behind */ - tn->overlapped = this->overlapped; jffs2_kill_tn(c, this); dbg_readinode("Like new node. Throw away old\n"); - return 0; + goto calc_overlaps; } } if (this->version < tn->version && @@ -293,7 +292,6 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, } /* ... and is good. Kill 'this'... */ rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); - tn->overlapped = this->overlapped; jffs2_kill_tn(c, this); /* ... and any subsequent nodes which are also overlapped */ this = tn_next(tn); @@ -309,7 +307,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, this = next; } dbg_readinode("Done inserting new\n"); - return 0; + goto calc_overlaps; } if (this->version > tn->version && this->fn->ofs <= tn->fn->ofs && @@ -321,6 +319,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, return 0; } /* ... but 'this' was bad. Replace it... */ + tn->overlapped = this->overlapped; rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); dbg_readinode("Bad CRC on old overlapping node. Kill it\n"); jffs2_kill_tn(c, this); @@ -359,6 +358,8 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, rb_link_node(&tn->rb, &insert_point->rb, link); rb_insert_color(&tn->rb, &rii->tn_root); } + + calc_overlaps: /* If there's anything behind that overlaps us, note it */ this = tn_prev(tn); if (this) { @@ -483,7 +484,7 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c, vers_next = tn_prev(this); eat_last(&ver_root, &this->rb); if (check_tn_node(c, this)) { - dbg_readinode("node ver %x, 0x%x-0x%x failed CRC\n", + dbg_readinode("node ver %d, 0x%x-0x%x failed CRC\n", this->version, this->fn->ofs, this->fn->ofs+this->fn->size); jffs2_kill_tn(c, this); @@ -496,7 +497,7 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c, high_ver = this->version; rii->latest_ref = this->fn->raw; } - dbg_readinode("Add %p (v %x, 0x%x-0x%x, ov %d) to fragtree\n", + dbg_readinode("Add %p (v %d, 0x%x-0x%x, ov %d) to fragtree\n", this, this->version, this->fn->ofs, this->fn->ofs+this->fn->size, this->overlapped); @@ -850,7 +851,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref return ret; } #ifdef JFFS2_DBG_READINODE_MESSAGES - dbg_readinode("After adding ver %d:\n", tn->version); + dbg_readinode("After adding ver %d:\n", je32_to_cpu(rd->version)); tn = tn_first(&rii->tn_root); while (tn) { dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n", -- cgit v1.2.3 From 96dd8d25d1ca8c233bd47752349d27a631c18719 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sun, 6 May 2007 14:41:40 +0100 Subject: [JFFS2] Remove broken insert_point optimisation in jffs2_add_tn_to_tree() The original code would remember, during the first pass over the tree, a suitable place to start the insertion from when we eventually come to add a new node. The optimisation was broken, and we sometimes ended up inserting a new node in the wrong place because we started the insertion from the wrong point. Just ditch the optimisation and start the insertion from the root of the tree, for now. I'll try it again when I'm feeling cleverer. Signed-off-by: David Woodhouse --- fs/jffs2/readinode.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'fs/jffs2') diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index b0645ac7769..f461604cf01 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -219,7 +219,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) { uint32_t fn_end = tn->fn->ofs + tn->fn->size; - struct jffs2_tmp_dnode_info *insert_point = NULL, *this; + struct jffs2_tmp_dnode_info *this; dbg_readinode("insert fragment %#04x-%#04x, ver %u\n", tn->fn->ofs, fn_end, tn->version); @@ -248,9 +248,6 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, return 0; } - /* If we add a new node it'll be somewhere under here. */ - insert_point = this; - /* If the node is coincident with another at a lower address, back up until the other node is found. It may be relevant */ while (tn->overlapped) @@ -325,24 +322,16 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, jffs2_kill_tn(c, this); return 0; } - /* We want to be inserted under the last node which is - either at a lower offset _or_ has a smaller range */ - if (this->fn->ofs < tn->fn->ofs || - (this->fn->ofs == tn->fn->ofs && - this->fn->size <= tn->fn->size)) - insert_point = this; this = tn_next(this); } - dbg_readinode("insert_point %p, ver %d, 0x%x-0x%x, ov %d\n", - insert_point, insert_point->version, insert_point->fn->ofs, - insert_point->fn->ofs+insert_point->fn->size, - insert_point->overlapped); + /* We neither completely obsoleted nor were completely - obsoleted by an earlier node. Insert under insert_point */ + obsoleted by an earlier node. Insert into the tree */ { - struct rb_node *parent = &insert_point->rb; - struct rb_node **link = &parent; + struct rb_node *parent; + struct rb_node **link = &rii->tn_root.rb_node; + struct jffs2_tmp_dnode_info *insert_point; while (*link) { parent = *link; @@ -458,7 +447,7 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c, this = tn_last(&rii->tn_root); while (this) { dbg_readinode("tn %p ver %d range 0x%x-0x%x ov %d\n", this, this->version, this->fn->ofs, - this->fn->ofs+this->fn->size, this->overlapped); + this->fn->ofs+this->fn->size, this->overlapped); this = tn_prev(this); } #endif -- cgit v1.2.3 From fcf3cafb3e7e7750f4876571492594c3a4854ee5 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 7 May 2007 13:16:13 +0100 Subject: [JFFS2] Remove another bogus optimisation in jffs2_add_tn_to_tree() We attempted to insert new nodes into the tree by just using rb_replace_node to let them replace an earlier node which they completely overlapped. However, that could place the new node into the wrong place in the tree, since its start could be node only before the start of the victim, but before the node _before_ the victim in the tree (if that previous node actually ends _after_ the new node, thus isn't entirely overlapped and wasn't itself chosen to be the victim). Signed-off-by: David Woodhouse --- fs/jffs2/readinode.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'fs/jffs2') diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index f461604cf01..bd31d4956c6 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -221,7 +221,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, uint32_t fn_end = tn->fn->ofs + tn->fn->size; struct jffs2_tmp_dnode_info *this; - dbg_readinode("insert fragment %#04x-%#04x, ver %u\n", tn->fn->ofs, fn_end, tn->version); + dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw)); /* If a node has zero dsize, we only have to keep if it if it might be the node with highest version -- i.e. the one which will end up as f->metadata. @@ -271,11 +271,11 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, return 0; } else { /* Who cares if the new one is good; keep it for now anyway. */ + dbg_readinode("Like new node. Throw away old\n"); rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); - /* Same overlapping from in front and behind */ jffs2_kill_tn(c, this); - dbg_readinode("Like new node. Throw away old\n"); - goto calc_overlaps; + /* Same overlapping from in front and behind */ + return 0; } } if (this->version < tn->version && @@ -287,11 +287,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, jffs2_kill_tn(c, tn); return 0; } - /* ... and is good. Kill 'this'... */ - rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); - jffs2_kill_tn(c, this); - /* ... and any subsequent nodes which are also overlapped */ - this = tn_next(tn); + /* ... and is good. Kill 'this' and any subsequent nodes which are also overlapped */ while (this && this->fn->ofs + this->fn->size < fn_end) { struct jffs2_tmp_dnode_info *next = tn_next(this); if (this->version < tn->version) { @@ -303,8 +299,8 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, } this = next; } - dbg_readinode("Done inserting new\n"); - goto calc_overlaps; + dbg_readinode("Done killing overlapped nodes\n"); + break; } if (this->version > tn->version && this->fn->ofs <= tn->fn->ofs && @@ -316,11 +312,10 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, return 0; } /* ... but 'this' was bad. Replace it... */ - tn->overlapped = this->overlapped; - rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); dbg_readinode("Bad CRC on old overlapping node. Kill it\n"); + tn_erase(this, &rii->tn_root); jffs2_kill_tn(c, this); - return 0; + break; } this = tn_next(this); -- cgit v1.2.3 From 1c97964520503c60aa91680d4b525236c2885a36 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 8 May 2007 00:19:54 +0100 Subject: [JFFS2] Simplify and clean up jffs2_add_tn_to_tree() some more. Fixing at least a couple more bugs in the process. Signed-off-by: David Woodhouse --- fs/jffs2/readinode.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'fs/jffs2') diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index bd31d4956c6..4884d5edfe6 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -240,20 +240,16 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, /* Find the earliest node which _may_ be relevant to this one */ this = jffs2_lookup_tn(&rii->tn_root, tn->fn->ofs); - if (!this) { - /* First addition to empty tree. $DEITY how I love the easy cases */ - rb_link_node(&tn->rb, NULL, &rii->tn_root.rb_node); - rb_insert_color(&tn->rb, &rii->tn_root); - dbg_readinode("keep new frag\n"); - return 0; - } - - /* If the node is coincident with another at a lower address, - back up until the other node is found. It may be relevant */ - while (tn->overlapped) - tn = tn_prev(tn); + if (this) { + /* If the node is coincident with another at a lower address, + back up until the other node is found. It may be relevant */ + while (this->overlapped) + this = tn_prev(this); - dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole"); + /* First node should never be marked overlapped */ + BUG_ON(!this); + dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole"); + } while (this) { if (this->fn->ofs > fn_end) @@ -288,7 +284,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, return 0; } /* ... and is good. Kill 'this' and any subsequent nodes which are also overlapped */ - while (this && this->fn->ofs + this->fn->size < fn_end) { + while (this && this->fn->ofs + this->fn->size <= fn_end) { struct jffs2_tmp_dnode_info *next = tn_next(this); if (this->version < tn->version) { tn_erase(this, &rii->tn_root); @@ -300,7 +296,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, this = next; } dbg_readinode("Done killing overlapped nodes\n"); - break; + continue; } if (this->version > tn->version && this->fn->ofs <= tn->fn->ofs && @@ -326,7 +322,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, { struct rb_node *parent; struct rb_node **link = &rii->tn_root.rb_node; - struct jffs2_tmp_dnode_info *insert_point; + struct jffs2_tmp_dnode_info *insert_point = NULL; while (*link) { parent = *link; @@ -343,7 +339,6 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, rb_insert_color(&tn->rb, &rii->tn_root); } - calc_overlaps: /* If there's anything behind that overlaps us, note it */ this = tn_prev(tn); if (this) { -- cgit v1.2.3