diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/dquot.c | 117 |
1 files changed, 86 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 | } |