aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/readinode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2/readinode.c')
-rw-r--r--fs/jffs2/readinode.c78
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",