[PATCH][JFFS2] Fix garbage collector block search
David Woodhouse
dwmw2 at infradead.org
Tue Apr 22 12:47:13 EDT 2008
On Fri, 2008-01-18 at 19:28 +0300, Alexander Belyakov wrote:
> On 1/15/08, Jörn Engel <joern at logfs.org> wrote:
> >
> > Right now the important thing is to dig deeper and understand the nature
> > of this bug. You can reproduce it, that is good. We also know that it
> > makes a difference whether the block is on one list or the other. But
> > we don't know yet, what difference exactly it makes.
>
> Question. What is success criteria for jffs2_garbage_collect_pass() execution?
>
> Why asking? In the case described above jffs2_find_gc_block() fails to
> find erase block for garbage collection but falling into
> jffs2_flush_wbuf_pad(c) which produces amount of erasing blocks. So
> jffs2_garbage_collect_pass() sees no single block for garbage
> collection, but filesystem still recieves fresh erasing blocks upon
> execution.
>
> Is it success or failure? Theoretically.
It depends. There are two callers of jffs2_garbage_collect_pass().
For jffs2_flush_wbuf_gc() it's not progress, so it should be handled
like failure.
For jffs2_reserve_space(), we can treat it as success... or we can have
a special case which calls jffs2_erase_pending_blocks() right away to
wait for the block to erase.
How about this... does it solve the problem for you?
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 26c7992..f2c6e88 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -221,6 +221,12 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
jeb = jffs2_find_gc_block(c);
if (!jeb) {
+ /* Couldn't find a free block. But maybe we can just erase one and make 'progress'? */
+ if (!list_empty(&c->erase_pending_list)) {
+ spin_unlock(&c->erase_completion_lock);
+ mutex_unlock(&c->alloc_sem);
+ return -EAGAIN;
+ }
D1 (printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n"));
spin_unlock(&c->erase_completion_lock);
mutex_unlock(&c->alloc_sem);
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 747a73f..952a828 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -116,7 +116,12 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
spin_unlock(&c->erase_completion_lock);
ret = jffs2_garbage_collect_pass(c);
- if (ret)
+ if (ret == -EAGAIN) {
+ jffs2_erase_pending_blocks(c, 1);
+ goto again;
+ }
+
+ if (ret)
return ret;
cond_resched();
@@ -124,6 +129,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
if (signal_pending(current))
return -EINTR;
+ again:
mutex_lock(&c->alloc_sem);
spin_lock(&c->erase_completion_lock);
}
--
dwmw2
More information about the linux-mtd
mailing list