diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2014-05-20 21:55:04 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2014-05-20 21:55:41 -0400 |
commit | c77fba9ab058d1e96ed51d4215e56905c9ef8d2a (patch) | |
tree | db7a68864ef1f3ba182b3a9471211bd2fd5118bc /drivers/scsi/virtio_scsi.c | |
parent | a17597d3b418ca5a394d14724ccfc295cb3186c8 (diff) |
virtio_scsi: don't call virtqueue_add_sgs(... GFP_NOIO) holding spinlock.
This triggers every time we do a SCSI abort:
virtscsi_tmf -> virtscsi_kick_cmd (grab lock and call) -> virtscsi_add_cmd
-> virtqueue_add_sgs (GFP_NOIO)
Logs look like this:
sd 0:0:0:0: [sda] abort
BUG: sleeping function called from invalid context at mm/slub.c:966
in_atomic(): 1, irqs_disabled(): 1, pid: 6, name: kworker/u2:0
3 locks held by kworker/u2:0/6:
#0: ("scsi_tmf_%d"shost->host_no){......}, at: [<c0153180>] process_one_work+0xe0/0x3d0
#1: ((&(&cmd->abort_work)->work)){......}, at: [<c0153180>] process_one_work+0xe0/0x3d0
#2: (&(&virtscsi_vq->vq_lock)->rlock){......}, at: [<c043f508>] virtscsi_kick_cmd+0x18/0x1b0
CPU: 0 PID: 6 Comm: kworker/u2:0 Not tainted 3.15.0-rc5+ #110
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5-rc1-0-gb1d4dc9-20140515_140003-nilsson.home.kraxel.org 04/01/2014
Workqueue: scsi_tmf_0 scmd_eh_abort_handler
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'drivers/scsi/virtio_scsi.c')
-rw-r--r-- | drivers/scsi/virtio_scsi.c | 15 |
1 files changed, 6 insertions, 9 deletions
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 16bfd50cd3fe..e2a68aece3da 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c | |||
@@ -433,11 +433,10 @@ static void virtscsi_event_done(struct virtqueue *vq) | |||
433 | * @cmd : command structure | 433 | * @cmd : command structure |
434 | * @req_size : size of the request buffer | 434 | * @req_size : size of the request buffer |
435 | * @resp_size : size of the response buffer | 435 | * @resp_size : size of the response buffer |
436 | * @gfp : flags to use for memory allocations | ||
437 | */ | 436 | */ |
438 | static int virtscsi_add_cmd(struct virtqueue *vq, | 437 | static int virtscsi_add_cmd(struct virtqueue *vq, |
439 | struct virtio_scsi_cmd *cmd, | 438 | struct virtio_scsi_cmd *cmd, |
440 | size_t req_size, size_t resp_size, gfp_t gfp) | 439 | size_t req_size, size_t resp_size) |
441 | { | 440 | { |
442 | struct scsi_cmnd *sc = cmd->sc; | 441 | struct scsi_cmnd *sc = cmd->sc; |
443 | struct scatterlist *sgs[4], req, resp; | 442 | struct scatterlist *sgs[4], req, resp; |
@@ -469,19 +468,19 @@ static int virtscsi_add_cmd(struct virtqueue *vq, | |||
469 | if (in) | 468 | if (in) |
470 | sgs[out_num + in_num++] = in->sgl; | 469 | sgs[out_num + in_num++] = in->sgl; |
471 | 470 | ||
472 | return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, gfp); | 471 | return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, GFP_ATOMIC); |
473 | } | 472 | } |
474 | 473 | ||
475 | static int virtscsi_kick_cmd(struct virtio_scsi_vq *vq, | 474 | static int virtscsi_kick_cmd(struct virtio_scsi_vq *vq, |
476 | struct virtio_scsi_cmd *cmd, | 475 | struct virtio_scsi_cmd *cmd, |
477 | size_t req_size, size_t resp_size, gfp_t gfp) | 476 | size_t req_size, size_t resp_size) |
478 | { | 477 | { |
479 | unsigned long flags; | 478 | unsigned long flags; |
480 | int err; | 479 | int err; |
481 | bool needs_kick = false; | 480 | bool needs_kick = false; |
482 | 481 | ||
483 | spin_lock_irqsave(&vq->vq_lock, flags); | 482 | spin_lock_irqsave(&vq->vq_lock, flags); |
484 | err = virtscsi_add_cmd(vq->vq, cmd, req_size, resp_size, gfp); | 483 | err = virtscsi_add_cmd(vq->vq, cmd, req_size, resp_size); |
485 | if (!err) | 484 | if (!err) |
486 | needs_kick = virtqueue_kick_prepare(vq->vq); | 485 | needs_kick = virtqueue_kick_prepare(vq->vq); |
487 | 486 | ||
@@ -530,8 +529,7 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi, | |||
530 | memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len); | 529 | memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len); |
531 | 530 | ||
532 | if (virtscsi_kick_cmd(req_vq, cmd, | 531 | if (virtscsi_kick_cmd(req_vq, cmd, |
533 | sizeof cmd->req.cmd, sizeof cmd->resp.cmd, | 532 | sizeof cmd->req.cmd, sizeof cmd->resp.cmd) == 0) |
534 | GFP_ATOMIC) == 0) | ||
535 | ret = 0; | 533 | ret = 0; |
536 | else | 534 | else |
537 | mempool_free(cmd, virtscsi_cmd_pool); | 535 | mempool_free(cmd, virtscsi_cmd_pool); |
@@ -596,8 +594,7 @@ static int virtscsi_tmf(struct virtio_scsi *vscsi, struct virtio_scsi_cmd *cmd) | |||
596 | 594 | ||
597 | cmd->comp = ∁ | 595 | cmd->comp = ∁ |
598 | if (virtscsi_kick_cmd(&vscsi->ctrl_vq, cmd, | 596 | if (virtscsi_kick_cmd(&vscsi->ctrl_vq, cmd, |
599 | sizeof cmd->req.tmf, sizeof cmd->resp.tmf, | 597 | sizeof cmd->req.tmf, sizeof cmd->resp.tmf) < 0) |
600 | GFP_NOIO) < 0) | ||
601 | goto out; | 598 | goto out; |
602 | 599 | ||
603 | wait_for_completion(&comp); | 600 | wait_for_completion(&comp); |