diff options
Diffstat (limited to 'fs/jffs2/nodemgmt.c')
-rw-r--r-- | fs/jffs2/nodemgmt.c | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 191359dde4e1..694aa5b03505 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c | |||
@@ -116,9 +116,21 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | |||
116 | 116 | ||
117 | ret = jffs2_garbage_collect_pass(c); | 117 | ret = jffs2_garbage_collect_pass(c); |
118 | 118 | ||
119 | if (ret == -EAGAIN) | 119 | if (ret == -EAGAIN) { |
120 | jffs2_erase_pending_blocks(c, 1); | 120 | spin_lock(&c->erase_completion_lock); |
121 | else if (ret) | 121 | if (c->nr_erasing_blocks && |
122 | list_empty(&c->erase_pending_list) && | ||
123 | list_empty(&c->erase_complete_list)) { | ||
124 | DECLARE_WAITQUEUE(wait, current); | ||
125 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
126 | add_wait_queue(&c->erase_wait, &wait); | ||
127 | D1(printk(KERN_DEBUG "%s waiting for erase to complete\n", __func__)); | ||
128 | spin_unlock(&c->erase_completion_lock); | ||
129 | |||
130 | schedule(); | ||
131 | } else | ||
132 | spin_unlock(&c->erase_completion_lock); | ||
133 | } else if (ret) | ||
122 | return ret; | 134 | return ret; |
123 | 135 | ||
124 | cond_resched(); | 136 | cond_resched(); |
@@ -217,7 +229,7 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c) | |||
217 | ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list); | 229 | ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list); |
218 | list_move_tail(&ejeb->list, &c->erase_pending_list); | 230 | list_move_tail(&ejeb->list, &c->erase_pending_list); |
219 | c->nr_erasing_blocks++; | 231 | c->nr_erasing_blocks++; |
220 | jffs2_erase_pending_trigger(c); | 232 | jffs2_garbage_collect_trigger(c); |
221 | D1(printk(KERN_DEBUG "jffs2_find_nextblock: Triggering erase of erasable block at 0x%08x\n", | 233 | D1(printk(KERN_DEBUG "jffs2_find_nextblock: Triggering erase of erasable block at 0x%08x\n", |
222 | ejeb->offset)); | 234 | ejeb->offset)); |
223 | } | 235 | } |
@@ -469,7 +481,9 @@ struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c, | |||
469 | void jffs2_complete_reservation(struct jffs2_sb_info *c) | 481 | void jffs2_complete_reservation(struct jffs2_sb_info *c) |
470 | { | 482 | { |
471 | D1(printk(KERN_DEBUG "jffs2_complete_reservation()\n")); | 483 | D1(printk(KERN_DEBUG "jffs2_complete_reservation()\n")); |
484 | spin_lock(&c->erase_completion_lock); | ||
472 | jffs2_garbage_collect_trigger(c); | 485 | jffs2_garbage_collect_trigger(c); |
486 | spin_unlock(&c->erase_completion_lock); | ||
473 | mutex_unlock(&c->alloc_sem); | 487 | mutex_unlock(&c->alloc_sem); |
474 | } | 488 | } |
475 | 489 | ||
@@ -611,7 +625,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
611 | D1(printk(KERN_DEBUG "...and adding to erase_pending_list\n")); | 625 | D1(printk(KERN_DEBUG "...and adding to erase_pending_list\n")); |
612 | list_add_tail(&jeb->list, &c->erase_pending_list); | 626 | list_add_tail(&jeb->list, &c->erase_pending_list); |
613 | c->nr_erasing_blocks++; | 627 | c->nr_erasing_blocks++; |
614 | jffs2_erase_pending_trigger(c); | 628 | jffs2_garbage_collect_trigger(c); |
615 | } else { | 629 | } else { |
616 | /* Sometimes, however, we leave it elsewhere so it doesn't get | 630 | /* Sometimes, however, we leave it elsewhere so it doesn't get |
617 | immediately reused, and we spread the load a bit. */ | 631 | immediately reused, and we spread the load a bit. */ |
@@ -732,6 +746,10 @@ int jffs2_thread_should_wake(struct jffs2_sb_info *c) | |||
732 | int nr_very_dirty = 0; | 746 | int nr_very_dirty = 0; |
733 | struct jffs2_eraseblock *jeb; | 747 | struct jffs2_eraseblock *jeb; |
734 | 748 | ||
749 | if (!list_empty(&c->erase_complete_list) || | ||
750 | !list_empty(&c->erase_pending_list)) | ||
751 | return 1; | ||
752 | |||
735 | if (c->unchecked_size) { | 753 | if (c->unchecked_size) { |
736 | D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): unchecked_size %d, checked_ino #%d\n", | 754 | D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): unchecked_size %d, checked_ino #%d\n", |
737 | c->unchecked_size, c->checked_ino)); | 755 | c->unchecked_size, c->checked_ino)); |