aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/dquot.c222
-rw-r--r--fs/quota.c8
-rw-r--r--include/linux/quota.h30
-rw-r--r--include/linux/quotaops.h91
4 files changed, 239 insertions, 112 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;
675we_slept: 675we_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)
1041static int check_idq(struct dquot *dquot, qsize_t inodes, char *warntype) 1041static 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)
1073static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *warntype) 1074static 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
1114static int info_idq_free(struct dquot *dquot, qsize_t inodes) 1116static 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 */
1509int vfs_dq_transfer(struct inode *inode, struct iattr *iattr) 1512int 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
1554static 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
1568static 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 */
1595int vfs_quota_off(struct super_block *sb, int type, int remount) 1560int 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
1675int 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/*
1694static 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 */
1689static 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() */
1825int vfs_quota_on(struct super_block *sb, int type, int format_id, char *name, 1828int 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 */
1849int 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);
1880out_lock:
1881 mutex_unlock(&dqopt->dqonoff_mutex);
1882 return ret;
1883 }
1884
1885load_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
1865out: 1913out:
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);
2055out:
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)
2032int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) 2082int 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);
2104out:
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
2057struct quotactl_ops vfs_quotactl_ops = { 2109struct quotactl_ops vfs_quotactl_ops = {
@@ -2213,9 +2265,11 @@ EXPORT_SYMBOL(register_quota_format);
2213EXPORT_SYMBOL(unregister_quota_format); 2265EXPORT_SYMBOL(unregister_quota_format);
2214EXPORT_SYMBOL(dqstats); 2266EXPORT_SYMBOL(dqstats);
2215EXPORT_SYMBOL(dq_data_lock); 2267EXPORT_SYMBOL(dq_data_lock);
2268EXPORT_SYMBOL(vfs_quota_enable);
2216EXPORT_SYMBOL(vfs_quota_on); 2269EXPORT_SYMBOL(vfs_quota_on);
2217EXPORT_SYMBOL(vfs_quota_on_path); 2270EXPORT_SYMBOL(vfs_quota_on_path);
2218EXPORT_SYMBOL(vfs_quota_on_mount); 2271EXPORT_SYMBOL(vfs_quota_on_mount);
2272EXPORT_SYMBOL(vfs_quota_disable);
2219EXPORT_SYMBOL(vfs_quota_off); 2273EXPORT_SYMBOL(vfs_quota_off);
2220EXPORT_SYMBOL(vfs_quota_sync); 2274EXPORT_SYMBOL(vfs_quota_sync);
2221EXPORT_SYMBOL(vfs_get_dqinfo); 2275EXPORT_SYMBOL(vfs_get_dqinfo);
diff --git a/fs/quota.c b/fs/quota.c
index b7fe44e01618..8678d9f35ee9 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -73,7 +73,7 @@ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid
73 case Q_SETQUOTA: 73 case Q_SETQUOTA:
74 case Q_GETQUOTA: 74 case Q_GETQUOTA:
75 /* This is just informative test so we are satisfied without a lock */ 75 /* This is just informative test so we are satisfied without a lock */
76 if (!sb_has_quota_enabled(sb, type)) 76 if (!sb_has_quota_active(sb, type))
77 return -ESRCH; 77 return -ESRCH;
78 } 78 }
79 79
@@ -175,7 +175,7 @@ static void quota_sync_sb(struct super_block *sb, int type)
175 for (cnt = 0; cnt < MAXQUOTAS; cnt++) { 175 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
176 if (type != -1 && cnt != type) 176 if (type != -1 && cnt != type)
177 continue; 177 continue;
178 if (!sb_has_quota_enabled(sb, cnt)) 178 if (!sb_has_quota_active(sb, cnt))
179 continue; 179 continue;
180 mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex, I_MUTEX_QUOTA); 180 mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex, I_MUTEX_QUOTA);
181 truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0); 181 truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0);
@@ -201,7 +201,7 @@ restart:
201 for (cnt = 0; cnt < MAXQUOTAS; cnt++) { 201 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
202 if (type != -1 && type != cnt) 202 if (type != -1 && type != cnt)
203 continue; 203 continue;
204 if (!sb_has_quota_enabled(sb, cnt)) 204 if (!sb_has_quota_active(sb, cnt))
205 continue; 205 continue;
206 if (!info_dirty(&sb_dqopt(sb)->info[cnt]) && 206 if (!info_dirty(&sb_dqopt(sb)->info[cnt]) &&
207 list_empty(&sb_dqopt(sb)->info[cnt].dqi_dirty_list)) 207 list_empty(&sb_dqopt(sb)->info[cnt].dqi_dirty_list))
@@ -245,7 +245,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void
245 __u32 fmt; 245 __u32 fmt;
246 246
247 down_read(&sb_dqopt(sb)->dqptr_sem); 247 down_read(&sb_dqopt(sb)->dqptr_sem);
248 if (!sb_has_quota_enabled(sb, type)) { 248 if (!sb_has_quota_active(sb, type)) {
249 up_read(&sb_dqopt(sb)->dqptr_sem); 249 up_read(&sb_dqopt(sb)->dqptr_sem);
250 return -ESRCH; 250 return -ESRCH;
251 } 251 }
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 9ea468363f9f..93717abcd35b 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -318,12 +318,34 @@ struct quota_format_type {
318 struct quota_format_type *qf_next; 318 struct quota_format_type *qf_next;
319}; 319};
320 320
321#define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */ 321/* Quota state flags - they actually come in two flavors - for users and groups */
322#define DQUOT_GRP_ENABLED 0x02 /* Group diskquotas enabled */ 322enum {
323#define DQUOT_USR_SUSPENDED 0x04 /* User diskquotas are off, but 323 _DQUOT_USAGE_ENABLED = 0, /* Track disk usage for users */
324 _DQUOT_LIMITS_ENABLED, /* Enforce quota limits for users */
325 _DQUOT_SUSPENDED, /* User diskquotas are off, but
324 * we have necessary info in 326 * we have necessary info in
325 * memory to turn them on */ 327 * memory to turn them on */
326#define DQUOT_GRP_SUSPENDED 0x08 /* The same for group quotas */ 328 _DQUOT_STATE_FLAGS
329};
330#define DQUOT_USAGE_ENABLED (1 << _DQUOT_USAGE_ENABLED)
331#define DQUOT_LIMITS_ENABLED (1 << _DQUOT_LIMITS_ENABLED)
332#define DQUOT_SUSPENDED (1 << _DQUOT_SUSPENDED)
333#define DQUOT_STATE_FLAGS (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED | \
334 DQUOT_SUSPENDED)
335
336static inline unsigned int dquot_state_flag(unsigned int flags, int type)
337{
338 if (type == USRQUOTA)
339 return flags;
340 return flags << _DQUOT_STATE_FLAGS;
341}
342
343static inline unsigned int dquot_generic_flag(unsigned int flags, int type)
344{
345 if (type == USRQUOTA)
346 return flags;
347 return flags >> _DQUOT_STATE_FLAGS;
348}
327 349
328struct quota_info { 350struct quota_info {
329 unsigned int flags; /* Flags for diskquotas on this device */ 351 unsigned int flags; /* Flags for diskquotas on this device */
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index ffd97071cd1e..3b3346fa657c 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -40,11 +40,14 @@ int dquot_mark_dquot_dirty(struct dquot *dquot);
40 40
41int vfs_quota_on(struct super_block *sb, int type, int format_id, 41int vfs_quota_on(struct super_block *sb, int type, int format_id,
42 char *path, int remount); 42 char *path, int remount);
43int vfs_quota_enable(struct inode *inode, int type, int format_id,
44 unsigned int flags);
43int vfs_quota_on_path(struct super_block *sb, int type, int format_id, 45int vfs_quota_on_path(struct super_block *sb, int type, int format_id,
44 struct path *path); 46 struct path *path);
45int vfs_quota_on_mount(struct super_block *sb, char *qf_name, 47int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
46 int format_id, int type); 48 int format_id, int type);
47int vfs_quota_off(struct super_block *sb, int type, int remount); 49int vfs_quota_off(struct super_block *sb, int type, int remount);
50int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags);
48int vfs_quota_sync(struct super_block *sb, int type); 51int vfs_quota_sync(struct super_block *sb, int type);
49int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); 52int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
50int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); 53int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
@@ -64,26 +67,22 @@ static inline struct mem_dqinfo *sb_dqinfo(struct super_block *sb, int type)
64 * Functions for checking status of quota 67 * Functions for checking status of quota
65 */ 68 */
66 69
67static inline int sb_has_quota_enabled(struct super_block *sb, int type) 70static inline int sb_has_quota_usage_enabled(struct super_block *sb, int type)
68{ 71{
69 if (type == USRQUOTA) 72 return sb_dqopt(sb)->flags &
70 return (sb_dqopt(sb)->flags & DQUOT_USR_ENABLED) 73 dquot_state_flag(DQUOT_USAGE_ENABLED, type);
71 && !(sb_dqopt(sb)->flags & DQUOT_USR_SUSPENDED);
72 return (sb_dqopt(sb)->flags & DQUOT_GRP_ENABLED)
73 && !(sb_dqopt(sb)->flags & DQUOT_GROUP_SUSPENDED);
74} 74}
75 75
76static inline int sb_any_quota_enabled(struct super_block *sb) 76static inline int sb_has_quota_limits_enabled(struct super_block *sb, int type)
77{ 77{
78 return sb_has_quota_enabled(sb, USRQUOTA) || 78 return sb_dqopt(sb)->flags &
79 sb_has_quota_enabled(sb, GRPQUOTA); 79 dquot_state_flag(DQUOT_LIMITS_ENABLED, type);
80} 80}
81 81
82static inline int sb_has_quota_suspended(struct super_block *sb, int type) 82static inline int sb_has_quota_suspended(struct super_block *sb, int type)
83{ 83{
84 if (type == USRQUOTA) 84 return sb_dqopt(sb)->flags &
85 return sb_dqopt(sb)->flags & DQUOT_USR_SUSPENDED; 85 dquot_state_flag(DQUOT_SUSPENDED, type);
86 return sb_dqopt(sb)->flags & DQUOT_GRP_SUSPENDED;
87} 86}
88 87
89static inline int sb_any_quota_suspended(struct super_block *sb) 88static inline int sb_any_quota_suspended(struct super_block *sb)
@@ -92,6 +91,34 @@ static inline int sb_any_quota_suspended(struct super_block *sb)
92 sb_has_quota_suspended(sb, GRPQUOTA); 91 sb_has_quota_suspended(sb, GRPQUOTA);
93} 92}
94 93
94/* Does kernel know about any quota information for given sb + type? */
95static inline int sb_has_quota_loaded(struct super_block *sb, int type)
96{
97 /* Currently if anything is on, then quota usage is on as well */
98 return sb_has_quota_usage_enabled(sb, type);
99}
100
101static inline int sb_any_quota_loaded(struct super_block *sb)
102{
103 return sb_has_quota_loaded(sb, USRQUOTA) ||
104 sb_has_quota_loaded(sb, GRPQUOTA);
105}
106
107static inline int sb_has_quota_active(struct super_block *sb, int type)
108{
109 return sb_has_quota_loaded(sb, type) &&
110 !sb_has_quota_suspended(sb, type);
111}
112
113static inline int sb_any_quota_active(struct super_block *sb)
114{
115 return sb_has_quota_active(sb, USRQUOTA) ||
116 sb_has_quota_active(sb, GRPQUOTA);
117}
118
119/* For backward compatibility until we remove all users */
120#define sb_any_quota_enabled(sb) sb_any_quota_active(sb)
121
95/* 122/*
96 * Operations supported for diskquotas. 123 * Operations supported for diskquotas.
97 */ 124 */
@@ -106,7 +133,7 @@ extern struct quotactl_ops vfs_quotactl_ops;
106static inline void vfs_dq_init(struct inode *inode) 133static inline void vfs_dq_init(struct inode *inode)
107{ 134{
108 BUG_ON(!inode->i_sb); 135 BUG_ON(!inode->i_sb);
109 if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode)) 136 if (sb_any_quota_active(inode->i_sb) && !IS_NOQUOTA(inode))
110 inode->i_sb->dq_op->initialize(inode, -1); 137 inode->i_sb->dq_op->initialize(inode, -1);
111} 138}
112 139
@@ -114,7 +141,7 @@ static inline void vfs_dq_init(struct inode *inode)
114 * a transaction (deadlocks possible otherwise) */ 141 * a transaction (deadlocks possible otherwise) */
115static inline int vfs_dq_prealloc_space_nodirty(struct inode *inode, qsize_t nr) 142static inline int vfs_dq_prealloc_space_nodirty(struct inode *inode, qsize_t nr)
116{ 143{
117 if (sb_any_quota_enabled(inode->i_sb)) { 144 if (sb_any_quota_active(inode->i_sb)) {
118 /* Used space is updated in alloc_space() */ 145 /* Used space is updated in alloc_space() */
119 if (inode->i_sb->dq_op->alloc_space(inode, nr, 1) == NO_QUOTA) 146 if (inode->i_sb->dq_op->alloc_space(inode, nr, 1) == NO_QUOTA)
120 return 1; 147 return 1;
@@ -134,7 +161,7 @@ static inline int vfs_dq_prealloc_space(struct inode *inode, qsize_t nr)
134 161
135static inline int vfs_dq_alloc_space_nodirty(struct inode *inode, qsize_t nr) 162static inline int vfs_dq_alloc_space_nodirty(struct inode *inode, qsize_t nr)
136{ 163{
137 if (sb_any_quota_enabled(inode->i_sb)) { 164 if (sb_any_quota_active(inode->i_sb)) {
138 /* Used space is updated in alloc_space() */ 165 /* Used space is updated in alloc_space() */
139 if (inode->i_sb->dq_op->alloc_space(inode, nr, 0) == NO_QUOTA) 166 if (inode->i_sb->dq_op->alloc_space(inode, nr, 0) == NO_QUOTA)
140 return 1; 167 return 1;
@@ -154,7 +181,7 @@ static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr)
154 181
155static inline int vfs_dq_alloc_inode(struct inode *inode) 182static inline int vfs_dq_alloc_inode(struct inode *inode)
156{ 183{
157 if (sb_any_quota_enabled(inode->i_sb)) { 184 if (sb_any_quota_active(inode->i_sb)) {
158 vfs_dq_init(inode); 185 vfs_dq_init(inode);
159 if (inode->i_sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) 186 if (inode->i_sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA)
160 return 1; 187 return 1;
@@ -164,7 +191,7 @@ static inline int vfs_dq_alloc_inode(struct inode *inode)
164 191
165static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr) 192static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
166{ 193{
167 if (sb_any_quota_enabled(inode->i_sb)) 194 if (sb_any_quota_active(inode->i_sb))
168 inode->i_sb->dq_op->free_space(inode, nr); 195 inode->i_sb->dq_op->free_space(inode, nr);
169 else 196 else
170 inode_sub_bytes(inode, nr); 197 inode_sub_bytes(inode, nr);
@@ -178,7 +205,7 @@ static inline void vfs_dq_free_space(struct inode *inode, qsize_t nr)
178 205
179static inline void vfs_dq_free_inode(struct inode *inode) 206static inline void vfs_dq_free_inode(struct inode *inode)
180{ 207{
181 if (sb_any_quota_enabled(inode->i_sb)) 208 if (sb_any_quota_active(inode->i_sb))
182 inode->i_sb->dq_op->free_inode(inode, 1); 209 inode->i_sb->dq_op->free_inode(inode, 1);
183} 210}
184 211
@@ -199,12 +226,12 @@ static inline int vfs_dq_off(struct super_block *sb, int remount)
199 226
200#else 227#else
201 228
202static inline int sb_has_quota_enabled(struct super_block *sb, int type) 229static inline int sb_has_quota_usage_enabled(struct super_block *sb, int type)
203{ 230{
204 return 0; 231 return 0;
205} 232}
206 233
207static inline int sb_any_quota_enabled(struct super_block *sb) 234static inline int sb_has_quota_limits_enabled(struct super_block *sb, int type)
208{ 235{
209 return 0; 236 return 0;
210} 237}
@@ -219,6 +246,30 @@ static inline int sb_any_quota_suspended(struct super_block *sb)
219 return 0; 246 return 0;
220} 247}
221 248
249/* Does kernel know about any quota information for given sb + type? */
250static inline int sb_has_quota_loaded(struct super_block *sb, int type)
251{
252 return 0;
253}
254
255static inline int sb_any_quota_loaded(struct super_block *sb)
256{
257 return 0;
258}
259
260static inline int sb_has_quota_active(struct super_block *sb, int type)
261{
262 return 0;
263}
264
265static inline int sb_any_quota_active(struct super_block *sb)
266{
267 return 0;
268}
269
270/* For backward compatibility until we remove all users */
271#define sb_any_quota_enabled(sb) sb_any_quota_active(sb)
272
222/* 273/*
223 * NO-OP when quota not configured. 274 * NO-OP when quota not configured.
224 */ 275 */