[PATC] small VFS change for JFFS2

Artem B. Bityuckiy dedekind at infradead.org
Mon Apr 18 10:07:32 EDT 2005


On Mon, 2005-04-18 at 23:16 +1000, David Woodhouse wrote:
> On Mon, 2005-04-18 at 13:46 +0100, Christoph Hellwig wrote:
> > Why doesn't __wait_on_freeing_inode get called? prune_icache sets
> > I_FREEING before it's dropping the inode lock.
> 
> Because prune_icache() _also_ removes the inode from the hash before
> dropping the inode lock. It shouldn't -- the inode should only get
> removed from the hash when it's actually been cleared. That's the real
> bug -- and I agree that the fix isn't to expose internal locks to let
> JFFS2 work around it.
> 
> prune_icache() (and probably invalidate_inodes() too) needs to leave the
> inode on the hash list while it's being freed.
> 

Please, then consider the following patch (I didn't test it well,
though).


Signed-off-by: Artem B. Bityuckiy <dedekind at infradead.org>

diff -auNrp linux-2.6.11.5/fs/inode.c linux-2.6.11.5_fixed/fs/inode.c
--- linux-2.6.11.5/fs/inode.c   2005-03-19 09:35:04.000000000 +0300
+++ linux-2.6.11.5_fixed/fs/inode.c     2005-04-18 17:54:16.000000000
+0400
@@ -284,6 +284,12 @@ static void dispose_list(struct list_hea
                if (inode->i_data.nrpages)
                        truncate_inode_pages(&inode->i_data, 0);
                clear_inode(inode);
+
+               spin_lock(&inode_lock);
+               hlist_del_init(&inode->i_hash);
+               list_del_init(&inode->i_sb_list);
+               spin_unlock(&inode_lock);
+
                destroy_inode(inode);
                nr_disposed++;
        }
@@ -319,8 +325,6 @@ static int invalidate_list(struct list_h
                inode = list_entry(tmp, struct inode, i_sb_list);
                invalidate_inode_buffers(inode);
                if (!atomic_read(&inode->i_count)) {
-                       hlist_del_init(&inode->i_hash);
-                       list_del(&inode->i_sb_list);
                        list_move(&inode->i_list, dispose);
                        inode->i_state |= I_FREEING;
                        count++;
@@ -455,8 +459,6 @@ static void prune_icache(int nr_to_scan)
                        if (!can_unuse(inode))
                                continue;
                }
-               hlist_del_init(&inode->i_hash);
-               list_del_init(&inode->i_sb_list);
                list_move(&inode->i_list, &freeable);
                inode->i_state |= I_FREEING;
                nr_pruned++;

-- 
Best Regards,
Artem B. Bityuckiy,
St.-Petersburg, Russia.





More information about the linux-mtd mailing list