diff options
author | Jan Kara <jack@suse.cz> | 2008-09-30 11:53:37 -0400 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:36:57 -0500 |
commit | ca785ec66b991e9ca74dd9840fc014487ad095e1 (patch) | |
tree | 271c7b36123e9c16f455ecd96352d24ecd20423c | |
parent | dcb30695f2cac86b71417629a6fe8042b4fe2ab2 (diff) |
quota: Introduce DQUOT_QUOTA_SYS_FILE flag
If filesystem can handle quota files as system files hidden from users, we can
skip a lot of cache invalidation, syncing, inode flags setting etc. when
turning quotas on, off and quota_sync. Allow filesystem to indicate that it is
hiding quota files from users by DQUOT_QUOTA_SYS_FILE flag.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
-rw-r--r-- | fs/dquot.c | 45 | ||||
-rw-r--r-- | fs/quota.c | 3 | ||||
-rw-r--r-- | include/linux/quota.h | 7 |
3 files changed, 40 insertions, 15 deletions
diff --git a/fs/dquot.c b/fs/dquot.c index 7569633efe0e..74185c34a4f0 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -1631,6 +1631,11 @@ int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags) | |||
1631 | dqopt->ops[cnt] = NULL; | 1631 | dqopt->ops[cnt] = NULL; |
1632 | } | 1632 | } |
1633 | mutex_unlock(&dqopt->dqonoff_mutex); | 1633 | mutex_unlock(&dqopt->dqonoff_mutex); |
1634 | |||
1635 | /* Skip syncing and setting flags if quota files are hidden */ | ||
1636 | if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) | ||
1637 | goto put_inodes; | ||
1638 | |||
1634 | /* Sync the superblock so that buffers with quota data are written to | 1639 | /* Sync the superblock so that buffers with quota data are written to |
1635 | * disk (and so userspace sees correct data afterwards). */ | 1640 | * disk (and so userspace sees correct data afterwards). */ |
1636 | if (sb->s_op->sync_fs) | 1641 | if (sb->s_op->sync_fs) |
@@ -1655,6 +1660,12 @@ int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags) | |||
1655 | mark_inode_dirty(toputinode[cnt]); | 1660 | mark_inode_dirty(toputinode[cnt]); |
1656 | } | 1661 | } |
1657 | mutex_unlock(&dqopt->dqonoff_mutex); | 1662 | mutex_unlock(&dqopt->dqonoff_mutex); |
1663 | } | ||
1664 | if (sb->s_bdev) | ||
1665 | invalidate_bdev(sb->s_bdev); | ||
1666 | put_inodes: | ||
1667 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | ||
1668 | if (toputinode[cnt]) { | ||
1658 | /* On remount RO, we keep the inode pointer so that we | 1669 | /* On remount RO, we keep the inode pointer so that we |
1659 | * can reenable quota on the subsequent remount RW. We | 1670 | * can reenable quota on the subsequent remount RW. We |
1660 | * have to check 'flags' variable and not use sb_has_ | 1671 | * have to check 'flags' variable and not use sb_has_ |
@@ -1667,8 +1678,6 @@ int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags) | |||
1667 | else if (!toputinode[cnt]->i_nlink) | 1678 | else if (!toputinode[cnt]->i_nlink) |
1668 | ret = -EBUSY; | 1679 | ret = -EBUSY; |
1669 | } | 1680 | } |
1670 | if (sb->s_bdev) | ||
1671 | invalidate_bdev(sb->s_bdev); | ||
1672 | return ret; | 1681 | return ret; |
1673 | } | 1682 | } |
1674 | 1683 | ||
@@ -1715,25 +1724,31 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
1715 | goto out_fmt; | 1724 | goto out_fmt; |
1716 | } | 1725 | } |
1717 | 1726 | ||
1718 | /* As we bypass the pagecache we must now flush the inode so that | 1727 | if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { |
1719 | * we see all the changes from userspace... */ | 1728 | /* As we bypass the pagecache we must now flush the inode so |
1720 | write_inode_now(inode, 1); | 1729 | * that we see all the changes from userspace... */ |
1721 | /* And now flush the block cache so that kernel sees the changes */ | 1730 | write_inode_now(inode, 1); |
1722 | invalidate_bdev(sb->s_bdev); | 1731 | /* And now flush the block cache so that kernel sees the |
1732 | * changes */ | ||
1733 | invalidate_bdev(sb->s_bdev); | ||
1734 | } | ||
1723 | mutex_lock(&inode->i_mutex); | 1735 | mutex_lock(&inode->i_mutex); |
1724 | mutex_lock(&dqopt->dqonoff_mutex); | 1736 | mutex_lock(&dqopt->dqonoff_mutex); |
1725 | if (sb_has_quota_loaded(sb, type)) { | 1737 | if (sb_has_quota_loaded(sb, type)) { |
1726 | error = -EBUSY; | 1738 | error = -EBUSY; |
1727 | goto out_lock; | 1739 | goto out_lock; |
1728 | } | 1740 | } |
1729 | /* We don't want quota and atime on quota files (deadlocks possible) | 1741 | |
1730 | * Also nobody should write to the file - we use special IO operations | 1742 | if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { |
1731 | * which ignore the immutable bit. */ | 1743 | /* We don't want quota and atime on quota files (deadlocks |
1732 | down_write(&dqopt->dqptr_sem); | 1744 | * possible) Also nobody should write to the file - we use |
1733 | oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | S_NOQUOTA); | 1745 | * special IO operations which ignore the immutable bit. */ |
1734 | inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE; | 1746 | down_write(&dqopt->dqptr_sem); |
1735 | up_write(&dqopt->dqptr_sem); | 1747 | oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | S_NOQUOTA); |
1736 | sb->dq_op->drop(inode); | 1748 | inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE; |
1749 | up_write(&dqopt->dqptr_sem); | ||
1750 | sb->dq_op->drop(inode); | ||
1751 | } | ||
1737 | 1752 | ||
1738 | error = -EIO; | 1753 | error = -EIO; |
1739 | dqopt->files[type] = igrab(inode); | 1754 | dqopt->files[type] = igrab(inode); |
diff --git a/fs/quota.c b/fs/quota.c index 8678d9f35ee9..4a8c94f05f76 100644 --- a/fs/quota.c +++ b/fs/quota.c | |||
@@ -160,6 +160,9 @@ static void quota_sync_sb(struct super_block *sb, int type) | |||
160 | int cnt; | 160 | int cnt; |
161 | 161 | ||
162 | sb->s_qcop->quota_sync(sb, type); | 162 | sb->s_qcop->quota_sync(sb, type); |
163 | |||
164 | if (sb_dqopt(sb)->flags & DQUOT_QUOTA_SYS_FILE) | ||
165 | return; | ||
163 | /* This is not very clever (and fast) but currently I don't know about | 166 | /* This is not very clever (and fast) but currently I don't know about |
164 | * any other simple way of getting quota data to disk and we must get | 167 | * any other simple way of getting quota data to disk and we must get |
165 | * them there for userspace to be visible... */ | 168 | * them there for userspace to be visible... */ |
diff --git a/include/linux/quota.h b/include/linux/quota.h index 93717abcd35b..80b8807b4988 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h | |||
@@ -332,6 +332,13 @@ enum { | |||
332 | #define DQUOT_SUSPENDED (1 << _DQUOT_SUSPENDED) | 332 | #define DQUOT_SUSPENDED (1 << _DQUOT_SUSPENDED) |
333 | #define DQUOT_STATE_FLAGS (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED | \ | 333 | #define DQUOT_STATE_FLAGS (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED | \ |
334 | DQUOT_SUSPENDED) | 334 | DQUOT_SUSPENDED) |
335 | /* Other quota flags */ | ||
336 | #define DQUOT_QUOTA_SYS_FILE (1 << 6) /* Quota file is a special | ||
337 | * system file and user cannot | ||
338 | * touch it. Filesystem is | ||
339 | * responsible for setting | ||
340 | * S_NOQUOTA, S_NOATIME flags | ||
341 | */ | ||
335 | 342 | ||
336 | static inline unsigned int dquot_state_flag(unsigned int flags, int type) | 343 | static inline unsigned int dquot_state_flag(unsigned int flags, int type) |
337 | { | 344 | { |