aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--fs/dquot.c110
-rw-r--r--include/linux/quota.h6
-rw-r--r--include/linux/quotaops.h53
3 files changed, 165 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 }
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 54b837fa64f2..a510d91561f4 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -311,6 +311,12 @@ struct dquot_operations {
311 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 */ 312 /* reserve quota for delayed block allocation */
313 int (*reserve_space) (struct inode *, qsize_t, int); 313 int (*reserve_space) (struct inode *, qsize_t, int);
314 /* claim reserved quota for delayed alloc */
315 int (*claim_space) (struct inode *, qsize_t);
316 /* release rsved quota for delayed alloc */
317 void (*release_rsv) (struct inode *, qsize_t);
318 /* get reserved quota for delayed alloc */
319 qsize_t (*get_reserved_space) (struct inode *);
314}; 320};
315 321
316/* Operations handling requests from userspace */ 322/* Operations handling requests from userspace */
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 3e3a0d2874d9..7369d04e0a86 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -35,6 +35,11 @@ void dquot_destroy(struct dquot *dquot);
35int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc); 35int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
36int dquot_alloc_inode(const struct inode *inode, qsize_t number); 36int dquot_alloc_inode(const struct inode *inode, qsize_t number);
37 37
38int dquot_reserve_space(struct inode *inode, qsize_t number, int prealloc);
39int dquot_claim_space(struct inode *inode, qsize_t number);
40void dquot_release_reserved_space(struct inode *inode, qsize_t number);
41qsize_t dquot_get_reserved_space(struct inode *inode);
42
38int dquot_free_space(struct inode *inode, qsize_t number); 43int dquot_free_space(struct inode *inode, qsize_t number);
39int dquot_free_inode(const struct inode *inode, qsize_t number); 44int dquot_free_inode(const struct inode *inode, qsize_t number);
40 45
@@ -203,6 +208,31 @@ static inline int vfs_dq_alloc_inode(struct inode *inode)
203 return 0; 208 return 0;
204} 209}
205 210
211/*
212 * Convert in-memory reserved quotas to real consumed quotas
213 */
214static inline int vfs_dq_claim_space(struct inode *inode, qsize_t nr)
215{
216 if (sb_any_quota_active(inode->i_sb)) {
217 if (inode->i_sb->dq_op->claim_space(inode, nr) == NO_QUOTA)
218 return 1;
219 } else
220 inode_add_bytes(inode, nr);
221
222 mark_inode_dirty(inode);
223 return 0;
224}
225
226/*
227 * Release reserved (in-memory) quotas
228 */
229static inline
230void vfs_dq_release_reservation_space(struct inode *inode, qsize_t nr)
231{
232 if (sb_any_quota_active(inode->i_sb))
233 inode->i_sb->dq_op->release_rsv(inode, nr);
234}
235
206static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr) 236static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
207{ 237{
208 if (sb_any_quota_active(inode->i_sb)) 238 if (sb_any_quota_active(inode->i_sb))
@@ -354,6 +384,17 @@ static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr)
354 return 0; 384 return 0;
355} 385}
356 386
387static inline int vfs_dq_claim_space(struct inode *inode, qsize_t nr)
388{
389 return vfs_dq_alloc_space(inode, nr);
390}
391
392static inline
393int vfs_dq_release_reservation_space(struct inode *inode, qsize_t nr)
394{
395 return 0;
396}
397
357static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr) 398static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
358{ 399{
359 inode_sub_bytes(inode, nr); 400 inode_sub_bytes(inode, nr);
@@ -397,6 +438,18 @@ static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr)
397 nr << inode->i_blkbits); 438 nr << inode->i_blkbits);
398} 439}
399 440
441static inline int vfs_dq_claim_block(struct inode *inode, qsize_t nr)
442{
443 return vfs_dq_claim_space(inode,
444 nr << inode->i_blkbits);
445}
446
447static inline
448void vfs_dq_release_reservation_block(struct inode *inode, qsize_t nr)
449{
450 vfs_dq_release_reservation_space(inode, nr << inode->i_blkbits);
451}
452
400static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr) 453static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr)
401{ 454{
402 vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits); 455 vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits);