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

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
...@@ -1335,7 +1335,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1335,7 +1335,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
kfree(qf_names[i]); kfree(qf_names[i]);
#endif #endif
err = -EINVAL; err = -EINVAL;
goto out_err; goto out_unlock;
} }
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
handle_quota_files(s, qf_names, &qfmt); handle_quota_files(s, qf_names, &qfmt);
...@@ -1379,7 +1379,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1379,7 +1379,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
if (blocks) { if (blocks) {
err = reiserfs_resize(s, blocks); err = reiserfs_resize(s, blocks);
if (err != 0) if (err != 0)
goto out_err; goto out_unlock;
} }
if (*mount_flags & MS_RDONLY) { if (*mount_flags & MS_RDONLY) {
...@@ -1389,9 +1389,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1389,9 +1389,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
/* it is read-only already */ /* it is read-only already */
goto out_ok; 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); err = dquot_suspend(s, -1);
if (err < 0) if (err < 0)
goto out_err; goto out_err;
reiserfs_write_lock(s);
/* try to remount file system with read-only permissions */ /* try to remount file system with read-only permissions */
if (sb_umount_state(rs) == REISERFS_VALID_FS 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) ...@@ -1401,7 +1407,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
err = journal_begin(&th, s, 10); err = journal_begin(&th, s, 10);
if (err) if (err)
goto out_err; goto out_unlock;
/* Mounting a rw partition read-only. */ /* Mounting a rw partition read-only. */
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); 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) ...@@ -1416,7 +1422,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
if (reiserfs_is_journal_aborted(journal)) { if (reiserfs_is_journal_aborted(journal)) {
err = journal->j_errno; err = journal->j_errno;
goto out_err; goto out_unlock;
} }
handle_data_mode(s, mount_options); handle_data_mode(s, mount_options);
...@@ -1425,7 +1431,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -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 */ s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */
err = journal_begin(&th, s, 10); err = journal_begin(&th, s, 10);
if (err) if (err)
goto out_err; goto out_unlock;
/* Mount a partition which is read-only, read-write */ /* Mount a partition which is read-only, read-write */
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); 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) ...@@ -1442,10 +1448,16 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
SB_JOURNAL(s)->j_must_wait = 1; SB_JOURNAL(s)->j_must_wait = 1;
err = journal_end(&th, s, 10); err = journal_end(&th, s, 10);
if (err) if (err)
goto out_err; goto out_unlock;
if (!(*mount_flags & MS_RDONLY)) { 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); dquot_resume(s, -1);
reiserfs_write_lock(s);
finish_unfinished(s); finish_unfinished(s);
reiserfs_xattr_init(s, *mount_flags); reiserfs_xattr_init(s, *mount_flags);
} }
...@@ -1455,9 +1467,10 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1455,9 +1467,10 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
reiserfs_write_unlock(s); reiserfs_write_unlock(s);
return 0; return 0;
out_unlock:
reiserfs_write_unlock(s);
out_err: out_err:
kfree(new_opts); kfree(new_opts);
reiserfs_write_unlock(s);
return err; return err;
} }
......
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