aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/erase.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2/erase.c')
-rw-r--r--fs/jffs2/erase.c56
1 files changed, 22 insertions, 34 deletions
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index dad68fdffe9e..1862e8bc101d 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -30,7 +30,6 @@ static void jffs2_erase_callback(struct erase_info *);
30#endif 30#endif
31static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset); 31static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset);
32static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); 32static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
33static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
34static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); 33static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
35 34
36static void jffs2_erase_block(struct jffs2_sb_info *c, 35static void jffs2_erase_block(struct jffs2_sb_info *c,
@@ -136,7 +135,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
136 c->used_size -= jeb->used_size; 135 c->used_size -= jeb->used_size;
137 c->dirty_size -= jeb->dirty_size; 136 c->dirty_size -= jeb->dirty_size;
138 jeb->wasted_size = jeb->used_size = jeb->dirty_size = jeb->free_size = 0; 137 jeb->wasted_size = jeb->used_size = jeb->dirty_size = jeb->free_size = 0;
139 jffs2_free_all_node_refs(c, jeb); 138 jffs2_free_jeb_node_refs(c, jeb);
140 list_add(&jeb->list, &c->erasing_list); 139 list_add(&jeb->list, &c->erasing_list);
141 spin_unlock(&c->erase_completion_lock); 140 spin_unlock(&c->erase_completion_lock);
142 141
@@ -231,6 +230,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
231 at the end of the linked list. Stash it and continue 230 at the end of the linked list. Stash it and continue
232 from the beginning of the list */ 231 from the beginning of the list */
233 ic = (struct jffs2_inode_cache *)(*prev); 232 ic = (struct jffs2_inode_cache *)(*prev);
233 BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
234 prev = &ic->nodes; 234 prev = &ic->nodes;
235 continue; 235 continue;
236 } 236 }
@@ -283,22 +283,27 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
283 jffs2_del_ino_cache(c, ic); 283 jffs2_del_ino_cache(c, ic);
284} 284}
285 285
286static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 286void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
287{ 287{
288 struct jffs2_raw_node_ref *ref; 288 struct jffs2_raw_node_ref *block, *ref;
289 D1(printk(KERN_DEBUG "Freeing all node refs for eraseblock offset 0x%08x\n", jeb->offset)); 289 D1(printk(KERN_DEBUG "Freeing all node refs for eraseblock offset 0x%08x\n", jeb->offset));
290 while(jeb->first_node) {
291 ref = jeb->first_node;
292 jeb->first_node = ref->next_phys;
293 290
294 /* Remove from the inode-list */ 291 block = ref = jeb->first_node;
295 if (ref->next_in_ino) 292
293 while (ref) {
294 if (ref->flash_offset == REF_LINK_NODE) {
295 ref = ref->next_in_ino;
296 jffs2_free_refblock(block);
297 block = ref;
298 continue;
299 }
300 if (ref->flash_offset != REF_EMPTY_NODE && ref->next_in_ino)
296 jffs2_remove_node_refs_from_ino_list(c, ref, jeb); 301 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 */ 302 /* else it was a non-inode node or already removed, so don't bother */
298 303
299 jffs2_free_raw_node_ref(ref); 304 ref++;
300 } 305 }
301 jeb->last_node = NULL; 306 jeb->first_node = jeb->last_node = NULL;
302} 307}
303 308
304static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *bad_offset) 309static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *bad_offset)
@@ -351,7 +356,6 @@ fail:
351 356
352static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 357static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
353{ 358{
354 struct jffs2_raw_node_ref *marker_ref = NULL;
355 size_t retlen; 359 size_t retlen;
356 int ret; 360 int ret;
357 uint32_t bad_offset; 361 uint32_t bad_offset;
@@ -373,12 +377,8 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
373 goto filebad; 377 goto filebad;
374 } 378 }
375 379
376 jeb->first_node = jeb->last_node = NULL; 380 /* Everything else got zeroed before the erase */
377 jeb->free_size = c->sector_size; 381 jeb->free_size = c->sector_size;
378 jeb->used_size = 0;
379 jeb->dirty_size = 0;
380 jeb->wasted_size = 0;
381
382 } else { 382 } else {
383 383
384 struct kvec vecs[1]; 384 struct kvec vecs[1];
@@ -388,11 +388,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
388 .totlen = cpu_to_je32(c->cleanmarker_size) 388 .totlen = cpu_to_je32(c->cleanmarker_size)
389 }; 389 };
390 390
391 marker_ref = jffs2_alloc_raw_node_ref(); 391 jffs2_prealloc_raw_node_refs(c, jeb, 1);
392 if (!marker_ref) {
393 printk(KERN_WARNING "Failed to allocate raw node ref for clean marker. Refiling\n");
394 goto refile;
395 }
396 392
397 marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4)); 393 marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4));
398 394
@@ -408,21 +404,13 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
408 printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n", 404 printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n",
409 jeb->offset, sizeof(marker), retlen); 405 jeb->offset, sizeof(marker), retlen);
410 406
411 jffs2_free_raw_node_ref(marker_ref);
412 goto filebad; 407 goto filebad;
413 } 408 }
414 409
415 marker_ref->next_in_ino = NULL; 410 /* Everything else got zeroed before the erase */
416 marker_ref->next_phys = NULL; 411 jeb->free_size = c->sector_size;
417 marker_ref->flash_offset = jeb->offset | REF_NORMAL; 412 /* FIXME Special case for cleanmarker in empty block */
418 marker_ref->__totlen = c->cleanmarker_size; 413 jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
419
420 jeb->first_node = jeb->last_node = marker_ref;
421
422 jeb->free_size = c->sector_size - c->cleanmarker_size;
423 jeb->used_size = c->cleanmarker_size;
424 jeb->dirty_size = 0;
425 jeb->wasted_size = 0;
426 } 414 }
427 415
428 spin_lock(&c->erase_completion_lock); 416 spin_lock(&c->erase_completion_lock);