diff options
author | Christoph Hellwig <hch@lst.de> | 2007-02-12 03:51:58 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-12 12:48:28 -0500 |
commit | d003fb70fd356d0684ee0cd37a785e058c8678de (patch) | |
tree | 2367a8afa16defd85633665fbdb2a9192cbe6081 | |
parent | fb58b7316a99703afb8d076b0e5f3e1e387e4b30 (diff) |
[PATCH] remove sb->s_files and file_list_lock usage in dquot.c
Iterate over sb->s_inodes instead of sb->s_files in add_dquot_ref. This
reduces list search and lock hold time aswell as getting rid of one of the
few uses of file_list_lock which Ingo identified as a scalability problem.
Previously we called dq_op->initialize for every inode handing of a
writeable file that wasn't initialized before. Now we're calling it for
every inode that has a non-zero i_writecount, aka a writeable file
descriptor refering to it.
Thanks a lot to Jan Kara for running this patch through his quota test
harness.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/dquot.c | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/fs/dquot.c b/fs/dquot.c index 5bdc4b2a872a..9eb166f91489 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -688,23 +688,27 @@ static int dqinit_needed(struct inode *inode, int type) | |||
688 | /* This routine is guarded by dqonoff_mutex mutex */ | 688 | /* This routine is guarded by dqonoff_mutex mutex */ |
689 | static void add_dquot_ref(struct super_block *sb, int type) | 689 | static void add_dquot_ref(struct super_block *sb, int type) |
690 | { | 690 | { |
691 | struct list_head *p; | 691 | struct inode *inode; |
692 | 692 | ||
693 | restart: | 693 | restart: |
694 | file_list_lock(); | 694 | spin_lock(&inode_lock); |
695 | list_for_each(p, &sb->s_files) { | 695 | list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { |
696 | struct file *filp = list_entry(p, struct file, f_u.fu_list); | 696 | if (!atomic_read(&inode->i_writecount)) |
697 | struct inode *inode = filp->f_path.dentry->d_inode; | 697 | continue; |
698 | if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) { | 698 | if (!dqinit_needed(inode, type)) |
699 | struct dentry *dentry = dget(filp->f_path.dentry); | 699 | continue; |
700 | file_list_unlock(); | 700 | if (inode->i_state & (I_FREEING|I_WILL_FREE)) |
701 | sb->dq_op->initialize(inode, type); | 701 | continue; |
702 | dput(dentry); | 702 | |
703 | /* As we may have blocked we had better restart... */ | 703 | __iget(inode); |
704 | goto restart; | 704 | spin_unlock(&inode_lock); |
705 | } | 705 | |
706 | sb->dq_op->initialize(inode, type); | ||
707 | iput(inode); | ||
708 | /* As we may have blocked we had better restart... */ | ||
709 | goto restart; | ||
706 | } | 710 | } |
707 | file_list_unlock(); | 711 | spin_unlock(&inode_lock); |
708 | } | 712 | } |
709 | 713 | ||
710 | /* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */ | 714 | /* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */ |