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.c137
1 files changed, 83 insertions, 54 deletions
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index f1695642d0f7..5fec012b02ed 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -66,7 +66,7 @@ static void jffs2_free_tmp_dnode_info_list(struct rb_root *list)
66 jffs2_free_full_dnode(tn->fn); 66 jffs2_free_full_dnode(tn->fn);
67 jffs2_free_tmp_dnode_info(tn); 67 jffs2_free_tmp_dnode_info(tn);
68 68
69 this = this->rb_parent; 69 this = rb_parent(this);
70 if (!this) 70 if (!this)
71 break; 71 break;
72 72
@@ -116,19 +116,42 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
116 uint32_t *latest_mctime, uint32_t *mctime_ver) 116 uint32_t *latest_mctime, uint32_t *mctime_ver)
117{ 117{
118 struct jffs2_full_dirent *fd; 118 struct jffs2_full_dirent *fd;
119 uint32_t crc;
119 120
120 /* The direntry nodes are checked during the flash scanning */
121 BUG_ON(ref_flags(ref) == REF_UNCHECKED);
122 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ 121 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
123 BUG_ON(ref_obsolete(ref)); 122 BUG_ON(ref_obsolete(ref));
124 123
125 /* Sanity check */ 124 crc = crc32(0, rd, sizeof(*rd) - 8);
126 if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { 125 if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
127 JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", 126 JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n",
128 ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); 127 ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
129 return 1; 128 return 1;
130 } 129 }
131 130
131 /* If we've never checked the CRCs on this node, check them now */
132 if (ref_flags(ref) == REF_UNCHECKED) {
133 struct jffs2_eraseblock *jeb;
134 int len;
135
136 /* Sanity check */
137 if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
138 JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
139 ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
140 return 1;
141 }
142
143 jeb = &c->blocks[ref->flash_offset / c->sector_size];
144 len = ref_totlen(c, jeb, ref);
145
146 spin_lock(&c->erase_completion_lock);
147 jeb->used_size += len;
148 jeb->unchecked_size -= len;
149 c->used_size += len;
150 c->unchecked_size -= len;
151 ref->flash_offset = ref_offset(ref) | REF_PRISTINE;
152 spin_unlock(&c->erase_completion_lock);
153 }
154
132 fd = jffs2_alloc_full_dirent(rd->nsize + 1); 155 fd = jffs2_alloc_full_dirent(rd->nsize + 1);
133 if (unlikely(!fd)) 156 if (unlikely(!fd))
134 return -ENOMEM; 157 return -ENOMEM;
@@ -198,13 +221,21 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
198 struct jffs2_tmp_dnode_info *tn; 221 struct jffs2_tmp_dnode_info *tn;
199 uint32_t len, csize; 222 uint32_t len, csize;
200 int ret = 1; 223 int ret = 1;
224 uint32_t crc;
201 225
202 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ 226 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
203 BUG_ON(ref_obsolete(ref)); 227 BUG_ON(ref_obsolete(ref));
204 228
229 crc = crc32(0, rd, sizeof(*rd) - 8);
230 if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
231 JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n",
232 ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
233 return 1;
234 }
235
205 tn = jffs2_alloc_tmp_dnode_info(); 236 tn = jffs2_alloc_tmp_dnode_info();
206 if (!tn) { 237 if (!tn) {
207 JFFS2_ERROR("failed to allocate tn (%d bytes).\n", sizeof(*tn)); 238 JFFS2_ERROR("failed to allocate tn (%zu bytes).\n", sizeof(*tn));
208 return -ENOMEM; 239 return -ENOMEM;
209 } 240 }
210 241
@@ -213,14 +244,6 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
213 244
214 /* If we've never checked the CRCs on this node, check them now */ 245 /* If we've never checked the CRCs on this node, check them now */
215 if (ref_flags(ref) == REF_UNCHECKED) { 246 if (ref_flags(ref) == REF_UNCHECKED) {
216 uint32_t crc;
217
218 crc = crc32(0, rd, sizeof(*rd) - 8);
219 if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
220 JFFS2_NOTICE("header CRC failed on node at %#08x: read %#08x, calculated %#08x\n",
221 ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
222 goto free_out;
223 }
224 247
225 /* Sanity checks */ 248 /* Sanity checks */
226 if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || 249 if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
@@ -343,7 +366,7 @@ free_out:
343 * Helper function for jffs2_get_inode_nodes(). 366 * Helper function for jffs2_get_inode_nodes().
344 * It is called every time an unknown node is found. 367 * It is called every time an unknown node is found.
345 * 368 *
346 * Returns: 0 on succes; 369 * Returns: 0 on success;
347 * 1 if the node should be marked obsolete; 370 * 1 if the node should be marked obsolete;
348 * negative error code on failure. 371 * negative error code on failure.
349 */ 372 */
@@ -354,37 +377,30 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re
354 377
355 un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); 378 un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
356 379
357 if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) { 380 switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
358 /* Hmmm. This should have been caught at scan time. */
359 JFFS2_NOTICE("node header CRC failed at %#08x. But it must have been OK earlier.\n", ref_offset(ref));
360 jffs2_dbg_dump_node(c, ref_offset(ref));
361 return 1;
362 } else {
363 switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
364 381
365 case JFFS2_FEATURE_INCOMPAT: 382 case JFFS2_FEATURE_INCOMPAT:
366 JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n", 383 JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
367 je16_to_cpu(un->nodetype), ref_offset(ref)); 384 je16_to_cpu(un->nodetype), ref_offset(ref));
368 /* EEP */ 385 /* EEP */
369 BUG(); 386 BUG();
370 break; 387 break;
371 388
372 case JFFS2_FEATURE_ROCOMPAT: 389 case JFFS2_FEATURE_ROCOMPAT:
373 JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n", 390 JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
374 je16_to_cpu(un->nodetype), ref_offset(ref)); 391 je16_to_cpu(un->nodetype), ref_offset(ref));
375 BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO)); 392 BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
376 break; 393 break;
377 394
378 case JFFS2_FEATURE_RWCOMPAT_COPY: 395 case JFFS2_FEATURE_RWCOMPAT_COPY:
379 JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n", 396 JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
380 je16_to_cpu(un->nodetype), ref_offset(ref)); 397 je16_to_cpu(un->nodetype), ref_offset(ref));
381 break; 398 break;
382 399
383 case JFFS2_FEATURE_RWCOMPAT_DELETE: 400 case JFFS2_FEATURE_RWCOMPAT_DELETE:
384 JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", 401 JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
385 je16_to_cpu(un->nodetype), ref_offset(ref)); 402 je16_to_cpu(un->nodetype), ref_offset(ref));
386 return 1; 403 return 1;
387 }
388 } 404 }
389 405
390 return 0; 406 return 0;
@@ -434,7 +450,7 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
434 } 450 }
435 451
436 if (retlen < len) { 452 if (retlen < len) {
437 JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", 453 JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n",
438 offs, retlen, len); 454 offs, retlen, len);
439 return -EIO; 455 return -EIO;
440 } 456 }
@@ -542,13 +558,25 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
542 } 558 }
543 559
544 if (retlen < len) { 560 if (retlen < len) {
545 JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ref_offset(ref), retlen, len); 561 JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", ref_offset(ref), retlen, len);
546 err = -EIO; 562 err = -EIO;
547 goto free_out; 563 goto free_out;
548 } 564 }
549 565
550 node = (union jffs2_node_union *)bufstart; 566 node = (union jffs2_node_union *)bufstart;
551 567
568 /* No need to mask in the valid bit; it shouldn't be invalid */
569 if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) {
570 JFFS2_NOTICE("Node header CRC failed at %#08x. {%04x,%04x,%08x,%08x}\n",
571 ref_offset(ref), je16_to_cpu(node->u.magic),
572 je16_to_cpu(node->u.nodetype),
573 je32_to_cpu(node->u.totlen),
574 je32_to_cpu(node->u.hdr_crc));
575 jffs2_dbg_dump_node(c, ref_offset(ref));
576 jffs2_mark_node_obsolete(c, ref);
577 goto cont;
578 }
579
552 switch (je16_to_cpu(node->u.nodetype)) { 580 switch (je16_to_cpu(node->u.nodetype)) {
553 581
554 case JFFS2_NODETYPE_DIRENT: 582 case JFFS2_NODETYPE_DIRENT:
@@ -606,6 +634,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
606 goto free_out; 634 goto free_out;
607 635
608 } 636 }
637 cont:
609 spin_lock(&c->erase_completion_lock); 638 spin_lock(&c->erase_completion_lock);
610 } 639 }
611 640
@@ -679,12 +708,12 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
679 jffs2_mark_node_obsolete(c, fn->raw); 708 jffs2_mark_node_obsolete(c, fn->raw);
680 709
681 BUG_ON(rb->rb_left); 710 BUG_ON(rb->rb_left);
682 if (rb->rb_parent && rb->rb_parent->rb_left == rb) { 711 if (rb_parent(rb) && rb_parent(rb)->rb_left == rb) {
683 /* We were then left-hand child of our parent. We need 712 /* We were then left-hand child of our parent. We need
684 * to move our own right-hand child into our place. */ 713 * to move our own right-hand child into our place. */
685 repl_rb = rb->rb_right; 714 repl_rb = rb->rb_right;
686 if (repl_rb) 715 if (repl_rb)
687 repl_rb->rb_parent = rb->rb_parent; 716 rb_set_parent(repl_rb, rb_parent(rb));
688 } else 717 } else
689 repl_rb = NULL; 718 repl_rb = NULL;
690 719
@@ -692,14 +721,14 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
692 721
693 /* Remove the spent tn from the tree; don't bother rebalancing 722 /* Remove the spent tn from the tree; don't bother rebalancing
694 * but put our right-hand child in our own place. */ 723 * but put our right-hand child in our own place. */
695 if (tn->rb.rb_parent) { 724 if (rb_parent(&tn->rb)) {
696 if (tn->rb.rb_parent->rb_left == &tn->rb) 725 if (rb_parent(&tn->rb)->rb_left == &tn->rb)
697 tn->rb.rb_parent->rb_left = repl_rb; 726 rb_parent(&tn->rb)->rb_left = repl_rb;
698 else if (tn->rb.rb_parent->rb_right == &tn->rb) 727 else if (rb_parent(&tn->rb)->rb_right == &tn->rb)
699 tn->rb.rb_parent->rb_right = repl_rb; 728 rb_parent(&tn->rb)->rb_right = repl_rb;
700 else BUG(); 729 else BUG();
701 } else if (tn->rb.rb_right) 730 } else if (tn->rb.rb_right)
702 tn->rb.rb_right->rb_parent = NULL; 731 rb_set_parent(tn->rb.rb_right, NULL);
703 732
704 jffs2_free_tmp_dnode_info(tn); 733 jffs2_free_tmp_dnode_info(tn);
705 if (ret) { 734 if (ret) {