diff options
Diffstat (limited to 'fs/quota')
-rw-r--r-- | fs/quota/dquot.c | 43 |
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 | */ |
952 | static int remove_inode_dquot_ref(struct inode *inode, int type, | 957 | static 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" |