diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/quota/dquot.c | 35 |
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; | |||
229 | struct dqstats dqstats; | 229 | struct dqstats dqstats; |
230 | EXPORT_SYMBOL(dqstats); | 230 | EXPORT_SYMBOL(dqstats); |
231 | 231 | ||
232 | static qsize_t inode_get_rsv_space(struct inode *inode); | ||
233 | |||
232 | static inline unsigned int | 234 | static inline unsigned int |
233 | hashfn(const struct super_block *sb, unsigned int id, int type) | 235 | hashfn(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) | |||
844 | static void add_dquot_ref(struct super_block *sb, int type) | 846 | static 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 | */ |
985 | static void dquot_claim_reserved_space(struct dquot *dquot, | 996 | static 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, | |||
993 | static inline | 1006 | static inline |
994 | void dquot_free_reserved_space(struct dquot *dquot, qsize_t number) | 1007 | void 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 | ||
999 | static void dquot_decr_inodes(struct dquot *dquot, qsize_t number) | 1017 | static 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 | } |
1295 | out_err: | 1322 | out_err: |