Commit ca785ec6 authored by Jan Kara's avatar Jan Kara Committed by Mark Fasheh

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: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
parent dcb30695
...@@ -1631,6 +1631,11 @@ int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags) ...@@ -1631,6 +1631,11 @@ int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags)
dqopt->ops[cnt] = NULL; dqopt->ops[cnt] = NULL;
} }
mutex_unlock(&dqopt->dqonoff_mutex); mutex_unlock(&dqopt->dqonoff_mutex);
/* Skip syncing and setting flags if quota files are hidden */
if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
goto put_inodes;
/* Sync the superblock so that buffers with quota data are written to /* Sync the superblock so that buffers with quota data are written to
* disk (and so userspace sees correct data afterwards). */ * disk (and so userspace sees correct data afterwards). */
if (sb->s_op->sync_fs) if (sb->s_op->sync_fs)
...@@ -1655,6 +1660,12 @@ int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags) ...@@ -1655,6 +1660,12 @@ int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags)
mark_inode_dirty(toputinode[cnt]); mark_inode_dirty(toputinode[cnt]);
} }
mutex_unlock(&dqopt->dqonoff_mutex); mutex_unlock(&dqopt->dqonoff_mutex);
}
if (sb->s_bdev)
invalidate_bdev(sb->s_bdev);
put_inodes:
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
if (toputinode[cnt]) {
/* On remount RO, we keep the inode pointer so that we /* On remount RO, we keep the inode pointer so that we
* can reenable quota on the subsequent remount RW. We * can reenable quota on the subsequent remount RW. We
* have to check 'flags' variable and not use sb_has_ * 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,8 +1678,6 @@ int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags)
else if (!toputinode[cnt]->i_nlink) else if (!toputinode[cnt]->i_nlink)
ret = -EBUSY; ret = -EBUSY;
} }
if (sb->s_bdev)
invalidate_bdev(sb->s_bdev);
return ret; return ret;
} }
...@@ -1715,25 +1724,31 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, ...@@ -1715,25 +1724,31 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
goto out_fmt; goto out_fmt;
} }
/* As we bypass the pagecache we must now flush the inode so that if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
* we see all the changes from userspace... */ /* As we bypass the pagecache we must now flush the inode so
write_inode_now(inode, 1); * that we see all the changes from userspace... */
/* And now flush the block cache so that kernel sees the changes */ write_inode_now(inode, 1);
invalidate_bdev(sb->s_bdev); /* And now flush the block cache so that kernel sees the
* changes */
invalidate_bdev(sb->s_bdev);
}
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
mutex_lock(&dqopt->dqonoff_mutex); mutex_lock(&dqopt->dqonoff_mutex);
if (sb_has_quota_loaded(sb, type)) { if (sb_has_quota_loaded(sb, type)) {
error = -EBUSY; error = -EBUSY;
goto out_lock; goto out_lock;
} }
/* We don't want quota and atime on quota files (deadlocks possible)
* Also nobody should write to the file - we use special IO operations if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
* which ignore the immutable bit. */ /* We don't want quota and atime on quota files (deadlocks
down_write(&dqopt->dqptr_sem); * possible) Also nobody should write to the file - we use
oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | S_NOQUOTA); * special IO operations which ignore the immutable bit. */
inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE; down_write(&dqopt->dqptr_sem);
up_write(&dqopt->dqptr_sem); oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | S_NOQUOTA);
sb->dq_op->drop(inode); inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE;
up_write(&dqopt->dqptr_sem);
sb->dq_op->drop(inode);
}
error = -EIO; error = -EIO;
dqopt->files[type] = igrab(inode); dqopt->files[type] = igrab(inode);
......
...@@ -160,6 +160,9 @@ static void quota_sync_sb(struct super_block *sb, int type) ...@@ -160,6 +160,9 @@ static void quota_sync_sb(struct super_block *sb, int type)
int cnt; int cnt;
sb->s_qcop->quota_sync(sb, type); sb->s_qcop->quota_sync(sb, type);
if (sb_dqopt(sb)->flags & DQUOT_QUOTA_SYS_FILE)
return;
/* This is not very clever (and fast) but currently I don't know about /* This is not very clever (and fast) but currently I don't know about
* any other simple way of getting quota data to disk and we must get * any other simple way of getting quota data to disk and we must get
* them there for userspace to be visible... */ * them there for userspace to be visible... */
......
...@@ -332,6 +332,13 @@ enum { ...@@ -332,6 +332,13 @@ enum {
#define DQUOT_SUSPENDED (1 << _DQUOT_SUSPENDED) #define DQUOT_SUSPENDED (1 << _DQUOT_SUSPENDED)
#define DQUOT_STATE_FLAGS (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED | \ #define DQUOT_STATE_FLAGS (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED | \
DQUOT_SUSPENDED) DQUOT_SUSPENDED)
/* Other quota flags */
#define DQUOT_QUOTA_SYS_FILE (1 << 6) /* Quota file is a special
* system file and user cannot
* touch it. Filesystem is
* responsible for setting
* S_NOQUOTA, S_NOATIME flags
*/
static inline unsigned int dquot_state_flag(unsigned int flags, int type) static inline unsigned int dquot_state_flag(unsigned int flags, int type)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment