Commit fcf3cafb authored by David Woodhouse's avatar David Woodhouse

[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: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent 96dd8d25
...@@ -221,7 +221,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *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; uint32_t fn_end = tn->fn->ofs + tn->fn->size;
struct jffs2_tmp_dnode_info *this; 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 /* 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. 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, ...@@ -271,11 +271,11 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
return 0; return 0;
} else { } else {
/* Who cares if the new one is good; keep it for now anyway. */ /* 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); rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
/* Same overlapping from in front and behind */
jffs2_kill_tn(c, this); jffs2_kill_tn(c, this);
dbg_readinode("Like new node. Throw away old\n"); /* Same overlapping from in front and behind */
goto calc_overlaps; return 0;
} }
} }
if (this->version < tn->version && if (this->version < tn->version &&
...@@ -287,11 +287,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, ...@@ -287,11 +287,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
jffs2_kill_tn(c, tn); jffs2_kill_tn(c, tn);
return 0; return 0;
} }
/* ... and is good. Kill 'this'... */ /* ... and is good. Kill 'this' and any subsequent nodes which are also overlapped */
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);
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); struct jffs2_tmp_dnode_info *next = tn_next(this);
if (this->version < tn->version) { if (this->version < tn->version) {
...@@ -303,8 +299,8 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, ...@@ -303,8 +299,8 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
} }
this = next; this = next;
} }
dbg_readinode("Done inserting new\n"); dbg_readinode("Done killing overlapped nodes\n");
goto calc_overlaps; break;
} }
if (this->version > tn->version && if (this->version > tn->version &&
this->fn->ofs <= tn->fn->ofs && this->fn->ofs <= tn->fn->ofs &&
...@@ -316,11 +312,10 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, ...@@ -316,11 +312,10 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
return 0; return 0;
} }
/* ... but 'this' was bad. Replace it... */ /* ... 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"); dbg_readinode("Bad CRC on old overlapping node. Kill it\n");
tn_erase(this, &rii->tn_root);
jffs2_kill_tn(c, this); jffs2_kill_tn(c, this);
return 0; break;
} }
this = tn_next(this); this = tn_next(this);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment