Skip to content

Commit 8d829b9

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.dk/linux-block
Pull block fixes from Jens Axboe: "This contains a set of fixes for xen-blkback by way of Konrad, and a performance regression fix for blk-mq for shared tags. The latter could account for as much as a 50x reduction in performance, with the test case from the user with 500 name spaces. A more realistic setup on my end with 32 drives showed a 3.5x drop. The fix has been thoroughly tested before being committed" * 'for-linus' of git://git.kernel.dk/linux-block: blk-mq: fix performance regression with shared tags xen-blkback: don't leak stack data via response ring xen/blkback: don't use xen_blkif_get() in xen-blkback kthread xen/blkback: don't free be structure too early xen/blkback: fix disconnect while I/Os in flight
2 parents 48b6bbe + 8e8320c commit 8d829b9

File tree

7 files changed

+87
-65
lines changed

7 files changed

+87
-65
lines changed

block/blk-mq-sched.c

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,45 @@ static void blk_mq_sched_assign_ioc(struct request_queue *q,
6868
__blk_mq_sched_assign_ioc(q, rq, bio, ioc);
6969
}
7070

71+
/*
72+
* Mark a hardware queue as needing a restart. For shared queues, maintain
73+
* a count of how many hardware queues are marked for restart.
74+
*/
75+
static void blk_mq_sched_mark_restart_hctx(struct blk_mq_hw_ctx *hctx)
76+
{
77+
if (test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
78+
return;
79+
80+
if (hctx->flags & BLK_MQ_F_TAG_SHARED) {
81+
struct request_queue *q = hctx->queue;
82+
83+
if (!test_and_set_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
84+
atomic_inc(&q->shared_hctx_restart);
85+
} else
86+
set_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
87+
}
88+
89+
static bool blk_mq_sched_restart_hctx(struct blk_mq_hw_ctx *hctx)
90+
{
91+
if (!test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
92+
return false;
93+
94+
if (hctx->flags & BLK_MQ_F_TAG_SHARED) {
95+
struct request_queue *q = hctx->queue;
96+
97+
if (test_and_clear_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
98+
atomic_dec(&q->shared_hctx_restart);
99+
} else
100+
clear_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
101+
102+
if (blk_mq_hctx_has_pending(hctx)) {
103+
blk_mq_run_hw_queue(hctx, true);
104+
return true;
105+
}
106+
107+
return false;
108+
}
109+
71110
struct request *blk_mq_sched_get_request(struct request_queue *q,
72111
struct bio *bio,
73112
unsigned int op,
@@ -266,18 +305,6 @@ static bool blk_mq_sched_bypass_insert(struct blk_mq_hw_ctx *hctx,
266305
return true;
267306
}
268307

269-
static bool blk_mq_sched_restart_hctx(struct blk_mq_hw_ctx *hctx)
270-
{
271-
if (test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state)) {
272-
clear_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
273-
if (blk_mq_hctx_has_pending(hctx)) {
274-
blk_mq_run_hw_queue(hctx, true);
275-
return true;
276-
}
277-
}
278-
return false;
279-
}
280-
281308
/**
282309
* list_for_each_entry_rcu_rr - iterate in a round-robin fashion over rcu list
283310
* @pos: loop cursor.
@@ -309,6 +336,13 @@ void blk_mq_sched_restart(struct blk_mq_hw_ctx *const hctx)
309336
unsigned int i, j;
310337

311338
if (set->flags & BLK_MQ_F_TAG_SHARED) {
339+
/*
340+
* If this is 0, then we know that no hardware queues
341+
* have RESTART marked. We're done.
342+
*/
343+
if (!atomic_read(&queue->shared_hctx_restart))
344+
return;
345+
312346
rcu_read_lock();
313347
list_for_each_entry_rcu_rr(q, queue, &set->tag_list,
314348
tag_set_list) {

block/blk-mq-sched.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,6 @@ static inline bool blk_mq_sched_has_work(struct blk_mq_hw_ctx *hctx)
115115
return false;
116116
}
117117

118-
/*
119-
* Mark a hardware queue as needing a restart.
120-
*/
121-
static inline void blk_mq_sched_mark_restart_hctx(struct blk_mq_hw_ctx *hctx)
122-
{
123-
if (!test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
124-
set_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
125-
}
126-
127118
static inline bool blk_mq_sched_needs_restart(struct blk_mq_hw_ctx *hctx)
128119
{
129120
return test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);

block/blk-mq.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2103,20 +2103,30 @@ static void blk_mq_map_swqueue(struct request_queue *q,
21032103
}
21042104
}
21052105

2106+
/*
2107+
* Caller needs to ensure that we're either frozen/quiesced, or that
2108+
* the queue isn't live yet.
2109+
*/
21062110
static void queue_set_hctx_shared(struct request_queue *q, bool shared)
21072111
{
21082112
struct blk_mq_hw_ctx *hctx;
21092113
int i;
21102114

21112115
queue_for_each_hw_ctx(q, hctx, i) {
2112-
if (shared)
2116+
if (shared) {
2117+
if (test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
2118+
atomic_inc(&q->shared_hctx_restart);
21132119
hctx->flags |= BLK_MQ_F_TAG_SHARED;
2114-
else
2120+
} else {
2121+
if (test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
2122+
atomic_dec(&q->shared_hctx_restart);
21152123
hctx->flags &= ~BLK_MQ_F_TAG_SHARED;
2124+
}
21162125
}
21172126
}
21182127

2119-
static void blk_mq_update_tag_set_depth(struct blk_mq_tag_set *set, bool shared)
2128+
static void blk_mq_update_tag_set_depth(struct blk_mq_tag_set *set,
2129+
bool shared)
21202130
{
21212131
struct request_queue *q;
21222132

drivers/block/xen-blkback/blkback.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -609,8 +609,6 @@ int xen_blkif_schedule(void *arg)
609609
unsigned long timeout;
610610
int ret;
611611

612-
xen_blkif_get(blkif);
613-
614612
set_freezable();
615613
while (!kthread_should_stop()) {
616614
if (try_to_freeze())
@@ -665,7 +663,6 @@ int xen_blkif_schedule(void *arg)
665663
print_stats(ring);
666664

667665
ring->xenblkd = NULL;
668-
xen_blkif_put(blkif);
669666

670667
return 0;
671668
}
@@ -1436,34 +1433,35 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring,
14361433
static void make_response(struct xen_blkif_ring *ring, u64 id,
14371434
unsigned short op, int st)
14381435
{
1439-
struct blkif_response resp;
1436+
struct blkif_response *resp;
14401437
unsigned long flags;
14411438
union blkif_back_rings *blk_rings;
14421439
int notify;
14431440

1444-
resp.id = id;
1445-
resp.operation = op;
1446-
resp.status = st;
1447-
14481441
spin_lock_irqsave(&ring->blk_ring_lock, flags);
14491442
blk_rings = &ring->blk_rings;
14501443
/* Place on the response ring for the relevant domain. */
14511444
switch (ring->blkif->blk_protocol) {
14521445
case BLKIF_PROTOCOL_NATIVE:
1453-
memcpy(RING_GET_RESPONSE(&blk_rings->native, blk_rings->native.rsp_prod_pvt),
1454-
&resp, sizeof(resp));
1446+
resp = RING_GET_RESPONSE(&blk_rings->native,
1447+
blk_rings->native.rsp_prod_pvt);
14551448
break;
14561449
case BLKIF_PROTOCOL_X86_32:
1457-
memcpy(RING_GET_RESPONSE(&blk_rings->x86_32, blk_rings->x86_32.rsp_prod_pvt),
1458-
&resp, sizeof(resp));
1450+
resp = RING_GET_RESPONSE(&blk_rings->x86_32,
1451+
blk_rings->x86_32.rsp_prod_pvt);
14591452
break;
14601453
case BLKIF_PROTOCOL_X86_64:
1461-
memcpy(RING_GET_RESPONSE(&blk_rings->x86_64, blk_rings->x86_64.rsp_prod_pvt),
1462-
&resp, sizeof(resp));
1454+
resp = RING_GET_RESPONSE(&blk_rings->x86_64,
1455+
blk_rings->x86_64.rsp_prod_pvt);
14631456
break;
14641457
default:
14651458
BUG();
14661459
}
1460+
1461+
resp->id = id;
1462+
resp->operation = op;
1463+
resp->status = st;
1464+
14671465
blk_rings->common.rsp_prod_pvt++;
14681466
RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify);
14691467
spin_unlock_irqrestore(&ring->blk_ring_lock, flags);

drivers/block/xen-blkback/common.h

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,8 @@ extern unsigned int xenblk_max_queues;
7575
struct blkif_common_request {
7676
char dummy;
7777
};
78-
struct blkif_common_response {
79-
char dummy;
80-
};
78+
79+
/* i386 protocol version */
8180

8281
struct blkif_x86_32_request_rw {
8382
uint8_t nr_segments; /* number of segments */
@@ -129,14 +128,6 @@ struct blkif_x86_32_request {
129128
} u;
130129
} __attribute__((__packed__));
131130

132-
/* i386 protocol version */
133-
#pragma pack(push, 4)
134-
struct blkif_x86_32_response {
135-
uint64_t id; /* copied from request */
136-
uint8_t operation; /* copied from request */
137-
int16_t status; /* BLKIF_RSP_??? */
138-
};
139-
#pragma pack(pop)
140131
/* x86_64 protocol version */
141132

142133
struct blkif_x86_64_request_rw {
@@ -193,18 +184,12 @@ struct blkif_x86_64_request {
193184
} u;
194185
} __attribute__((__packed__));
195186

196-
struct blkif_x86_64_response {
197-
uint64_t __attribute__((__aligned__(8))) id;
198-
uint8_t operation; /* copied from request */
199-
int16_t status; /* BLKIF_RSP_??? */
200-
};
201-
202187
DEFINE_RING_TYPES(blkif_common, struct blkif_common_request,
203-
struct blkif_common_response);
188+
struct blkif_response);
204189
DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request,
205-
struct blkif_x86_32_response);
190+
struct blkif_response __packed);
206191
DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request,
207-
struct blkif_x86_64_response);
192+
struct blkif_response);
208193

209194
union blkif_back_rings {
210195
struct blkif_back_ring native;
@@ -281,6 +266,7 @@ struct xen_blkif_ring {
281266

282267
wait_queue_head_t wq;
283268
atomic_t inflight;
269+
bool active;
284270
/* One thread per blkif ring. */
285271
struct task_struct *xenblkd;
286272
unsigned int waiting_reqs;

drivers/block/xen-blkback/xenbus.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ static int xen_blkif_alloc_rings(struct xen_blkif *blkif)
159159
init_waitqueue_head(&ring->shutdown_wq);
160160
ring->blkif = blkif;
161161
ring->st_print = jiffies;
162-
xen_blkif_get(blkif);
162+
ring->active = true;
163163
}
164164

165165
return 0;
@@ -249,10 +249,12 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
249249
struct xen_blkif_ring *ring = &blkif->rings[r];
250250
unsigned int i = 0;
251251

252+
if (!ring->active)
253+
continue;
254+
252255
if (ring->xenblkd) {
253256
kthread_stop(ring->xenblkd);
254257
wake_up(&ring->shutdown_wq);
255-
ring->xenblkd = NULL;
256258
}
257259

258260
/* The above kthread_stop() guarantees that at this point we
@@ -296,7 +298,7 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
296298
BUG_ON(ring->free_pages_num != 0);
297299
BUG_ON(ring->persistent_gnt_c != 0);
298300
WARN_ON(i != (XEN_BLKIF_REQS_PER_PAGE * blkif->nr_ring_pages));
299-
xen_blkif_put(blkif);
301+
ring->active = false;
300302
}
301303
blkif->nr_ring_pages = 0;
302304
/*
@@ -312,9 +314,10 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
312314

313315
static void xen_blkif_free(struct xen_blkif *blkif)
314316
{
315-
316-
xen_blkif_disconnect(blkif);
317+
WARN_ON(xen_blkif_disconnect(blkif));
317318
xen_vbd_free(&blkif->vbd);
319+
kfree(blkif->be->mode);
320+
kfree(blkif->be);
318321

319322
/* Make sure everything is drained before shutting down */
320323
kmem_cache_free(xen_blkif_cachep, blkif);
@@ -511,8 +514,6 @@ static int xen_blkbk_remove(struct xenbus_device *dev)
511514
xen_blkif_put(be->blkif);
512515
}
513516

514-
kfree(be->mode);
515-
kfree(be);
516517
return 0;
517518
}
518519

include/linux/blkdev.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,8 @@ struct request_queue {
391391
int nr_rqs[2]; /* # allocated [a]sync rqs */
392392
int nr_rqs_elvpriv; /* # allocated rqs w/ elvpriv */
393393

394+
atomic_t shared_hctx_restart;
395+
394396
struct blk_queue_stats *stats;
395397
struct rq_wb *rq_wb;
396398

0 commit comments

Comments
 (0)