Commit c3b00446 authored by Jan Kara's avatar Jan Kara

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: default avatarJan Kara <jack@suse.cz>
parent 5f530de6
...@@ -119,8 +119,7 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, ...@@ -2350,7 +2336,6 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
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) ...@@ -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) ...@@ -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); ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 */
......
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