Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3bb3e1fc authored by Jan Kara's avatar Jan Kara
Browse files

reiserfs: Fix lock ordering during remount



When remounting reiserfs dquot_suspend() or dquot_resume() can be called.
These functions take dqonoff_mutex which ranks above write lock so we have
to drop it before calling into quota code.

CC: stable@vger.kernel.org # >= 3.0
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 77b67063
Loading
Loading
Loading
Loading
+20 −7
Original line number Diff line number Diff line
@@ -1335,7 +1335,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
				kfree(qf_names[i]);
#endif
		err = -EINVAL;
		goto out_err;
		goto out_unlock;
	}
#ifdef CONFIG_QUOTA
	handle_quota_files(s, qf_names, &qfmt);
@@ -1379,7 +1379,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
	if (blocks) {
		err = reiserfs_resize(s, blocks);
		if (err != 0)
			goto out_err;
			goto out_unlock;
	}

	if (*mount_flags & MS_RDONLY) {
@@ -1389,9 +1389,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
			/* it is read-only already */
			goto out_ok;

		/*
		 * Drop write lock. Quota will retake it when needed and lock
		 * ordering requires calling dquot_suspend() without it.
		 */
		reiserfs_write_unlock(s);
		err = dquot_suspend(s, -1);
		if (err < 0)
			goto out_err;
		reiserfs_write_lock(s);

		/* try to remount file system with read-only permissions */
		if (sb_umount_state(rs) == REISERFS_VALID_FS
@@ -1401,7 +1407,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)

		err = journal_begin(&th, s, 10);
		if (err)
			goto out_err;
			goto out_unlock;

		/* Mounting a rw partition read-only. */
		reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
@@ -1416,7 +1422,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)

		if (reiserfs_is_journal_aborted(journal)) {
			err = journal->j_errno;
			goto out_err;
			goto out_unlock;
		}

		handle_data_mode(s, mount_options);
@@ -1425,7 +1431,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
		s->s_flags &= ~MS_RDONLY;	/* now it is safe to call journal_begin */
		err = journal_begin(&th, s, 10);
		if (err)
			goto out_err;
			goto out_unlock;

		/* Mount a partition which is read-only, read-write */
		reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
@@ -1442,10 +1448,16 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
	SB_JOURNAL(s)->j_must_wait = 1;
	err = journal_end(&th, s, 10);
	if (err)
		goto out_err;
		goto out_unlock;

	if (!(*mount_flags & MS_RDONLY)) {
		/*
		 * Drop write lock. Quota will retake it when needed and lock
		 * ordering requires calling dquot_resume() without it.
		 */
		reiserfs_write_unlock(s);
		dquot_resume(s, -1);
		reiserfs_write_lock(s);
		finish_unfinished(s);
		reiserfs_xattr_init(s, *mount_flags);
	}
@@ -1455,9 +1467,10 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
	reiserfs_write_unlock(s);
	return 0;

out_unlock:
	reiserfs_write_unlock(s);
out_err:
	kfree(new_opts);
	reiserfs_write_unlock(s);
	return err;
}