diff options
author | NeilBrown <neilb@suse.com> | 2017-10-16 22:46:43 -0400 |
---|---|---|
committer | Shaohua Li <shli@fb.com> | 2017-11-02 00:32:18 -0400 |
commit | 52a0d49de3d592a3118e13f35985e3d99eaf43df (patch) | |
tree | ae731c4f47a7c913873c7ec87be821b4c9b60291 | |
parent | 4d5324f760aacaefeb721b172aa14bf66045c332 (diff) |
md: don't call bitmap_create() while array is quiesced.
bitmap_create() allocates memory with GFP_KERNEL and
so can wait for IO.
If called while the array is quiesced, it could wait indefinitely
for write out to the array - deadlock.
So call bitmap_create() before quiescing the array.
Signed-off-by: NeilBrown <neilb@suse.com>
Signed-off-by: Shaohua Li <shli@fb.com>
-rw-r--r-- | drivers/md/md.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 9767bb33df56..2cb49f639809 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -6621,22 +6621,26 @@ static int set_bitmap_file(struct mddev *mddev, int fd) | |||
6621 | return -ENOENT; /* cannot remove what isn't there */ | 6621 | return -ENOENT; /* cannot remove what isn't there */ |
6622 | err = 0; | 6622 | err = 0; |
6623 | if (mddev->pers) { | 6623 | if (mddev->pers) { |
6624 | mddev->pers->quiesce(mddev, 1); | ||
6625 | if (fd >= 0) { | 6624 | if (fd >= 0) { |
6626 | struct bitmap *bitmap; | 6625 | struct bitmap *bitmap; |
6627 | 6626 | ||
6628 | bitmap = bitmap_create(mddev, -1); | 6627 | bitmap = bitmap_create(mddev, -1); |
6628 | mddev->pers->quiesce(mddev, 1); | ||
6629 | if (!IS_ERR(bitmap)) { | 6629 | if (!IS_ERR(bitmap)) { |
6630 | mddev->bitmap = bitmap; | 6630 | mddev->bitmap = bitmap; |
6631 | err = bitmap_load(mddev); | 6631 | err = bitmap_load(mddev); |
6632 | } else | 6632 | } else |
6633 | err = PTR_ERR(bitmap); | 6633 | err = PTR_ERR(bitmap); |
6634 | } | 6634 | if (err) { |
6635 | if (fd < 0 || err) { | 6635 | bitmap_destroy(mddev); |
6636 | fd = -1; | ||
6637 | } | ||
6638 | mddev->pers->quiesce(mddev, 0); | ||
6639 | } else if (fd < 0) { | ||
6640 | mddev->pers->quiesce(mddev, 1); | ||
6636 | bitmap_destroy(mddev); | 6641 | bitmap_destroy(mddev); |
6637 | fd = -1; /* make sure to put the file */ | 6642 | mddev->pers->quiesce(mddev, 0); |
6638 | } | 6643 | } |
6639 | mddev->pers->quiesce(mddev, 0); | ||
6640 | } | 6644 | } |
6641 | if (fd < 0) { | 6645 | if (fd < 0) { |
6642 | struct file *f = mddev->bitmap_info.file; | 6646 | struct file *f = mddev->bitmap_info.file; |
@@ -6920,8 +6924,8 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info) | |||
6920 | mddev->bitmap_info.default_offset; | 6924 | mddev->bitmap_info.default_offset; |
6921 | mddev->bitmap_info.space = | 6925 | mddev->bitmap_info.space = |
6922 | mddev->bitmap_info.default_space; | 6926 | mddev->bitmap_info.default_space; |
6923 | mddev->pers->quiesce(mddev, 1); | ||
6924 | bitmap = bitmap_create(mddev, -1); | 6927 | bitmap = bitmap_create(mddev, -1); |
6928 | mddev->pers->quiesce(mddev, 1); | ||
6925 | if (!IS_ERR(bitmap)) { | 6929 | if (!IS_ERR(bitmap)) { |
6926 | mddev->bitmap = bitmap; | 6930 | mddev->bitmap = bitmap; |
6927 | rv = bitmap_load(mddev); | 6931 | rv = bitmap_load(mddev); |