[PATCH] JFFS2 appears to "freeze" during erase
Joakim Tjernlund
joakim.tjernlund at transmode.se
Mon Jun 4 05:44:30 EDT 2007
On Mon, 2007-06-04 at 11:20 +0200, Joakim Tjernlund wrote:
> On Fri, 2007-06-01 at 19:04 +0100, David Woodhouse wrote:
> > On Fri, 2007-06-01 at 11:51 +0200, Joakim Tjernlund wrote:
> > > This is a old patch from Radoslaw Bisewski(see MTD list). The patch
> > > fixes the long stalls I am seeing in "GC starves write's in 2.6.20" I
> > > sent yesterday. Please apply.
> >
> > It seems to make sense; I need to convince myself that every other user
> > of the erase_free_sem is actually OK with it. I think
> > jffs2_g_c_deletion_dirent() should be OK, at first glance. I'm less
> > convinced about jffs2_mark_node_obsolete(), where we currently hold the
> > erase_free_sem while we actually mark the node obsolete. Will look into
> > it...
> >
>
> looked a litte closer on the new locking in erase.c and wonder
> why not jffs2_erase_succeeded() and jffs2_erase_failed() needs
> to take erase_free_sem?
>
> Jocke
Found another bug, here is an addon diff. Also added erase_free_sem to
jffs2_erase_succeeded() and jffs2_erase_failed() as I think it should
take the erase_free_sem there too.
Jocke
Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund at transmode.se>
---
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index 5b5c291..45b9f3e 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -93,6 +93,7 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
c->dirty_size += c->sector_size;
jeb->dirty_size = c->sector_size;
spin_unlock(&c->erase_completion_lock);
+ up(&c->erase_free_sem);
return;
}
@@ -163,9 +164,11 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
{
D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset));
+ down(&c->erase_free_sem);
spin_lock(&c->erase_completion_lock);
list_move_tail(&jeb->list, &c->erase_complete_list);
spin_unlock(&c->erase_completion_lock);
+ up(&c->erase_free_sem);
/* Ensure that kupdated calls us again to mark them clean */
jffs2_erase_pending_trigger(c);
}
@@ -179,22 +182,26 @@ static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock
failed too many times. */
if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) {
/* We'd like to give this block another try. */
+ down(&c->erase_free_sem);
spin_lock(&c->erase_completion_lock);
list_move(&jeb->list, &c->erase_pending_list);
c->erasing_size -= c->sector_size;
c->dirty_size += c->sector_size;
jeb->dirty_size = c->sector_size;
spin_unlock(&c->erase_completion_lock);
+ up(&c->erase_free_sem);
return;
}
}
+ down(&c->erase_free_sem);
spin_lock(&c->erase_completion_lock);
c->erasing_size -= c->sector_size;
c->bad_size += c->sector_size;
list_move(&jeb->list, &c->bad_list);
c->nr_erasing_blocks--;
spin_unlock(&c->erase_completion_lock);
+ up(&c->erase_free_sem);
wake_up(&c->erase_wait);
}
More information about the linux-mtd
mailing list