aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-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 f11255b18b58..6c849de5dc8f 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -229,6 +229,8 @@ static struct hlist_head *dquot_hash;
229struct dqstats dqstats; 229struct dqstats dqstats;
230EXPORT_SYMBOL(dqstats); 230EXPORT_SYMBOL(dqstats);
231 231
232static qsize_t inode_get_rsv_space(struct inode *inode);
233
232static inline unsigned int 234static inline unsigned int
233hashfn(const struct super_block *sb, unsigned int id, int type) 235hashfn(const struct super_block *sb, unsigned int id, int type)
234{ 236{
@@ -844,11 +846,14 @@ static int dqinit_needed(struct inode *inode, int type)
844static void add_dquot_ref(struct super_block *sb, int type) 846static void add_dquot_ref(struct super_block *sb, int type)
845{ 847{
846 struct inode *inode, *old_inode = NULL; 848 struct inode *inode, *old_inode = NULL;
849 int reserved = 0;
847 850
848 spin_lock(&inode_lock); 851 spin_lock(&inode_lock);
849 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { 852 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
850 if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW)) 853 if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW))
851 continue; 854 continue;
855 if (unlikely(inode_get_rsv_space(inode) > 0))
856 reserved = 1;
852 if (!atomic_read(&inode->i_writecount)) 857 if (!atomic_read(&inode->i_writecount))
853 continue; 858 continue;
854 if (!dqinit_needed(inode, type)) 859 if (!dqinit_needed(inode, type))
@@ -869,6 +874,12 @@ static void add_dquot_ref(struct super_block *sb, int type)
869 } 874 }
870 spin_unlock(&inode_lock); 875 spin_unlock(&inode_lock);
871 iput(old_inode); 876 iput(old_inode);
877
878 if (reserved) {
879 printk(KERN_WARNING "VFS (%s): Writes happened before quota"
880 " was turned on thus quota information is probably "
881 "inconsistent. Please run quotacheck(8).\n", sb->s_id);
882 }
872} 883}
873 884
874/* 885/*
@@ -982,10 +993,12 @@ static inline void dquot_resv_space(struct dquot *dquot, qsize_t number)
982/* 993/*
983 * Claim reserved quota space 994 * Claim reserved quota space
984 */ 995 */
985static void dquot_claim_reserved_space(struct dquot *dquot, 996static void dquot_claim_reserved_space(struct dquot *dquot, qsize_t number)
986 qsize_t number)
987{ 997{
988 WARN_ON(dquot->dq_dqb.dqb_rsvspace < number); 998 if (dquot->dq_dqb.dqb_rsvspace < number) {
999 WARN_ON_ONCE(1);
1000 number = dquot->dq_dqb.dqb_rsvspace;
1001 }
989 dquot->dq_dqb.dqb_curspace += number; 1002 dquot->dq_dqb.dqb_curspace += number;
990 dquot->dq_dqb.dqb_rsvspace -= number; 1003 dquot->dq_dqb.dqb_rsvspace -= number;
991} 1004}
@@ -993,7 +1006,12 @@ static void dquot_claim_reserved_space(struct dquot *dquot,
993static inline 1006static inline
994void dquot_free_reserved_space(struct dquot *dquot, qsize_t number) 1007void dquot_free_reserved_space(struct dquot *dquot, qsize_t number)
995{ 1008{
996 dquot->dq_dqb.dqb_rsvspace -= number; 1009 if (dquot->dq_dqb.dqb_rsvspace >= number)
1010 dquot->dq_dqb.dqb_rsvspace -= number;
1011 else {
1012 WARN_ON_ONCE(1);
1013 dquot->dq_dqb.dqb_rsvspace = 0;
1014 }
997} 1015}
998 1016
999static void dquot_decr_inodes(struct dquot *dquot, qsize_t number) 1017static void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
@@ -1246,6 +1264,7 @@ static int info_bdq_free(struct dquot *dquot, qsize_t space)
1246 return QUOTA_NL_BHARDBELOW; 1264 return QUOTA_NL_BHARDBELOW;
1247 return QUOTA_NL_NOWARN; 1265 return QUOTA_NL_NOWARN;
1248} 1266}
1267
1249/* 1268/*
1250 * Initialize quota pointers in inode 1269 * Initialize quota pointers in inode
1251 * We do things in a bit complicated way but by that we avoid calling 1270 * We do things in a bit complicated way but by that we avoid calling
@@ -1257,6 +1276,7 @@ int dquot_initialize(struct inode *inode, int type)
1257 int cnt, ret = 0; 1276 int cnt, ret = 0;
1258 struct dquot *got[MAXQUOTAS] = { NULL, NULL }; 1277 struct dquot *got[MAXQUOTAS] = { NULL, NULL };
1259 struct super_block *sb = inode->i_sb; 1278 struct super_block *sb = inode->i_sb;
1279 qsize_t rsv;
1260 1280
1261 /* First test before acquiring mutex - solves deadlocks when we 1281 /* First test before acquiring mutex - solves deadlocks when we
1262 * re-enter the quota code and are already holding the mutex */ 1282 * re-enter the quota code and are already holding the mutex */
@@ -1290,6 +1310,13 @@ int dquot_initialize(struct inode *inode, int type)
1290 if (!inode->i_dquot[cnt]) { 1310 if (!inode->i_dquot[cnt]) {
1291 inode->i_dquot[cnt] = got[cnt]; 1311 inode->i_dquot[cnt] = got[cnt];
1292 got[cnt] = NULL; 1312 got[cnt] = NULL;
1313 /*
1314 * Make quota reservation system happy if someone
1315 * did a write before quota was turned on
1316 */
1317 rsv = inode_get_rsv_space(inode);
1318 if (unlikely(rsv))
1319 dquot_resv_space(inode->i_dquot[cnt], rsv);
1293 } 1320 }
1294 } 1321 }
1295out_err: 1322out_err: