diff options
Diffstat (limited to 'fs/jffs2/readinode.c')
-rw-r--r-- | fs/jffs2/readinode.c | 78 |
1 files changed, 29 insertions, 49 deletions
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 6aff38930b50..4884d5edfe65 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c | |||
@@ -219,9 +219,9 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
219 | struct jffs2_tmp_dnode_info *tn) | 219 | struct jffs2_tmp_dnode_info *tn) |
220 | { | 220 | { |
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 *insert_point = NULL, *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. |
@@ -240,23 +240,16 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
240 | 240 | ||
241 | /* Find the earliest node which _may_ be relevant to this one */ | 241 | /* Find the earliest node which _may_ be relevant to this one */ |
242 | this = jffs2_lookup_tn(&rii->tn_root, tn->fn->ofs); | 242 | this = jffs2_lookup_tn(&rii->tn_root, tn->fn->ofs); |
243 | if (!this) { | 243 | if (this) { |
244 | /* First addition to empty tree. $DEITY how I love the easy cases */ | 244 | /* If the node is coincident with another at a lower address, |
245 | rb_link_node(&tn->rb, NULL, &rii->tn_root.rb_node); | 245 | back up until the other node is found. It may be relevant */ |
246 | rb_insert_color(&tn->rb, &rii->tn_root); | 246 | while (this->overlapped) |
247 | dbg_readinode("keep new frag\n"); | 247 | this = tn_prev(this); |
248 | return 0; | ||
249 | } | ||
250 | |||
251 | /* If we add a new node it'll be somewhere under here. */ | ||
252 | insert_point = this; | ||
253 | |||
254 | /* If the node is coincident with another at a lower address, | ||
255 | back up until the other node is found. It may be relevant */ | ||
256 | while (tn->overlapped) | ||
257 | tn = tn_prev(tn); | ||
258 | 248 | ||
259 | dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole"); | 249 | /* First node should never be marked overlapped */ |
250 | BUG_ON(!this); | ||
251 | dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole"); | ||
252 | } | ||
260 | 253 | ||
261 | while (this) { | 254 | while (this) { |
262 | if (this->fn->ofs > fn_end) | 255 | if (this->fn->ofs > fn_end) |
@@ -274,11 +267,10 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
274 | return 0; | 267 | return 0; |
275 | } else { | 268 | } else { |
276 | /* Who cares if the new one is good; keep it for now anyway. */ | 269 | /* Who cares if the new one is good; keep it for now anyway. */ |
270 | dbg_readinode("Like new node. Throw away old\n"); | ||
277 | rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); | 271 | rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); |
278 | /* Same overlapping from in front and behind */ | ||
279 | tn->overlapped = this->overlapped; | ||
280 | jffs2_kill_tn(c, this); | 272 | jffs2_kill_tn(c, this); |
281 | dbg_readinode("Like new node. Throw away old\n"); | 273 | /* Same overlapping from in front and behind */ |
282 | return 0; | 274 | return 0; |
283 | } | 275 | } |
284 | } | 276 | } |
@@ -291,13 +283,8 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
291 | jffs2_kill_tn(c, tn); | 283 | jffs2_kill_tn(c, tn); |
292 | return 0; | 284 | return 0; |
293 | } | 285 | } |
294 | /* ... and is good. Kill 'this'... */ | 286 | /* ... and is good. Kill 'this' and any subsequent nodes which are also overlapped */ |
295 | rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); | 287 | while (this && this->fn->ofs + this->fn->size <= fn_end) { |
296 | tn->overlapped = this->overlapped; | ||
297 | jffs2_kill_tn(c, this); | ||
298 | /* ... and any subsequent nodes which are also overlapped */ | ||
299 | this = tn_next(tn); | ||
300 | while (this && this->fn->ofs + this->fn->size < fn_end) { | ||
301 | struct jffs2_tmp_dnode_info *next = tn_next(this); | 288 | struct jffs2_tmp_dnode_info *next = tn_next(this); |
302 | if (this->version < tn->version) { | 289 | if (this->version < tn->version) { |
303 | tn_erase(this, &rii->tn_root); | 290 | tn_erase(this, &rii->tn_root); |
@@ -308,8 +295,8 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
308 | } | 295 | } |
309 | this = next; | 296 | this = next; |
310 | } | 297 | } |
311 | dbg_readinode("Done inserting new\n"); | 298 | dbg_readinode("Done killing overlapped nodes\n"); |
312 | return 0; | 299 | continue; |
313 | } | 300 | } |
314 | if (this->version > tn->version && | 301 | if (this->version > tn->version && |
315 | this->fn->ofs <= tn->fn->ofs && | 302 | this->fn->ofs <= tn->fn->ofs && |
@@ -321,29 +308,21 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
321 | return 0; | 308 | return 0; |
322 | } | 309 | } |
323 | /* ... but 'this' was bad. Replace it... */ | 310 | /* ... but 'this' was bad. Replace it... */ |
324 | rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); | ||
325 | dbg_readinode("Bad CRC on old overlapping node. Kill it\n"); | 311 | dbg_readinode("Bad CRC on old overlapping node. Kill it\n"); |
312 | tn_erase(this, &rii->tn_root); | ||
326 | jffs2_kill_tn(c, this); | 313 | jffs2_kill_tn(c, this); |
327 | return 0; | 314 | break; |
328 | } | 315 | } |
329 | /* We want to be inserted under the last node which is | ||
330 | either at a lower offset _or_ has a smaller range */ | ||
331 | if (this->fn->ofs < tn->fn->ofs || | ||
332 | (this->fn->ofs == tn->fn->ofs && | ||
333 | this->fn->size <= tn->fn->size)) | ||
334 | insert_point = this; | ||
335 | 316 | ||
336 | this = tn_next(this); | 317 | this = tn_next(this); |
337 | } | 318 | } |
338 | dbg_readinode("insert_point %p, ver %d, 0x%x-0x%x, ov %d\n", | 319 | |
339 | insert_point, insert_point->version, insert_point->fn->ofs, | ||
340 | insert_point->fn->ofs+insert_point->fn->size, | ||
341 | insert_point->overlapped); | ||
342 | /* We neither completely obsoleted nor were completely | 320 | /* We neither completely obsoleted nor were completely |
343 | obsoleted by an earlier node. Insert under insert_point */ | 321 | obsoleted by an earlier node. Insert into the tree */ |
344 | { | 322 | { |
345 | struct rb_node *parent = &insert_point->rb; | 323 | struct rb_node *parent; |
346 | struct rb_node **link = &parent; | 324 | struct rb_node **link = &rii->tn_root.rb_node; |
325 | struct jffs2_tmp_dnode_info *insert_point = NULL; | ||
347 | 326 | ||
348 | while (*link) { | 327 | while (*link) { |
349 | parent = *link; | 328 | parent = *link; |
@@ -359,6 +338,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
359 | rb_link_node(&tn->rb, &insert_point->rb, link); | 338 | rb_link_node(&tn->rb, &insert_point->rb, link); |
360 | rb_insert_color(&tn->rb, &rii->tn_root); | 339 | rb_insert_color(&tn->rb, &rii->tn_root); |
361 | } | 340 | } |
341 | |||
362 | /* If there's anything behind that overlaps us, note it */ | 342 | /* If there's anything behind that overlaps us, note it */ |
363 | this = tn_prev(tn); | 343 | this = tn_prev(tn); |
364 | if (this) { | 344 | if (this) { |
@@ -457,7 +437,7 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c, | |||
457 | this = tn_last(&rii->tn_root); | 437 | this = tn_last(&rii->tn_root); |
458 | while (this) { | 438 | while (this) { |
459 | dbg_readinode("tn %p ver %d range 0x%x-0x%x ov %d\n", this, this->version, this->fn->ofs, | 439 | dbg_readinode("tn %p ver %d range 0x%x-0x%x ov %d\n", this, this->version, this->fn->ofs, |
460 | this->fn->ofs+this->fn->size, this->overlapped); | 440 | this->fn->ofs+this->fn->size, this->overlapped); |
461 | this = tn_prev(this); | 441 | this = tn_prev(this); |
462 | } | 442 | } |
463 | #endif | 443 | #endif |
@@ -483,7 +463,7 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c, | |||
483 | vers_next = tn_prev(this); | 463 | vers_next = tn_prev(this); |
484 | eat_last(&ver_root, &this->rb); | 464 | eat_last(&ver_root, &this->rb); |
485 | if (check_tn_node(c, this)) { | 465 | if (check_tn_node(c, this)) { |
486 | dbg_readinode("node ver %x, 0x%x-0x%x failed CRC\n", | 466 | dbg_readinode("node ver %d, 0x%x-0x%x failed CRC\n", |
487 | this->version, this->fn->ofs, | 467 | this->version, this->fn->ofs, |
488 | this->fn->ofs+this->fn->size); | 468 | this->fn->ofs+this->fn->size); |
489 | jffs2_kill_tn(c, this); | 469 | jffs2_kill_tn(c, this); |
@@ -496,7 +476,7 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c, | |||
496 | high_ver = this->version; | 476 | high_ver = this->version; |
497 | rii->latest_ref = this->fn->raw; | 477 | rii->latest_ref = this->fn->raw; |
498 | } | 478 | } |
499 | dbg_readinode("Add %p (v %x, 0x%x-0x%x, ov %d) to fragtree\n", | 479 | dbg_readinode("Add %p (v %d, 0x%x-0x%x, ov %d) to fragtree\n", |
500 | this, this->version, this->fn->ofs, | 480 | this, this->version, this->fn->ofs, |
501 | this->fn->ofs+this->fn->size, this->overlapped); | 481 | this->fn->ofs+this->fn->size, this->overlapped); |
502 | 482 | ||
@@ -850,7 +830,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
850 | return ret; | 830 | return ret; |
851 | } | 831 | } |
852 | #ifdef JFFS2_DBG_READINODE_MESSAGES | 832 | #ifdef JFFS2_DBG_READINODE_MESSAGES |
853 | dbg_readinode("After adding ver %d:\n", tn->version); | 833 | dbg_readinode("After adding ver %d:\n", je32_to_cpu(rd->version)); |
854 | tn = tn_first(&rii->tn_root); | 834 | tn = tn_first(&rii->tn_root); |
855 | while (tn) { | 835 | while (tn) { |
856 | dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n", | 836 | dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n", |