Commit aabb8fdb authored by Nick Piggin's avatar Nick Piggin Committed by Al Viro

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: default avatarNick Piggin <npiggin@suse.de>
Acked-by: default avatarJan Kara <jack@suse.cz>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 1bd79035
...@@ -789,12 +789,12 @@ static void add_dquot_ref(struct super_block *sb, int type) ...@@ -789,12 +789,12 @@ static void add_dquot_ref(struct super_block *sb, int type)
spin_lock(&inode_lock); spin_lock(&inode_lock);
list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { 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)) if (!atomic_read(&inode->i_writecount))
continue; continue;
if (!dqinit_needed(inode, type)) if (!dqinit_needed(inode, type))
continue; continue;
if (inode->i_state & (I_FREEING|I_WILL_FREE))
continue;
__iget(inode); __iget(inode);
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
...@@ -870,6 +870,12 @@ static void remove_dquot_ref(struct super_block *sb, int type, ...@@ -870,6 +870,12 @@ static void remove_dquot_ref(struct super_block *sb, int type,
spin_lock(&inode_lock); spin_lock(&inode_lock);
list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { 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)) if (!IS_NOQUOTA(inode))
remove_inode_dquot_ref(inode, type, tofree_head); remove_inode_dquot_ref(inode, type, tofree_head);
} }
......
...@@ -18,7 +18,7 @@ static void drop_pagecache_sb(struct super_block *sb) ...@@ -18,7 +18,7 @@ static void drop_pagecache_sb(struct super_block *sb)
spin_lock(&inode_lock); spin_lock(&inode_lock);
list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { 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; continue;
if (inode->i_mapping->nrpages == 0) if (inode->i_mapping->nrpages == 0)
continue; continue;
......
...@@ -356,6 +356,8 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose) ...@@ -356,6 +356,8 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose)
if (tmp == head) if (tmp == head)
break; break;
inode = list_entry(tmp, struct inode, i_sb_list); inode = list_entry(tmp, struct inode, i_sb_list);
if (inode->i_state & I_NEW)
continue;
invalidate_inode_buffers(inode); invalidate_inode_buffers(inode);
if (!atomic_read(&inode->i_count)) { if (!atomic_read(&inode->i_count)) {
list_move(&inode->i_list, dispose); list_move(&inode->i_list, dispose);
......
...@@ -379,6 +379,14 @@ void inotify_unmount_inodes(struct list_head *list) ...@@ -379,6 +379,14 @@ void inotify_unmount_inodes(struct list_head *list)
struct inode *need_iput_tmp; struct inode *need_iput_tmp;
struct list_head *watches; 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 * If i_count is zero, the inode cannot have any watches and
* doing an __iget/iput with MS_ACTIVE clear would actually * doing an __iget/iput with MS_ACTIVE clear would actually
...@@ -388,14 +396,6 @@ void inotify_unmount_inodes(struct list_head *list) ...@@ -388,14 +396,6 @@ void inotify_unmount_inodes(struct list_head *list)
if (!atomic_read(&inode->i_count)) if (!atomic_read(&inode->i_count))
continue; 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_tmp = need_iput;
need_iput = NULL; need_iput = NULL;
/* In case inotify_remove_watch_locked() drops a reference. */ /* In case inotify_remove_watch_locked() drops a reference. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment