The I_WILL_FREE is currently set for inodes that we write out during
umount after dropping their last reference. It is handled equally
to I_FREEING in most places. The two execptions are:
- writeback_single_inode skips all list manipulations for I_FREEING,
but not for I_WILL_FREE. We don't care about which list an
I_WILL_FREE inode is on, because we will remove it from the list
a little bit later.
- __mark_inode_dirty skips I_FREEING inodes but not I_WILL_FREE
inodes. This only matters for filesystem that re-dirty the inode
during writeback and then use the I_DIRTY flags inside
->evict_inode.
The formers is done by XFS, but it uses it's internal state to flush
the inode. I could not find any filesystem that looks at I_DIRTY
inside ->evict_inode either.
Besides cleaning up the code removing I_WILL_FREE will allow us to
avoid one i_lock roundtrip once inode_lock is split and keep iput_final
more logic. This includes removing the __remove_inode_hash call in
iput_final, given that we never drop the protection from lookups now
that I_FREEING is set earlier.
Signed-off-by: Christoph Hellwig<hch@xxxxxx>
Index: linux-2.6/fs/btrfs/inode.c
===================================================================
--- linux-2.6.orig/fs/btrfs/inode.c 2010-10-24 16:30:05.000000000
+0200
+++ linux-2.6/fs/btrfs/inode.c 2010-10-24 16:32:43.647253791 +0200
@@ -3862,8 +3862,7 @@ again:
else if (inode->i_ino> entry->vfs_inode.i_ino)
p =&parent->rb_right;
else {
- WARN_ON(!(entry->vfs_inode.i_state&
- (I_WILL_FREE | I_FREEING)));
+ WARN_ON(!(entry->vfs_inode.i_state& I_FREEING));
rb_erase(parent,&root->inode_tree);
RB_CLEAR_NODE(parent);
spin_unlock(&root->inode_lock);
Index: linux-2.6/fs/drop_caches.c
===================================================================
--- linux-2.6.orig/fs/drop_caches.c 2010-10-24 16:30:05.000000000
+0200
+++ linux-2.6/fs/drop_caches.c 2010-10-24 16:32:43.647253791 +0200
@@ -18,7 +18,7 @@ static void drop_pagecache_sb(struct sup
spin_lock(&inode_lock);
list_for_each_entry(inode,&sb->s_inodes, i_sb_list) {
- if (inode->i_state& (I_FREEING|I_WILL_FREE|I_NEW))
+ if (inode->i_state& (I_FREEING | I_NEW))
continue;
if (inode->i_mapping->nrpages == 0)
continue;
Index: linux-2.6/fs/gfs2/inode.c
===================================================================
--- linux-2.6.orig/fs/gfs2/inode.c 2010-10-24 16:30:05.000000000
+0200
+++ linux-2.6/fs/gfs2/inode.c 2010-10-24 16:32:43.650253651 +0200
@@ -84,7 +84,7 @@ static int iget_skip_test(struct inode *
struct gfs2_skip_data *data = opaque;
if (ip->i_no_addr == data->no_addr) {
- if (inode->i_state& (I_FREEING|I_WILL_FREE)){
+ if (inode->i_state& I_FREEING){
data->skipped = 1;
return 0;
}
Index: linux-2.6/fs/fs-writeback.c
===================================================================
--- linux-2.6.orig/fs/fs-writeback.c 2010-10-24 16:32:39.000000000
+0200
+++ linux-2.6/fs/fs-writeback.c 2010-10-24 16:32:43.654254629 +0200
@@ -301,8 +301,7 @@ static void inode_wait_for_writeback(str
/*
* Write out an inode's dirty pages. Called under inode_lock.
Either the
- * caller has ref on the inode (either via __iget or via syscall
against an fd)
- * or the inode has I_WILL_FREE set (via generic_forget_inode)
+ * caller has ref on the inode or the inode is beeing freed.