diff options
author | Shaohua Li <shli@fb.com> | 2017-07-03 14:34:23 -0700 |
---|---|---|
committer | Shaohua Li <shli@fb.com> | 2017-07-03 14:38:59 -0700 |
commit | 7184ef8bab0cb865c3cea9dd1a675771145df0af (patch) | |
tree | 2c356cf60b64c32d4ad39e434a9759f14e2ba287 | |
parent | 7f053a6a745557b3f3ad63e9d28ba85c3c0b1563 (diff) |
MD: fix sleep in atomic
bioset_free() will take a mutex, so can't get called with spinlock hold.
Fix: 5a85071c2cbc(md: use a separate bio_set for synchronous IO.)
Cc: NeilBrown <neilb@suse.com>
Signed-off-by: Shaohua Li <shli@fb.com>
-rw-r--r-- | drivers/md/md.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 092b48f8095e..66f6b928a80b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -475,6 +475,8 @@ static void mddev_delayed_delete(struct work_struct *ws); static void mddev_put(struct mddev *mddev) { + struct bio_set *bs = NULL, *sync_bs = NULL; + if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock)) return; if (!mddev->raid_disks && list_empty(&mddev->disks) && @@ -482,10 +484,8 @@ static void mddev_put(struct mddev *mddev) /* Array is not configured at all, and not held active, * so destroy it */ list_del_init(&mddev->all_mddevs); - if (mddev->bio_set) - bioset_free(mddev->bio_set); - if (mddev->sync_set) - bioset_free(mddev->sync_set); + bs = mddev->bio_set; + sync_bs = mddev->sync_set; mddev->bio_set = NULL; mddev->sync_set = NULL; if (mddev->gendisk) { @@ -500,6 +500,10 @@ static void mddev_put(struct mddev *mddev) kfree(mddev); } spin_unlock(&all_mddevs_lock); + if (bs) + bioset_free(bs); + if (sync_bs) + bioset_free(sync_bs); } static void md_safemode_timeout(unsigned long data); |