aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2010-02-09 12:20:39 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-04-01 19:02:12 -0400
commite58bb78fcd092688765b18574ea4055c2509aee5 (patch)
tree7c8cb63e9288239024652660d3295e605f75f69e
parent1f371c1a285e3dab9c6951cb9f4410c17bcb6ba1 (diff)
quota: Fix warning when a delayed write happens before quota is enabled
commit 0a5a9c725512461d19397490f3adf29931dca1f2 upstream. If a delayed-allocation write happens before quota is enabled, the kernel spits out a warning: WARNING: at fs/quota/dquot.c:988 dquot_claim_space+0x77/0x112() because the fact that user has some delayed allocation is not recorded in quota structure. Make dquot_initialize() update amount of reserved space for user if it sees inode has some space reserved. Also make sure that reserved quota space does not go negative and we warn about the filesystem bug just once. Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--fs/quota/dquot.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 7b980954993b..6e722c11ce13 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -225,6 +225,8 @@ static struct hlist_head *dquot_hash;
225struct dqstats dqstats; 225struct dqstats dqstats;
226EXPORT_SYMBOL(dqstats); 226EXPORT_SYMBOL(dqstats);
227 227
228static qsize_t inode_get_rsv_space(struct inode *inode);
229
228static inline unsigned int 230static inline unsigned int
229hashfn(const struct super_block *sb, unsigned int id, int type) 231hashfn(const struct super_block *sb, unsigned int id, int type)
230{ 232{
@@ -840,11 +842,14 @@ static int dqinit_needed(struct inode *inode, int type)
840static void add_dquot_ref(struct super_block *sb, int type) 842static void add_dquot_ref(struct super_block *sb, int type)
841{ 843{
842 struct inode *inode, *old_inode = NULL; 844 struct inode *inode, *old_inode = NULL;
845 int reserved = 0;
843 846
844 spin_lock(&inode_lock); 847 spin_lock(&inode_lock);
845 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { 848 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
846 if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW)) 849 if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW))
847 continue; 850 continue;
851 if (unlikely(inode_get_rsv_space(inode) > 0))
852 reserved = 1;
848 if (!atomic_read(&inode->i_writecount)) 853 if (!atomic_read(&inode->i_writecount))
849 continue; 854 continue;
850 if (!dqinit_needed(inode, type)) 855 if (!dqinit_needed(inode, type))
@@ -865,6 +870,12 @@ static void add_dquot_ref(struct super_block *sb, int type)
865 } 870 }
866 spin_unlock(&inode_lock); 871 spin_unlock(&inode_lock);
867 iput(old_inode); 872 iput(old_inode);
873
874 if (reserved) {
875 printk(KERN_WARNING "VFS (%s): Writes happened before quota"
876 " was turned on thus quota information is probably "
877 "inconsistent. Please run quotacheck(8).\n", sb->s_id);
878 }
868} 879}
869 880
870/* 881/*
@@ -978,10 +989,12 @@ static inline void dquot_resv_space(struct dquot *dquot, qsize_t number)
978/* 989/*
979 * Claim reserved quota space 990 * Claim reserved quota space
980 */ 991 */
981static void dquot_claim_reserved_space(struct dquot *dquot, 992static void dquot_claim_reserved_space(struct dquot *dquot, qsize_t number)
982 qsize_t number)
983{ 993{
984 WARN_ON(dquot->dq_dqb.dqb_rsvspace < number); 994 if (dquot->dq_dqb.dqb_rsvspace < number) {
995 WARN_ON_ONCE(1);
996 number = dquot->dq_dqb.dqb_rsvspace;
997 }
985 dquot->dq_dqb.dqb_curspace += number; 998 dquot->dq_dqb.dqb_curspace += number;
986 dquot->dq_dqb.dqb_rsvspace -= number; 999 dquot->dq_dqb.dqb_rsvspace -= number;
987} 1000}
@@ -989,7 +1002,12 @@ static void dquot_claim_reserved_space(struct dquot *dquot,
989static inline 1002static inline
990void dquot_free_reserved_space(struct dquot *dquot, qsize_t number) 1003void dquot_free_reserved_space(struct dquot *dquot, qsize_t number)
991{ 1004{
992 dquot->dq_dqb.dqb_rsvspace -= number; 1005 if (dquot->dq_dqb.dqb_rsvspace >= number)
1006 dquot->dq_dqb.dqb_rsvspace -= number;
1007 else {
1008 WARN_ON_ONCE(1);
1009 dquot->dq_dqb.dqb_rsvspace = 0;
1010 }
993} 1011}
994 1012
995static void dquot_decr_inodes(struct dquot *dquot, qsize_t number) 1013static void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
@@ -1242,6 +1260,7 @@ static int info_bdq_free(struct dquot *dquot, qsize_t space)
1242 return QUOTA_NL_BHARDBELOW; 1260 return QUOTA_NL_BHARDBELOW;
1243 return QUOTA_NL_NOWARN; 1261 return QUOTA_NL_NOWARN;
1244} 1262}
1263
1245/* 1264/*
1246 * Initialize quota pointers in inode 1265 * Initialize quota pointers in inode
1247 * We do things in a bit complicated way but by that we avoid calling 1266 * We do things in a bit complicated way but by that we avoid calling
@@ -1253,6 +1272,7 @@ int dquot_initialize(struct inode *inode, int type)
1253 int cnt, ret = 0; 1272 int cnt, ret = 0;
1254 struct dquot *got[MAXQUOTAS] = { NULL, NULL }; 1273 struct dquot *got[MAXQUOTAS] = { NULL, NULL };
1255 struct super_block *sb = inode->i_sb; 1274 struct super_block *sb = inode->i_sb;
1275 qsize_t rsv;
1256 1276
1257 /* First test before acquiring mutex - solves deadlocks when we 1277 /* First test before acquiring mutex - solves deadlocks when we
1258 * re-enter the quota code and are already holding the mutex */ 1278 * re-enter the quota code and are already holding the mutex */
@@ -1287,6 +1307,13 @@ int dquot_initialize(struct inode *inode, int type)
1287 if (!inode->i_dquot[cnt]) { 1307 if (!inode->i_dquot[cnt]) {
1288 inode->i_dquot[cnt] = got[cnt]; 1308 inode->i_dquot[cnt] = got[cnt];
1289 got[cnt] = NULL; 1309 got[cnt] = NULL;
1310 /*
1311 * Make quota reservation system happy if someone
1312 * did a write before quota was turned on
1313 */
1314 rsv = inode_get_rsv_space(inode);
1315 if (unlikely(rsv))
1316 dquot_resv_space(inode->i_dquot[cnt], rsv);
1290 } 1317 }
1291 } 1318 }
1292out_err: 1319out_err: