[dm-devel] dm mpath: Fix a dm_blk_ioctl() deadlock
Bart Van Assche
bart.vanassche at sandisk.com
Tue Jun 28 18:29:42 UTC 2016
On 06/28/2016 08:15 PM, Mike Snitzer wrote:
> This patch doesn't make sense.
>
> In the context of dm-mpath.c:multipath_prepare_ioctl, *bdev is only
> valid if r == 0. But r == -ENOTCONN so how can *bdev be valid?
Sorry but the dm code is not my area of expertise. How about the patch
below? Please note that so far only the queue-length path selector has
been tested.
Thanks,
Bart.
diff --git a/drivers/md/dm-queue-length.c b/drivers/md/dm-queue-length.c
index 23f1786..4c36648 100644
--- a/drivers/md/dm-queue-length.c
+++ b/drivers/md/dm-queue-length.c
@@ -199,6 +199,8 @@ static struct dm_path *ql_select_path(struct path_selector *ps, size_t nr_bytes)
list_move_tail(s->valid_paths.next, &s->valid_paths);
list_for_each_entry(pi, &s->valid_paths, list) {
+ if (blk_queue_dying(bdev_get_queue(pi->path->dev->bdev)))
+ continue;
if (!best ||
(atomic_read(&pi->qlen) < atomic_read(&best->qlen)))
best = pi;
diff --git a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c
index 4ace1da..56e3919 100644
--- a/drivers/md/dm-round-robin.c
+++ b/drivers/md/dm-round-robin.c
@@ -217,13 +217,17 @@ static struct dm_path *rr_select_path(struct path_selector *ps, size_t nr_bytes)
return current_path;
}
+ current_path = NULL;
+
spin_lock_irqsave(&s->lock, flags);
- if (!list_empty(&s->valid_paths)) {
- pi = list_entry(s->valid_paths.next, struct path_info, list);
+ list_for_each_entry(pi, &s->valid_paths, list) {
+ if (blk_queue_dying(bdev_get_queue(pi->path->dev->bdev)))
+ continue;
list_move_tail(&pi->list, &s->valid_paths);
percpu_counter_set(&s->repeat_count, pi->repeat_count);
set_percpu_current_path(s, pi->path);
current_path = pi->path;
+ break;
}
spin_unlock_irqrestore(&s->lock, flags);
diff --git a/drivers/md/dm-service-time.c b/drivers/md/dm-service-time.c
index 7b86420..fccf66a 100644
--- a/drivers/md/dm-service-time.c
+++ b/drivers/md/dm-service-time.c
@@ -285,9 +285,12 @@ static struct dm_path *st_select_path(struct path_selector *ps, size_t nr_bytes)
/* Change preferred (first in list) path to evenly balance. */
list_move_tail(s->valid_paths.next, &s->valid_paths);
- list_for_each_entry(pi, &s->valid_paths, list)
+ list_for_each_entry(pi, &s->valid_paths, list) {
+ if (blk_queue_dying(bdev_get_queue(pi->path->dev->bdev)))
+ continue;
if (!best || (st_compare_load(pi, best, nr_bytes) < 0))
best = pi;
+ }
if (!best)
goto out;
--
2.8.4
More information about the dm-devel
mailing list