quota: Remove dqonoff_mutex
The only places that were grabbing dqonoff_mutex are functions turning quotas on and off and these are properly serialized using s_umount semaphore. Remove dqonoff_mutex. Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
5f530de63c
commit
c3b004460d
|
@ -119,8 +119,7 @@
|
||||||
* spinlock to internal buffers before writing.
|
* spinlock to internal buffers before writing.
|
||||||
*
|
*
|
||||||
* Lock ordering (including related VFS locks) is the following:
|
* Lock ordering (including related VFS locks) is the following:
|
||||||
* dqonoff_mutex > i_mutex > journal_lock > dquot->dq_lock > dqio_mutex
|
* s_umount > i_mutex > journal_lock > dquot->dq_lock > dqio_mutex
|
||||||
* dqonoff_mutex > i_mutex comes from dquot_quota_sync, dquot_enable, etc.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock);
|
static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock);
|
||||||
|
@ -933,7 +932,7 @@ static int dqinit_needed(struct inode *inode, int type)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This routine is guarded by dqonoff_mutex mutex */
|
/* This routine is guarded by s_umount semaphore */
|
||||||
static void add_dquot_ref(struct super_block *sb, int type)
|
static void add_dquot_ref(struct super_block *sb, int type)
|
||||||
{
|
{
|
||||||
struct inode *inode, *old_inode = NULL;
|
struct inode *inode, *old_inode = NULL;
|
||||||
|
@ -2108,18 +2107,14 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags)
|
||||||
DQUOT_USAGE_ENABLED)))
|
DQUOT_USAGE_ENABLED)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* We need to serialize quota_off() for device */
|
|
||||||
mutex_lock(&dqopt->dqonoff_mutex);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip everything if there's nothing to do. We have to do this because
|
* Skip everything if there's nothing to do. We have to do this because
|
||||||
* sometimes we are called when fill_super() failed and calling
|
* sometimes we are called when fill_super() failed and calling
|
||||||
* sync_fs() in such cases does no good.
|
* sync_fs() in such cases does no good.
|
||||||
*/
|
*/
|
||||||
if (!sb_any_quota_loaded(sb)) {
|
if (!sb_any_quota_loaded(sb))
|
||||||
mutex_unlock(&dqopt->dqonoff_mutex);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||||
toputinode[cnt] = NULL;
|
toputinode[cnt] = NULL;
|
||||||
if (type != -1 && cnt != type)
|
if (type != -1 && cnt != type)
|
||||||
|
@ -2173,7 +2168,6 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags)
|
||||||
dqopt->info[cnt].dqi_bgrace = 0;
|
dqopt->info[cnt].dqi_bgrace = 0;
|
||||||
dqopt->ops[cnt] = NULL;
|
dqopt->ops[cnt] = NULL;
|
||||||
}
|
}
|
||||||
mutex_unlock(&dqopt->dqonoff_mutex);
|
|
||||||
|
|
||||||
/* Skip syncing and setting flags if quota files are hidden */
|
/* Skip syncing and setting flags if quota files are hidden */
|
||||||
if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
|
if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
|
||||||
|
@ -2191,19 +2185,13 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags)
|
||||||
* changes done by userspace on the next quotaon() */
|
* changes done by userspace on the next quotaon() */
|
||||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
|
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
|
||||||
if (toputinode[cnt]) {
|
if (toputinode[cnt]) {
|
||||||
mutex_lock(&dqopt->dqonoff_mutex);
|
WARN_ON_ONCE(sb_has_quota_loaded(sb, cnt));
|
||||||
/* If quota was reenabled in the meantime, we have
|
inode_lock(toputinode[cnt]);
|
||||||
* nothing to do */
|
toputinode[cnt]->i_flags &= ~(S_IMMUTABLE |
|
||||||
if (!sb_has_quota_loaded(sb, cnt)) {
|
|
||||||
inode_lock(toputinode[cnt]);
|
|
||||||
toputinode[cnt]->i_flags &= ~(S_IMMUTABLE |
|
|
||||||
S_NOATIME | S_NOQUOTA);
|
S_NOATIME | S_NOQUOTA);
|
||||||
truncate_inode_pages(&toputinode[cnt]->i_data,
|
truncate_inode_pages(&toputinode[cnt]->i_data, 0);
|
||||||
0);
|
inode_unlock(toputinode[cnt]);
|
||||||
inode_unlock(toputinode[cnt]);
|
mark_inode_dirty_sync(toputinode[cnt]);
|
||||||
mark_inode_dirty_sync(toputinode[cnt]);
|
|
||||||
}
|
|
||||||
mutex_unlock(&dqopt->dqonoff_mutex);
|
|
||||||
}
|
}
|
||||||
if (sb->s_bdev)
|
if (sb->s_bdev)
|
||||||
invalidate_bdev(sb->s_bdev);
|
invalidate_bdev(sb->s_bdev);
|
||||||
|
@ -2275,6 +2263,10 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
|
||||||
error = -EINVAL;
|
error = -EINVAL;
|
||||||
goto out_fmt;
|
goto out_fmt;
|
||||||
}
|
}
|
||||||
|
if (sb_has_quota_loaded(sb, type)) {
|
||||||
|
error = -EBUSY;
|
||||||
|
goto out_fmt;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
|
if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
|
||||||
/* As we bypass the pagecache we must now flush all the
|
/* As we bypass the pagecache we must now flush all the
|
||||||
|
@ -2286,11 +2278,6 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
|
||||||
sync_filesystem(sb);
|
sync_filesystem(sb);
|
||||||
invalidate_bdev(sb->s_bdev);
|
invalidate_bdev(sb->s_bdev);
|
||||||
}
|
}
|
||||||
mutex_lock(&dqopt->dqonoff_mutex);
|
|
||||||
if (sb_has_quota_loaded(sb, type)) {
|
|
||||||
error = -EBUSY;
|
|
||||||
goto out_lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
|
if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
|
||||||
/* We don't want quota and atime on quota files (deadlocks
|
/* We don't want quota and atime on quota files (deadlocks
|
||||||
|
@ -2311,7 +2298,7 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
|
||||||
error = -EIO;
|
error = -EIO;
|
||||||
dqopt->files[type] = igrab(inode);
|
dqopt->files[type] = igrab(inode);
|
||||||
if (!dqopt->files[type])
|
if (!dqopt->files[type])
|
||||||
goto out_lock;
|
goto out_file_flags;
|
||||||
error = -EINVAL;
|
error = -EINVAL;
|
||||||
if (!fmt->qf_ops->check_quota_file(sb, type))
|
if (!fmt->qf_ops->check_quota_file(sb, type))
|
||||||
goto out_file_init;
|
goto out_file_init;
|
||||||
|
@ -2334,14 +2321,13 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
|
||||||
spin_unlock(&dq_state_lock);
|
spin_unlock(&dq_state_lock);
|
||||||
|
|
||||||
add_dquot_ref(sb, type);
|
add_dquot_ref(sb, type);
|
||||||
mutex_unlock(&dqopt->dqonoff_mutex);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_file_init:
|
out_file_init:
|
||||||
dqopt->files[type] = NULL;
|
dqopt->files[type] = NULL;
|
||||||
iput(inode);
|
iput(inode);
|
||||||
out_lock:
|
out_file_flags:
|
||||||
if (oldflags != -1) {
|
if (oldflags != -1) {
|
||||||
inode_lock(inode);
|
inode_lock(inode);
|
||||||
/* Set the flags back (in the case of accidental quotaon()
|
/* Set the flags back (in the case of accidental quotaon()
|
||||||
|
@ -2350,7 +2336,6 @@ out_lock:
|
||||||
inode->i_flags |= oldflags;
|
inode->i_flags |= oldflags;
|
||||||
inode_unlock(inode);
|
inode_unlock(inode);
|
||||||
}
|
}
|
||||||
mutex_unlock(&dqopt->dqonoff_mutex);
|
|
||||||
out_fmt:
|
out_fmt:
|
||||||
put_quota_format(fmt);
|
put_quota_format(fmt);
|
||||||
|
|
||||||
|
@ -2372,12 +2357,9 @@ int dquot_resume(struct super_block *sb, int type)
|
||||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||||
if (type != -1 && cnt != type)
|
if (type != -1 && cnt != type)
|
||||||
continue;
|
continue;
|
||||||
|
if (!sb_has_quota_suspended(sb, cnt))
|
||||||
mutex_lock(&dqopt->dqonoff_mutex);
|
|
||||||
if (!sb_has_quota_suspended(sb, cnt)) {
|
|
||||||
mutex_unlock(&dqopt->dqonoff_mutex);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
inode = dqopt->files[cnt];
|
inode = dqopt->files[cnt];
|
||||||
dqopt->files[cnt] = NULL;
|
dqopt->files[cnt] = NULL;
|
||||||
spin_lock(&dq_state_lock);
|
spin_lock(&dq_state_lock);
|
||||||
|
@ -2386,7 +2368,6 @@ int dquot_resume(struct super_block *sb, int type)
|
||||||
cnt);
|
cnt);
|
||||||
dqopt->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, cnt);
|
dqopt->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, cnt);
|
||||||
spin_unlock(&dq_state_lock);
|
spin_unlock(&dq_state_lock);
|
||||||
mutex_unlock(&dqopt->dqonoff_mutex);
|
|
||||||
|
|
||||||
flags = dquot_generic_flag(flags, cnt);
|
flags = dquot_generic_flag(flags, cnt);
|
||||||
ret = vfs_load_quota_inode(inode, cnt,
|
ret = vfs_load_quota_inode(inode, cnt,
|
||||||
|
@ -2422,9 +2403,7 @@ EXPORT_SYMBOL(dquot_quota_on);
|
||||||
int dquot_enable(struct inode *inode, int type, int format_id,
|
int dquot_enable(struct inode *inode, int type, int format_id,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
struct quota_info *dqopt = sb_dqopt(sb);
|
|
||||||
|
|
||||||
/* Just unsuspend quotas? */
|
/* Just unsuspend quotas? */
|
||||||
BUG_ON(flags & DQUOT_SUSPENDED);
|
BUG_ON(flags & DQUOT_SUSPENDED);
|
||||||
|
@ -2436,31 +2415,18 @@ int dquot_enable(struct inode *inode, int type, int format_id,
|
||||||
return 0;
|
return 0;
|
||||||
/* Just updating flags needed? */
|
/* Just updating flags needed? */
|
||||||
if (sb_has_quota_loaded(sb, type)) {
|
if (sb_has_quota_loaded(sb, type)) {
|
||||||
mutex_lock(&dqopt->dqonoff_mutex);
|
|
||||||
/* Now do a reliable test... */
|
|
||||||
if (!sb_has_quota_loaded(sb, type)) {
|
|
||||||
mutex_unlock(&dqopt->dqonoff_mutex);
|
|
||||||
goto load_quota;
|
|
||||||
}
|
|
||||||
if (flags & DQUOT_USAGE_ENABLED &&
|
if (flags & DQUOT_USAGE_ENABLED &&
|
||||||
sb_has_quota_usage_enabled(sb, type)) {
|
sb_has_quota_usage_enabled(sb, type))
|
||||||
ret = -EBUSY;
|
return -EBUSY;
|
||||||
goto out_lock;
|
|
||||||
}
|
|
||||||
if (flags & DQUOT_LIMITS_ENABLED &&
|
if (flags & DQUOT_LIMITS_ENABLED &&
|
||||||
sb_has_quota_limits_enabled(sb, type)) {
|
sb_has_quota_limits_enabled(sb, type))
|
||||||
ret = -EBUSY;
|
return -EBUSY;
|
||||||
goto out_lock;
|
|
||||||
}
|
|
||||||
spin_lock(&dq_state_lock);
|
spin_lock(&dq_state_lock);
|
||||||
sb_dqopt(sb)->flags |= dquot_state_flag(flags, type);
|
sb_dqopt(sb)->flags |= dquot_state_flag(flags, type);
|
||||||
spin_unlock(&dq_state_lock);
|
spin_unlock(&dq_state_lock);
|
||||||
out_lock:
|
return 0;
|
||||||
mutex_unlock(&dqopt->dqonoff_mutex);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
load_quota:
|
|
||||||
return vfs_load_quota_inode(inode, type, format_id, flags);
|
return vfs_load_quota_inode(inode, type, format_id, flags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dquot_enable);
|
EXPORT_SYMBOL(dquot_enable);
|
||||||
|
|
|
@ -244,7 +244,6 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
|
||||||
mutex_init(&s->s_vfs_rename_mutex);
|
mutex_init(&s->s_vfs_rename_mutex);
|
||||||
lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key);
|
lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key);
|
||||||
mutex_init(&s->s_dquot.dqio_mutex);
|
mutex_init(&s->s_dquot.dqio_mutex);
|
||||||
mutex_init(&s->s_dquot.dqonoff_mutex);
|
|
||||||
s->s_maxbytes = MAX_NON_LFS;
|
s->s_maxbytes = MAX_NON_LFS;
|
||||||
s->s_op = &default_op;
|
s->s_op = &default_op;
|
||||||
s->s_time_gran = 1000000000;
|
s->s_time_gran = 1000000000;
|
||||||
|
|
|
@ -520,7 +520,6 @@ static inline void quota_send_warning(struct kqid qid, dev_t dev,
|
||||||
struct quota_info {
|
struct quota_info {
|
||||||
unsigned int flags; /* Flags for diskquotas on this device */
|
unsigned int flags; /* Flags for diskquotas on this device */
|
||||||
struct mutex dqio_mutex; /* lock device while I/O in progress */
|
struct mutex dqio_mutex; /* lock device while I/O in progress */
|
||||||
struct mutex dqonoff_mutex; /* Serialize quotaon & quotaoff */
|
|
||||||
struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */
|
struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */
|
||||||
struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */
|
struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */
|
||||||
const struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */
|
const struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */
|
||||||
|
|
Loading…
Reference in New Issue