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 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: