diff options
author | Jan Kara <jack@suse.cz> | 2012-11-13 08:55:52 -0500 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2012-11-19 15:34:32 -0500 |
commit | 3bb3e1fc47aca554e7e2cc4deeddc24750987ac2 (patch) | |
tree | 2460e3e16353e865b9e322981760d2b220bcf69c /fs/reiserfs | |
parent | 77b67063bb6bce6d475e910d3b886a606d0d91f7 (diff) |
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: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/reiserfs')
-rw-r--r-- | fs/reiserfs/super.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 1078ae179993..5372980ec458 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -1335,7 +1335,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) | |||
1335 | kfree(qf_names[i]); | 1335 | kfree(qf_names[i]); |
1336 | #endif | 1336 | #endif |
1337 | err = -EINVAL; | 1337 | err = -EINVAL; |
1338 | goto out_err; | 1338 | goto out_unlock; |
1339 | } | 1339 | } |
1340 | #ifdef CONFIG_QUOTA | 1340 | #ifdef CONFIG_QUOTA |
1341 | handle_quota_files(s, qf_names, &qfmt); | 1341 | 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 | if (blocks) { | 1379 | if (blocks) { |
1380 | err = reiserfs_resize(s, blocks); | 1380 | err = reiserfs_resize(s, blocks); |
1381 | if (err != 0) | 1381 | if (err != 0) |
1382 | goto out_err; | 1382 | goto out_unlock; |
1383 | } | 1383 | } |
1384 | 1384 | ||
1385 | if (*mount_flags & MS_RDONLY) { | 1385 | if (*mount_flags & MS_RDONLY) { |
@@ -1389,9 +1389,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) | |||
1389 | /* it is read-only already */ | 1389 | /* it is read-only already */ |
1390 | goto out_ok; | 1390 | goto out_ok; |
1391 | 1391 | ||
1392 | /* | ||
1393 | * Drop write lock. Quota will retake it when needed and lock | ||
1394 | * ordering requires calling dquot_suspend() without it. | ||
1395 | */ | ||
1396 | reiserfs_write_unlock(s); | ||
1392 | err = dquot_suspend(s, -1); | 1397 | err = dquot_suspend(s, -1); |
1393 | if (err < 0) | 1398 | if (err < 0) |
1394 | goto out_err; | 1399 | goto out_err; |
1400 | reiserfs_write_lock(s); | ||
1395 | 1401 | ||
1396 | /* try to remount file system with read-only permissions */ | 1402 | /* try to remount file system with read-only permissions */ |
1397 | if (sb_umount_state(rs) == REISERFS_VALID_FS | 1403 | 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 | 1407 | ||
1402 | err = journal_begin(&th, s, 10); | 1408 | err = journal_begin(&th, s, 10); |
1403 | if (err) | 1409 | if (err) |
1404 | goto out_err; | 1410 | goto out_unlock; |
1405 | 1411 | ||
1406 | /* Mounting a rw partition read-only. */ | 1412 | /* Mounting a rw partition read-only. */ |
1407 | reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); | 1413 | 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 | 1422 | ||
1417 | if (reiserfs_is_journal_aborted(journal)) { | 1423 | if (reiserfs_is_journal_aborted(journal)) { |
1418 | err = journal->j_errno; | 1424 | err = journal->j_errno; |
1419 | goto out_err; | 1425 | goto out_unlock; |
1420 | } | 1426 | } |
1421 | 1427 | ||
1422 | handle_data_mode(s, mount_options); | 1428 | handle_data_mode(s, mount_options); |
@@ -1425,7 +1431,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) | |||
1425 | s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */ | 1431 | s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */ |
1426 | err = journal_begin(&th, s, 10); | 1432 | err = journal_begin(&th, s, 10); |
1427 | if (err) | 1433 | if (err) |
1428 | goto out_err; | 1434 | goto out_unlock; |
1429 | 1435 | ||
1430 | /* Mount a partition which is read-only, read-write */ | 1436 | /* Mount a partition which is read-only, read-write */ |
1431 | reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); | 1437 | 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 | SB_JOURNAL(s)->j_must_wait = 1; | 1448 | SB_JOURNAL(s)->j_must_wait = 1; |
1443 | err = journal_end(&th, s, 10); | 1449 | err = journal_end(&th, s, 10); |
1444 | if (err) | 1450 | if (err) |
1445 | goto out_err; | 1451 | goto out_unlock; |
1446 | 1452 | ||
1447 | if (!(*mount_flags & MS_RDONLY)) { | 1453 | if (!(*mount_flags & MS_RDONLY)) { |
1454 | /* | ||
1455 | * Drop write lock. Quota will retake it when needed and lock | ||
1456 | * ordering requires calling dquot_resume() without it. | ||
1457 | */ | ||
1458 | reiserfs_write_unlock(s); | ||
1448 | dquot_resume(s, -1); | 1459 | dquot_resume(s, -1); |
1460 | reiserfs_write_lock(s); | ||
1449 | finish_unfinished(s); | 1461 | finish_unfinished(s); |
1450 | reiserfs_xattr_init(s, *mount_flags); | 1462 | reiserfs_xattr_init(s, *mount_flags); |
1451 | } | 1463 | } |
@@ -1455,9 +1467,10 @@ out_ok: | |||
1455 | reiserfs_write_unlock(s); | 1467 | reiserfs_write_unlock(s); |
1456 | return 0; | 1468 | return 0; |
1457 | 1469 | ||
1470 | out_unlock: | ||
1471 | reiserfs_write_unlock(s); | ||
1458 | out_err: | 1472 | out_err: |
1459 | kfree(new_opts); | 1473 | kfree(new_opts); |
1460 | reiserfs_write_unlock(s); | ||
1461 | return err; | 1474 | return err; |
1462 | } | 1475 | } |
1463 | 1476 | ||