aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dquot.c
diff options
context:
space:
mode:
authorMingming Cao <cmm@us.ibm.com>2009-01-13 10:43:14 -0500
committerJan Kara <jack@suse.cz>2009-03-25 21:18:24 -0400
commit740d9dcd949a986c88886a591054a0cdb89ef669 (patch)
tree3a422d30c838c80d35b8d52a05a4c55d3c806e4e /fs/dquot.c
parentf18df228997fb716990590d248663981a15f17d4 (diff)
quota: Add quota reservation claim and released operations
Reserved quota will be claimed at the block allocation time. Over-booked quota could be returned back with the release callback function. Signed-off-by: Mingming Cao <cmm@us.ibm.com> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/dquot.c')
-rw-r--r--fs/dquot.c110
1 files changed, 106 insertions, 4 deletions
diff --git a/fs/dquot.c b/fs/dquot.c
index 9b1c4d3c9d83..2916f91ca40c 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -904,6 +904,23 @@ static inline void dquot_resv_space(struct dquot *dquot, qsize_t number)
904 dquot->dq_dqb.dqb_rsvspace += number; 904 dquot->dq_dqb.dqb_rsvspace += number;
905} 905}
906 906
907/*
908 * Claim reserved quota space
909 */
910static void dquot_claim_reserved_space(struct dquot *dquot,
911 qsize_t number)
912{
913 WARN_ON(dquot->dq_dqb.dqb_rsvspace < number);
914 dquot->dq_dqb.dqb_curspace += number;
915 dquot->dq_dqb.dqb_rsvspace -= number;
916}
917
918static inline
919void dquot_free_reserved_space(struct dquot *dquot, qsize_t number)
920{
921 dquot->dq_dqb.dqb_rsvspace -= number;
922}
923
907static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number) 924static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
908{ 925{
909 if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE || 926 if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE ||
@@ -1452,6 +1469,72 @@ warn_put_all:
1452 return ret; 1469 return ret;
1453} 1470}
1454 1471
1472int dquot_claim_space(struct inode *inode, qsize_t number)
1473{
1474 int cnt;
1475 int ret = QUOTA_OK;
1476
1477 if (IS_NOQUOTA(inode)) {
1478 inode_add_bytes(inode, number);
1479 goto out;
1480 }
1481
1482 down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
1483 if (IS_NOQUOTA(inode)) {
1484 up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
1485 inode_add_bytes(inode, number);
1486 goto out;
1487 }
1488
1489 spin_lock(&dq_data_lock);
1490 /* Claim reserved quotas to allocated quotas */
1491 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1492 if (inode->i_dquot[cnt] != NODQUOT)
1493 dquot_claim_reserved_space(inode->i_dquot[cnt],
1494 number);
1495 }
1496 /* Update inode bytes */
1497 inode_add_bytes(inode, number);
1498 spin_unlock(&dq_data_lock);
1499 /* Dirtify all the dquots - this can block when journalling */
1500 for (cnt = 0; cnt < MAXQUOTAS; cnt++)
1501 if (inode->i_dquot[cnt])
1502 mark_dquot_dirty(inode->i_dquot[cnt]);
1503 up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
1504out:
1505 return ret;
1506}
1507EXPORT_SYMBOL(dquot_claim_space);
1508
1509/*
1510 * Release reserved quota space
1511 */
1512void dquot_release_reserved_space(struct inode *inode, qsize_t number)
1513{
1514 int cnt;
1515
1516 if (IS_NOQUOTA(inode))
1517 goto out;
1518
1519 down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
1520 if (IS_NOQUOTA(inode))
1521 goto out_unlock;
1522
1523 spin_lock(&dq_data_lock);
1524 /* Release reserved dquots */
1525 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1526 if (inode->i_dquot[cnt] != NODQUOT)
1527 dquot_free_reserved_space(inode->i_dquot[cnt], number);
1528 }
1529 spin_unlock(&dq_data_lock);
1530
1531out_unlock:
1532 up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
1533out:
1534 return;
1535}
1536EXPORT_SYMBOL(dquot_release_reserved_space);
1537
1455/* 1538/*
1456 * This operation can block, but only after everything is updated 1539 * This operation can block, but only after everything is updated
1457 */ 1540 */
@@ -1529,6 +1612,19 @@ int dquot_free_inode(const struct inode *inode, qsize_t number)
1529} 1612}
1530 1613
1531/* 1614/*
1615 * call back function, get reserved quota space from underlying fs
1616 */
1617qsize_t dquot_get_reserved_space(struct inode *inode)
1618{
1619 qsize_t reserved_space = 0;
1620
1621 if (sb_any_quota_active(inode->i_sb) &&
1622 inode->i_sb->dq_op->get_reserved_space)
1623 reserved_space = inode->i_sb->dq_op->get_reserved_space(inode);
1624 return reserved_space;
1625}
1626
1627/*
1532 * Transfer the number of inode and blocks from one diskquota to an other. 1628 * Transfer the number of inode and blocks from one diskquota to an other.
1533 * 1629 *
1534 * This operation can block, but only after everything is updated 1630 * This operation can block, but only after everything is updated
@@ -1536,7 +1632,8 @@ int dquot_free_inode(const struct inode *inode, qsize_t number)
1536 */ 1632 */
1537int dquot_transfer(struct inode *inode, struct iattr *iattr) 1633int dquot_transfer(struct inode *inode, struct iattr *iattr)
1538{ 1634{
1539 qsize_t space; 1635 qsize_t space, cur_space;
1636 qsize_t rsv_space = 0;
1540 struct dquot *transfer_from[MAXQUOTAS]; 1637 struct dquot *transfer_from[MAXQUOTAS];
1541 struct dquot *transfer_to[MAXQUOTAS]; 1638 struct dquot *transfer_to[MAXQUOTAS];
1542 int cnt, ret = QUOTA_OK; 1639 int cnt, ret = QUOTA_OK;
@@ -1575,7 +1672,9 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
1575 goto put_all; 1672 goto put_all;
1576 } 1673 }
1577 spin_lock(&dq_data_lock); 1674 spin_lock(&dq_data_lock);
1578 space = inode_get_bytes(inode); 1675 cur_space = inode_get_bytes(inode);
1676 rsv_space = dquot_get_reserved_space(inode);
1677 space = cur_space + rsv_space;
1579 /* Build the transfer_from list and check the limits */ 1678 /* Build the transfer_from list and check the limits */
1580 for (cnt = 0; cnt < MAXQUOTAS; cnt++) { 1679 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1581 if (transfer_to[cnt] == NODQUOT) 1680 if (transfer_to[cnt] == NODQUOT)
@@ -1604,11 +1703,14 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
1604 warntype_from_space[cnt] = 1703 warntype_from_space[cnt] =
1605 info_bdq_free(transfer_from[cnt], space); 1704 info_bdq_free(transfer_from[cnt], space);
1606 dquot_decr_inodes(transfer_from[cnt], 1); 1705 dquot_decr_inodes(transfer_from[cnt], 1);
1607 dquot_decr_space(transfer_from[cnt], space); 1706 dquot_decr_space(transfer_from[cnt], cur_space);
1707 dquot_free_reserved_space(transfer_from[cnt],
1708 rsv_space);
1608 } 1709 }
1609 1710
1610 dquot_incr_inodes(transfer_to[cnt], 1); 1711 dquot_incr_inodes(transfer_to[cnt], 1);
1611 dquot_incr_space(transfer_to[cnt], space); 1712 dquot_incr_space(transfer_to[cnt], cur_space);
1713 dquot_resv_space(transfer_to[cnt], rsv_space);
1612 1714
1613 inode->i_dquot[cnt] = transfer_to[cnt]; 1715 inode->i_dquot[cnt] = transfer_to[cnt];
1614 } 1716 }