diff options
-rw-r--r-- | fs/dquot.c | 117 | ||||
-rw-r--r-- | include/linux/quota.h | 3 | ||||
-rw-r--r-- | include/linux/quotaops.h | 21 |
3 files changed, 110 insertions, 31 deletions
diff --git a/fs/dquot.c b/fs/dquot.c index bca3cac4bee7..9b1c4d3c9d83 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -899,6 +899,11 @@ static inline void dquot_incr_space(struct dquot *dquot, qsize_t number) | |||
899 | dquot->dq_dqb.dqb_curspace += number; | 899 | dquot->dq_dqb.dqb_curspace += number; |
900 | } | 900 | } |
901 | 901 | ||
902 | static inline void dquot_resv_space(struct dquot *dquot, qsize_t number) | ||
903 | { | ||
904 | dquot->dq_dqb.dqb_rsvspace += number; | ||
905 | } | ||
906 | |||
902 | static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number) | 907 | static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number) |
903 | { | 908 | { |
904 | if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE || | 909 | if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE || |
@@ -1068,7 +1073,11 @@ err_out: | |||
1068 | kfree_skb(skb); | 1073 | kfree_skb(skb); |
1069 | } | 1074 | } |
1070 | #endif | 1075 | #endif |
1071 | 1076 | /* | |
1077 | * Write warnings to the console and send warning messages over netlink. | ||
1078 | * | ||
1079 | * Note that this function can sleep. | ||
1080 | */ | ||
1072 | static inline void flush_warnings(struct dquot * const *dquots, char *warntype) | 1081 | static inline void flush_warnings(struct dquot * const *dquots, char *warntype) |
1073 | { | 1082 | { |
1074 | int i; | 1083 | int i; |
@@ -1129,13 +1138,18 @@ static int check_idq(struct dquot *dquot, qsize_t inodes, char *warntype) | |||
1129 | /* needs dq_data_lock */ | 1138 | /* needs dq_data_lock */ |
1130 | static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *warntype) | 1139 | static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *warntype) |
1131 | { | 1140 | { |
1141 | qsize_t tspace; | ||
1142 | |||
1132 | *warntype = QUOTA_NL_NOWARN; | 1143 | *warntype = QUOTA_NL_NOWARN; |
1133 | if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) || | 1144 | if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) || |
1134 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) | 1145 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) |
1135 | return QUOTA_OK; | 1146 | return QUOTA_OK; |
1136 | 1147 | ||
1148 | tspace = dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace | ||
1149 | + space; | ||
1150 | |||
1137 | if (dquot->dq_dqb.dqb_bhardlimit && | 1151 | if (dquot->dq_dqb.dqb_bhardlimit && |
1138 | dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bhardlimit && | 1152 | tspace > dquot->dq_dqb.dqb_bhardlimit && |
1139 | !ignore_hardlimit(dquot)) { | 1153 | !ignore_hardlimit(dquot)) { |
1140 | if (!prealloc) | 1154 | if (!prealloc) |
1141 | *warntype = QUOTA_NL_BHARDWARN; | 1155 | *warntype = QUOTA_NL_BHARDWARN; |
@@ -1143,7 +1157,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war | |||
1143 | } | 1157 | } |
1144 | 1158 | ||
1145 | if (dquot->dq_dqb.dqb_bsoftlimit && | 1159 | if (dquot->dq_dqb.dqb_bsoftlimit && |
1146 | dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit && | 1160 | tspace > dquot->dq_dqb.dqb_bsoftlimit && |
1147 | dquot->dq_dqb.dqb_btime && get_seconds() >= dquot->dq_dqb.dqb_btime && | 1161 | dquot->dq_dqb.dqb_btime && get_seconds() >= dquot->dq_dqb.dqb_btime && |
1148 | !ignore_hardlimit(dquot)) { | 1162 | !ignore_hardlimit(dquot)) { |
1149 | if (!prealloc) | 1163 | if (!prealloc) |
@@ -1152,7 +1166,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war | |||
1152 | } | 1166 | } |
1153 | 1167 | ||
1154 | if (dquot->dq_dqb.dqb_bsoftlimit && | 1168 | if (dquot->dq_dqb.dqb_bsoftlimit && |
1155 | dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit && | 1169 | tspace > dquot->dq_dqb.dqb_bsoftlimit && |
1156 | dquot->dq_dqb.dqb_btime == 0) { | 1170 | dquot->dq_dqb.dqb_btime == 0) { |
1157 | if (!prealloc) { | 1171 | if (!prealloc) { |
1158 | *warntype = QUOTA_NL_BSOFTWARN; | 1172 | *warntype = QUOTA_NL_BSOFTWARN; |
@@ -1306,51 +1320,92 @@ void vfs_dq_drop(struct inode *inode) | |||
1306 | /* | 1320 | /* |
1307 | * This operation can block, but only after everything is updated | 1321 | * This operation can block, but only after everything is updated |
1308 | */ | 1322 | */ |
1309 | int dquot_alloc_space(struct inode *inode, qsize_t number, int warn) | 1323 | int __dquot_alloc_space(struct inode *inode, qsize_t number, |
1324 | int warn, int reserve) | ||
1310 | { | 1325 | { |
1311 | int cnt, ret = NO_QUOTA; | 1326 | int cnt, ret = QUOTA_OK; |
1312 | char warntype[MAXQUOTAS]; | 1327 | char warntype[MAXQUOTAS]; |
1313 | 1328 | ||
1314 | /* First test before acquiring mutex - solves deadlocks when we | ||
1315 | * re-enter the quota code and are already holding the mutex */ | ||
1316 | if (IS_NOQUOTA(inode)) { | ||
1317 | out_add: | ||
1318 | inode_add_bytes(inode, number); | ||
1319 | return QUOTA_OK; | ||
1320 | } | ||
1321 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | 1329 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) |
1322 | warntype[cnt] = QUOTA_NL_NOWARN; | 1330 | warntype[cnt] = QUOTA_NL_NOWARN; |
1323 | 1331 | ||
1324 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1325 | if (IS_NOQUOTA(inode)) { /* Now we can do reliable test... */ | ||
1326 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1327 | goto out_add; | ||
1328 | } | ||
1329 | spin_lock(&dq_data_lock); | 1332 | spin_lock(&dq_data_lock); |
1330 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1333 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1331 | if (inode->i_dquot[cnt] == NODQUOT) | 1334 | if (inode->i_dquot[cnt] == NODQUOT) |
1332 | continue; | 1335 | continue; |
1333 | if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt) == NO_QUOTA) | 1336 | if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt) |
1334 | goto warn_put_all; | 1337 | == NO_QUOTA) { |
1338 | ret = NO_QUOTA; | ||
1339 | goto out_unlock; | ||
1340 | } | ||
1335 | } | 1341 | } |
1336 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1342 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
1337 | if (inode->i_dquot[cnt] == NODQUOT) | 1343 | if (inode->i_dquot[cnt] == NODQUOT) |
1338 | continue; | 1344 | continue; |
1339 | dquot_incr_space(inode->i_dquot[cnt], number); | 1345 | if (reserve) |
1346 | dquot_resv_space(inode->i_dquot[cnt], number); | ||
1347 | else | ||
1348 | dquot_incr_space(inode->i_dquot[cnt], number); | ||
1340 | } | 1349 | } |
1341 | inode_add_bytes(inode, number); | 1350 | if (!reserve) |
1342 | ret = QUOTA_OK; | 1351 | inode_add_bytes(inode, number); |
1343 | warn_put_all: | 1352 | out_unlock: |
1344 | spin_unlock(&dq_data_lock); | 1353 | spin_unlock(&dq_data_lock); |
1345 | if (ret == QUOTA_OK) | ||
1346 | /* Dirtify all the dquots - this can block when journalling */ | ||
1347 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | ||
1348 | if (inode->i_dquot[cnt]) | ||
1349 | mark_dquot_dirty(inode->i_dquot[cnt]); | ||
1350 | flush_warnings(inode->i_dquot, warntype); | 1354 | flush_warnings(inode->i_dquot, warntype); |
1355 | return ret; | ||
1356 | } | ||
1357 | |||
1358 | int dquot_alloc_space(struct inode *inode, qsize_t number, int warn) | ||
1359 | { | ||
1360 | int cnt, ret = QUOTA_OK; | ||
1361 | |||
1362 | /* | ||
1363 | * First test before acquiring mutex - solves deadlocks when we | ||
1364 | * re-enter the quota code and are already holding the mutex | ||
1365 | */ | ||
1366 | if (IS_NOQUOTA(inode)) { | ||
1367 | inode_add_bytes(inode, number); | ||
1368 | goto out; | ||
1369 | } | ||
1370 | |||
1371 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1372 | if (IS_NOQUOTA(inode)) { | ||
1373 | inode_add_bytes(inode, number); | ||
1374 | goto out_unlock; | ||
1375 | } | ||
1376 | |||
1377 | ret = __dquot_alloc_space(inode, number, warn, 0); | ||
1378 | if (ret == NO_QUOTA) | ||
1379 | goto out_unlock; | ||
1380 | |||
1381 | /* Dirtify all the dquots - this can block when journalling */ | ||
1382 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | ||
1383 | if (inode->i_dquot[cnt]) | ||
1384 | mark_dquot_dirty(inode->i_dquot[cnt]); | ||
1385 | out_unlock: | ||
1351 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1386 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
1387 | out: | ||
1388 | return ret; | ||
1389 | } | ||
1390 | |||
1391 | int dquot_reserve_space(struct inode *inode, qsize_t number, int warn) | ||
1392 | { | ||
1393 | int ret = QUOTA_OK; | ||
1394 | |||
1395 | if (IS_NOQUOTA(inode)) | ||
1396 | goto out; | ||
1397 | |||
1398 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1399 | if (IS_NOQUOTA(inode)) | ||
1400 | goto out_unlock; | ||
1401 | |||
1402 | ret = __dquot_alloc_space(inode, number, warn, 1); | ||
1403 | out_unlock: | ||
1404 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1405 | out: | ||
1352 | return ret; | 1406 | return ret; |
1353 | } | 1407 | } |
1408 | EXPORT_SYMBOL(dquot_reserve_space); | ||
1354 | 1409 | ||
1355 | /* | 1410 | /* |
1356 | * This operation can block, but only after everything is updated | 1411 | * This operation can block, but only after everything is updated |
@@ -2057,7 +2112,7 @@ static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di) | |||
2057 | spin_lock(&dq_data_lock); | 2112 | spin_lock(&dq_data_lock); |
2058 | di->dqb_bhardlimit = stoqb(dm->dqb_bhardlimit); | 2113 | di->dqb_bhardlimit = stoqb(dm->dqb_bhardlimit); |
2059 | di->dqb_bsoftlimit = stoqb(dm->dqb_bsoftlimit); | 2114 | di->dqb_bsoftlimit = stoqb(dm->dqb_bsoftlimit); |
2060 | di->dqb_curspace = dm->dqb_curspace; | 2115 | di->dqb_curspace = dm->dqb_curspace + dm->dqb_rsvspace; |
2061 | di->dqb_ihardlimit = dm->dqb_ihardlimit; | 2116 | di->dqb_ihardlimit = dm->dqb_ihardlimit; |
2062 | di->dqb_isoftlimit = dm->dqb_isoftlimit; | 2117 | di->dqb_isoftlimit = dm->dqb_isoftlimit; |
2063 | di->dqb_curinodes = dm->dqb_curinodes; | 2118 | di->dqb_curinodes = dm->dqb_curinodes; |
@@ -2097,7 +2152,7 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) | |||
2097 | 2152 | ||
2098 | spin_lock(&dq_data_lock); | 2153 | spin_lock(&dq_data_lock); |
2099 | if (di->dqb_valid & QIF_SPACE) { | 2154 | if (di->dqb_valid & QIF_SPACE) { |
2100 | dm->dqb_curspace = di->dqb_curspace; | 2155 | dm->dqb_curspace = di->dqb_curspace - dm->dqb_rsvspace; |
2101 | check_blim = 1; | 2156 | check_blim = 1; |
2102 | __set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags); | 2157 | __set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags); |
2103 | } | 2158 | } |
diff --git a/include/linux/quota.h b/include/linux/quota.h index d72d5d84fde5..54b837fa64f2 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h | |||
@@ -198,6 +198,7 @@ struct mem_dqblk { | |||
198 | qsize_t dqb_bhardlimit; /* absolute limit on disk blks alloc */ | 198 | qsize_t dqb_bhardlimit; /* absolute limit on disk blks alloc */ |
199 | qsize_t dqb_bsoftlimit; /* preferred limit on disk blks */ | 199 | qsize_t dqb_bsoftlimit; /* preferred limit on disk blks */ |
200 | qsize_t dqb_curspace; /* current used space */ | 200 | qsize_t dqb_curspace; /* current used space */ |
201 | qsize_t dqb_rsvspace; /* current reserved space for delalloc*/ | ||
201 | qsize_t dqb_ihardlimit; /* absolute limit on allocated inodes */ | 202 | qsize_t dqb_ihardlimit; /* absolute limit on allocated inodes */ |
202 | qsize_t dqb_isoftlimit; /* preferred inode limit */ | 203 | qsize_t dqb_isoftlimit; /* preferred inode limit */ |
203 | qsize_t dqb_curinodes; /* current # allocated inodes */ | 204 | qsize_t dqb_curinodes; /* current # allocated inodes */ |
@@ -308,6 +309,8 @@ struct dquot_operations { | |||
308 | int (*release_dquot) (struct dquot *); /* Quota is going to be deleted from disk */ | 309 | int (*release_dquot) (struct dquot *); /* Quota is going to be deleted from disk */ |
309 | int (*mark_dirty) (struct dquot *); /* Dquot is marked dirty */ | 310 | int (*mark_dirty) (struct dquot *); /* Dquot is marked dirty */ |
310 | int (*write_info) (struct super_block *, int); /* Write of quota "superblock" */ | 311 | int (*write_info) (struct super_block *, int); /* Write of quota "superblock" */ |
312 | /* reserve quota for delayed block allocation */ | ||
313 | int (*reserve_space) (struct inode *, qsize_t, int); | ||
311 | }; | 314 | }; |
312 | 315 | ||
313 | /* Operations handling requests from userspace */ | 316 | /* Operations handling requests from userspace */ |
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 0b35b3a1be05..3e3a0d2874d9 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h | |||
@@ -183,6 +183,16 @@ static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr) | |||
183 | return ret; | 183 | return ret; |
184 | } | 184 | } |
185 | 185 | ||
186 | static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr) | ||
187 | { | ||
188 | if (sb_any_quota_active(inode->i_sb)) { | ||
189 | /* Used space is updated in alloc_space() */ | ||
190 | if (inode->i_sb->dq_op->reserve_space(inode, nr, 0) == NO_QUOTA) | ||
191 | return 1; | ||
192 | } | ||
193 | return 0; | ||
194 | } | ||
195 | |||
186 | static inline int vfs_dq_alloc_inode(struct inode *inode) | 196 | static inline int vfs_dq_alloc_inode(struct inode *inode) |
187 | { | 197 | { |
188 | if (sb_any_quota_active(inode->i_sb)) { | 198 | if (sb_any_quota_active(inode->i_sb)) { |
@@ -339,6 +349,11 @@ static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr) | |||
339 | return 0; | 349 | return 0; |
340 | } | 350 | } |
341 | 351 | ||
352 | static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr) | ||
353 | { | ||
354 | return 0; | ||
355 | } | ||
356 | |||
342 | static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr) | 357 | static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr) |
343 | { | 358 | { |
344 | inode_sub_bytes(inode, nr); | 359 | inode_sub_bytes(inode, nr); |
@@ -376,6 +391,12 @@ static inline int vfs_dq_alloc_block(struct inode *inode, qsize_t nr) | |||
376 | nr << inode->i_sb->s_blocksize_bits); | 391 | nr << inode->i_sb->s_blocksize_bits); |
377 | } | 392 | } |
378 | 393 | ||
394 | static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr) | ||
395 | { | ||
396 | return vfs_dq_reserve_space(inode, | ||
397 | nr << inode->i_blkbits); | ||
398 | } | ||
399 | |||
379 | static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr) | 400 | static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr) |
380 | { | 401 | { |
381 | vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits); | 402 | vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits); |