aboutsummaryrefslogtreecommitdiffstats
path: root/fs/quota
diff options
context:
space:
mode:
Diffstat (limited to 'fs/quota')
-rw-r--r--fs/quota/dquot.c43
1 files changed, 24 insertions, 19 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index b59ee61f4b9a..d3c032f5fa0a 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -76,7 +76,7 @@
76#include <linux/buffer_head.h> 76#include <linux/buffer_head.h>
77#include <linux/capability.h> 77#include <linux/capability.h>
78#include <linux/quotaops.h> 78#include <linux/quotaops.h>
79#include <linux/writeback.h> /* for inode_lock, oddly enough.. */ 79#include "../internal.h" /* ugh */
80 80
81#include <asm/uaccess.h> 81#include <asm/uaccess.h>
82 82
@@ -895,33 +895,38 @@ static void add_dquot_ref(struct super_block *sb, int type)
895 int reserved = 0; 895 int reserved = 0;
896#endif 896#endif
897 897
898 spin_lock(&inode_lock); 898 spin_lock(&inode_sb_list_lock);
899 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { 899 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
900 if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) 900 spin_lock(&inode->i_lock);
901 if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) ||
902 !atomic_read(&inode->i_writecount) ||
903 !dqinit_needed(inode, type)) {
904 spin_unlock(&inode->i_lock);
901 continue; 905 continue;
906 }
902#ifdef CONFIG_QUOTA_DEBUG 907#ifdef CONFIG_QUOTA_DEBUG
903 if (unlikely(inode_get_rsv_space(inode) > 0)) 908 if (unlikely(inode_get_rsv_space(inode) > 0))
904 reserved = 1; 909 reserved = 1;
905#endif 910#endif
906 if (!atomic_read(&inode->i_writecount))
907 continue;
908 if (!dqinit_needed(inode, type))
909 continue;
910
911 __iget(inode); 911 __iget(inode);
912 spin_unlock(&inode_lock); 912 spin_unlock(&inode->i_lock);
913 spin_unlock(&inode_sb_list_lock);
913 914
914 iput(old_inode); 915 iput(old_inode);
915 __dquot_initialize(inode, type); 916 __dquot_initialize(inode, type);
916 /* We hold a reference to 'inode' so it couldn't have been 917
917 * removed from s_inodes list while we dropped the inode_lock. 918 /*
918 * We cannot iput the inode now as we can be holding the last 919 * We hold a reference to 'inode' so it couldn't have been
919 * reference and we cannot iput it under inode_lock. So we 920 * removed from s_inodes list while we dropped the
920 * keep the reference and iput it later. */ 921 * inode_sb_list_lock We cannot iput the inode now as we can be
922 * holding the last reference and we cannot iput it under
923 * inode_sb_list_lock. So we keep the reference and iput it
924 * later.
925 */
921 old_inode = inode; 926 old_inode = inode;
922 spin_lock(&inode_lock); 927 spin_lock(&inode_sb_list_lock);
923 } 928 }
924 spin_unlock(&inode_lock); 929 spin_unlock(&inode_sb_list_lock);
925 iput(old_inode); 930 iput(old_inode);
926 931
927#ifdef CONFIG_QUOTA_DEBUG 932#ifdef CONFIG_QUOTA_DEBUG
@@ -946,7 +951,7 @@ static inline int dqput_blocks(struct dquot *dquot)
946 951
947/* 952/*
948 * Remove references to dquots from inode and add dquot to list for freeing 953 * Remove references to dquots from inode and add dquot to list for freeing
949 * if we have the last referece to dquot 954 * if we have the last reference to dquot
950 * We can't race with anybody because we hold dqptr_sem for writing... 955 * We can't race with anybody because we hold dqptr_sem for writing...
951 */ 956 */
952static int remove_inode_dquot_ref(struct inode *inode, int type, 957static int remove_inode_dquot_ref(struct inode *inode, int type,
@@ -1002,7 +1007,7 @@ static void remove_dquot_ref(struct super_block *sb, int type,
1002 struct inode *inode; 1007 struct inode *inode;
1003 int reserved = 0; 1008 int reserved = 0;
1004 1009
1005 spin_lock(&inode_lock); 1010 spin_lock(&inode_sb_list_lock);
1006 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { 1011 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
1007 /* 1012 /*
1008 * We have to scan also I_NEW inodes because they can already 1013 * We have to scan also I_NEW inodes because they can already
@@ -1016,7 +1021,7 @@ static void remove_dquot_ref(struct super_block *sb, int type,
1016 remove_inode_dquot_ref(inode, type, tofree_head); 1021 remove_inode_dquot_ref(inode, type, tofree_head);
1017 } 1022 }
1018 } 1023 }
1019 spin_unlock(&inode_lock); 1024 spin_unlock(&inode_sb_list_lock);
1020#ifdef CONFIG_QUOTA_DEBUG 1025#ifdef CONFIG_QUOTA_DEBUG
1021 if (reserved) { 1026 if (reserved) {
1022 printk(KERN_WARNING "VFS (%s): Writes happened after quota" 1027 printk(KERN_WARNING "VFS (%s): Writes happened after quota"