diff options
author | Jan Kara <jack@suse.cz> | 2008-08-20 11:50:32 -0400 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:36:56 -0500 |
commit | f55abc0fb9c3189de3da829adf3220322c0da43e (patch) | |
tree | 0db4b838b0b90f27401783e8e7e45842ec91f90a /fs/dquot.c | |
parent | e4bc7b4b7ff783779b6928d55a9308910bf180a3 (diff) |
quota: Allow to separately enable quota accounting and enforcing limits
Split DQUOT_USR_ENABLED (and DQUOT_GRP_ENABLED) into DQUOT_USR_USAGE_ENABLED
and DQUOT_USR_LIMITS_ENABLED. This way we are able to separately enable /
disable whether we should:
1) ignore quotas completely
2) just keep uptodate information about usage
3) actually enforce quota limits
This is going to be useful when quota is treated as filesystem metadata - we
then want to keep quota information uptodate all the time and just enable /
disable limits enforcement.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/dquot.c')
-rw-r--r-- | fs/dquot.c | 222 |
1 files changed, 138 insertions, 84 deletions
diff --git a/fs/dquot.c b/fs/dquot.c index 22340c610e1a..7569633efe0e 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -489,7 +489,7 @@ int vfs_quota_sync(struct super_block *sb, int type) | |||
489 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 489 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
490 | if (type != -1 && cnt != type) | 490 | if (type != -1 && cnt != type) |
491 | continue; | 491 | continue; |
492 | if (!sb_has_quota_enabled(sb, cnt)) | 492 | if (!sb_has_quota_active(sb, cnt)) |
493 | continue; | 493 | continue; |
494 | spin_lock(&dq_list_lock); | 494 | spin_lock(&dq_list_lock); |
495 | dirty = &dqopt->info[cnt].dqi_dirty_list; | 495 | dirty = &dqopt->info[cnt].dqi_dirty_list; |
@@ -514,8 +514,8 @@ int vfs_quota_sync(struct super_block *sb, int type) | |||
514 | } | 514 | } |
515 | 515 | ||
516 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | 516 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) |
517 | if ((cnt == type || type == -1) && sb_has_quota_enabled(sb, cnt) | 517 | if ((cnt == type || type == -1) && sb_has_quota_active(sb, cnt) |
518 | && info_dirty(&dqopt->info[cnt])) | 518 | && info_dirty(&dqopt->info[cnt])) |
519 | sb->dq_op->write_info(sb, cnt); | 519 | sb->dq_op->write_info(sb, cnt); |
520 | spin_lock(&dq_list_lock); | 520 | spin_lock(&dq_list_lock); |
521 | dqstats.syncs++; | 521 | dqstats.syncs++; |
@@ -594,7 +594,7 @@ we_slept: | |||
594 | /* We have more than one user... nothing to do */ | 594 | /* We have more than one user... nothing to do */ |
595 | atomic_dec(&dquot->dq_count); | 595 | atomic_dec(&dquot->dq_count); |
596 | /* Releasing dquot during quotaoff phase? */ | 596 | /* Releasing dquot during quotaoff phase? */ |
597 | if (!sb_has_quota_enabled(dquot->dq_sb, dquot->dq_type) && | 597 | if (!sb_has_quota_active(dquot->dq_sb, dquot->dq_type) && |
598 | atomic_read(&dquot->dq_count) == 1) | 598 | atomic_read(&dquot->dq_count) == 1) |
599 | wake_up(&dquot->dq_wait_unused); | 599 | wake_up(&dquot->dq_wait_unused); |
600 | spin_unlock(&dq_list_lock); | 600 | spin_unlock(&dq_list_lock); |
@@ -670,7 +670,7 @@ static struct dquot *dqget(struct super_block *sb, unsigned int id, int type) | |||
670 | unsigned int hashent = hashfn(sb, id, type); | 670 | unsigned int hashent = hashfn(sb, id, type); |
671 | struct dquot *dquot, *empty = NODQUOT; | 671 | struct dquot *dquot, *empty = NODQUOT; |
672 | 672 | ||
673 | if (!sb_has_quota_enabled(sb, type)) | 673 | if (!sb_has_quota_active(sb, type)) |
674 | return NODQUOT; | 674 | return NODQUOT; |
675 | we_slept: | 675 | we_slept: |
676 | spin_lock(&dq_list_lock); | 676 | spin_lock(&dq_list_lock); |
@@ -1041,7 +1041,8 @@ static inline char ignore_hardlimit(struct dquot *dquot) | |||
1041 | static int check_idq(struct dquot *dquot, qsize_t inodes, char *warntype) | 1041 | static int check_idq(struct dquot *dquot, qsize_t inodes, char *warntype) |
1042 | { | 1042 | { |
1043 | *warntype = QUOTA_NL_NOWARN; | 1043 | *warntype = QUOTA_NL_NOWARN; |
1044 | if (test_bit(DQ_FAKE_B, &dquot->dq_flags)) | 1044 | if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) || |
1045 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) | ||
1045 | return QUOTA_OK; | 1046 | return QUOTA_OK; |
1046 | 1047 | ||
1047 | if (dquot->dq_dqb.dqb_ihardlimit && | 1048 | if (dquot->dq_dqb.dqb_ihardlimit && |
@@ -1073,7 +1074,8 @@ static int check_idq(struct dquot *dquot, qsize_t inodes, char *warntype) | |||
1073 | static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *warntype) | 1074 | static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *warntype) |
1074 | { | 1075 | { |
1075 | *warntype = QUOTA_NL_NOWARN; | 1076 | *warntype = QUOTA_NL_NOWARN; |
1076 | if (test_bit(DQ_FAKE_B, &dquot->dq_flags)) | 1077 | if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) || |
1078 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) | ||
1077 | return QUOTA_OK; | 1079 | return QUOTA_OK; |
1078 | 1080 | ||
1079 | if (dquot->dq_dqb.dqb_bhardlimit && | 1081 | if (dquot->dq_dqb.dqb_bhardlimit && |
@@ -1114,7 +1116,8 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war | |||
1114 | static int info_idq_free(struct dquot *dquot, qsize_t inodes) | 1116 | static int info_idq_free(struct dquot *dquot, qsize_t inodes) |
1115 | { | 1117 | { |
1116 | if (test_bit(DQ_FAKE_B, &dquot->dq_flags) || | 1118 | if (test_bit(DQ_FAKE_B, &dquot->dq_flags) || |
1117 | dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit) | 1119 | dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit || |
1120 | !sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type)) | ||
1118 | return QUOTA_NL_NOWARN; | 1121 | return QUOTA_NL_NOWARN; |
1119 | 1122 | ||
1120 | if (dquot->dq_dqb.dqb_curinodes - inodes <= dquot->dq_dqb.dqb_isoftlimit) | 1123 | if (dquot->dq_dqb.dqb_curinodes - inodes <= dquot->dq_dqb.dqb_isoftlimit) |
@@ -1508,7 +1511,7 @@ warn_put_all: | |||
1508 | /* Wrapper for transferring ownership of an inode */ | 1511 | /* Wrapper for transferring ownership of an inode */ |
1509 | int vfs_dq_transfer(struct inode *inode, struct iattr *iattr) | 1512 | int vfs_dq_transfer(struct inode *inode, struct iattr *iattr) |
1510 | { | 1513 | { |
1511 | if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode)) { | 1514 | if (sb_any_quota_active(inode->i_sb) && !IS_NOQUOTA(inode)) { |
1512 | vfs_dq_init(inode); | 1515 | vfs_dq_init(inode); |
1513 | if (inode->i_sb->dq_op->transfer(inode, iattr) == NO_QUOTA) | 1516 | if (inode->i_sb->dq_op->transfer(inode, iattr) == NO_QUOTA) |
1514 | return 1; | 1517 | return 1; |
@@ -1551,53 +1554,22 @@ struct dquot_operations dquot_operations = { | |||
1551 | .destroy_dquot = dquot_destroy, | 1554 | .destroy_dquot = dquot_destroy, |
1552 | }; | 1555 | }; |
1553 | 1556 | ||
1554 | static inline void set_enable_flags(struct quota_info *dqopt, int type) | ||
1555 | { | ||
1556 | switch (type) { | ||
1557 | case USRQUOTA: | ||
1558 | dqopt->flags |= DQUOT_USR_ENABLED; | ||
1559 | dqopt->flags &= ~DQUOT_USR_SUSPENDED; | ||
1560 | break; | ||
1561 | case GRPQUOTA: | ||
1562 | dqopt->flags |= DQUOT_GRP_ENABLED; | ||
1563 | dqopt->flags &= ~DQUOT_GRP_SUSPENDED; | ||
1564 | break; | ||
1565 | } | ||
1566 | } | ||
1567 | |||
1568 | static inline void reset_enable_flags(struct quota_info *dqopt, int type, | ||
1569 | int remount) | ||
1570 | { | ||
1571 | switch (type) { | ||
1572 | case USRQUOTA: | ||
1573 | if (remount) | ||
1574 | dqopt->flags |= DQUOT_USR_SUSPENDED; | ||
1575 | else { | ||
1576 | dqopt->flags &= ~DQUOT_USR_ENABLED; | ||
1577 | dqopt->flags &= ~DQUOT_USR_SUSPENDED; | ||
1578 | } | ||
1579 | break; | ||
1580 | case GRPQUOTA: | ||
1581 | if (remount) | ||
1582 | dqopt->flags |= DQUOT_GRP_SUSPENDED; | ||
1583 | else { | ||
1584 | dqopt->flags &= ~DQUOT_GRP_ENABLED; | ||
1585 | dqopt->flags &= ~DQUOT_GRP_SUSPENDED; | ||
1586 | } | ||
1587 | break; | ||
1588 | } | ||
1589 | } | ||
1590 | |||
1591 | |||
1592 | /* | 1557 | /* |
1593 | * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount) | 1558 | * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount) |
1594 | */ | 1559 | */ |
1595 | int vfs_quota_off(struct super_block *sb, int type, int remount) | 1560 | int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags) |
1596 | { | 1561 | { |
1597 | int cnt, ret = 0; | 1562 | int cnt, ret = 0; |
1598 | struct quota_info *dqopt = sb_dqopt(sb); | 1563 | struct quota_info *dqopt = sb_dqopt(sb); |
1599 | struct inode *toputinode[MAXQUOTAS]; | 1564 | struct inode *toputinode[MAXQUOTAS]; |
1600 | 1565 | ||
1566 | /* Cannot turn off usage accounting without turning off limits, or | ||
1567 | * suspend quotas and simultaneously turn quotas off. */ | ||
1568 | if ((flags & DQUOT_USAGE_ENABLED && !(flags & DQUOT_LIMITS_ENABLED)) | ||
1569 | || (flags & DQUOT_SUSPENDED && flags & (DQUOT_LIMITS_ENABLED | | ||
1570 | DQUOT_USAGE_ENABLED))) | ||
1571 | return -EINVAL; | ||
1572 | |||
1601 | /* We need to serialize quota_off() for device */ | 1573 | /* We need to serialize quota_off() for device */ |
1602 | mutex_lock(&dqopt->dqonoff_mutex); | 1574 | mutex_lock(&dqopt->dqonoff_mutex); |
1603 | 1575 | ||
@@ -1606,7 +1578,7 @@ int vfs_quota_off(struct super_block *sb, int type, int remount) | |||
1606 | * sometimes we are called when fill_super() failed and calling | 1578 | * sometimes we are called when fill_super() failed and calling |
1607 | * sync_fs() in such cases does no good. | 1579 | * sync_fs() in such cases does no good. |
1608 | */ | 1580 | */ |
1609 | if (!sb_any_quota_enabled(sb) && !sb_any_quota_suspended(sb)) { | 1581 | if (!sb_any_quota_loaded(sb)) { |
1610 | mutex_unlock(&dqopt->dqonoff_mutex); | 1582 | mutex_unlock(&dqopt->dqonoff_mutex); |
1611 | return 0; | 1583 | return 0; |
1612 | } | 1584 | } |
@@ -1614,17 +1586,28 @@ int vfs_quota_off(struct super_block *sb, int type, int remount) | |||
1614 | toputinode[cnt] = NULL; | 1586 | toputinode[cnt] = NULL; |
1615 | if (type != -1 && cnt != type) | 1587 | if (type != -1 && cnt != type) |
1616 | continue; | 1588 | continue; |
1617 | /* If we keep inodes of quota files after remount and quotaoff | 1589 | if (!sb_has_quota_loaded(sb, cnt)) |
1618 | * is called, drop kept inodes. */ | ||
1619 | if (!remount && sb_has_quota_suspended(sb, cnt)) { | ||
1620 | iput(dqopt->files[cnt]); | ||
1621 | dqopt->files[cnt] = NULL; | ||
1622 | reset_enable_flags(dqopt, cnt, 0); | ||
1623 | continue; | 1590 | continue; |
1591 | |||
1592 | if (flags & DQUOT_SUSPENDED) { | ||
1593 | dqopt->flags |= | ||
1594 | dquot_state_flag(DQUOT_SUSPENDED, cnt); | ||
1595 | } else { | ||
1596 | dqopt->flags &= ~dquot_state_flag(flags, cnt); | ||
1597 | /* Turning off suspended quotas? */ | ||
1598 | if (!sb_has_quota_loaded(sb, cnt) && | ||
1599 | sb_has_quota_suspended(sb, cnt)) { | ||
1600 | dqopt->flags &= ~dquot_state_flag( | ||
1601 | DQUOT_SUSPENDED, cnt); | ||
1602 | iput(dqopt->files[cnt]); | ||
1603 | dqopt->files[cnt] = NULL; | ||
1604 | continue; | ||
1605 | } | ||
1624 | } | 1606 | } |
1625 | if (!sb_has_quota_enabled(sb, cnt)) | 1607 | |
1608 | /* We still have to keep quota loaded? */ | ||
1609 | if (sb_has_quota_loaded(sb, cnt) && !(flags & DQUOT_SUSPENDED)) | ||
1626 | continue; | 1610 | continue; |
1627 | reset_enable_flags(dqopt, cnt, remount); | ||
1628 | 1611 | ||
1629 | /* Note: these are blocking operations */ | 1612 | /* Note: these are blocking operations */ |
1630 | drop_dquot_ref(sb, cnt); | 1613 | drop_dquot_ref(sb, cnt); |
@@ -1640,7 +1623,7 @@ int vfs_quota_off(struct super_block *sb, int type, int remount) | |||
1640 | put_quota_format(dqopt->info[cnt].dqi_format); | 1623 | put_quota_format(dqopt->info[cnt].dqi_format); |
1641 | 1624 | ||
1642 | toputinode[cnt] = dqopt->files[cnt]; | 1625 | toputinode[cnt] = dqopt->files[cnt]; |
1643 | if (!remount) | 1626 | if (!sb_has_quota_loaded(sb, cnt)) |
1644 | dqopt->files[cnt] = NULL; | 1627 | dqopt->files[cnt] = NULL; |
1645 | dqopt->info[cnt].dqi_flags = 0; | 1628 | dqopt->info[cnt].dqi_flags = 0; |
1646 | dqopt->info[cnt].dqi_igrace = 0; | 1629 | dqopt->info[cnt].dqi_igrace = 0; |
@@ -1663,7 +1646,7 @@ int vfs_quota_off(struct super_block *sb, int type, int remount) | |||
1663 | mutex_lock(&dqopt->dqonoff_mutex); | 1646 | mutex_lock(&dqopt->dqonoff_mutex); |
1664 | /* If quota was reenabled in the meantime, we have | 1647 | /* If quota was reenabled in the meantime, we have |
1665 | * nothing to do */ | 1648 | * nothing to do */ |
1666 | if (!sb_has_quota_enabled(sb, cnt)) { | 1649 | if (!sb_has_quota_loaded(sb, cnt)) { |
1667 | mutex_lock_nested(&toputinode[cnt]->i_mutex, I_MUTEX_QUOTA); | 1650 | mutex_lock_nested(&toputinode[cnt]->i_mutex, I_MUTEX_QUOTA); |
1668 | toputinode[cnt]->i_flags &= ~(S_IMMUTABLE | | 1651 | toputinode[cnt]->i_flags &= ~(S_IMMUTABLE | |
1669 | S_NOATIME | S_NOQUOTA); | 1652 | S_NOATIME | S_NOQUOTA); |
@@ -1673,10 +1656,13 @@ int vfs_quota_off(struct super_block *sb, int type, int remount) | |||
1673 | } | 1656 | } |
1674 | mutex_unlock(&dqopt->dqonoff_mutex); | 1657 | mutex_unlock(&dqopt->dqonoff_mutex); |
1675 | /* On remount RO, we keep the inode pointer so that we | 1658 | /* On remount RO, we keep the inode pointer so that we |
1676 | * can reenable quota on the subsequent remount RW. | 1659 | * can reenable quota on the subsequent remount RW. We |
1677 | * But we have better not keep inode pointer when there | 1660 | * have to check 'flags' variable and not use sb_has_ |
1678 | * is pending delete on the quota file... */ | 1661 | * function because another quotaon / quotaoff could |
1679 | if (!remount) | 1662 | * change global state before we got here. We refuse |
1663 | * to suspend quotas when there is pending delete on | ||
1664 | * the quota file... */ | ||
1665 | if (!(flags & DQUOT_SUSPENDED)) | ||
1680 | iput(toputinode[cnt]); | 1666 | iput(toputinode[cnt]); |
1681 | else if (!toputinode[cnt]->i_nlink) | 1667 | else if (!toputinode[cnt]->i_nlink) |
1682 | ret = -EBUSY; | 1668 | ret = -EBUSY; |
@@ -1686,12 +1672,22 @@ int vfs_quota_off(struct super_block *sb, int type, int remount) | |||
1686 | return ret; | 1672 | return ret; |
1687 | } | 1673 | } |
1688 | 1674 | ||
1675 | int vfs_quota_off(struct super_block *sb, int type, int remount) | ||
1676 | { | ||
1677 | return vfs_quota_disable(sb, type, remount ? DQUOT_SUSPENDED : | ||
1678 | (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED)); | ||
1679 | } | ||
1680 | |||
1689 | /* | 1681 | /* |
1690 | * Turn quotas on on a device | 1682 | * Turn quotas on on a device |
1691 | */ | 1683 | */ |
1692 | 1684 | ||
1693 | /* Helper function when we already have the inode */ | 1685 | /* |
1694 | static int vfs_quota_on_inode(struct inode *inode, int type, int format_id) | 1686 | * Helper function to turn quotas on when we already have the inode of |
1687 | * quota file and no quota information is loaded. | ||
1688 | */ | ||
1689 | static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | ||
1690 | unsigned int flags) | ||
1695 | { | 1691 | { |
1696 | struct quota_format_type *fmt = find_quota_format(format_id); | 1692 | struct quota_format_type *fmt = find_quota_format(format_id); |
1697 | struct super_block *sb = inode->i_sb; | 1693 | struct super_block *sb = inode->i_sb; |
@@ -1713,6 +1709,11 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id) | |||
1713 | error = -EINVAL; | 1709 | error = -EINVAL; |
1714 | goto out_fmt; | 1710 | goto out_fmt; |
1715 | } | 1711 | } |
1712 | /* Usage always has to be set... */ | ||
1713 | if (!(flags & DQUOT_USAGE_ENABLED)) { | ||
1714 | error = -EINVAL; | ||
1715 | goto out_fmt; | ||
1716 | } | ||
1716 | 1717 | ||
1717 | /* As we bypass the pagecache we must now flush the inode so that | 1718 | /* As we bypass the pagecache we must now flush the inode so that |
1718 | * we see all the changes from userspace... */ | 1719 | * we see all the changes from userspace... */ |
@@ -1721,8 +1722,7 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id) | |||
1721 | invalidate_bdev(sb->s_bdev); | 1722 | invalidate_bdev(sb->s_bdev); |
1722 | mutex_lock(&inode->i_mutex); | 1723 | mutex_lock(&inode->i_mutex); |
1723 | mutex_lock(&dqopt->dqonoff_mutex); | 1724 | mutex_lock(&dqopt->dqonoff_mutex); |
1724 | if (sb_has_quota_enabled(sb, type) || | 1725 | if (sb_has_quota_loaded(sb, type)) { |
1725 | sb_has_quota_suspended(sb, type)) { | ||
1726 | error = -EBUSY; | 1726 | error = -EBUSY; |
1727 | goto out_lock; | 1727 | goto out_lock; |
1728 | } | 1728 | } |
@@ -1754,7 +1754,7 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id) | |||
1754 | } | 1754 | } |
1755 | mutex_unlock(&dqopt->dqio_mutex); | 1755 | mutex_unlock(&dqopt->dqio_mutex); |
1756 | mutex_unlock(&inode->i_mutex); | 1756 | mutex_unlock(&inode->i_mutex); |
1757 | set_enable_flags(dqopt, type); | 1757 | dqopt->flags |= dquot_state_flag(flags, type); |
1758 | 1758 | ||
1759 | add_dquot_ref(sb, type); | 1759 | add_dquot_ref(sb, type); |
1760 | mutex_unlock(&dqopt->dqonoff_mutex); | 1760 | mutex_unlock(&dqopt->dqonoff_mutex); |
@@ -1787,20 +1787,23 @@ static int vfs_quota_on_remount(struct super_block *sb, int type) | |||
1787 | struct quota_info *dqopt = sb_dqopt(sb); | 1787 | struct quota_info *dqopt = sb_dqopt(sb); |
1788 | struct inode *inode; | 1788 | struct inode *inode; |
1789 | int ret; | 1789 | int ret; |
1790 | unsigned int flags; | ||
1790 | 1791 | ||
1791 | mutex_lock(&dqopt->dqonoff_mutex); | 1792 | mutex_lock(&dqopt->dqonoff_mutex); |
1792 | if (!sb_has_quota_suspended(sb, type)) { | 1793 | if (!sb_has_quota_suspended(sb, type)) { |
1793 | mutex_unlock(&dqopt->dqonoff_mutex); | 1794 | mutex_unlock(&dqopt->dqonoff_mutex); |
1794 | return 0; | 1795 | return 0; |
1795 | } | 1796 | } |
1796 | BUG_ON(sb_has_quota_enabled(sb, type)); | ||
1797 | |||
1798 | inode = dqopt->files[type]; | 1797 | inode = dqopt->files[type]; |
1799 | dqopt->files[type] = NULL; | 1798 | dqopt->files[type] = NULL; |
1800 | reset_enable_flags(dqopt, type, 0); | 1799 | flags = dqopt->flags & dquot_state_flag(DQUOT_USAGE_ENABLED | |
1800 | DQUOT_LIMITS_ENABLED, type); | ||
1801 | dqopt->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, type); | ||
1801 | mutex_unlock(&dqopt->dqonoff_mutex); | 1802 | mutex_unlock(&dqopt->dqonoff_mutex); |
1802 | 1803 | ||
1803 | ret = vfs_quota_on_inode(inode, type, dqopt->info[type].dqi_fmt_id); | 1804 | flags = dquot_generic_flag(flags, type); |
1805 | ret = vfs_load_quota_inode(inode, type, dqopt->info[type].dqi_fmt_id, | ||
1806 | flags); | ||
1804 | iput(inode); | 1807 | iput(inode); |
1805 | 1808 | ||
1806 | return ret; | 1809 | return ret; |
@@ -1816,12 +1819,12 @@ int vfs_quota_on_path(struct super_block *sb, int type, int format_id, | |||
1816 | if (path->mnt->mnt_sb != sb) | 1819 | if (path->mnt->mnt_sb != sb) |
1817 | error = -EXDEV; | 1820 | error = -EXDEV; |
1818 | else | 1821 | else |
1819 | error = vfs_quota_on_inode(path->dentry->d_inode, type, | 1822 | error = vfs_load_quota_inode(path->dentry->d_inode, type, |
1820 | format_id); | 1823 | format_id, DQUOT_USAGE_ENABLED | |
1824 | DQUOT_LIMITS_ENABLED); | ||
1821 | return error; | 1825 | return error; |
1822 | } | 1826 | } |
1823 | 1827 | ||
1824 | /* Actual function called from quotactl() */ | ||
1825 | int vfs_quota_on(struct super_block *sb, int type, int format_id, char *name, | 1828 | int vfs_quota_on(struct super_block *sb, int type, int format_id, char *name, |
1826 | int remount) | 1829 | int remount) |
1827 | { | 1830 | { |
@@ -1840,6 +1843,50 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *name, | |||
1840 | } | 1843 | } |
1841 | 1844 | ||
1842 | /* | 1845 | /* |
1846 | * More powerful function for turning on quotas allowing setting | ||
1847 | * of individual quota flags | ||
1848 | */ | ||
1849 | int vfs_quota_enable(struct inode *inode, int type, int format_id, | ||
1850 | unsigned int flags) | ||
1851 | { | ||
1852 | int ret = 0; | ||
1853 | struct super_block *sb = inode->i_sb; | ||
1854 | struct quota_info *dqopt = sb_dqopt(sb); | ||
1855 | |||
1856 | /* Just unsuspend quotas? */ | ||
1857 | if (flags & DQUOT_SUSPENDED) | ||
1858 | return vfs_quota_on_remount(sb, type); | ||
1859 | if (!flags) | ||
1860 | return 0; | ||
1861 | /* Just updating flags needed? */ | ||
1862 | if (sb_has_quota_loaded(sb, type)) { | ||
1863 | mutex_lock(&dqopt->dqonoff_mutex); | ||
1864 | /* Now do a reliable test... */ | ||
1865 | if (!sb_has_quota_loaded(sb, type)) { | ||
1866 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
1867 | goto load_quota; | ||
1868 | } | ||
1869 | if (flags & DQUOT_USAGE_ENABLED && | ||
1870 | sb_has_quota_usage_enabled(sb, type)) { | ||
1871 | ret = -EBUSY; | ||
1872 | goto out_lock; | ||
1873 | } | ||
1874 | if (flags & DQUOT_LIMITS_ENABLED && | ||
1875 | sb_has_quota_limits_enabled(sb, type)) { | ||
1876 | ret = -EBUSY; | ||
1877 | goto out_lock; | ||
1878 | } | ||
1879 | sb_dqopt(sb)->flags |= dquot_state_flag(flags, type); | ||
1880 | out_lock: | ||
1881 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
1882 | return ret; | ||
1883 | } | ||
1884 | |||
1885 | load_quota: | ||
1886 | return vfs_load_quota_inode(inode, type, format_id, flags); | ||
1887 | } | ||
1888 | |||
1889 | /* | ||
1843 | * This function is used when filesystem needs to initialize quotas | 1890 | * This function is used when filesystem needs to initialize quotas |
1844 | * during mount time. | 1891 | * during mount time. |
1845 | */ | 1892 | */ |
@@ -1860,7 +1907,8 @@ int vfs_quota_on_mount(struct super_block *sb, char *qf_name, | |||
1860 | 1907 | ||
1861 | error = security_quota_on(dentry); | 1908 | error = security_quota_on(dentry); |
1862 | if (!error) | 1909 | if (!error) |
1863 | error = vfs_quota_on_inode(dentry->d_inode, type, format_id); | 1910 | error = vfs_load_quota_inode(dentry->d_inode, type, format_id, |
1911 | DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED); | ||
1864 | 1912 | ||
1865 | out: | 1913 | out: |
1866 | dput(dentry); | 1914 | dput(dentry); |
@@ -1997,12 +2045,14 @@ int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d | |||
1997 | int rc; | 2045 | int rc; |
1998 | 2046 | ||
1999 | mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); | 2047 | mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); |
2000 | if (!(dquot = dqget(sb, id, type))) { | 2048 | dquot = dqget(sb, id, type); |
2001 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); | 2049 | if (!dquot) { |
2002 | return -ESRCH; | 2050 | rc = -ESRCH; |
2051 | goto out; | ||
2003 | } | 2052 | } |
2004 | rc = do_set_dqblk(dquot, di); | 2053 | rc = do_set_dqblk(dquot, di); |
2005 | dqput(dquot); | 2054 | dqput(dquot); |
2055 | out: | ||
2006 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); | 2056 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); |
2007 | return rc; | 2057 | return rc; |
2008 | } | 2058 | } |
@@ -2013,7 +2063,7 @@ int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) | |||
2013 | struct mem_dqinfo *mi; | 2063 | struct mem_dqinfo *mi; |
2014 | 2064 | ||
2015 | mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); | 2065 | mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); |
2016 | if (!sb_has_quota_enabled(sb, type)) { | 2066 | if (!sb_has_quota_active(sb, type)) { |
2017 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); | 2067 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); |
2018 | return -ESRCH; | 2068 | return -ESRCH; |
2019 | } | 2069 | } |
@@ -2032,11 +2082,12 @@ int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) | |||
2032 | int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) | 2082 | int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) |
2033 | { | 2083 | { |
2034 | struct mem_dqinfo *mi; | 2084 | struct mem_dqinfo *mi; |
2085 | int err = 0; | ||
2035 | 2086 | ||
2036 | mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); | 2087 | mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); |
2037 | if (!sb_has_quota_enabled(sb, type)) { | 2088 | if (!sb_has_quota_active(sb, type)) { |
2038 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); | 2089 | err = -ESRCH; |
2039 | return -ESRCH; | 2090 | goto out; |
2040 | } | 2091 | } |
2041 | mi = sb_dqopt(sb)->info + type; | 2092 | mi = sb_dqopt(sb)->info + type; |
2042 | spin_lock(&dq_data_lock); | 2093 | spin_lock(&dq_data_lock); |
@@ -2050,8 +2101,9 @@ int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) | |||
2050 | mark_info_dirty(sb, type); | 2101 | mark_info_dirty(sb, type); |
2051 | /* Force write to disk */ | 2102 | /* Force write to disk */ |
2052 | sb->dq_op->write_info(sb, type); | 2103 | sb->dq_op->write_info(sb, type); |
2104 | out: | ||
2053 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); | 2105 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); |
2054 | return 0; | 2106 | return err; |
2055 | } | 2107 | } |
2056 | 2108 | ||
2057 | struct quotactl_ops vfs_quotactl_ops = { | 2109 | struct quotactl_ops vfs_quotactl_ops = { |
@@ -2213,9 +2265,11 @@ EXPORT_SYMBOL(register_quota_format); | |||
2213 | EXPORT_SYMBOL(unregister_quota_format); | 2265 | EXPORT_SYMBOL(unregister_quota_format); |
2214 | EXPORT_SYMBOL(dqstats); | 2266 | EXPORT_SYMBOL(dqstats); |
2215 | EXPORT_SYMBOL(dq_data_lock); | 2267 | EXPORT_SYMBOL(dq_data_lock); |
2268 | EXPORT_SYMBOL(vfs_quota_enable); | ||
2216 | EXPORT_SYMBOL(vfs_quota_on); | 2269 | EXPORT_SYMBOL(vfs_quota_on); |
2217 | EXPORT_SYMBOL(vfs_quota_on_path); | 2270 | EXPORT_SYMBOL(vfs_quota_on_path); |
2218 | EXPORT_SYMBOL(vfs_quota_on_mount); | 2271 | EXPORT_SYMBOL(vfs_quota_on_mount); |
2272 | EXPORT_SYMBOL(vfs_quota_disable); | ||
2219 | EXPORT_SYMBOL(vfs_quota_off); | 2273 | EXPORT_SYMBOL(vfs_quota_off); |
2220 | EXPORT_SYMBOL(vfs_quota_sync); | 2274 | EXPORT_SYMBOL(vfs_quota_sync); |
2221 | EXPORT_SYMBOL(vfs_get_dqinfo); | 2275 | EXPORT_SYMBOL(vfs_get_dqinfo); |