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); |