diff options
author | Dmitry Monakhov <dmonakhov@openvz.org> | 2009-12-14 07:21:13 -0500 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2009-12-23 07:33:54 -0500 |
commit | fd8fbfc1709822bd94247c5b2ab15a5f5041e103 (patch) | |
tree | 225be57d6afafcd7c893c5b9026719f9b23def69 /fs/quota/dquot.c | |
parent | b462707e7ccad058ae151e5c5b06eb5cadcb737f (diff) |
quota: decouple fs reserved space from quota reservation
Currently inode_reservation is managed by fs itself and this
reservation is transfered on dquot_transfer(). This means what
inode_reservation must always be in sync with
dquot->dq_dqb.dqb_rsvspace. Otherwise dquot_transfer() will result
in incorrect quota(WARN_ON in dquot_claim_reserved_space() will be
triggered)
This is not easy because of complex locking order issues
for example http://bugzilla.kernel.org/show_bug.cgi?id=14739
The patch introduce quota reservation field for each fs-inode
(fs specific inode is used in order to prevent bloating generic
vfs inode). This reservation is managed by quota code internally
similar to i_blocks/i_bytes and may not be always in sync with
internal fs reservation.
Also perform some code rearrangement:
- Unify dquot_reserve_space() and dquot_reserve_space()
- Unify dquot_release_reserved_space() and dquot_free_space()
- Also this patch add missing warning update to release_rsv()
dquot_release_reserved_space() must call flush_warnings() as
dquot_free_space() does.
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/quota/dquot.c')
-rw-r--r-- | fs/quota/dquot.c | 213 |
1 files changed, 119 insertions, 94 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index cd6bb9a33c13..1cb8fa84300f 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
@@ -1319,6 +1319,67 @@ void vfs_dq_drop(struct inode *inode) | |||
1319 | EXPORT_SYMBOL(vfs_dq_drop); | 1319 | EXPORT_SYMBOL(vfs_dq_drop); |
1320 | 1320 | ||
1321 | /* | 1321 | /* |
1322 | * inode_reserved_space is managed internally by quota, and protected by | ||
1323 | * i_lock similar to i_blocks+i_bytes. | ||
1324 | */ | ||
1325 | static qsize_t *inode_reserved_space(struct inode * inode) | ||
1326 | { | ||
1327 | /* Filesystem must explicitly define it's own method in order to use | ||
1328 | * quota reservation interface */ | ||
1329 | BUG_ON(!inode->i_sb->dq_op->get_reserved_space); | ||
1330 | return inode->i_sb->dq_op->get_reserved_space(inode); | ||
1331 | } | ||
1332 | |||
1333 | static void inode_add_rsv_space(struct inode *inode, qsize_t number) | ||
1334 | { | ||
1335 | spin_lock(&inode->i_lock); | ||
1336 | *inode_reserved_space(inode) += number; | ||
1337 | spin_unlock(&inode->i_lock); | ||
1338 | } | ||
1339 | |||
1340 | |||
1341 | static void inode_claim_rsv_space(struct inode *inode, qsize_t number) | ||
1342 | { | ||
1343 | spin_lock(&inode->i_lock); | ||
1344 | *inode_reserved_space(inode) -= number; | ||
1345 | __inode_add_bytes(inode, number); | ||
1346 | spin_unlock(&inode->i_lock); | ||
1347 | } | ||
1348 | |||
1349 | static void inode_sub_rsv_space(struct inode *inode, qsize_t number) | ||
1350 | { | ||
1351 | spin_lock(&inode->i_lock); | ||
1352 | *inode_reserved_space(inode) -= number; | ||
1353 | spin_unlock(&inode->i_lock); | ||
1354 | } | ||
1355 | |||
1356 | static qsize_t inode_get_rsv_space(struct inode *inode) | ||
1357 | { | ||
1358 | qsize_t ret; | ||
1359 | spin_lock(&inode->i_lock); | ||
1360 | ret = *inode_reserved_space(inode); | ||
1361 | spin_unlock(&inode->i_lock); | ||
1362 | return ret; | ||
1363 | } | ||
1364 | |||
1365 | static void inode_incr_space(struct inode *inode, qsize_t number, | ||
1366 | int reserve) | ||
1367 | { | ||
1368 | if (reserve) | ||
1369 | inode_add_rsv_space(inode, number); | ||
1370 | else | ||
1371 | inode_add_bytes(inode, number); | ||
1372 | } | ||
1373 | |||
1374 | static void inode_decr_space(struct inode *inode, qsize_t number, int reserve) | ||
1375 | { | ||
1376 | if (reserve) | ||
1377 | inode_sub_rsv_space(inode, number); | ||
1378 | else | ||
1379 | inode_sub_bytes(inode, number); | ||
1380 | } | ||
1381 | |||
1382 | /* | ||
1322 | * Following four functions update i_blocks+i_bytes fields and | 1383 | * Following four functions update i_blocks+i_bytes fields and |
1323 | * quota information (together with appropriate checks) | 1384 | * quota information (together with appropriate checks) |
1324 | * NOTE: We absolutely rely on the fact that caller dirties | 1385 | * NOTE: We absolutely rely on the fact that caller dirties |
@@ -1336,6 +1397,21 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, | |||
1336 | int cnt, ret = QUOTA_OK; | 1397 | int cnt, ret = QUOTA_OK; |
1337 | char warntype[MAXQUOTAS]; | 1398 | char warntype[MAXQUOTAS]; |
1338 | 1399 | ||
1400 | /* | ||
1401 | * First test before acquiring mutex - solves deadlocks when we | ||
1402 | * re-enter the quota code and are already holding the mutex | ||
1403 | */ | ||
1404 | if (IS_NOQUOTA(inode)) { | ||
1405 | inode_incr_space(inode, number, reserve); | ||
1406 | goto out; | ||
1407 | } | ||
1408 | |||
1409 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1410 | if (IS_NOQUOTA(inode)) { | ||
1411 | inode_incr_space(inode, number, reserve); | ||
1412 | goto out_unlock; | ||
1413 | } | ||
1414 | |||
1339 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | 1415 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) |
1340 | warntype[cnt] = QUOTA_NL_NOWARN; | 1416 | warntype[cnt] = QUOTA_NL_NOWARN; |
1341 | 1417 | ||
@@ -1346,7 +1422,8 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, | |||
1346 | if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt) | 1422 | if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt) |
1347 | == NO_QUOTA) { | 1423 | == NO_QUOTA) { |
1348 | ret = NO_QUOTA; | 1424 | ret = NO_QUOTA; |
1349 | goto out_unlock; | 1425 | spin_unlock(&dq_data_lock); |
1426 | goto out_flush_warn; | ||
1350 | } | 1427 | } |
1351 | } | 1428 | } |
1352 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1429 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
@@ -1357,64 +1434,32 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, | |||
1357 | else | 1434 | else |
1358 | dquot_incr_space(inode->i_dquot[cnt], number); | 1435 | dquot_incr_space(inode->i_dquot[cnt], number); |
1359 | } | 1436 | } |
1360 | if (!reserve) | 1437 | inode_incr_space(inode, number, reserve); |
1361 | inode_add_bytes(inode, number); | ||
1362 | out_unlock: | ||
1363 | spin_unlock(&dq_data_lock); | 1438 | spin_unlock(&dq_data_lock); |
1364 | flush_warnings(inode->i_dquot, warntype); | ||
1365 | return ret; | ||
1366 | } | ||
1367 | |||
1368 | int dquot_alloc_space(struct inode *inode, qsize_t number, int warn) | ||
1369 | { | ||
1370 | int cnt, ret = QUOTA_OK; | ||
1371 | |||
1372 | /* | ||
1373 | * First test before acquiring mutex - solves deadlocks when we | ||
1374 | * re-enter the quota code and are already holding the mutex | ||
1375 | */ | ||
1376 | if (IS_NOQUOTA(inode)) { | ||
1377 | inode_add_bytes(inode, number); | ||
1378 | goto out; | ||
1379 | } | ||
1380 | |||
1381 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1382 | if (IS_NOQUOTA(inode)) { | ||
1383 | inode_add_bytes(inode, number); | ||
1384 | goto out_unlock; | ||
1385 | } | ||
1386 | |||
1387 | ret = __dquot_alloc_space(inode, number, warn, 0); | ||
1388 | if (ret == NO_QUOTA) | ||
1389 | goto out_unlock; | ||
1390 | 1439 | ||
1440 | if (reserve) | ||
1441 | goto out_flush_warn; | ||
1391 | /* Dirtify all the dquots - this can block when journalling */ | 1442 | /* Dirtify all the dquots - this can block when journalling */ |
1392 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | 1443 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) |
1393 | if (inode->i_dquot[cnt]) | 1444 | if (inode->i_dquot[cnt]) |
1394 | mark_dquot_dirty(inode->i_dquot[cnt]); | 1445 | mark_dquot_dirty(inode->i_dquot[cnt]); |
1446 | out_flush_warn: | ||
1447 | flush_warnings(inode->i_dquot, warntype); | ||
1395 | out_unlock: | 1448 | out_unlock: |
1396 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1449 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
1397 | out: | 1450 | out: |
1398 | return ret; | 1451 | return ret; |
1399 | } | 1452 | } |
1453 | |||
1454 | int dquot_alloc_space(struct inode *inode, qsize_t number, int warn) | ||
1455 | { | ||
1456 | return __dquot_alloc_space(inode, number, warn, 0); | ||
1457 | } | ||
1400 | EXPORT_SYMBOL(dquot_alloc_space); | 1458 | EXPORT_SYMBOL(dquot_alloc_space); |
1401 | 1459 | ||
1402 | int dquot_reserve_space(struct inode *inode, qsize_t number, int warn) | 1460 | int dquot_reserve_space(struct inode *inode, qsize_t number, int warn) |
1403 | { | 1461 | { |
1404 | int ret = QUOTA_OK; | 1462 | return __dquot_alloc_space(inode, number, warn, 1); |
1405 | |||
1406 | if (IS_NOQUOTA(inode)) | ||
1407 | goto out; | ||
1408 | |||
1409 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1410 | if (IS_NOQUOTA(inode)) | ||
1411 | goto out_unlock; | ||
1412 | |||
1413 | ret = __dquot_alloc_space(inode, number, warn, 1); | ||
1414 | out_unlock: | ||
1415 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1416 | out: | ||
1417 | return ret; | ||
1418 | } | 1463 | } |
1419 | EXPORT_SYMBOL(dquot_reserve_space); | 1464 | EXPORT_SYMBOL(dquot_reserve_space); |
1420 | 1465 | ||
@@ -1471,14 +1516,14 @@ int dquot_claim_space(struct inode *inode, qsize_t number) | |||
1471 | int ret = QUOTA_OK; | 1516 | int ret = QUOTA_OK; |
1472 | 1517 | ||
1473 | if (IS_NOQUOTA(inode)) { | 1518 | if (IS_NOQUOTA(inode)) { |
1474 | inode_add_bytes(inode, number); | 1519 | inode_claim_rsv_space(inode, number); |
1475 | goto out; | 1520 | goto out; |
1476 | } | 1521 | } |
1477 | 1522 | ||
1478 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1523 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
1479 | if (IS_NOQUOTA(inode)) { | 1524 | if (IS_NOQUOTA(inode)) { |
1480 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1525 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
1481 | inode_add_bytes(inode, number); | 1526 | inode_claim_rsv_space(inode, number); |
1482 | goto out; | 1527 | goto out; |
1483 | } | 1528 | } |
1484 | 1529 | ||
@@ -1490,7 +1535,7 @@ int dquot_claim_space(struct inode *inode, qsize_t number) | |||
1490 | number); | 1535 | number); |
1491 | } | 1536 | } |
1492 | /* Update inode bytes */ | 1537 | /* Update inode bytes */ |
1493 | inode_add_bytes(inode, number); | 1538 | inode_claim_rsv_space(inode, number); |
1494 | spin_unlock(&dq_data_lock); | 1539 | spin_unlock(&dq_data_lock); |
1495 | /* Dirtify all the dquots - this can block when journalling */ | 1540 | /* Dirtify all the dquots - this can block when journalling */ |
1496 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | 1541 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) |
@@ -1503,38 +1548,9 @@ out: | |||
1503 | EXPORT_SYMBOL(dquot_claim_space); | 1548 | EXPORT_SYMBOL(dquot_claim_space); |
1504 | 1549 | ||
1505 | /* | 1550 | /* |
1506 | * Release reserved quota space | ||
1507 | */ | ||
1508 | void dquot_release_reserved_space(struct inode *inode, qsize_t number) | ||
1509 | { | ||
1510 | int cnt; | ||
1511 | |||
1512 | if (IS_NOQUOTA(inode)) | ||
1513 | goto out; | ||
1514 | |||
1515 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1516 | if (IS_NOQUOTA(inode)) | ||
1517 | goto out_unlock; | ||
1518 | |||
1519 | spin_lock(&dq_data_lock); | ||
1520 | /* Release reserved dquots */ | ||
1521 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | ||
1522 | if (inode->i_dquot[cnt]) | ||
1523 | dquot_free_reserved_space(inode->i_dquot[cnt], number); | ||
1524 | } | ||
1525 | spin_unlock(&dq_data_lock); | ||
1526 | |||
1527 | out_unlock: | ||
1528 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | ||
1529 | out: | ||
1530 | return; | ||
1531 | } | ||
1532 | EXPORT_SYMBOL(dquot_release_reserved_space); | ||
1533 | |||
1534 | /* | ||
1535 | * This operation can block, but only after everything is updated | 1551 | * This operation can block, but only after everything is updated |
1536 | */ | 1552 | */ |
1537 | int dquot_free_space(struct inode *inode, qsize_t number) | 1553 | int __dquot_free_space(struct inode *inode, qsize_t number, int reserve) |
1538 | { | 1554 | { |
1539 | unsigned int cnt; | 1555 | unsigned int cnt; |
1540 | char warntype[MAXQUOTAS]; | 1556 | char warntype[MAXQUOTAS]; |
@@ -1543,7 +1559,7 @@ int dquot_free_space(struct inode *inode, qsize_t number) | |||
1543 | * re-enter the quota code and are already holding the mutex */ | 1559 | * re-enter the quota code and are already holding the mutex */ |
1544 | if (IS_NOQUOTA(inode)) { | 1560 | if (IS_NOQUOTA(inode)) { |
1545 | out_sub: | 1561 | out_sub: |
1546 | inode_sub_bytes(inode, number); | 1562 | inode_decr_space(inode, number, reserve); |
1547 | return QUOTA_OK; | 1563 | return QUOTA_OK; |
1548 | } | 1564 | } |
1549 | 1565 | ||
@@ -1558,21 +1574,43 @@ out_sub: | |||
1558 | if (!inode->i_dquot[cnt]) | 1574 | if (!inode->i_dquot[cnt]) |
1559 | continue; | 1575 | continue; |
1560 | warntype[cnt] = info_bdq_free(inode->i_dquot[cnt], number); | 1576 | warntype[cnt] = info_bdq_free(inode->i_dquot[cnt], number); |
1561 | dquot_decr_space(inode->i_dquot[cnt], number); | 1577 | if (reserve) |
1578 | dquot_free_reserved_space(inode->i_dquot[cnt], number); | ||
1579 | else | ||
1580 | dquot_decr_space(inode->i_dquot[cnt], number); | ||
1562 | } | 1581 | } |
1563 | inode_sub_bytes(inode, number); | 1582 | inode_decr_space(inode, number, reserve); |
1564 | spin_unlock(&dq_data_lock); | 1583 | spin_unlock(&dq_data_lock); |
1584 | |||
1585 | if (reserve) | ||
1586 | goto out_unlock; | ||
1565 | /* Dirtify all the dquots - this can block when journalling */ | 1587 | /* Dirtify all the dquots - this can block when journalling */ |
1566 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | 1588 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) |
1567 | if (inode->i_dquot[cnt]) | 1589 | if (inode->i_dquot[cnt]) |
1568 | mark_dquot_dirty(inode->i_dquot[cnt]); | 1590 | mark_dquot_dirty(inode->i_dquot[cnt]); |
1591 | out_unlock: | ||
1569 | flush_warnings(inode->i_dquot, warntype); | 1592 | flush_warnings(inode->i_dquot, warntype); |
1570 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1593 | up_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
1571 | return QUOTA_OK; | 1594 | return QUOTA_OK; |
1572 | } | 1595 | } |
1596 | |||
1597 | int dquot_free_space(struct inode *inode, qsize_t number) | ||
1598 | { | ||
1599 | return __dquot_free_space(inode, number, 0); | ||
1600 | } | ||
1573 | EXPORT_SYMBOL(dquot_free_space); | 1601 | EXPORT_SYMBOL(dquot_free_space); |
1574 | 1602 | ||
1575 | /* | 1603 | /* |
1604 | * Release reserved quota space | ||
1605 | */ | ||
1606 | void dquot_release_reserved_space(struct inode *inode, qsize_t number) | ||
1607 | { | ||
1608 | __dquot_free_space(inode, number, 1); | ||
1609 | |||
1610 | } | ||
1611 | EXPORT_SYMBOL(dquot_release_reserved_space); | ||
1612 | |||
1613 | /* | ||
1576 | * This operation can block, but only after everything is updated | 1614 | * This operation can block, but only after everything is updated |
1577 | */ | 1615 | */ |
1578 | int dquot_free_inode(const struct inode *inode, qsize_t number) | 1616 | int dquot_free_inode(const struct inode *inode, qsize_t number) |
@@ -1610,19 +1648,6 @@ int dquot_free_inode(const struct inode *inode, qsize_t number) | |||
1610 | EXPORT_SYMBOL(dquot_free_inode); | 1648 | EXPORT_SYMBOL(dquot_free_inode); |
1611 | 1649 | ||
1612 | /* | 1650 | /* |
1613 | * call back function, get reserved quota space from underlying fs | ||
1614 | */ | ||
1615 | qsize_t dquot_get_reserved_space(struct inode *inode) | ||
1616 | { | ||
1617 | qsize_t reserved_space = 0; | ||
1618 | |||
1619 | if (sb_any_quota_active(inode->i_sb) && | ||
1620 | inode->i_sb->dq_op->get_reserved_space) | ||
1621 | reserved_space = inode->i_sb->dq_op->get_reserved_space(inode); | ||
1622 | return reserved_space; | ||
1623 | } | ||
1624 | |||
1625 | /* | ||
1626 | * Transfer the number of inode and blocks from one diskquota to an other. | 1651 | * Transfer the number of inode and blocks from one diskquota to an other. |
1627 | * | 1652 | * |
1628 | * This operation can block, but only after everything is updated | 1653 | * This operation can block, but only after everything is updated |
@@ -1665,7 +1690,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) | |||
1665 | } | 1690 | } |
1666 | spin_lock(&dq_data_lock); | 1691 | spin_lock(&dq_data_lock); |
1667 | cur_space = inode_get_bytes(inode); | 1692 | cur_space = inode_get_bytes(inode); |
1668 | rsv_space = dquot_get_reserved_space(inode); | 1693 | rsv_space = inode_get_rsv_space(inode); |
1669 | space = cur_space + rsv_space; | 1694 | space = cur_space + rsv_space; |
1670 | /* Build the transfer_from list and check the limits */ | 1695 | /* Build the transfer_from list and check the limits */ |
1671 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1696 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |