diff options
Diffstat (limited to 'fs/jffs2/erase.c')
-rw-r--r-- | fs/jffs2/erase.c | 56 |
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 |
31 | static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset); | 31 | static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset); |
32 | static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); | 32 | static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); |
33 | static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); | ||
34 | static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); | 33 | static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); |
35 | 34 | ||
36 | static void jffs2_erase_block(struct jffs2_sb_info *c, | 35 | static 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 | ||
286 | static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) | 286 | void 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 | ||
304 | static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *bad_offset) | 309 | static 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 | ||
352 | static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) | 357 | static 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); |