aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2007-05-07 08:16:13 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2007-05-07 08:16:13 -0400
commitfcf3cafb3e7e7750f4876571492594c3a4854ee5 (patch)
tree803c98c2335c7fbb336cfca805ee500b6eae0b69
parent96dd8d25d1ca8c233bd47752349d27a631c18719 (diff)
[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 <dwmw2@infradead.org>
-rw-r--r--fs/jffs2/readinode.c23
1 files changed, 9 insertions, 14 deletions
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index f461604cf01f..bd31d4956c6d 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,
221 uint32_t fn_end = tn->fn->ofs + tn->fn->size; 221 uint32_t fn_end = tn->fn->ofs + tn->fn->size;
222 struct jffs2_tmp_dnode_info *this; 222 struct jffs2_tmp_dnode_info *this;
223 223
224 dbg_readinode("insert fragment %#04x-%#04x, ver %u\n", tn->fn->ofs, fn_end, tn->version); 224 dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw));
225 225
226 /* If a node has zero dsize, we only have to keep if it if it might be the 226 /* If a node has zero dsize, we only have to keep if it if it might be the
227 node with highest version -- i.e. the one which will end up as f->metadata. 227 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 return 0; 271 return 0;
272 } else { 272 } else {
273 /* Who cares if the new one is good; keep it for now anyway. */ 273 /* Who cares if the new one is good; keep it for now anyway. */
274 dbg_readinode("Like new node. Throw away old\n");
274 rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); 275 rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
275 /* Same overlapping from in front and behind */
276 jffs2_kill_tn(c, this); 276 jffs2_kill_tn(c, this);
277 dbg_readinode("Like new node. Throw away old\n"); 277 /* Same overlapping from in front and behind */
278 goto calc_overlaps; 278 return 0;
279 } 279 }
280 } 280 }
281 if (this->version < tn->version && 281 if (this->version < tn->version &&
@@ -287,11 +287,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
287 jffs2_kill_tn(c, tn); 287 jffs2_kill_tn(c, tn);
288 return 0; 288 return 0;
289 } 289 }
290 /* ... and is good. Kill 'this'... */ 290 /* ... and is good. Kill 'this' and any subsequent nodes which are also overlapped */
291 rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
292 jffs2_kill_tn(c, this);
293 /* ... and any subsequent nodes which are also overlapped */
294 this = tn_next(tn);
295 while (this && this->fn->ofs + this->fn->size < fn_end) { 291 while (this && this->fn->ofs + this->fn->size < fn_end) {
296 struct jffs2_tmp_dnode_info *next = tn_next(this); 292 struct jffs2_tmp_dnode_info *next = tn_next(this);
297 if (this->version < tn->version) { 293 if (this->version < tn->version) {
@@ -303,8 +299,8 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
303 } 299 }
304 this = next; 300 this = next;
305 } 301 }
306 dbg_readinode("Done inserting new\n"); 302 dbg_readinode("Done killing overlapped nodes\n");
307 goto calc_overlaps; 303 break;
308 } 304 }
309 if (this->version > tn->version && 305 if (this->version > tn->version &&
310 this->fn->ofs <= tn->fn->ofs && 306 this->fn->ofs <= tn->fn->ofs &&
@@ -316,11 +312,10 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
316 return 0; 312 return 0;
317 } 313 }
318 /* ... but 'this' was bad. Replace it... */ 314 /* ... but 'this' was bad. Replace it... */
319 tn->overlapped = this->overlapped;
320 rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
321 dbg_readinode("Bad CRC on old overlapping node. Kill it\n"); 315 dbg_readinode("Bad CRC on old overlapping node. Kill it\n");
316 tn_erase(this, &rii->tn_root);
322 jffs2_kill_tn(c, this); 317 jffs2_kill_tn(c, this);
323 return 0; 318 break;
324 } 319 }
325 320
326 this = tn_next(this); 321 this = tn_next(this);