diff options
| author | David Woodhouse <dwmw2@infradead.org> | 2007-05-05 11:29:34 -0400 |
|---|---|---|
| committer | David Woodhouse <dwmw2@infradead.org> | 2007-05-05 11:29:34 -0400 |
| commit | 1123e2a85941c7f506bd42c91c7e9ab74fc42d79 (patch) | |
| tree | dd8474b7d3a00442178b18baf62c09642d306845 | |
| parent | 3fddb6c985e3823c991399840d2d5ef5940e1b60 (diff) | |
[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 <dwmw2@infradead.org>
| -rw-r--r-- | fs/jffs2/readinode.c | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 6aff38930b50..b0645ac7769a 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, | |||
| 276 | /* Who cares if the new one is good; keep it for now anyway. */ | 276 | /* Who cares if the new one is good; keep it for now anyway. */ |
| 277 | rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); | 277 | rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); |
| 278 | /* Same overlapping from in front and behind */ | 278 | /* Same overlapping from in front and behind */ |
| 279 | tn->overlapped = this->overlapped; | ||
| 280 | jffs2_kill_tn(c, this); | 279 | jffs2_kill_tn(c, this); |
| 281 | dbg_readinode("Like new node. Throw away old\n"); | 280 | dbg_readinode("Like new node. Throw away old\n"); |
| 282 | return 0; | 281 | goto calc_overlaps; |
| 283 | } | 282 | } |
| 284 | } | 283 | } |
| 285 | if (this->version < tn->version && | 284 | if (this->version < tn->version && |
| @@ -293,7 +292,6 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
| 293 | } | 292 | } |
| 294 | /* ... and is good. Kill 'this'... */ | 293 | /* ... and is good. Kill 'this'... */ |
| 295 | rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); | 294 | rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); |
| 296 | tn->overlapped = this->overlapped; | ||
| 297 | jffs2_kill_tn(c, this); | 295 | jffs2_kill_tn(c, this); |
| 298 | /* ... and any subsequent nodes which are also overlapped */ | 296 | /* ... and any subsequent nodes which are also overlapped */ |
| 299 | this = tn_next(tn); | 297 | this = tn_next(tn); |
| @@ -309,7 +307,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
| 309 | this = next; | 307 | this = next; |
| 310 | } | 308 | } |
| 311 | dbg_readinode("Done inserting new\n"); | 309 | dbg_readinode("Done inserting new\n"); |
| 312 | return 0; | 310 | goto calc_overlaps; |
| 313 | } | 311 | } |
| 314 | if (this->version > tn->version && | 312 | if (this->version > tn->version && |
| 315 | this->fn->ofs <= tn->fn->ofs && | 313 | this->fn->ofs <= tn->fn->ofs && |
| @@ -321,6 +319,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
| 321 | return 0; | 319 | return 0; |
| 322 | } | 320 | } |
| 323 | /* ... but 'this' was bad. Replace it... */ | 321 | /* ... but 'this' was bad. Replace it... */ |
| 322 | tn->overlapped = this->overlapped; | ||
| 324 | rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); | 323 | rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); |
| 325 | dbg_readinode("Bad CRC on old overlapping node. Kill it\n"); | 324 | dbg_readinode("Bad CRC on old overlapping node. Kill it\n"); |
| 326 | jffs2_kill_tn(c, this); | 325 | jffs2_kill_tn(c, this); |
| @@ -359,6 +358,8 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
| 359 | rb_link_node(&tn->rb, &insert_point->rb, link); | 358 | rb_link_node(&tn->rb, &insert_point->rb, link); |
| 360 | rb_insert_color(&tn->rb, &rii->tn_root); | 359 | rb_insert_color(&tn->rb, &rii->tn_root); |
| 361 | } | 360 | } |
| 361 | |||
| 362 | calc_overlaps: | ||
| 362 | /* If there's anything behind that overlaps us, note it */ | 363 | /* If there's anything behind that overlaps us, note it */ |
| 363 | this = tn_prev(tn); | 364 | this = tn_prev(tn); |
| 364 | if (this) { | 365 | if (this) { |
| @@ -483,7 +484,7 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c, | |||
| 483 | vers_next = tn_prev(this); | 484 | vers_next = tn_prev(this); |
| 484 | eat_last(&ver_root, &this->rb); | 485 | eat_last(&ver_root, &this->rb); |
| 485 | if (check_tn_node(c, this)) { | 486 | if (check_tn_node(c, this)) { |
| 486 | dbg_readinode("node ver %x, 0x%x-0x%x failed CRC\n", | 487 | dbg_readinode("node ver %d, 0x%x-0x%x failed CRC\n", |
| 487 | this->version, this->fn->ofs, | 488 | this->version, this->fn->ofs, |
| 488 | this->fn->ofs+this->fn->size); | 489 | this->fn->ofs+this->fn->size); |
| 489 | jffs2_kill_tn(c, this); | 490 | jffs2_kill_tn(c, this); |
| @@ -496,7 +497,7 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c, | |||
| 496 | high_ver = this->version; | 497 | high_ver = this->version; |
| 497 | rii->latest_ref = this->fn->raw; | 498 | rii->latest_ref = this->fn->raw; |
| 498 | } | 499 | } |
| 499 | dbg_readinode("Add %p (v %x, 0x%x-0x%x, ov %d) to fragtree\n", | 500 | dbg_readinode("Add %p (v %d, 0x%x-0x%x, ov %d) to fragtree\n", |
| 500 | this, this->version, this->fn->ofs, | 501 | this, this->version, this->fn->ofs, |
| 501 | this->fn->ofs+this->fn->size, this->overlapped); | 502 | this->fn->ofs+this->fn->size, this->overlapped); |
| 502 | 503 | ||
| @@ -850,7 +851,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
| 850 | return ret; | 851 | return ret; |
| 851 | } | 852 | } |
| 852 | #ifdef JFFS2_DBG_READINODE_MESSAGES | 853 | #ifdef JFFS2_DBG_READINODE_MESSAGES |
| 853 | dbg_readinode("After adding ver %d:\n", tn->version); | 854 | dbg_readinode("After adding ver %d:\n", je32_to_cpu(rd->version)); |
| 854 | tn = tn_first(&rii->tn_root); | 855 | tn = tn_first(&rii->tn_root); |
| 855 | while (tn) { | 856 | while (tn) { |
| 856 | dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n", | 857 | dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n", |
