Skip to content

Commit 01263a1

Browse files
committed
xen/blkback: use lateeoi irq binding
In order to reduce the chance for the system becoming unresponsive due to event storms triggered by a misbehaving blkfront use the lateeoi irq binding for blkback and unmask the event channel only after processing all pending requests. As the thread processing requests is used to do purging work in regular intervals an EOI may be sent only after having received an event. If there was no pending I/O request flag the EOI as spurious. This is part of XSA-332. Cc: stable@vger.kernel.org Reported-by: Julien Grall <julien@xen.org> Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Wei Liu <wl@xen.org>
1 parent 54c9de8 commit 01263a1

File tree

2 files changed

+19
-8
lines changed

2 files changed

+19
-8
lines changed

drivers/block/xen-blkback/blkback.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ static inline void shrink_free_pagepool(struct xen_blkif_ring *ring, int num)
201201

202202
#define vaddr(page) ((unsigned long)pfn_to_kaddr(page_to_pfn(page)))
203203

204-
static int do_block_io_op(struct xen_blkif_ring *ring);
204+
static int do_block_io_op(struct xen_blkif_ring *ring, unsigned int *eoi_flags);
205205
static int dispatch_rw_block_io(struct xen_blkif_ring *ring,
206206
struct blkif_request *req,
207207
struct pending_req *pending_req);
@@ -612,6 +612,8 @@ int xen_blkif_schedule(void *arg)
612612
struct xen_vbd *vbd = &blkif->vbd;
613613
unsigned long timeout;
614614
int ret;
615+
bool do_eoi;
616+
unsigned int eoi_flags = XEN_EOI_FLAG_SPURIOUS;
615617

616618
set_freezable();
617619
while (!kthread_should_stop()) {
@@ -636,16 +638,23 @@ int xen_blkif_schedule(void *arg)
636638
if (timeout == 0)
637639
goto purge_gnt_list;
638640

641+
do_eoi = ring->waiting_reqs;
642+
639643
ring->waiting_reqs = 0;
640644
smp_mb(); /* clear flag *before* checking for work */
641645

642-
ret = do_block_io_op(ring);
646+
ret = do_block_io_op(ring, &eoi_flags);
643647
if (ret > 0)
644648
ring->waiting_reqs = 1;
645649
if (ret == -EACCES)
646650
wait_event_interruptible(ring->shutdown_wq,
647651
kthread_should_stop());
648652

653+
if (do_eoi && !ring->waiting_reqs) {
654+
xen_irq_lateeoi(ring->irq, eoi_flags);
655+
eoi_flags |= XEN_EOI_FLAG_SPURIOUS;
656+
}
657+
649658
purge_gnt_list:
650659
if (blkif->vbd.feature_gnt_persistent &&
651660
time_after(jiffies, ring->next_lru)) {
@@ -1121,7 +1130,7 @@ static void end_block_io_op(struct bio *bio)
11211130
* and transmute it to the block API to hand it over to the proper block disk.
11221131
*/
11231132
static int
1124-
__do_block_io_op(struct xen_blkif_ring *ring)
1133+
__do_block_io_op(struct xen_blkif_ring *ring, unsigned int *eoi_flags)
11251134
{
11261135
union blkif_back_rings *blk_rings = &ring->blk_rings;
11271136
struct blkif_request req;
@@ -1144,6 +1153,9 @@ __do_block_io_op(struct xen_blkif_ring *ring)
11441153
if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc))
11451154
break;
11461155

1156+
/* We've seen a request, so clear spurious eoi flag. */
1157+
*eoi_flags &= ~XEN_EOI_FLAG_SPURIOUS;
1158+
11471159
if (kthread_should_stop()) {
11481160
more_to_do = 1;
11491161
break;
@@ -1202,13 +1214,13 @@ __do_block_io_op(struct xen_blkif_ring *ring)
12021214
}
12031215

12041216
static int
1205-
do_block_io_op(struct xen_blkif_ring *ring)
1217+
do_block_io_op(struct xen_blkif_ring *ring, unsigned int *eoi_flags)
12061218
{
12071219
union blkif_back_rings *blk_rings = &ring->blk_rings;
12081220
int more_to_do;
12091221

12101222
do {
1211-
more_to_do = __do_block_io_op(ring);
1223+
more_to_do = __do_block_io_op(ring, eoi_flags);
12121224
if (more_to_do)
12131225
break;
12141226

drivers/block/xen-blkback/xenbus.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,8 @@ static int xen_blkif_map(struct xen_blkif_ring *ring, grant_ref_t *gref,
246246
if (req_prod - rsp_prod > size)
247247
goto fail;
248248

249-
err = bind_interdomain_evtchn_to_irqhandler(blkif->domid, evtchn,
250-
xen_blkif_be_int, 0,
251-
"blkif-backend", ring);
249+
err = bind_interdomain_evtchn_to_irqhandler_lateeoi(blkif->domid,
250+
evtchn, xen_blkif_be_int, 0, "blkif-backend", ring);
252251
if (err < 0)
253252
goto fail;
254253
ring->irq = err;

0 commit comments

Comments
 (0)