Skip to content

Commit

Permalink
reiserfs: Fix lock ordering during remount
Browse files Browse the repository at this point in the history
commit 3bb3e1f upstream.

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.

Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Jan Kara authored and Greg Kroah-Hartman committed Nov 26, 2012
1 parent 31fcdd0 commit daa88cb
Showing 1 changed file with 20 additions and 7 deletions.
27 changes: 20 additions & 7 deletions fs/reiserfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1207,7 +1207,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);
Expand Down Expand Up @@ -1250,7 +1250,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) {
Expand All @@ -1260,9 +1260,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
Expand All @@ -1272,7 +1278,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);
Expand All @@ -1287,7 +1293,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);
Expand All @@ -1296,7 +1302,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);
Expand All @@ -1313,11 +1319,17 @@ 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;
s->s_dirt = 0;

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);
}
Expand All @@ -1327,9 +1339,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;
}

Expand Down

0 comments on commit daa88cb

Please sign in to comment.