fs: move i_sb_list out from under inode_lock
Protect the per-sb inode list with a new global lock inode_sb_list_lock and use it to protect the list manipulations and traversals. This lock replaces the inode_lock as the inodes on the list can be validity checked while holding the inode->i_lock and hence the inode_lock is no longer needed to protect the list. Signed-off-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:

zatwierdzone przez
Al Viro

rodzic
f283c86afe
commit
55fa6091d8
@@ -76,7 +76,7 @@
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/quotaops.h>
|
||||
#include <linux/writeback.h> /* for inode_lock, oddly enough.. */
|
||||
#include "../internal.h" /* ugh */
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
@@ -900,7 +900,7 @@ static void add_dquot_ref(struct super_block *sb, int type)
|
||||
int reserved = 0;
|
||||
#endif
|
||||
|
||||
spin_lock(&inode_lock);
|
||||
spin_lock(&inode_sb_list_lock);
|
||||
list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
|
||||
spin_lock(&inode->i_lock);
|
||||
if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) ||
|
||||
@@ -915,19 +915,23 @@ static void add_dquot_ref(struct super_block *sb, int type)
|
||||
#endif
|
||||
__iget(inode);
|
||||
spin_unlock(&inode->i_lock);
|
||||
spin_unlock(&inode_lock);
|
||||
spin_unlock(&inode_sb_list_lock);
|
||||
|
||||
iput(old_inode);
|
||||
__dquot_initialize(inode, type);
|
||||
/* We hold a reference to 'inode' so it couldn't have been
|
||||
* removed from s_inodes list while we dropped the inode_lock.
|
||||
* We cannot iput the inode now as we can be holding the last
|
||||
* reference and we cannot iput it under inode_lock. So we
|
||||
* keep the reference and iput it later. */
|
||||
|
||||
/*
|
||||
* We hold a reference to 'inode' so it couldn't have been
|
||||
* removed from s_inodes list while we dropped the
|
||||
* inode_sb_list_lock We cannot iput the inode now as we can be
|
||||
* holding the last reference and we cannot iput it under
|
||||
* inode_sb_list_lock. So we keep the reference and iput it
|
||||
* later.
|
||||
*/
|
||||
old_inode = inode;
|
||||
spin_lock(&inode_lock);
|
||||
spin_lock(&inode_sb_list_lock);
|
||||
}
|
||||
spin_unlock(&inode_lock);
|
||||
spin_unlock(&inode_sb_list_lock);
|
||||
iput(old_inode);
|
||||
|
||||
#ifdef CONFIG_QUOTA_DEBUG
|
||||
@@ -1008,7 +1012,7 @@ static void remove_dquot_ref(struct super_block *sb, int type,
|
||||
struct inode *inode;
|
||||
int reserved = 0;
|
||||
|
||||
spin_lock(&inode_lock);
|
||||
spin_lock(&inode_sb_list_lock);
|
||||
list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
|
||||
/*
|
||||
* We have to scan also I_NEW inodes because they can already
|
||||
@@ -1022,7 +1026,7 @@ static void remove_dquot_ref(struct super_block *sb, int type,
|
||||
remove_inode_dquot_ref(inode, type, tofree_head);
|
||||
}
|
||||
}
|
||||
spin_unlock(&inode_lock);
|
||||
spin_unlock(&inode_sb_list_lock);
|
||||
#ifdef CONFIG_QUOTA_DEBUG
|
||||
if (reserved) {
|
||||
printk(KERN_WARNING "VFS (%s): Writes happened after quota"
|
||||
|
Reference in New Issue
Block a user