Commit c3b00446 authored by Jan Kara's avatar Jan Kara
Browse files

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
Loading
Loading
Loading
Loading
+23 −57
Original line number Diff line number Diff line
@@ -119,8 +119,7 @@
 * spinlock to internal buffers before writing.
 *
 * Lock ordering (including related VFS locks) is the following:
 *   dqonoff_mutex > i_mutex > journal_lock > dquot->dq_lock > dqio_mutex
 * dqonoff_mutex > i_mutex comes from dquot_quota_sync, dquot_enable, etc.
 *   s_umount > i_mutex > journal_lock > dquot->dq_lock > dqio_mutex
 */

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;
}

/* 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)
{
	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)))
		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
	 * sometimes we are called when fill_super() failed and calling
	 * sync_fs() in such cases does no good.
	 */
	if (!sb_any_quota_loaded(sb)) {
		mutex_unlock(&dqopt->dqonoff_mutex);
	if (!sb_any_quota_loaded(sb))
		return 0;
	}

	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
		toputinode[cnt] = NULL;
		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->ops[cnt] = NULL;
	}
	mutex_unlock(&dqopt->dqonoff_mutex);

	/* Skip syncing and setting flags if quota files are hidden */
	if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
@@ -2191,20 +2185,14 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags)
	 * changes done by userspace on the next quotaon() */
	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
		if (toputinode[cnt]) {
			mutex_lock(&dqopt->dqonoff_mutex);
			/* If quota was reenabled in the meantime, we have
			 * nothing to do */
			if (!sb_has_quota_loaded(sb, cnt)) {
			WARN_ON_ONCE(sb_has_quota_loaded(sb, cnt));
			inode_lock(toputinode[cnt]);
			toputinode[cnt]->i_flags &= ~(S_IMMUTABLE |
				  S_NOATIME | S_NOQUOTA);
				truncate_inode_pages(&toputinode[cnt]->i_data,
						     0);
			truncate_inode_pages(&toputinode[cnt]->i_data, 0);
			inode_unlock(toputinode[cnt]);
			mark_inode_dirty_sync(toputinode[cnt]);
		}
			mutex_unlock(&dqopt->dqonoff_mutex);
		}
	if (sb->s_bdev)
		invalidate_bdev(sb->s_bdev);
put_inodes:
@@ -2275,6 +2263,10 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
		error = -EINVAL;
		goto out_fmt;
	}
	if (sb_has_quota_loaded(sb, type)) {
		error = -EBUSY;
		goto out_fmt;
	}

	if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
		/* 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);
		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)) {
		/* 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;
	dqopt->files[type] = igrab(inode);
	if (!dqopt->files[type])
		goto out_lock;
		goto out_file_flags;
	error = -EINVAL;
	if (!fmt->qf_ops->check_quota_file(sb, type))
		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);

	add_dquot_ref(sb, type);
	mutex_unlock(&dqopt->dqonoff_mutex);

	return 0;

out_file_init:
	dqopt->files[type] = NULL;
	iput(inode);
out_lock:
out_file_flags:
	if (oldflags != -1) {
		inode_lock(inode);
		/* Set the flags back (in the case of accidental quotaon()
@@ -2350,7 +2336,6 @@ out_lock:
		inode->i_flags |= oldflags;
		inode_unlock(inode);
	}
	mutex_unlock(&dqopt->dqonoff_mutex);
out_fmt:
	put_quota_format(fmt);

@@ -2372,12 +2357,9 @@ int dquot_resume(struct super_block *sb, int type)
	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
		if (type != -1 && cnt != type)
			continue;

		mutex_lock(&dqopt->dqonoff_mutex);
		if (!sb_has_quota_suspended(sb, cnt)) {
			mutex_unlock(&dqopt->dqonoff_mutex);
		if (!sb_has_quota_suspended(sb, cnt))
			continue;
		}

		inode = dqopt->files[cnt];
		dqopt->files[cnt] = NULL;
		spin_lock(&dq_state_lock);
@@ -2386,7 +2368,6 @@ int dquot_resume(struct super_block *sb, int type)
							cnt);
		dqopt->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, cnt);
		spin_unlock(&dq_state_lock);
		mutex_unlock(&dqopt->dqonoff_mutex);

		flags = dquot_generic_flag(flags, 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,
		 unsigned int flags)
{
	int ret = 0;
	struct super_block *sb = inode->i_sb;
	struct quota_info *dqopt = sb_dqopt(sb);

	/* Just unsuspend quotas? */
	BUG_ON(flags & DQUOT_SUSPENDED);
@@ -2436,31 +2415,18 @@ int dquot_enable(struct inode *inode, int type, int format_id,
		return 0;
	/* Just updating flags needed? */
	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 &&
		    sb_has_quota_usage_enabled(sb, type)) {
			ret = -EBUSY;
			goto out_lock;
		}
		    sb_has_quota_usage_enabled(sb, type))
			return -EBUSY;
		if (flags & DQUOT_LIMITS_ENABLED &&
		    sb_has_quota_limits_enabled(sb, type)) {
			ret = -EBUSY;
			goto out_lock;
		}
		    sb_has_quota_limits_enabled(sb, type))
			return -EBUSY;
		spin_lock(&dq_state_lock);
		sb_dqopt(sb)->flags |= dquot_state_flag(flags, type);
		spin_unlock(&dq_state_lock);
out_lock:
		mutex_unlock(&dqopt->dqonoff_mutex);
		return ret;
		return 0;
	}

load_quota:
	return vfs_load_quota_inode(inode, type, format_id, flags);
}
EXPORT_SYMBOL(dquot_enable);
+0 −1
Original line number Diff line number Diff line
@@ -244,7 +244,6 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
	mutex_init(&s->s_vfs_rename_mutex);
	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.dqonoff_mutex);
	s->s_maxbytes = MAX_NON_LFS;
	s->s_op = &default_op;
	s->s_time_gran = 1000000000;
+0 −1
Original line number Diff line number Diff line
@@ -520,7 +520,6 @@ static inline void quota_send_warning(struct kqid qid, dev_t dev,
struct quota_info {
	unsigned int flags;			/* Flags for diskquotas on this device */
	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 mem_dqinfo info[MAXQUOTAS];	/* Information for each quota type */
	const struct quota_format_ops *ops[MAXQUOTAS];	/* Operations for each type */