fs: avoid I_NEW inodes
authorNick Piggin <npiggin@suse.de>
Wed, 11 Mar 2009 20:17:36 +0000 (13:17 -0700)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 27 Mar 2009 18:44:05 +0000 (14:44 -0400)
To be on the safe side, it should be less fragile to exclude I_NEW inodes
from inode list scans by default (unless there is an important reason to
have them).

Normally they will get excluded (eg.  by zero refcount or writecount etc),
however it is a bit fragile for list walkers to know exactly what parts of
the inode state is set up and valid to test when in I_NEW.  So along these
lines, move I_NEW checks upward as well (sometimes taking I_FREEING etc
checks with them too -- this shouldn't be a problem should it?)

Signed-off-by: Nick Piggin <npiggin@suse.de>
Acked-by: Jan Kara <jack@suse.cz>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/dquot.c
fs/drop_caches.c
fs/inode.c
fs/notify/inotify/inotify.c

index bca3cac4bee76e831b71f6b59c13641b91e48103..cb1c3bc324defdcf482855940b1fcd6f15e00074 100644 (file)
@@ -789,12 +789,12 @@ static void add_dquot_ref(struct super_block *sb, int type)
 
        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))
+                       continue;
                if (!atomic_read(&inode->i_writecount))
                        continue;
                if (!dqinit_needed(inode, type))
                        continue;
-               if (inode->i_state & (I_FREEING|I_WILL_FREE))
-                       continue;
 
                __iget(inode);
                spin_unlock(&inode_lock);
@@ -870,6 +870,12 @@ static void remove_dquot_ref(struct super_block *sb, int type,
 
        spin_lock(&inode_lock);
        list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
+               /*
+                *  We have to scan also I_NEW inodes because they can already
+                *  have quota pointer initialized. Luckily, we need to touch
+                *  only quota pointers and these have separate locking
+                *  (dqptr_sem).
+                */
                if (!IS_NOQUOTA(inode))
                        remove_inode_dquot_ref(inode, type, tofree_head);
        }
index 3e5637fc377962e1aaca5665f3e03d89366673e3..44d725f612cf346ec2e4d9bf2801913de393b967 100644 (file)
@@ -18,7 +18,7 @@ static void drop_pagecache_sb(struct super_block *sb)
 
        spin_lock(&inode_lock);
        list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
-               if (inode->i_state & (I_FREEING|I_WILL_FREE))
+               if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW))
                        continue;
                if (inode->i_mapping->nrpages == 0)
                        continue;
index 826fb0b9d1c38f4dbe4ad16c6ec938a7e31cdc88..06aa5a1fb61bc883c52420d0f8a546d74429e9f9 100644 (file)
@@ -356,6 +356,8 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose)
                if (tmp == head)
                        break;
                inode = list_entry(tmp, struct inode, i_sb_list);
+               if (inode->i_state & I_NEW)
+                       continue;
                invalidate_inode_buffers(inode);
                if (!atomic_read(&inode->i_count)) {
                        list_move(&inode->i_list, dispose);
index 331f2e88e284e44e373cbda23ab41a024c01c6b1..220c13f0d73d254f757636f6f03501b7fdf1b2fb 100644 (file)
@@ -379,6 +379,14 @@ void inotify_unmount_inodes(struct list_head *list)
                struct inode *need_iput_tmp;
                struct list_head *watches;
 
+               /*
+                * We cannot __iget() an inode in state I_CLEAR, I_FREEING,
+                * I_WILL_FREE, or I_NEW which is fine because by that point
+                * the inode cannot have any associated watches.
+                */
+               if (inode->i_state & (I_CLEAR|I_FREEING|I_WILL_FREE|I_NEW))
+                       continue;
+
                /*
                 * If i_count is zero, the inode cannot have any watches and
                 * doing an __iget/iput with MS_ACTIVE clear would actually
@@ -388,14 +396,6 @@ void inotify_unmount_inodes(struct list_head *list)
                if (!atomic_read(&inode->i_count))
                        continue;
 
-               /*
-                * We cannot __iget() an inode in state I_CLEAR, I_FREEING, or
-                * I_WILL_FREE which is fine because by that point the inode
-                * cannot have any associated watches.
-                */
-               if (inode->i_state & (I_CLEAR | I_FREEING | I_WILL_FREE))
-                       continue;
-
                need_iput_tmp = need_iput;
                need_iput = NULL;
                /* In case inotify_remove_watch_locked() drops a reference. */