diff options
| author | David Woodhouse <dwmw2@infradead.org> | 2006-05-23 21:04:45 -0400 |
|---|---|---|
| committer | David Woodhouse <dwmw2@infradead.org> | 2006-05-23 21:04:45 -0400 |
| commit | 2f785402f39b96a077b6e62bf26164bfb8e0c980 (patch) | |
| tree | 3f3a38b484ef2dabda1599d4d8f08b121bd03a76 | |
| parent | 4cbb9b80e171107c6c34116283fe38e5a396c68b (diff) | |
[JFFS2] Reduce visibility of raw_node_ref to upper layers of JFFS2 code.
As the first step towards eliminating the ref->next_phys member and saving
memory by using an _array_ of struct jffs2_raw_node_ref per eraseblock,
stop the write functions from allocating their own refs; have them just
_reserve_ the appropriate number instead. Then jffs2_link_node_ref() can
just fill them in.
Use a linked list of pre-allocated refs in the superblock, for now. Once
we switch to an array, it'll just be a case of extending that array.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
| -rw-r--r-- | fs/jffs2/erase.c | 16 | ||||
| -rw-r--r-- | fs/jffs2/gc.c | 25 | ||||
| -rw-r--r-- | fs/jffs2/jffs2_fs_sb.h | 3 | ||||
| -rw-r--r-- | fs/jffs2/malloc.c | 26 | ||||
| -rw-r--r-- | fs/jffs2/nodelist.c | 51 | ||||
| -rw-r--r-- | fs/jffs2/nodelist.h | 19 | ||||
| -rw-r--r-- | fs/jffs2/nodemgmt.c | 39 | ||||
| -rw-r--r-- | fs/jffs2/scan.c | 77 | ||||
| -rw-r--r-- | fs/jffs2/summary.c | 162 | ||||
| -rw-r--r-- | fs/jffs2/wbuf.c | 26 | ||||
| -rw-r--r-- | fs/jffs2/write.c | 71 | ||||
| -rw-r--r-- | fs/jffs2/xattr.c | 38 |
12 files changed, 204 insertions, 349 deletions
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index 4616fed75730..f939f908b948 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c | |||
| @@ -296,7 +296,7 @@ void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock * | |||
| 296 | jffs2_remove_node_refs_from_ino_list(c, ref, jeb); | 296 | jffs2_remove_node_refs_from_ino_list(c, ref, jeb); |
| 297 | /* else it was a non-inode node or already removed, so don't bother */ | 297 | /* else it was a non-inode node or already removed, so don't bother */ |
| 298 | 298 | ||
| 299 | jffs2_free_raw_node_ref(ref); | 299 | __jffs2_free_raw_node_ref(ref); |
| 300 | } | 300 | } |
| 301 | jeb->last_node = NULL; | 301 | jeb->last_node = NULL; |
| 302 | } | 302 | } |
| @@ -351,7 +351,6 @@ fail: | |||
| 351 | 351 | ||
| 352 | static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) | 352 | static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) |
| 353 | { | 353 | { |
| 354 | struct jffs2_raw_node_ref *marker_ref = NULL; | ||
| 355 | size_t retlen; | 354 | size_t retlen; |
| 356 | int ret; | 355 | int ret; |
| 357 | uint32_t bad_offset; | 356 | uint32_t bad_offset; |
| @@ -384,11 +383,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb | |||
| 384 | .totlen = cpu_to_je32(c->cleanmarker_size) | 383 | .totlen = cpu_to_je32(c->cleanmarker_size) |
| 385 | }; | 384 | }; |
| 386 | 385 | ||
| 387 | marker_ref = jffs2_alloc_raw_node_ref(); | 386 | jffs2_prealloc_raw_node_refs(c, 1); |
| 388 | if (!marker_ref) { | ||
| 389 | printk(KERN_WARNING "Failed to allocate raw node ref for clean marker. Refiling\n"); | ||
| 390 | goto refile; | ||
| 391 | } | ||
| 392 | 387 | ||
| 393 | marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4)); | 388 | marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4)); |
| 394 | 389 | ||
| @@ -404,16 +399,13 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb | |||
| 404 | printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n", | 399 | printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n", |
| 405 | jeb->offset, sizeof(marker), retlen); | 400 | jeb->offset, sizeof(marker), retlen); |
| 406 | 401 | ||
| 407 | jffs2_free_raw_node_ref(marker_ref); | ||
| 408 | goto filebad; | 402 | goto filebad; |
| 409 | } | 403 | } |
| 410 | 404 | ||
| 411 | /* Everything else got zeroed before the erase */ | 405 | /* Everything else got zeroed before the erase */ |
| 412 | jeb->free_size = c->sector_size; | 406 | jeb->free_size = c->sector_size; |
| 413 | 407 | /* FIXME Special case for cleanmarker in empty block */ | |
| 414 | marker_ref->flash_offset = jeb->offset | REF_NORMAL; | 408 | jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL); |
| 415 | |||
| 416 | jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size, NULL); | ||
| 417 | } | 409 | } |
| 418 | 410 | ||
| 419 | spin_lock(&c->erase_completion_lock); | 411 | spin_lock(&c->erase_completion_lock); |
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index f9e982a65ac2..a22ff5df7fcc 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c | |||
| @@ -528,7 +528,6 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, | |||
| 528 | struct jffs2_raw_node_ref *raw) | 528 | struct jffs2_raw_node_ref *raw) |
| 529 | { | 529 | { |
| 530 | union jffs2_node_union *node; | 530 | union jffs2_node_union *node; |
| 531 | struct jffs2_raw_node_ref *nraw; | ||
| 532 | size_t retlen; | 531 | size_t retlen; |
| 533 | int ret; | 532 | int ret; |
| 534 | uint32_t phys_ofs, alloclen; | 533 | uint32_t phys_ofs, alloclen; |
| @@ -618,30 +617,21 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, | |||
| 618 | } | 617 | } |
| 619 | } | 618 | } |
| 620 | 619 | ||
| 621 | nraw = jffs2_alloc_raw_node_ref(); | ||
| 622 | if (!nraw) { | ||
| 623 | ret = -ENOMEM; | ||
| 624 | goto out_node; | ||
| 625 | } | ||
| 626 | |||
| 627 | /* OK, all the CRCs are good; this node can just be copied as-is. */ | 620 | /* OK, all the CRCs are good; this node can just be copied as-is. */ |
| 628 | retry: | 621 | retry: |
| 629 | nraw->flash_offset = phys_ofs = write_ofs(c); | 622 | phys_ofs = write_ofs(c); |
| 630 | 623 | ||
| 631 | ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node); | 624 | ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node); |
| 632 | 625 | ||
| 633 | if (ret || (retlen != rawlen)) { | 626 | if (ret || (retlen != rawlen)) { |
| 634 | printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n", | 627 | printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n", |
| 635 | rawlen, nraw->flash_offset, ret, retlen); | 628 | rawlen, phys_ofs, ret, retlen); |
| 636 | if (retlen) { | 629 | if (retlen) { |
| 637 | nraw->flash_offset |= REF_OBSOLETE; | 630 | jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL); |
| 638 | jffs2_add_physical_node_ref(c, nraw, rawlen, NULL); | ||
| 639 | jffs2_mark_node_obsolete(c, nraw); | ||
| 640 | } else { | 631 | } else { |
| 641 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset); | 632 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", phys_ofs); |
| 642 | jffs2_free_raw_node_ref(nraw); | ||
| 643 | } | 633 | } |
| 644 | if (!retried && (nraw = jffs2_alloc_raw_node_ref())) { | 634 | if (!retried) { |
| 645 | /* Try to reallocate space and retry */ | 635 | /* Try to reallocate space and retry */ |
| 646 | uint32_t dummy; | 636 | uint32_t dummy; |
| 647 | struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size]; | 637 | struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size]; |
| @@ -666,16 +656,13 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, | |||
| 666 | goto retry; | 656 | goto retry; |
| 667 | } | 657 | } |
| 668 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); | 658 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); |
| 669 | jffs2_free_raw_node_ref(nraw); | ||
| 670 | } | 659 | } |
| 671 | 660 | ||
| 672 | jffs2_free_raw_node_ref(nraw); | ||
| 673 | if (!ret) | 661 | if (!ret) |
| 674 | ret = -EIO; | 662 | ret = -EIO; |
| 675 | goto out_node; | 663 | goto out_node; |
| 676 | } | 664 | } |
| 677 | nraw->flash_offset |= REF_PRISTINE; | 665 | jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, rawlen, ic); |
| 678 | jffs2_add_physical_node_ref(c, nraw, rawlen, ic); | ||
| 679 | 666 | ||
| 680 | jffs2_mark_node_obsolete(c, raw); | 667 | jffs2_mark_node_obsolete(c, raw); |
| 681 | D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw))); | 668 | D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw))); |
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index 272fbea55192..67529f0a44dd 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h | |||
| @@ -26,6 +26,9 @@ struct jffs2_inodirty; | |||
| 26 | struct jffs2_sb_info { | 26 | struct jffs2_sb_info { |
| 27 | struct mtd_info *mtd; | 27 | struct mtd_info *mtd; |
| 28 | 28 | ||
| 29 | struct jffs2_raw_node_ref *refs; | ||
| 30 | int reserved_refs; | ||
| 31 | |||
| 29 | uint32_t highest_ino; | 32 | uint32_t highest_ino; |
| 30 | uint32_t checked_ino; | 33 | uint32_t checked_ino; |
| 31 | 34 | ||
diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index f2473fa2fd16..3df3250314a2 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c | |||
| @@ -190,7 +190,29 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x) | |||
| 190 | kmem_cache_free(tmp_dnode_info_slab, x); | 190 | kmem_cache_free(tmp_dnode_info_slab, x); |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) | 193 | int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c, int nr) |
| 194 | { | ||
| 195 | struct jffs2_raw_node_ref *p = c->refs; | ||
| 196 | |||
| 197 | dbg_memalloc("%d\n", nr); | ||
| 198 | |||
| 199 | while (nr && p) { | ||
| 200 | p = p->next_in_ino; | ||
| 201 | nr--; | ||
| 202 | } | ||
| 203 | while (nr) { | ||
| 204 | p = __jffs2_alloc_raw_node_ref(); | ||
| 205 | if (!p) | ||
| 206 | return -ENOMEM; | ||
| 207 | p->next_in_ino = c->refs; | ||
| 208 | c->refs = p; | ||
| 209 | nr--; | ||
| 210 | } | ||
| 211 | c->reserved_refs = nr; | ||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | |||
| 215 | struct jffs2_raw_node_ref *__jffs2_alloc_raw_node_ref(void) | ||
| 194 | { | 216 | { |
| 195 | struct jffs2_raw_node_ref *ret; | 217 | struct jffs2_raw_node_ref *ret; |
| 196 | ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); | 218 | ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); |
| @@ -198,7 +220,7 @@ struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) | |||
| 198 | return ret; | 220 | return ret; |
| 199 | } | 221 | } |
| 200 | 222 | ||
| 201 | void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) | 223 | void __jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) |
| 202 | { | 224 | { |
| 203 | dbg_memalloc("%p\n", x); | 225 | dbg_memalloc("%p\n", x); |
| 204 | kmem_cache_free(raw_node_ref_slab, x); | 226 | kmem_cache_free(raw_node_ref_slab, x); |
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index d25d4919ca97..1e6eabd730f2 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c | |||
| @@ -953,13 +953,19 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c) | |||
| 953 | 953 | ||
| 954 | for (i=0; i<c->nr_blocks; i++) { | 954 | for (i=0; i<c->nr_blocks; i++) { |
| 955 | this = c->blocks[i].first_node; | 955 | this = c->blocks[i].first_node; |
| 956 | while(this) { | 956 | while (this) { |
| 957 | next = this->next_phys; | 957 | next = this->next_phys; |
| 958 | jffs2_free_raw_node_ref(this); | 958 | __jffs2_free_raw_node_ref(this); |
| 959 | this = next; | 959 | this = next; |
| 960 | } | 960 | } |
| 961 | c->blocks[i].first_node = c->blocks[i].last_node = NULL; | 961 | c->blocks[i].first_node = c->blocks[i].last_node = NULL; |
| 962 | } | 962 | } |
| 963 | this = c->refs; | ||
| 964 | while (this) { | ||
| 965 | next = this->next_in_ino; | ||
| 966 | __jffs2_free_raw_node_ref(this); | ||
| 967 | this = next; | ||
| 968 | } | ||
| 963 | } | 969 | } |
| 964 | 970 | ||
| 965 | struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset) | 971 | struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset) |
| @@ -1047,10 +1053,27 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) | |||
| 1047 | } | 1053 | } |
| 1048 | } | 1054 | } |
| 1049 | 1055 | ||
| 1050 | void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 1056 | struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c, |
| 1051 | struct jffs2_raw_node_ref *ref, uint32_t len, | 1057 | struct jffs2_eraseblock *jeb, |
| 1052 | struct jffs2_inode_cache *ic) | 1058 | uint32_t ofs, uint32_t len, |
| 1059 | struct jffs2_inode_cache *ic) | ||
| 1053 | { | 1060 | { |
| 1061 | struct jffs2_raw_node_ref *ref; | ||
| 1062 | |||
| 1063 | /* These will be preallocated _very_ shortly. */ | ||
| 1064 | ref = c->refs; | ||
| 1065 | if (!c->refs) { | ||
| 1066 | JFFS2_WARNING("Using non-preallocated refs!\n"); | ||
| 1067 | ref = __jffs2_alloc_raw_node_ref(); | ||
| 1068 | BUG_ON(!ref); | ||
| 1069 | WARN_ON(1); | ||
| 1070 | } else { | ||
| 1071 | c->refs = ref->next_in_ino; | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | ref->next_phys = NULL; | ||
| 1075 | ref->flash_offset = ofs; | ||
| 1076 | |||
| 1054 | if (!jeb->first_node) | 1077 | if (!jeb->first_node) |
| 1055 | jeb->first_node = ref; | 1078 | jeb->first_node = ref; |
| 1056 | if (jeb->last_node) { | 1079 | if (jeb->last_node) { |
| @@ -1093,15 +1116,15 @@ void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | |||
| 1093 | c->free_size -= len; | 1116 | c->free_size -= len; |
| 1094 | jeb->free_size -= len; | 1117 | jeb->free_size -= len; |
| 1095 | 1118 | ||
| 1096 | ref->next_phys = NULL; | ||
| 1097 | #ifdef TEST_TOTLEN | 1119 | #ifdef TEST_TOTLEN |
| 1098 | /* Set (and test) __totlen field... for now */ | 1120 | /* Set (and test) __totlen field... for now */ |
| 1099 | ref->__totlen = len; | 1121 | ref->__totlen = len; |
| 1100 | ref_totlen(c, jeb, ref); | 1122 | ref_totlen(c, jeb, ref); |
| 1101 | #endif | 1123 | #endif |
| 1124 | return ref; | ||
| 1102 | } | 1125 | } |
| 1103 | 1126 | ||
| 1104 | /* No locking. Do not use on a live file system */ | 1127 | /* No locking, no reservation of 'ref'. Do not use on a live file system */ |
| 1105 | int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 1128 | int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
| 1106 | uint32_t size) | 1129 | uint32_t size) |
| 1107 | { | 1130 | { |
| @@ -1121,18 +1144,10 @@ int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb | |||
| 1121 | jeb->dirty_size += size; | 1144 | jeb->dirty_size += size; |
| 1122 | jeb->free_size -= size; | 1145 | jeb->free_size -= size; |
| 1123 | } else { | 1146 | } else { |
| 1124 | struct jffs2_raw_node_ref *ref; | 1147 | uint32_t ofs = jeb->offset + c->sector_size - jeb->free_size; |
| 1125 | ref = jffs2_alloc_raw_node_ref(); | 1148 | ofs |= REF_OBSOLETE; |
| 1126 | if (!ref) | ||
| 1127 | return -ENOMEM; | ||
| 1128 | |||
| 1129 | ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size; | ||
| 1130 | ref->flash_offset |= REF_OBSOLETE; | ||
| 1131 | #ifdef TEST_TOTLEN | ||
| 1132 | ref->__totlen = size; | ||
| 1133 | #endif | ||
| 1134 | 1149 | ||
| 1135 | jffs2_link_node_ref(c, jeb, ref, size, NULL); | 1150 | jffs2_link_node_ref(c, jeb, ofs, size, NULL); |
| 1136 | } | 1151 | } |
| 1137 | 1152 | ||
| 1138 | return 0; | 1153 | return 0; |
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 76f1b9419eea..7cc74d2ab4dc 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h | |||
| @@ -318,9 +318,10 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t | |||
| 318 | int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); | 318 | int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); |
| 319 | void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); | 319 | void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); |
| 320 | int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); | 320 | int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); |
| 321 | void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 321 | struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c, |
| 322 | struct jffs2_raw_node_ref *ref, uint32_t len, | 322 | struct jffs2_eraseblock *jeb, |
| 323 | struct jffs2_inode_cache *ic); | 323 | uint32_t ofs, uint32_t len, |
| 324 | struct jffs2_inode_cache *ic); | ||
| 324 | extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, | 325 | extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, |
| 325 | struct jffs2_eraseblock *jeb, | 326 | struct jffs2_eraseblock *jeb, |
| 326 | struct jffs2_raw_node_ref *ref); | 327 | struct jffs2_raw_node_ref *ref); |
| @@ -331,10 +332,9 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | |||
| 331 | uint32_t *len, int prio, uint32_t sumsize); | 332 | uint32_t *len, int prio, uint32_t sumsize); |
| 332 | int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, | 333 | int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, |
| 333 | uint32_t *len, uint32_t sumsize); | 334 | uint32_t *len, uint32_t sumsize); |
| 334 | int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, | 335 | struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c, |
| 335 | struct jffs2_raw_node_ref *new, | 336 | uint32_t ofs, uint32_t len, |
| 336 | uint32_t len, | 337 | struct jffs2_inode_cache *ic); |
| 337 | struct jffs2_inode_cache *ic); | ||
| 338 | void jffs2_complete_reservation(struct jffs2_sb_info *c); | 338 | void jffs2_complete_reservation(struct jffs2_sb_info *c); |
| 339 | void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); | 339 | void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); |
| 340 | 340 | ||
| @@ -378,8 +378,9 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void); | |||
| 378 | void jffs2_free_raw_inode(struct jffs2_raw_inode *); | 378 | void jffs2_free_raw_inode(struct jffs2_raw_inode *); |
| 379 | struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void); | 379 | struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void); |
| 380 | void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *); | 380 | void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *); |
| 381 | struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void); | 381 | int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c, int nr); |
| 382 | void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *); | 382 | struct jffs2_raw_node_ref *__jffs2_alloc_raw_node_ref(void); |
| 383 | void __jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *); | ||
| 383 | struct jffs2_node_frag *jffs2_alloc_node_frag(void); | 384 | struct jffs2_node_frag *jffs2_alloc_node_frag(void); |
| 384 | void jffs2_free_node_frag(struct jffs2_node_frag *); | 385 | void jffs2_free_node_frag(struct jffs2_node_frag *); |
| 385 | struct jffs2_inode_cache *jffs2_alloc_inode_cache(void); | 386 | struct jffs2_inode_cache *jffs2_alloc_inode_cache(void); |
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 8feb8749bc75..01bf2773fe4d 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c | |||
| @@ -137,6 +137,8 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | |||
| 137 | } | 137 | } |
| 138 | } | 138 | } |
| 139 | spin_unlock(&c->erase_completion_lock); | 139 | spin_unlock(&c->erase_completion_lock); |
| 140 | if (!ret) | ||
| 141 | ret = jffs2_prealloc_raw_node_refs(c, 1); | ||
| 140 | if (ret) | 142 | if (ret) |
| 141 | up(&c->alloc_sem); | 143 | up(&c->alloc_sem); |
| 142 | return ret; | 144 | return ret; |
| @@ -158,6 +160,9 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, | |||
| 158 | } | 160 | } |
| 159 | } | 161 | } |
| 160 | spin_unlock(&c->erase_completion_lock); | 162 | spin_unlock(&c->erase_completion_lock); |
| 163 | if (!ret) | ||
| 164 | ret = jffs2_prealloc_raw_node_refs(c, 1); | ||
| 165 | |||
| 161 | return ret; | 166 | return ret; |
| 162 | } | 167 | } |
| 163 | 168 | ||
| @@ -381,30 +386,30 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | |||
| 381 | * Must be called with the alloc_sem held. | 386 | * Must be called with the alloc_sem held. |
| 382 | */ | 387 | */ |
| 383 | 388 | ||
| 384 | int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, | 389 | struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c, |
| 385 | uint32_t len, struct jffs2_inode_cache *ic) | 390 | uint32_t ofs, uint32_t len, |
| 391 | struct jffs2_inode_cache *ic) | ||
| 386 | { | 392 | { |
| 387 | struct jffs2_eraseblock *jeb; | 393 | struct jffs2_eraseblock *jeb; |
| 394 | struct jffs2_raw_node_ref *new; | ||
| 388 | 395 | ||
| 389 | jeb = &c->blocks[new->flash_offset / c->sector_size]; | 396 | jeb = &c->blocks[ofs / c->sector_size]; |
| 390 | #ifdef TEST_TOTLEN | ||
| 391 | new->__totlen = len; | ||
| 392 | #endif | ||
| 393 | 397 | ||
| 394 | D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len)); | 398 | D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", |
| 399 | ofs & ~3, ofs & 3, len)); | ||
| 395 | #if 1 | 400 | #if 1 |
| 396 | /* we could get some obsolete nodes after nextblock was refiled | 401 | /* Allow non-obsolete nodes only to be added at the end of c->nextblock, |
| 397 | in wbuf.c */ | 402 | if c->nextblock is set. Note that wbuf.c will file obsolete nodes |
| 398 | if ((c->nextblock || !ref_obsolete(new)) | 403 | even after refiling c->nextblock */ |
| 399 | &&(jeb != c->nextblock || ref_offset(new) != jeb->offset + (c->sector_size - jeb->free_size))) { | 404 | if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE)) |
| 405 | && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) { | ||
| 400 | printk(KERN_WARNING "argh. node added in wrong place\n"); | 406 | printk(KERN_WARNING "argh. node added in wrong place\n"); |
| 401 | jffs2_free_raw_node_ref(new); | 407 | return ERR_PTR(-EINVAL); |
| 402 | return -EINVAL; | ||
| 403 | } | 408 | } |
| 404 | #endif | 409 | #endif |
| 405 | spin_lock(&c->erase_completion_lock); | 410 | spin_lock(&c->erase_completion_lock); |
| 406 | 411 | ||
| 407 | jffs2_link_node_ref(c, jeb, new, len, ic); | 412 | new = jffs2_link_node_ref(c, jeb, ofs, len, ic); |
| 408 | 413 | ||
| 409 | if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) { | 414 | if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) { |
| 410 | /* If it lives on the dirty_list, jffs2_reserve_space will put it there */ | 415 | /* If it lives on the dirty_list, jffs2_reserve_space will put it there */ |
| @@ -425,7 +430,7 @@ int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_r | |||
| 425 | 430 | ||
| 426 | spin_unlock(&c->erase_completion_lock); | 431 | spin_unlock(&c->erase_completion_lock); |
| 427 | 432 | ||
| 428 | return 0; | 433 | return new; |
| 429 | } | 434 | } |
| 430 | 435 | ||
| 431 | 436 | ||
| @@ -697,7 +702,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
| 697 | } | 702 | } |
| 698 | spin_unlock(&c->erase_completion_lock); | 703 | spin_unlock(&c->erase_completion_lock); |
| 699 | 704 | ||
| 700 | jffs2_free_raw_node_ref(n); | 705 | __jffs2_free_raw_node_ref(n); |
| 701 | } | 706 | } |
| 702 | 707 | ||
| 703 | /* Also merge with the previous node in the list, if there is one | 708 | /* Also merge with the previous node in the list, if there is one |
| @@ -722,7 +727,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
| 722 | jeb->gc_node=p; | 727 | jeb->gc_node=p; |
| 723 | } | 728 | } |
| 724 | p->next_phys = ref->next_phys; | 729 | p->next_phys = ref->next_phys; |
| 725 | jffs2_free_raw_node_ref(ref); | 730 | __jffs2_free_raw_node_ref(ref); |
| 726 | } | 731 | } |
| 727 | spin_unlock(&c->erase_completion_lock); | 732 | spin_unlock(&c->erase_completion_lock); |
| 728 | } | 733 | } |
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 6fce703c0543..87b0a416b6a0 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c | |||
| @@ -317,7 +317,6 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc | |||
| 317 | struct jffs2_summary *s) | 317 | struct jffs2_summary *s) |
| 318 | { | 318 | { |
| 319 | struct jffs2_xattr_datum *xd; | 319 | struct jffs2_xattr_datum *xd; |
| 320 | struct jffs2_raw_node_ref *raw; | ||
| 321 | uint32_t totlen, crc; | 320 | uint32_t totlen, crc; |
| 322 | int err; | 321 | int err; |
| 323 | 322 | ||
| @@ -340,13 +339,8 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc | |||
| 340 | return 0; | 339 | return 0; |
| 341 | } | 340 | } |
| 342 | 341 | ||
| 343 | raw = jffs2_alloc_raw_node_ref(); | ||
| 344 | if (!raw) | ||
| 345 | return -ENOMEM; | ||
| 346 | |||
| 347 | xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version)); | 342 | xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version)); |
| 348 | if (IS_ERR(xd)) { | 343 | if (IS_ERR(xd)) { |
| 349 | jffs2_free_raw_node_ref(raw); | ||
| 350 | if (PTR_ERR(xd) == -EEXIST) { | 344 | if (PTR_ERR(xd) == -EEXIST) { |
| 351 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rx->totlen))))) | 345 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rx->totlen))))) |
| 352 | return err; | 346 | return err; |
| @@ -358,12 +352,9 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc | |||
| 358 | xd->name_len = rx->name_len; | 352 | xd->name_len = rx->name_len; |
| 359 | xd->value_len = je16_to_cpu(rx->value_len); | 353 | xd->value_len = je16_to_cpu(rx->value_len); |
| 360 | xd->data_crc = je32_to_cpu(rx->data_crc); | 354 | xd->data_crc = je32_to_cpu(rx->data_crc); |
| 361 | xd->node = raw; | ||
| 362 | |||
| 363 | raw->flash_offset = ofs | REF_PRISTINE; | ||
| 364 | 355 | ||
| 365 | jffs2_link_node_ref(c, jeb, raw, totlen, NULL); | 356 | xd->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL); |
| 366 | /* FIXME */ raw->next_in_ino = (void *)xd; | 357 | /* FIXME */ xd->node->next_in_ino = (void *)xd; |
| 367 | 358 | ||
| 368 | if (jffs2_sum_active()) | 359 | if (jffs2_sum_active()) |
| 369 | jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset); | 360 | jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset); |
| @@ -377,7 +368,6 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
| 377 | struct jffs2_summary *s) | 368 | struct jffs2_summary *s) |
| 378 | { | 369 | { |
| 379 | struct jffs2_xattr_ref *ref; | 370 | struct jffs2_xattr_ref *ref; |
| 380 | struct jffs2_raw_node_ref *raw; | ||
| 381 | uint32_t crc; | 371 | uint32_t crc; |
| 382 | int err; | 372 | int err; |
| 383 | 373 | ||
| @@ -404,12 +394,6 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
| 404 | if (!ref) | 394 | if (!ref) |
| 405 | return -ENOMEM; | 395 | return -ENOMEM; |
| 406 | 396 | ||
| 407 | raw = jffs2_alloc_raw_node_ref(); | ||
| 408 | if (!raw) { | ||
| 409 | jffs2_free_xattr_ref(ref); | ||
| 410 | return -ENOMEM; | ||
| 411 | } | ||
| 412 | |||
| 413 | /* BEFORE jffs2_build_xattr_subsystem() called, | 397 | /* BEFORE jffs2_build_xattr_subsystem() called, |
| 414 | * ref->xid is used to store 32bit xid, xd is not used | 398 | * ref->xid is used to store 32bit xid, xd is not used |
| 415 | * ref->ino is used to store 32bit inode-number, ic is not used | 399 | * ref->ino is used to store 32bit inode-number, ic is not used |
| @@ -418,16 +402,13 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
| 418 | * used to chain all xattr_ref object. It's re-chained to | 402 | * used to chain all xattr_ref object. It's re-chained to |
| 419 | * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly. | 403 | * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly. |
| 420 | */ | 404 | */ |
| 421 | ref->node = raw; | ||
| 422 | ref->ino = je32_to_cpu(rr->ino); | 405 | ref->ino = je32_to_cpu(rr->ino); |
| 423 | ref->xid = je32_to_cpu(rr->xid); | 406 | ref->xid = je32_to_cpu(rr->xid); |
| 424 | ref->next = c->xref_temp; | 407 | ref->next = c->xref_temp; |
| 425 | c->xref_temp = ref; | 408 | c->xref_temp = ref; |
| 426 | 409 | ||
| 427 | raw->flash_offset = ofs | REF_PRISTINE; | 410 | ref->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), NULL); |
| 428 | 411 | /* FIXME */ ref->node->next_in_ino = (void *)ref; | |
| 429 | jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rr->totlen)), NULL); | ||
| 430 | /* FIXME */ raw->next_in_ino = (void *)ref; | ||
| 431 | 412 | ||
| 432 | if (jffs2_sum_active()) | 413 | if (jffs2_sum_active()) |
| 433 | jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset); | 414 | jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset); |
| @@ -597,6 +578,11 @@ scan_more: | |||
| 597 | 578 | ||
| 598 | jffs2_dbg_acct_paranoia_check_nolock(c, jeb); | 579 | jffs2_dbg_acct_paranoia_check_nolock(c, jeb); |
| 599 | 580 | ||
| 581 | /* Make sure there are node refs available for use */ | ||
| 582 | err = jffs2_prealloc_raw_node_refs(c, 2); | ||
| 583 | if (err) | ||
| 584 | return err; | ||
| 585 | |||
| 600 | cond_resched(); | 586 | cond_resched(); |
| 601 | 587 | ||
| 602 | if (ofs & 3) { | 588 | if (ofs & 3) { |
| @@ -839,14 +825,7 @@ scan_more: | |||
| 839 | return err; | 825 | return err; |
| 840 | ofs += PAD(sizeof(struct jffs2_unknown_node)); | 826 | ofs += PAD(sizeof(struct jffs2_unknown_node)); |
| 841 | } else { | 827 | } else { |
| 842 | struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); | 828 | jffs2_link_node_ref(c, jeb, ofs | REF_NORMAL, c->cleanmarker_size, NULL); |
| 843 | if (!marker_ref) { | ||
| 844 | printk(KERN_NOTICE "Failed to allocate node ref for clean marker\n"); | ||
| 845 | return -ENOMEM; | ||
| 846 | } | ||
| 847 | marker_ref->flash_offset = ofs | REF_NORMAL; | ||
| 848 | |||
| 849 | jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size, NULL); | ||
| 850 | 829 | ||
| 851 | ofs += PAD(c->cleanmarker_size); | 830 | ofs += PAD(c->cleanmarker_size); |
| 852 | } | 831 | } |
| @@ -884,14 +863,9 @@ scan_more: | |||
| 884 | break; | 863 | break; |
| 885 | 864 | ||
| 886 | case JFFS2_FEATURE_RWCOMPAT_COPY: { | 865 | case JFFS2_FEATURE_RWCOMPAT_COPY: { |
| 887 | struct jffs2_raw_node_ref *ref; | ||
| 888 | D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); | 866 | D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); |
| 889 | 867 | ||
| 890 | ref = jffs2_alloc_raw_node_ref(); | 868 | jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(node->totlen)), NULL); |
| 891 | if (!ref) | ||
| 892 | return -ENOMEM; | ||
| 893 | ref->flash_offset = ofs | REF_PRISTINE; | ||
| 894 | jffs2_link_node_ref(c, jeb, ref, PAD(je32_to_cpu(node->totlen)), NULL); | ||
| 895 | 869 | ||
| 896 | /* We can't summarise nodes we don't grok */ | 870 | /* We can't summarise nodes we don't grok */ |
| 897 | jffs2_sum_disable_collecting(s); | 871 | jffs2_sum_disable_collecting(s); |
| @@ -953,7 +927,6 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin | |||
| 953 | static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 927 | static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
| 954 | struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) | 928 | struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) |
| 955 | { | 929 | { |
| 956 | struct jffs2_raw_node_ref *raw; | ||
| 957 | struct jffs2_inode_cache *ic; | 930 | struct jffs2_inode_cache *ic; |
| 958 | uint32_t ino = je32_to_cpu(ri->ino); | 931 | uint32_t ino = je32_to_cpu(ri->ino); |
| 959 | int err; | 932 | int err; |
| @@ -969,12 +942,6 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc | |||
| 969 | Which means that the _full_ amount of time to get to proper write mode with GC | 942 | Which means that the _full_ amount of time to get to proper write mode with GC |
| 970 | operational may actually be _longer_ than before. Sucks to be me. */ | 943 | operational may actually be _longer_ than before. Sucks to be me. */ |
| 971 | 944 | ||
| 972 | raw = jffs2_alloc_raw_node_ref(); | ||
| 973 | if (!raw) { | ||
| 974 | printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n"); | ||
| 975 | return -ENOMEM; | ||
| 976 | } | ||
| 977 | |||
| 978 | ic = jffs2_get_ino_cache(c, ino); | 945 | ic = jffs2_get_ino_cache(c, ino); |
| 979 | if (!ic) { | 946 | if (!ic) { |
| 980 | /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the | 947 | /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the |
| @@ -988,21 +955,15 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc | |||
| 988 | /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ | 955 | /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ |
| 989 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(ri->totlen))))) | 956 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(ri->totlen))))) |
| 990 | return err; | 957 | return err; |
| 991 | jffs2_free_raw_node_ref(raw); | ||
| 992 | return 0; | 958 | return 0; |
| 993 | } | 959 | } |
| 994 | ic = jffs2_scan_make_ino_cache(c, ino); | 960 | ic = jffs2_scan_make_ino_cache(c, ino); |
| 995 | if (!ic) { | 961 | if (!ic) |
| 996 | jffs2_free_raw_node_ref(raw); | ||
| 997 | return -ENOMEM; | 962 | return -ENOMEM; |
| 998 | } | ||
| 999 | } | 963 | } |
| 1000 | 964 | ||
| 1001 | /* Wheee. It worked */ | 965 | /* Wheee. It worked */ |
| 1002 | 966 | jffs2_link_node_ref(c, jeb, ofs | REF_UNCHECKED, PAD(je32_to_cpu(ri->totlen)), ic); | |
| 1003 | raw->flash_offset = ofs | REF_UNCHECKED; | ||
| 1004 | |||
| 1005 | jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(ri->totlen)), ic); | ||
| 1006 | 967 | ||
| 1007 | D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", | 968 | D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", |
| 1008 | je32_to_cpu(ri->ino), je32_to_cpu(ri->version), | 969 | je32_to_cpu(ri->ino), je32_to_cpu(ri->version), |
| @@ -1021,7 +982,6 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc | |||
| 1021 | static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 982 | static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
| 1022 | struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s) | 983 | struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s) |
| 1023 | { | 984 | { |
| 1024 | struct jffs2_raw_node_ref *raw; | ||
| 1025 | struct jffs2_full_dirent *fd; | 985 | struct jffs2_full_dirent *fd; |
| 1026 | struct jffs2_inode_cache *ic; | 986 | struct jffs2_inode_cache *ic; |
| 1027 | uint32_t crc; | 987 | uint32_t crc; |
| @@ -1063,23 +1023,14 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
| 1063 | return err; | 1023 | return err; |
| 1064 | return 0; | 1024 | return 0; |
| 1065 | } | 1025 | } |
| 1066 | raw = jffs2_alloc_raw_node_ref(); | ||
| 1067 | if (!raw) { | ||
| 1068 | jffs2_free_full_dirent(fd); | ||
| 1069 | printk(KERN_NOTICE "jffs2_scan_dirent_node(): allocation of node reference failed\n"); | ||
| 1070 | return -ENOMEM; | ||
| 1071 | } | ||
| 1072 | ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino)); | 1026 | ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino)); |
| 1073 | if (!ic) { | 1027 | if (!ic) { |
| 1074 | jffs2_free_full_dirent(fd); | 1028 | jffs2_free_full_dirent(fd); |
| 1075 | jffs2_free_raw_node_ref(raw); | ||
| 1076 | return -ENOMEM; | 1029 | return -ENOMEM; |
| 1077 | } | 1030 | } |
| 1078 | 1031 | ||
| 1079 | raw->flash_offset = ofs | REF_PRISTINE; | 1032 | fd->raw = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rd->totlen)), ic); |
| 1080 | jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rd->totlen)), ic); | ||
| 1081 | 1033 | ||
| 1082 | fd->raw = raw; | ||
| 1083 | fd->next = NULL; | 1034 | fd->next = NULL; |
| 1084 | fd->version = je32_to_cpu(rd->version); | 1035 | fd->version = je32_to_cpu(rd->version); |
| 1085 | fd->ino = je32_to_cpu(rd->ino); | 1036 | fd->ino = je32_to_cpu(rd->ino); |
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 351ba9f8185e..ccb6803a6e41 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c | |||
| @@ -369,22 +369,18 @@ no_mem: | |||
| 369 | return -ENOMEM; | 369 | return -ENOMEM; |
| 370 | } | 370 | } |
| 371 | 371 | ||
| 372 | static struct jffs2_raw_node_ref *alloc_ref_at(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 372 | static struct jffs2_raw_node_ref *sum_link_node_ref(struct jffs2_sb_info *c, |
| 373 | uint32_t offset) | 373 | struct jffs2_eraseblock *jeb, |
| 374 | uint32_t ofs, uint32_t len, | ||
| 375 | struct jffs2_inode_cache *ic) | ||
| 374 | { | 376 | { |
| 375 | struct jffs2_raw_node_ref *ref; | ||
| 376 | /* If there was a gap, mark it dirty */ | 377 | /* If there was a gap, mark it dirty */ |
| 377 | if (offset > c->sector_size - jeb->free_size) { | 378 | if ((ofs & ~3) > c->sector_size - jeb->free_size) { |
| 378 | int ret = jffs2_scan_dirty_space(c, jeb, offset - (c->sector_size - jeb->free_size)); | 379 | /* Ew. Summary doesn't actually tell us explicitly about dirty space */ |
| 379 | if (ret) | 380 | jffs2_scan_dirty_space(c, jeb, (ofs & ~3) - (c->sector_size - jeb->free_size)); |
| 380 | return NULL; | ||
| 381 | } | 381 | } |
| 382 | ref = jffs2_alloc_raw_node_ref(); | ||
| 383 | if (!ref) | ||
| 384 | return NULL; | ||
| 385 | 382 | ||
| 386 | ref->flash_offset = jeb->offset + offset; | 383 | return jffs2_link_node_ref(c, jeb, jeb->offset + ofs, len, ic); |
| 387 | return ref; | ||
| 388 | } | 384 | } |
| 389 | 385 | ||
| 390 | /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ | 386 | /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ |
| @@ -392,7 +388,6 @@ static struct jffs2_raw_node_ref *alloc_ref_at(struct jffs2_sb_info *c, struct j | |||
| 392 | static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 388 | static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
| 393 | struct jffs2_raw_summary *summary, uint32_t *pseudo_random) | 389 | struct jffs2_raw_summary *summary, uint32_t *pseudo_random) |
| 394 | { | 390 | { |
| 395 | struct jffs2_raw_node_ref *raw; | ||
| 396 | struct jffs2_inode_cache *ic; | 391 | struct jffs2_inode_cache *ic; |
| 397 | struct jffs2_full_dirent *fd; | 392 | struct jffs2_full_dirent *fd; |
| 398 | void *sp; | 393 | void *sp; |
| @@ -404,6 +399,11 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
| 404 | for (i=0; i<je32_to_cpu(summary->sum_num); i++) { | 399 | for (i=0; i<je32_to_cpu(summary->sum_num); i++) { |
| 405 | dbg_summary("processing summary index %d\n", i); | 400 | dbg_summary("processing summary index %d\n", i); |
| 406 | 401 | ||
| 402 | /* Make sure there's a spare ref for dirty space */ | ||
| 403 | err = jffs2_prealloc_raw_node_refs(c, 2); | ||
| 404 | if (err) | ||
| 405 | return err; | ||
| 406 | |||
| 407 | switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { | 407 | switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { |
| 408 | case JFFS2_NODETYPE_INODE: { | 408 | case JFFS2_NODETYPE_INODE: { |
| 409 | struct jffs2_sum_inode_flash *spi; | 409 | struct jffs2_sum_inode_flash *spi; |
| @@ -415,22 +415,14 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
| 415 | jeb->offset + je32_to_cpu(spi->offset), | 415 | jeb->offset + je32_to_cpu(spi->offset), |
| 416 | jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spu->totlen)); | 416 | jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spu->totlen)); |
| 417 | 417 | ||
| 418 | raw = alloc_ref_at(c, jeb, je32_to_cpu(spi->offset)); | ||
| 419 | if (!raw) { | ||
| 420 | JFFS2_NOTICE("allocation of node reference failed\n"); | ||
| 421 | return -ENOMEM; | ||
| 422 | } | ||
| 423 | |||
| 424 | ic = jffs2_scan_make_ino_cache(c, ino); | 418 | ic = jffs2_scan_make_ino_cache(c, ino); |
| 425 | if (!ic) { | 419 | if (!ic) { |
| 426 | JFFS2_NOTICE("scan_make_ino_cache failed\n"); | 420 | JFFS2_NOTICE("scan_make_ino_cache failed\n"); |
| 427 | jffs2_free_raw_node_ref(raw); | ||
| 428 | return -ENOMEM; | 421 | return -ENOMEM; |
| 429 | } | 422 | } |
| 430 | 423 | ||
| 431 | raw->flash_offset |= REF_UNCHECKED; | 424 | sum_link_node_ref(c, jeb, je32_to_cpu(spi->offset) | REF_UNCHECKED, |
| 432 | 425 | PAD(je32_to_cpu(spi->totlen)), ic); | |
| 433 | jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spi->totlen)), ic); | ||
| 434 | 426 | ||
| 435 | *pseudo_random += je32_to_cpu(spi->version); | 427 | *pseudo_random += je32_to_cpu(spi->version); |
| 436 | 428 | ||
| @@ -455,24 +447,15 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
| 455 | memcpy(&fd->name, spd->name, spd->nsize); | 447 | memcpy(&fd->name, spd->name, spd->nsize); |
| 456 | fd->name[spd->nsize] = 0; | 448 | fd->name[spd->nsize] = 0; |
| 457 | 449 | ||
| 458 | raw = alloc_ref_at(c, jeb, je32_to_cpu(spd->offset)); | ||
| 459 | if (!raw) { | ||
| 460 | jffs2_free_full_dirent(fd); | ||
| 461 | JFFS2_NOTICE("allocation of node reference failed\n"); | ||
| 462 | return -ENOMEM; | ||
| 463 | } | ||
| 464 | |||
| 465 | ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino)); | 450 | ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino)); |
| 466 | if (!ic) { | 451 | if (!ic) { |
| 467 | jffs2_free_full_dirent(fd); | 452 | jffs2_free_full_dirent(fd); |
| 468 | jffs2_free_raw_node_ref(raw); | ||
| 469 | return -ENOMEM; | 453 | return -ENOMEM; |
| 470 | } | 454 | } |
| 471 | 455 | ||
| 472 | raw->flash_offset |= REF_PRISTINE; | 456 | fd->raw = sum_link_node_ref(c, jeb, je32_to_cpu(spd->offset) | REF_PRISTINE, |
| 473 | jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spd->totlen)), ic); | 457 | PAD(je32_to_cpu(spd->totlen)), ic); |
| 474 | 458 | ||
| 475 | fd->raw = raw; | ||
| 476 | fd->next = NULL; | 459 | fd->next = NULL; |
| 477 | fd->version = je32_to_cpu(spd->version); | 460 | fd->version = je32_to_cpu(spd->version); |
| 478 | fd->ino = je32_to_cpu(spd->ino); | 461 | fd->ino = je32_to_cpu(spd->ino); |
| @@ -497,15 +480,10 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
| 497 | jeb->offset + je32_to_cpu(spx->offset), | 480 | jeb->offset + je32_to_cpu(spx->offset), |
| 498 | jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen), | 481 | jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen), |
| 499 | je32_to_cpu(spx->xid), je32_to_cpu(spx->version)); | 482 | je32_to_cpu(spx->xid), je32_to_cpu(spx->version)); |
| 500 | raw = alloc_ref_at(c, jeb, je32_to_cpu(spx->offset)); | 483 | |
| 501 | if (!raw) { | ||
| 502 | JFFS2_NOTICE("allocation of node reference failed\n"); | ||
| 503 | return -ENOMEM; | ||
| 504 | } | ||
| 505 | xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid), | 484 | xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid), |
| 506 | je32_to_cpu(spx->version)); | 485 | je32_to_cpu(spx->version)); |
| 507 | if (IS_ERR(xd)) { | 486 | if (IS_ERR(xd)) { |
| 508 | jffs2_free_raw_node_ref(raw); | ||
| 509 | if (PTR_ERR(xd) == -EEXIST) { | 487 | if (PTR_ERR(xd) == -EEXIST) { |
| 510 | /* a newer version of xd exists */ | 488 | /* a newer version of xd exists */ |
| 511 | if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen)))) | 489 | if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen)))) |
| @@ -516,12 +494,10 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
| 516 | JFFS2_NOTICE("allocation of xattr_datum failed\n"); | 494 | JFFS2_NOTICE("allocation of xattr_datum failed\n"); |
| 517 | return PTR_ERR(xd); | 495 | return PTR_ERR(xd); |
| 518 | } | 496 | } |
| 519 | xd->node = raw; | ||
| 520 | 497 | ||
| 521 | raw->flash_offset |= REF_UNCHECKED; | 498 | xd->node = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED, |
| 522 | 499 | PAD(je32_to_cpu(spx->totlen)), NULL); | |
| 523 | jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spx->totlen)), NULL); | 500 | /* FIXME */ xd->node->next_in_ino = (void *)xd; |
| 524 | /* FIXME */ raw->next_in_ino = (void *)xd; | ||
| 525 | 501 | ||
| 526 | *pseudo_random += je32_to_cpu(spx->xid); | 502 | *pseudo_random += je32_to_cpu(spx->xid); |
| 527 | sp += JFFS2_SUMMARY_XATTR_SIZE; | 503 | sp += JFFS2_SUMMARY_XATTR_SIZE; |
| @@ -537,29 +513,21 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
| 537 | jeb->offset + je32_to_cpu(spr->offset), | 513 | jeb->offset + je32_to_cpu(spr->offset), |
| 538 | jeb->offset + je32_to_cpu(spr->offset) + PAD(sizeof(struct jffs2_raw_xref))); | 514 | jeb->offset + je32_to_cpu(spr->offset) + PAD(sizeof(struct jffs2_raw_xref))); |
| 539 | 515 | ||
| 540 | raw = alloc_ref_at(c, jeb, je32_to_cpu(spr->offset)); | ||
| 541 | if (!raw) { | ||
| 542 | JFFS2_NOTICE("allocation of node reference failed\n"); | ||
| 543 | return -ENOMEM; | ||
| 544 | } | ||
| 545 | ref = jffs2_alloc_xattr_ref(); | 516 | ref = jffs2_alloc_xattr_ref(); |
| 546 | if (!ref) { | 517 | if (!ref) { |
| 547 | JFFS2_NOTICE("allocation of xattr_datum failed\n"); | 518 | JFFS2_NOTICE("allocation of xattr_datum failed\n"); |
| 548 | jffs2_free_raw_node_ref(raw); | ||
| 549 | return -ENOMEM; | 519 | return -ENOMEM; |
| 550 | } | 520 | } |
| 551 | ref->ino = 0xfffffffe; | 521 | ref->ino = 0xfffffffe; |
| 552 | ref->xid = 0xfffffffd; | 522 | ref->xid = 0xfffffffd; |
| 553 | ref->node = raw; | ||
| 554 | ref->next = c->xref_temp; | 523 | ref->next = c->xref_temp; |
| 555 | c->xref_temp = ref; | 524 | c->xref_temp = ref; |
| 556 | 525 | ||
| 557 | raw->flash_offset |= REF_UNCHECKED; | 526 | ref->node = sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED, |
| 527 | PAD(sizeof(struct jffs2_raw_xref)), NULL); | ||
| 528 | /* FIXME */ ref->node->next_in_ino = (void *)ref; | ||
| 558 | 529 | ||
| 559 | jffs2_link_node_ref(c, jeb, raw, PAD(sizeof(struct jffs2_raw_xref)), NULL); | 530 | *pseudo_random += ref->node->flash_offset; |
| 560 | /* FIXME */ raw->next_in_ino = (void *)ref; | ||
| 561 | |||
| 562 | *pseudo_random += raw->flash_offset; | ||
| 563 | sp += JFFS2_SUMMARY_XREF_SIZE; | 531 | sp += JFFS2_SUMMARY_XREF_SIZE; |
| 564 | 532 | ||
| 565 | break; | 533 | break; |
| @@ -584,7 +552,6 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
| 584 | } | 552 | } |
| 585 | } | 553 | } |
| 586 | } | 554 | } |
| 587 | |||
| 588 | return 0; | 555 | return 0; |
| 589 | } | 556 | } |
| 590 | 557 | ||
| @@ -594,7 +561,6 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb | |||
| 594 | uint32_t *pseudo_random) | 561 | uint32_t *pseudo_random) |
| 595 | { | 562 | { |
| 596 | struct jffs2_unknown_node crcnode; | 563 | struct jffs2_unknown_node crcnode; |
| 597 | struct jffs2_raw_node_ref *cache_ref; | ||
| 598 | int ret, ofs; | 564 | int ret, ofs; |
| 599 | uint32_t crc; | 565 | uint32_t crc; |
| 600 | int err; | 566 | int err; |
| @@ -650,16 +616,8 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb | |||
| 650 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr))))) | 616 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr))))) |
| 651 | return err; | 617 | return err; |
| 652 | } else { | 618 | } else { |
| 653 | struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); | 619 | jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, |
| 654 | 620 | je32_to_cpu(summary->cln_mkr), NULL); | |
| 655 | if (!marker_ref) { | ||
| 656 | JFFS2_NOTICE("Failed to allocate node ref for clean marker\n"); | ||
| 657 | return -ENOMEM; | ||
| 658 | } | ||
| 659 | |||
| 660 | marker_ref->flash_offset = jeb->offset | REF_NORMAL; | ||
| 661 | |||
| 662 | jffs2_link_node_ref(c, jeb, marker_ref, je32_to_cpu(summary->cln_mkr), NULL); | ||
| 663 | } | 621 | } |
| 664 | } | 622 | } |
| 665 | 623 | ||
| @@ -672,16 +630,11 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb | |||
| 672 | return ret; /* real error */ | 630 | return ret; /* real error */ |
| 673 | 631 | ||
| 674 | /* for PARANOIA_CHECK */ | 632 | /* for PARANOIA_CHECK */ |
| 675 | cache_ref = alloc_ref_at(c, jeb, ofs); | 633 | ret = jffs2_prealloc_raw_node_refs(c, 1); |
| 676 | 634 | if (ret) | |
| 677 | if (!cache_ref) { | 635 | return ret; |
| 678 | JFFS2_NOTICE("Failed to allocate node ref for cache\n"); | ||
| 679 | return -ENOMEM; | ||
| 680 | } | ||
| 681 | |||
| 682 | cache_ref->flash_offset |= REF_NORMAL; | ||
| 683 | 636 | ||
| 684 | jffs2_link_node_ref(c, jeb, cache_ref, sumsize, NULL); | 637 | jffs2_link_node_ref(c, jeb, (jeb->offset + ofs) | REF_NORMAL, sumsize, NULL); |
| 685 | 638 | ||
| 686 | if (unlikely(jeb->free_size)) { | 639 | if (unlikely(jeb->free_size)) { |
| 687 | JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n", | 640 | JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n", |
| @@ -709,6 +662,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
| 709 | union jffs2_sum_mem *temp; | 662 | union jffs2_sum_mem *temp; |
| 710 | struct jffs2_sum_marker *sm; | 663 | struct jffs2_sum_marker *sm; |
| 711 | struct kvec vecs[2]; | 664 | struct kvec vecs[2]; |
| 665 | uint32_t sum_ofs; | ||
| 712 | void *wpage; | 666 | void *wpage; |
| 713 | int ret; | 667 | int ret; |
| 714 | size_t retlen; | 668 | size_t retlen; |
| @@ -821,36 +775,31 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
| 821 | vecs[1].iov_base = c->summary->sum_buf; | 775 | vecs[1].iov_base = c->summary->sum_buf; |
| 822 | vecs[1].iov_len = datasize; | 776 | vecs[1].iov_len = datasize; |
| 823 | 777 | ||
| 778 | sum_ofs = jeb->offset + c->sector_size - jeb->free_size; | ||
| 779 | |||
| 824 | dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n", | 780 | dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n", |
| 825 | jeb->offset + c->sector_size - jeb->free_size); | 781 | sum_ofs); |
| 826 | 782 | ||
| 827 | spin_unlock(&c->erase_completion_lock); | 783 | ret = jffs2_flash_writev(c, vecs, 2, sum_ofs, &retlen, 0); |
| 828 | ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size - | ||
| 829 | jeb->free_size, &retlen, 0); | ||
| 830 | 784 | ||
| 831 | if (ret || (retlen != infosize)) { | 785 | if (ret || (retlen != infosize)) { |
| 832 | struct jffs2_raw_node_ref *ref; | ||
| 833 | 786 | ||
| 834 | JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n", | 787 | JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n", |
| 835 | infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen); | 788 | infosize, sum_ofs, ret, retlen); |
| 836 | 789 | ||
| 837 | /* Waste remaining space */ | 790 | /* Waste remaining space */ |
| 838 | ref = jffs2_alloc_raw_node_ref(); | 791 | spin_lock(&c->erase_completion_lock); |
| 839 | if (ref) { | 792 | jffs2_link_node_ref(c, jeb, sum_ofs | REF_OBSOLETE, infosize, NULL); |
| 840 | spin_lock(&c->erase_completion_lock); | 793 | spin_unlock(&c->erase_completion_lock); |
| 841 | |||
| 842 | ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size; | ||
| 843 | ref->flash_offset |= REF_OBSOLETE; | ||
| 844 | |||
| 845 | jffs2_link_node_ref(c, jeb, ref, c->sector_size - jeb->free_size, NULL); | ||
| 846 | } | ||
| 847 | 794 | ||
| 848 | c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; | 795 | c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; |
| 849 | 796 | ||
| 850 | return 1; | 797 | return 0; |
| 851 | } | 798 | } |
| 852 | 799 | ||
| 853 | spin_lock(&c->erase_completion_lock); | 800 | spin_lock(&c->erase_completion_lock); |
| 801 | jffs2_link_node_ref(c, jeb, sum_ofs | REF_NORMAL, infosize, NULL); | ||
| 802 | spin_unlock(&c->erase_completion_lock); | ||
| 854 | 803 | ||
| 855 | return 0; | 804 | return 0; |
| 856 | } | 805 | } |
| @@ -859,12 +808,15 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
| 859 | 808 | ||
| 860 | int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) | 809 | int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) |
| 861 | { | 810 | { |
| 862 | struct jffs2_raw_node_ref *summary_ref; | 811 | int datasize, infosize, padsize; |
| 863 | int datasize, infosize, padsize, ret; | ||
| 864 | struct jffs2_eraseblock *jeb; | 812 | struct jffs2_eraseblock *jeb; |
| 813 | int ret; | ||
| 865 | 814 | ||
| 866 | dbg_summary("called\n"); | 815 | dbg_summary("called\n"); |
| 867 | 816 | ||
| 817 | spin_unlock(&c->erase_completion_lock); | ||
| 818 | jffs2_prealloc_raw_node_refs(c, 1); | ||
| 819 | |||
| 868 | jeb = c->nextblock; | 820 | jeb = c->nextblock; |
| 869 | 821 | ||
| 870 | if (!c->summary->sum_num || !c->summary->sum_list_head) { | 822 | if (!c->summary->sum_num || !c->summary->sum_list_head) { |
| @@ -888,22 +840,6 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) | |||
| 888 | } | 840 | } |
| 889 | 841 | ||
| 890 | ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); | 842 | ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); |
| 891 | if (ret) | ||
| 892 | return 0; /* can't write out summary, block is marked as NOSUM_SIZE */ | ||
| 893 | |||
| 894 | /* for ACCT_PARANOIA_CHECK */ | ||
| 895 | spin_unlock(&c->erase_completion_lock); | ||
| 896 | summary_ref = jffs2_alloc_raw_node_ref(); | ||
| 897 | |||
| 898 | if (!summary_ref) { | ||
| 899 | JFFS2_NOTICE("Failed to allocate node ref for summary\n"); | ||
| 900 | return -ENOMEM; | ||
| 901 | } | ||
| 902 | |||
| 903 | summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL; | ||
| 904 | |||
| 905 | spin_lock(&c->erase_completion_lock); | 843 | spin_lock(&c->erase_completion_lock); |
| 906 | jffs2_link_node_ref(c, jeb, summary_ref, infosize, NULL); | 844 | return ret; |
| 907 | |||
| 908 | return 0; | ||
| 909 | } | 845 | } |
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 916c87d3393b..0d7abb260489 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c | |||
| @@ -179,6 +179,9 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
| 179 | unsigned char *buf; | 179 | unsigned char *buf; |
| 180 | uint32_t start, end, ofs, len; | 180 | uint32_t start, end, ofs, len; |
| 181 | 181 | ||
| 182 | if (jffs2_prealloc_raw_node_refs(c, c->reserved_refs + 1)) | ||
| 183 | return; | ||
| 184 | |||
| 182 | spin_lock(&c->erase_completion_lock); | 185 | spin_lock(&c->erase_completion_lock); |
| 183 | 186 | ||
| 184 | jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; | 187 | jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; |
| @@ -306,17 +309,9 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
| 306 | printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n"); | 309 | printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n"); |
| 307 | kfree(buf); | 310 | kfree(buf); |
| 308 | 311 | ||
| 309 | if (retlen) { | 312 | if (retlen) |
| 310 | struct jffs2_raw_node_ref *raw2; | 313 | jffs2_add_physical_node_ref(c, ofs | REF_OBSOLETE, ref_totlen(c, jeb, *first_raw), NULL); |
| 311 | |||
| 312 | raw2 = jffs2_alloc_raw_node_ref(); | ||
| 313 | if (!raw2) | ||
| 314 | return; | ||
| 315 | |||
| 316 | raw2->flash_offset = ofs | REF_OBSOLETE; | ||
| 317 | 314 | ||
| 318 | jffs2_add_physical_node_ref(c, raw2, ref_totlen(c, jeb, *first_raw), NULL); | ||
| 319 | } | ||
| 320 | return; | 315 | return; |
| 321 | } | 316 | } |
| 322 | printk(KERN_NOTICE "Recovery of wbuf succeeded to %08x\n", ofs); | 317 | printk(KERN_NOTICE "Recovery of wbuf succeeded to %08x\n", ofs); |
| @@ -428,6 +423,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
| 428 | if (!c->wbuf_len) /* already checked c->wbuf above */ | 423 | if (!c->wbuf_len) /* already checked c->wbuf above */ |
| 429 | return 0; | 424 | return 0; |
| 430 | 425 | ||
| 426 | if (jffs2_prealloc_raw_node_refs(c, c->reserved_refs + 1)) | ||
| 427 | return -ENOMEM; | ||
| 428 | |||
| 431 | /* claim remaining space on the page | 429 | /* claim remaining space on the page |
| 432 | this happens, if we have a change to a new block, | 430 | this happens, if we have a change to a new block, |
| 433 | or if fsync forces us to flush the writebuffer. | 431 | or if fsync forces us to flush the writebuffer. |
| @@ -485,7 +483,6 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
| 485 | /* Adjust free size of the block if we padded. */ | 483 | /* Adjust free size of the block if we padded. */ |
| 486 | if (pad) { | 484 | if (pad) { |
| 487 | struct jffs2_eraseblock *jeb; | 485 | struct jffs2_eraseblock *jeb; |
| 488 | struct jffs2_raw_node_ref *ref; | ||
| 489 | uint32_t waste = c->wbuf_pagesize - c->wbuf_len; | 486 | uint32_t waste = c->wbuf_pagesize - c->wbuf_len; |
| 490 | 487 | ||
| 491 | jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; | 488 | jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; |
| @@ -503,15 +500,10 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
| 503 | jeb->offset, jeb->free_size); | 500 | jeb->offset, jeb->free_size); |
| 504 | BUG(); | 501 | BUG(); |
| 505 | } | 502 | } |
| 506 | ref = jffs2_alloc_raw_node_ref(); | ||
| 507 | if (!ref) | ||
| 508 | return -ENOMEM; | ||
| 509 | ref->flash_offset = c->wbuf_ofs + c->wbuf_len; | ||
| 510 | ref->flash_offset |= REF_OBSOLETE; | ||
| 511 | 503 | ||
| 512 | spin_lock(&c->erase_completion_lock); | 504 | spin_lock(&c->erase_completion_lock); |
| 513 | 505 | ||
| 514 | jffs2_link_node_ref(c, jeb, ref, waste, NULL); | 506 | jffs2_link_node_ref(c, jeb, (c->wbuf_ofs + c->wbuf_len) | REF_OBSOLETE, waste, NULL); |
| 515 | /* FIXME: that made it count as dirty. Convert to wasted */ | 507 | /* FIXME: that made it count as dirty. Convert to wasted */ |
| 516 | jeb->dirty_size -= waste; | 508 | jeb->dirty_size -= waste; |
| 517 | c->dirty_size -= waste; | 509 | c->dirty_size -= waste; |
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 0e12b7561b71..67176792e138 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c | |||
| @@ -61,7 +61,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
| 61 | uint32_t datalen, int alloc_mode) | 61 | uint32_t datalen, int alloc_mode) |
| 62 | 62 | ||
| 63 | { | 63 | { |
| 64 | struct jffs2_raw_node_ref *raw; | ||
| 65 | struct jffs2_full_dnode *fn; | 64 | struct jffs2_full_dnode *fn; |
| 66 | size_t retlen; | 65 | size_t retlen; |
| 67 | uint32_t flash_ofs; | 66 | uint32_t flash_ofs; |
| @@ -83,27 +82,16 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
| 83 | if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { | 82 | if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { |
| 84 | printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); | 83 | printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); |
| 85 | } | 84 | } |
| 86 | raw = jffs2_alloc_raw_node_ref(); | ||
| 87 | if (!raw) | ||
| 88 | return ERR_PTR(-ENOMEM); | ||
| 89 | 85 | ||
| 90 | fn = jffs2_alloc_full_dnode(); | 86 | fn = jffs2_alloc_full_dnode(); |
| 91 | if (!fn) { | 87 | if (!fn) |
| 92 | jffs2_free_raw_node_ref(raw); | ||
| 93 | return ERR_PTR(-ENOMEM); | 88 | return ERR_PTR(-ENOMEM); |
| 94 | } | ||
| 95 | |||
| 96 | fn->ofs = je32_to_cpu(ri->offset); | ||
| 97 | fn->size = je32_to_cpu(ri->dsize); | ||
| 98 | fn->frags = 0; | ||
| 99 | 89 | ||
| 100 | /* check number of valid vecs */ | 90 | /* check number of valid vecs */ |
| 101 | if (!datalen || !data) | 91 | if (!datalen || !data) |
| 102 | cnt = 1; | 92 | cnt = 1; |
| 103 | retry: | 93 | retry: |
| 104 | fn->raw = raw; | 94 | flash_ofs = write_ofs(c); |
| 105 | |||
| 106 | raw->flash_offset = flash_ofs = write_ofs(c); | ||
| 107 | 95 | ||
| 108 | jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); | 96 | jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); |
| 109 | 97 | ||
| @@ -130,14 +118,11 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
| 130 | seem corrupted, in which case the scan would skip over | 118 | seem corrupted, in which case the scan would skip over |
| 131 | any node we write before the original intended end of | 119 | any node we write before the original intended end of |
| 132 | this node */ | 120 | this node */ |
| 133 | raw->flash_offset |= REF_OBSOLETE; | 121 | jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*ri)+datalen), NULL); |
| 134 | jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen), NULL); | ||
| 135 | jffs2_mark_node_obsolete(c, raw); | ||
| 136 | } else { | 122 | } else { |
| 137 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); | 123 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs); |
| 138 | jffs2_free_raw_node_ref(raw); | ||
| 139 | } | 124 | } |
| 140 | if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) { | 125 | if (!retried && alloc_mode != ALLOC_NORETRY) { |
| 141 | /* Try to reallocate space and retry */ | 126 | /* Try to reallocate space and retry */ |
| 142 | uint32_t dummy; | 127 | uint32_t dummy; |
| 143 | struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; | 128 | struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; |
| @@ -172,7 +157,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
| 172 | goto retry; | 157 | goto retry; |
| 173 | } | 158 | } |
| 174 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); | 159 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); |
| 175 | jffs2_free_raw_node_ref(raw); | ||
| 176 | } | 160 | } |
| 177 | /* Release the full_dnode which is now useless, and return */ | 161 | /* Release the full_dnode which is now useless, and return */ |
| 178 | jffs2_free_full_dnode(fn); | 162 | jffs2_free_full_dnode(fn); |
| @@ -186,14 +170,17 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
| 186 | if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || | 170 | if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || |
| 187 | ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && | 171 | ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && |
| 188 | (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) { | 172 | (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) { |
| 189 | raw->flash_offset |= REF_PRISTINE; | 173 | flash_ofs |= REF_PRISTINE; |
| 190 | } else { | 174 | } else { |
| 191 | raw->flash_offset |= REF_NORMAL; | 175 | flash_ofs |= REF_NORMAL; |
| 192 | } | 176 | } |
| 193 | jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen), f->inocache); | 177 | fn->raw = jffs2_add_physical_node_ref(c, flash_ofs, PAD(sizeof(*ri)+datalen), f->inocache); |
| 178 | fn->ofs = je32_to_cpu(ri->offset); | ||
| 179 | fn->size = je32_to_cpu(ri->dsize); | ||
| 180 | fn->frags = 0; | ||
| 194 | 181 | ||
| 195 | D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", | 182 | D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", |
| 196 | flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), | 183 | flash_ofs & ~3, flash_ofs & 3, je32_to_cpu(ri->dsize), |
| 197 | je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), | 184 | je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), |
| 198 | je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); | 185 | je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); |
| 199 | 186 | ||
| @@ -208,11 +195,10 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff | |||
| 208 | struct jffs2_raw_dirent *rd, const unsigned char *name, | 195 | struct jffs2_raw_dirent *rd, const unsigned char *name, |
| 209 | uint32_t namelen, int alloc_mode) | 196 | uint32_t namelen, int alloc_mode) |
| 210 | { | 197 | { |
| 211 | struct jffs2_raw_node_ref *raw; | ||
| 212 | struct jffs2_full_dirent *fd; | 198 | struct jffs2_full_dirent *fd; |
| 213 | size_t retlen; | 199 | size_t retlen; |
| 214 | struct kvec vecs[2]; | 200 | struct kvec vecs[2]; |
| 215 | uint32_t flash_ofs = write_ofs(c); | 201 | uint32_t flash_ofs; |
| 216 | int retried = 0; | 202 | int retried = 0; |
| 217 | int ret; | 203 | int ret; |
| 218 | 204 | ||
| @@ -223,26 +209,16 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff | |||
| 223 | D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { | 209 | D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { |
| 224 | printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); | 210 | printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); |
| 225 | BUG(); | 211 | BUG(); |
| 226 | } | 212 | }); |
| 227 | ); | ||
| 228 | 213 | ||
| 229 | vecs[0].iov_base = rd; | 214 | vecs[0].iov_base = rd; |
| 230 | vecs[0].iov_len = sizeof(*rd); | 215 | vecs[0].iov_len = sizeof(*rd); |
| 231 | vecs[1].iov_base = (unsigned char *)name; | 216 | vecs[1].iov_base = (unsigned char *)name; |
| 232 | vecs[1].iov_len = namelen; | 217 | vecs[1].iov_len = namelen; |
| 233 | 218 | ||
| 234 | jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); | ||
| 235 | |||
| 236 | raw = jffs2_alloc_raw_node_ref(); | ||
| 237 | |||
| 238 | if (!raw) | ||
| 239 | return ERR_PTR(-ENOMEM); | ||
| 240 | |||
| 241 | fd = jffs2_alloc_full_dirent(namelen+1); | 219 | fd = jffs2_alloc_full_dirent(namelen+1); |
| 242 | if (!fd) { | 220 | if (!fd) |
| 243 | jffs2_free_raw_node_ref(raw); | ||
| 244 | return ERR_PTR(-ENOMEM); | 221 | return ERR_PTR(-ENOMEM); |
| 245 | } | ||
| 246 | 222 | ||
| 247 | fd->version = je32_to_cpu(rd->version); | 223 | fd->version = je32_to_cpu(rd->version); |
| 248 | fd->ino = je32_to_cpu(rd->ino); | 224 | fd->ino = je32_to_cpu(rd->ino); |
| @@ -252,9 +228,9 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff | |||
| 252 | fd->name[namelen]=0; | 228 | fd->name[namelen]=0; |
| 253 | 229 | ||
| 254 | retry: | 230 | retry: |
| 255 | fd->raw = raw; | 231 | flash_ofs = write_ofs(c); |
| 256 | 232 | ||
| 257 | raw->flash_offset = flash_ofs; | 233 | jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); |
| 258 | 234 | ||
| 259 | if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) { | 235 | if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) { |
| 260 | BUG_ON(!retried); | 236 | BUG_ON(!retried); |
| @@ -273,14 +249,11 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff | |||
| 273 | sizeof(*rd)+namelen, flash_ofs, ret, retlen); | 249 | sizeof(*rd)+namelen, flash_ofs, ret, retlen); |
| 274 | /* Mark the space as dirtied */ | 250 | /* Mark the space as dirtied */ |
| 275 | if (retlen) { | 251 | if (retlen) { |
| 276 | raw->flash_offset |= REF_OBSOLETE; | 252 | jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*rd)+namelen), NULL); |
| 277 | jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen), NULL); | ||
| 278 | jffs2_mark_node_obsolete(c, raw); | ||
| 279 | } else { | 253 | } else { |
| 280 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); | 254 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs); |
| 281 | jffs2_free_raw_node_ref(raw); | ||
| 282 | } | 255 | } |
| 283 | if (!retried && (raw = jffs2_alloc_raw_node_ref())) { | 256 | if (!retried) { |
| 284 | /* Try to reallocate space and retry */ | 257 | /* Try to reallocate space and retry */ |
| 285 | uint32_t dummy; | 258 | uint32_t dummy; |
| 286 | struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; | 259 | struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; |
| @@ -313,15 +286,13 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff | |||
| 313 | goto retry; | 286 | goto retry; |
| 314 | } | 287 | } |
| 315 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); | 288 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); |
| 316 | jffs2_free_raw_node_ref(raw); | ||
| 317 | } | 289 | } |
| 318 | /* Release the full_dnode which is now useless, and return */ | 290 | /* Release the full_dnode which is now useless, and return */ |
| 319 | jffs2_free_full_dirent(fd); | 291 | jffs2_free_full_dirent(fd); |
| 320 | return ERR_PTR(ret?ret:-EIO); | 292 | return ERR_PTR(ret?ret:-EIO); |
| 321 | } | 293 | } |
| 322 | /* Mark the space used */ | 294 | /* Mark the space used */ |
| 323 | raw->flash_offset |= REF_PRISTINE; | 295 | fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | REF_PRISTINE, PAD(sizeof(*rd)+namelen), f->inocache); |
| 324 | jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen), f->inocache); | ||
| 325 | 296 | ||
| 326 | if (retried) { | 297 | if (retried) { |
| 327 | jffs2_dbg_acct_sanity_check(c,NULL); | 298 | jffs2_dbg_acct_sanity_check(c,NULL); |
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 008f91b1c171..2255f1367bd5 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c | |||
| @@ -304,8 +304,8 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x | |||
| 304 | static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) | 304 | static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) |
| 305 | { | 305 | { |
| 306 | /* must be called under down_write(xattr_sem) */ | 306 | /* must be called under down_write(xattr_sem) */ |
| 307 | struct jffs2_raw_xattr rx; | ||
| 308 | struct jffs2_raw_node_ref *raw; | 307 | struct jffs2_raw_node_ref *raw; |
| 308 | struct jffs2_raw_xattr rx; | ||
| 309 | struct kvec vecs[2]; | 309 | struct kvec vecs[2]; |
| 310 | uint32_t length; | 310 | uint32_t length; |
| 311 | int rc, totlen; | 311 | int rc, totlen; |
| @@ -319,11 +319,6 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x | |||
| 319 | vecs[1].iov_len = xd->name_len + 1 + xd->value_len; | 319 | vecs[1].iov_len = xd->name_len + 1 + xd->value_len; |
| 320 | totlen = vecs[0].iov_len + vecs[1].iov_len; | 320 | totlen = vecs[0].iov_len + vecs[1].iov_len; |
| 321 | 321 | ||
| 322 | raw = jffs2_alloc_raw_node_ref(); | ||
| 323 | if (!raw) | ||
| 324 | return -ENOMEM; | ||
| 325 | raw->flash_offset = phys_ofs; | ||
| 326 | |||
| 327 | /* Setup raw-xattr */ | 322 | /* Setup raw-xattr */ |
| 328 | rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 323 | rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
| 329 | rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR); | 324 | rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR); |
| @@ -343,19 +338,14 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x | |||
| 343 | JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%u, at %#08x\n", | 338 | JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%u, at %#08x\n", |
| 344 | rc, totlen, length, phys_ofs); | 339 | rc, totlen, length, phys_ofs); |
| 345 | rc = rc ? rc : -EIO; | 340 | rc = rc ? rc : -EIO; |
| 346 | if (length) { | 341 | if (length) |
| 347 | raw->flash_offset |= REF_OBSOLETE; | 342 | jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(totlen), NULL); |
| 348 | jffs2_add_physical_node_ref(c, raw, PAD(totlen), NULL); | 343 | |
| 349 | jffs2_mark_node_obsolete(c, raw); | ||
| 350 | } else { | ||
| 351 | jffs2_free_raw_node_ref(raw); | ||
| 352 | } | ||
| 353 | return rc; | 344 | return rc; |
| 354 | } | 345 | } |
| 355 | 346 | ||
| 356 | /* success */ | 347 | /* success */ |
| 357 | raw->flash_offset |= REF_PRISTINE; | 348 | raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), NULL); |
| 358 | jffs2_add_physical_node_ref(c, raw, PAD(totlen), NULL); | ||
| 359 | /* FIXME */ raw->next_in_ino = (void *)xd; | 349 | /* FIXME */ raw->next_in_ino = (void *)xd; |
| 360 | 350 | ||
| 361 | if (xd->node) | 351 | if (xd->node) |
| @@ -563,11 +553,6 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) | |||
| 563 | uint32_t phys_ofs = write_ofs(c); | 553 | uint32_t phys_ofs = write_ofs(c); |
| 564 | int ret; | 554 | int ret; |
| 565 | 555 | ||
| 566 | raw = jffs2_alloc_raw_node_ref(); | ||
| 567 | if (!raw) | ||
| 568 | return -ENOMEM; | ||
| 569 | raw->flash_offset = phys_ofs; | ||
| 570 | |||
| 571 | rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 556 | rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
| 572 | rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF); | 557 | rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF); |
| 573 | rr.totlen = cpu_to_je32(PAD(sizeof(rr))); | 558 | rr.totlen = cpu_to_je32(PAD(sizeof(rr))); |
| @@ -582,18 +567,13 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) | |||
| 582 | JFFS2_WARNING("jffs2_flash_write() returned %d, request=%u, retlen=%u, at %#08x\n", | 567 | JFFS2_WARNING("jffs2_flash_write() returned %d, request=%u, retlen=%u, at %#08x\n", |
| 583 | ret, sizeof(rr), length, phys_ofs); | 568 | ret, sizeof(rr), length, phys_ofs); |
| 584 | ret = ret ? ret : -EIO; | 569 | ret = ret ? ret : -EIO; |
| 585 | if (length) { | 570 | if (length) |
| 586 | raw->flash_offset |= REF_OBSOLETE; | 571 | jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(sizeof(rr)), NULL); |
| 587 | jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr)), NULL); | 572 | |
| 588 | jffs2_mark_node_obsolete(c, raw); | ||
| 589 | } else { | ||
| 590 | jffs2_free_raw_node_ref(raw); | ||
| 591 | } | ||
| 592 | return ret; | 573 | return ret; |
| 593 | } | 574 | } |
| 594 | raw->flash_offset |= REF_PRISTINE; | ||
| 595 | 575 | ||
| 596 | jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr)), NULL); | 576 | raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), NULL); |
| 597 | /* FIXME */ raw->next_in_ino = (void *)ref; | 577 | /* FIXME */ raw->next_in_ino = (void *)ref; |
| 598 | if (ref->node) | 578 | if (ref->node) |
| 599 | delete_xattr_ref_node(c, ref); | 579 | delete_xattr_ref_node(c, ref); |
