aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2009-03-11 16:17:36 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2009-03-27 14:44:05 -0400
commitaabb8fdb41128705fd1627f56fdd571e45fdbcdb (patch)
treebae6e9abf167cf20b9a2d3e5c38520d3f17b777d /fs
parent1bd7903560f1f713e85188a5aaf4d2428b6c8b50 (diff)
fs: avoid I_NEW inodes
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/dquot.c10
-rw-r--r--fs/drop_caches.c2
-rw-r--r--fs/inode.c2
-rw-r--r--fs/notify/inotify/inotify.c16
4 files changed, 19 insertions, 11 deletions
diff --git a/fs/dquot.c b/fs/dquot.c
index bca3cac4bee7..cb1c3bc324de 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -789,12 +789,12 @@ static void add_dquot_ref(struct super_block *sb, int type)
789 789
790 spin_lock(&inode_lock); 790 spin_lock(&inode_lock);
791 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { 791 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
792 if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW))
793 continue;
792 if (!atomic_read(&inode->i_writecount)) 794 if (!atomic_read(&inode->i_writecount))
793 continue; 795 continue;
794 if (!dqinit_needed(inode, type)) 796 if (!dqinit_needed(inode, type))
795 continue; 797 continue;
796 if (inode->i_state & (I_FREEING|I_WILL_FREE))
797 continue;
798 798
799 __iget(inode); 799 __iget(inode);
800 spin_unlock(&inode_lock); 800 spin_unlock(&inode_lock);
@@ -870,6 +870,12 @@ static void remove_dquot_ref(struct super_block *sb, int type,
870 870
871 spin_lock(&inode_lock); 871 spin_lock(&inode_lock);
872 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { 872 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
873 /*
874 * We have to scan also I_NEW inodes because they can already
875 * have quota pointer initialized. Luckily, we need to touch
876 * only quota pointers and these have separate locking
877 * (dqptr_sem).
878 */
873 if (!IS_NOQUOTA(inode)) 879 if (!IS_NOQUOTA(inode))
874 remove_inode_dquot_ref(inode, type, tofree_head); 880 remove_inode_dquot_ref(inode, type, tofree_head);
875 } 881 }
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
index 3e5637fc3779..44d725f612cf 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -18,7 +18,7 @@ static void drop_pagecache_sb(struct super_block *sb)
18 18
19 spin_lock(&inode_lock); 19 spin_lock(&inode_lock);
20 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { 20 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
21 if (inode->i_state & (I_FREEING|I_WILL_FREE)) 21 if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW))
22 continue; 22 continue;
23 if (inode->i_mapping->nrpages == 0) 23 if (inode->i_mapping->nrpages == 0)
24 continue; 24 continue;
diff --git a/fs/inode.c b/fs/inode.c
index 826fb0b9d1c3..06aa5a1fb61b 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -356,6 +356,8 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose)
356 if (tmp == head) 356 if (tmp == head)
357 break; 357 break;
358 inode = list_entry(tmp, struct inode, i_sb_list); 358 inode = list_entry(tmp, struct inode, i_sb_list);
359 if (inode->i_state & I_NEW)
360 continue;
359 invalidate_inode_buffers(inode); 361 invalidate_inode_buffers(inode);
360 if (!atomic_read(&inode->i_count)) { 362 if (!atomic_read(&inode->i_count)) {
361 list_move(&inode->i_list, dispose); 363 list_move(&inode->i_list, dispose);
diff --git a/fs/notify/inotify/inotify.c b/fs/notify/inotify/inotify.c
index 331f2e88e284..220c13f0d73d 100644
--- a/fs/notify/inotify/inotify.c
+++ b/fs/notify/inotify/inotify.c
@@ -380,6 +380,14 @@ void inotify_unmount_inodes(struct list_head *list)
380 struct list_head *watches; 380 struct list_head *watches;
381 381
382 /* 382 /*
383 * We cannot __iget() an inode in state I_CLEAR, I_FREEING,
384 * I_WILL_FREE, or I_NEW which is fine because by that point
385 * the inode cannot have any associated watches.
386 */
387 if (inode->i_state & (I_CLEAR|I_FREEING|I_WILL_FREE|I_NEW))
388 continue;
389
390 /*
383 * If i_count is zero, the inode cannot have any watches and 391 * If i_count is zero, the inode cannot have any watches and
384 * doing an __iget/iput with MS_ACTIVE clear would actually 392 * doing an __iget/iput with MS_ACTIVE clear would actually
385 * evict all inodes with zero i_count from icache which is 393 * evict all inodes with zero i_count from icache which is
@@ -388,14 +396,6 @@ void inotify_unmount_inodes(struct list_head *list)
388 if (!atomic_read(&inode->i_count)) 396 if (!atomic_read(&inode->i_count))
389 continue; 397 continue;
390 398
391 /*
392 * We cannot __iget() an inode in state I_CLEAR, I_FREEING, or
393 * I_WILL_FREE which is fine because by that point the inode
394 * cannot have any associated watches.
395 */
396 if (inode->i_state & (I_CLEAR | I_FREEING | I_WILL_FREE))
397 continue;
398
399 need_iput_tmp = need_iput; 399 need_iput_tmp = need_iput;
400 need_iput = NULL; 400 need_iput = NULL;
401 /* In case inotify_remove_watch_locked() drops a reference. */ 401 /* In case inotify_remove_watch_locked() drops a reference. */