]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.suse/dm-mpath-requeue-for-stopped-queue
Move xen patchset to new version's subdir.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.suse / dm-mpath-requeue-for-stopped-queue
CommitLineData
00e5a55c
BS
1From: Hannes Reinecke <hare@suse.de>
2Subject: Handle I/O on stopped queues correctly
3References: bnc#458393
4
5The current multipath infrastructure has several issues when I/O is
6submitted during a table reload.
7The make_request_fn must not fail if no table is present, as I/O
8will be queued properly in the request queue. But on the other hand
9we should not submit queued I/Os if the queue of the underlying
10device is stopped; that queue is undergoing reconfiguration
11time and may be in all sort of states.
12
13And while we're at it, we should detach any hardware handler
14if the multipath table doesn't specify one.
15
16Signed-off-by: Hannes Reinecke <hare@suse.de>
17
18Index: linux-2.6.27/drivers/md/dm-mpath.c
19===================================================================
20--- linux-2.6.27.orig/drivers/md/dm-mpath.c
21+++ linux-2.6.27/drivers/md/dm-mpath.c
22@@ -159,9 +159,7 @@ static struct priority_group *alloc_prio
23
24 static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
25 {
26- unsigned long flags;
27 struct pgpath *pgpath, *tmp;
28- struct multipath *m = ti->private;
29
30 list_for_each_entry_safe(pgpath, tmp, pgpaths, list) {
31 list_del(&pgpath->list);
32@@ -436,8 +434,8 @@ static void process_queued_ios(struct wo
33 {
34 struct multipath *m =
35 container_of(work, struct multipath, process_queued_ios);
36- struct pgpath *pgpath = NULL, *tmp;
37- unsigned must_queue = 1;
38+ struct pgpath *pgpath = NULL, *tmp;
39+ unsigned must_queue = 1;
40 unsigned long flags;
41
42 spin_lock_irqsave(&m->lock, flags);
43@@ -450,6 +448,12 @@ static void process_queued_ios(struct wo
44
45 pgpath = m->current_pgpath;
46
47+ if (pgpath) {
48+ struct block_device *bdev = pgpath->path.dev->bdev;
49+ if (unlikely(blk_queue_stopped(bdev_get_queue(bdev))))
50+ goto out;
51+ }
52+
53 if ((pgpath && !m->queue_io) ||
54 (!pgpath && !m->queue_if_no_path))
55 must_queue = 0;
56@@ -619,22 +623,24 @@ static struct pgpath *parse_path(struct
57 memcpy(p->path.pdev, p->path.dev->name, 16);
58 }
59
60- if (m->hw_handler_name && p->path.dev) {
61+ if (p->path.dev) {
62 struct request_queue *q = bdev_get_queue(p->path.dev->bdev);
63
64- r = scsi_dh_attach(q, m->hw_handler_name);
65- if (r == -EBUSY) {
66- /*
67- * Already attached to different hw_handler,
68- * try to reattach with correct one.
69- */
70- scsi_dh_detach(q);
71+ if (m->hw_handler_name) {
72 r = scsi_dh_attach(q, m->hw_handler_name);
73- }
74- if (r < 0) {
75- ti->error = "error attaching hardware handler";
76- dm_put_device(ti, p->path.dev);
77- goto bad;
78+ if (r == -EBUSY) {
79+ /*
80+ * Already attached to different hw_handler,
81+ * try to reattach with correct one.
82+ */
83+ scsi_dh_detach(q);
84+ r = scsi_dh_attach(q, m->hw_handler_name);
85+ }
86+ if (r < 0) {
87+ ti->error = "error attaching hardware handler";
88+ dm_put_device(ti, p->path.dev);
89+ goto bad;
90+ }
91 }
92 }
93
94@@ -644,6 +653,11 @@ static struct pgpath *parse_path(struct
95 goto bad;
96 }
97
98+ if (!p->is_active) {
99+ ps->type->fail_path(ps, &p->path);
100+ p->fail_count++;
101+ m->nr_valid_paths--;
102+ }
103 return p;
104
105 bad:
106Index: linux-2.6.27/drivers/md/dm.c
107===================================================================
108--- linux-2.6.27.orig/drivers/md/dm.c
109+++ linux-2.6.27/drivers/md/dm.c
110@@ -1304,7 +1304,11 @@ static int dm_make_request(struct reques
111 return 0;
112 }
113
114- if (unlikely(!md->map)) {
115+ /*
116+ * Submitting to a stopped queue with no map is okay;
117+ * might happen during reconfiguration.
118+ */
119+ if (unlikely(!md->map) && !blk_queue_stopped(q)) {
120 bio_endio(bio, -EIO);
121 return 0;
122 }