Commit 669f044170d8933c3d66d231b69ea97cb8447338

Authored by Bart Van Assche
Committed by Martin K. Petersen
1 parent 27c3d76821

scsi: srp_transport: Move queuecommand() wait code to SCSI core

Additionally, rename srp_wait_for_queuecommand() into
scsi_wait_for_queuecommand() and add a comment about the queuecommand()
call from scsi_send_eh_cmnd().

Note: this patch changes scsi_internal_device_block from a function that
did not sleep into a function that may sleep. This is fine for all
callers of this function:

* scsi_internal_device_block() is called from the mpt3sas device while
  that driver holds the ioc->dm_cmds.mutex. This means that the mpt3sas
  driver calls this function from thread context.
* scsi_target_block() is called by __iscsi_block_session() from
  kernel thread context and with IRQs enabled.
* The SRP transport code also calls scsi_target_block() from kernel
  thread context while sleeping is allowed.
* The snic driver also calls scsi_target_block() from a context from
  which sleeping is allowed. The scsi_target_block() call namely occurs
  immediately after a scsi_flush_work() call.

[mkp: s/shost/sdev/]

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Cc: James Bottomley <jejb@linux.vnet.ibm.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Doug Ledford <dledford@redhat.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

Showing 2 changed files with 45 additions and 37 deletions Side-by-side Diff

drivers/scsi/scsi_lib.c
... ... @@ -2734,6 +2734,39 @@
2734 2734 EXPORT_SYMBOL_GPL(sdev_evt_send_simple);
2735 2735  
2736 2736 /**
  2737 + * scsi_request_fn_active() - number of kernel threads inside scsi_request_fn()
  2738 + * @sdev: SCSI device to count the number of scsi_request_fn() callers for.
  2739 + */
  2740 +static int scsi_request_fn_active(struct scsi_device *sdev)
  2741 +{
  2742 + struct request_queue *q = sdev->request_queue;
  2743 + int request_fn_active;
  2744 +
  2745 + WARN_ON_ONCE(sdev->host->use_blk_mq);
  2746 +
  2747 + spin_lock_irq(q->queue_lock);
  2748 + request_fn_active = q->request_fn_active;
  2749 + spin_unlock_irq(q->queue_lock);
  2750 +
  2751 + return request_fn_active;
  2752 +}
  2753 +
  2754 +/**
  2755 + * scsi_wait_for_queuecommand() - wait for ongoing queuecommand() calls
  2756 + * @sdev: SCSI device pointer.
  2757 + *
  2758 + * Wait until the ongoing shost->hostt->queuecommand() calls that are
  2759 + * invoked from scsi_request_fn() have finished.
  2760 + */
  2761 +static void scsi_wait_for_queuecommand(struct scsi_device *sdev)
  2762 +{
  2763 + WARN_ON_ONCE(sdev->host->use_blk_mq);
  2764 +
  2765 + while (scsi_request_fn_active(sdev))
  2766 + msleep(20);
  2767 +}
  2768 +
  2769 +/**
2737 2770 * scsi_device_quiesce - Block user issued commands.
2738 2771 * @sdev: scsi device to quiesce.
2739 2772 *
... ... @@ -2817,8 +2850,7 @@
2817 2850 * @sdev: device to block
2818 2851 *
2819 2852 * Block request made by scsi lld's to temporarily stop all
2820   - * scsi commands on the specified device. Called from interrupt
2821   - * or normal process context.
  2853 + * scsi commands on the specified device. May sleep.
2822 2854 *
2823 2855 * Returns zero if successful or error if not
2824 2856 *
... ... @@ -2827,6 +2859,10 @@
2827 2859 * (which must be a legal transition). When the device is in this
2828 2860 * state, all commands are deferred until the scsi lld reenables
2829 2861 * the device with scsi_device_unblock or device_block_tmo fires.
  2862 + *
  2863 + * To do: avoid that scsi_send_eh_cmnd() calls queuecommand() after
  2864 + * scsi_internal_device_block() has blocked a SCSI device and also
  2865 + * remove the rport mutex lock and unlock calls from srp_queuecommand().
2830 2866 */
2831 2867 int
2832 2868 scsi_internal_device_block(struct scsi_device *sdev)
... ... @@ -2854,6 +2890,7 @@
2854 2890 spin_lock_irqsave(q->queue_lock, flags);
2855 2891 blk_stop_queue(q);
2856 2892 spin_unlock_irqrestore(q->queue_lock, flags);
  2893 + scsi_wait_for_queuecommand(sdev);
2857 2894 }
2858 2895  
2859 2896 return 0;
drivers/scsi/scsi_transport_srp.c
... ... @@ -24,7 +24,6 @@
24 24 #include <linux/err.h>
25 25 #include <linux/slab.h>
26 26 #include <linux/string.h>
27   -#include <linux/delay.h>
28 27  
29 28 #include <scsi/scsi.h>
30 29 #include <scsi/scsi_cmnd.h>
... ... @@ -393,36 +392,6 @@
393 392 }
394 393 }
395 394  
396   -/**
397   - * scsi_request_fn_active() - number of kernel threads inside scsi_request_fn()
398   - * @shost: SCSI host for which to count the number of scsi_request_fn() callers.
399   - *
400   - * To do: add support for scsi-mq in this function.
401   - */
402   -static int scsi_request_fn_active(struct Scsi_Host *shost)
403   -{
404   - struct scsi_device *sdev;
405   - struct request_queue *q;
406   - int request_fn_active = 0;
407   -
408   - shost_for_each_device(sdev, shost) {
409   - q = sdev->request_queue;
410   -
411   - spin_lock_irq(q->queue_lock);
412   - request_fn_active += q->request_fn_active;
413   - spin_unlock_irq(q->queue_lock);
414   - }
415   -
416   - return request_fn_active;
417   -}
418   -
419   -/* Wait until ongoing shost->hostt->queuecommand() calls have finished. */
420   -static void srp_wait_for_queuecommand(struct Scsi_Host *shost)
421   -{
422   - while (scsi_request_fn_active(shost))
423   - msleep(20);
424   -}
425   -
426 395 static void __rport_fail_io_fast(struct srp_rport *rport)
427 396 {
428 397 struct Scsi_Host *shost = rport_to_shost(rport);
429 398  
430 399  
... ... @@ -432,14 +401,17 @@
432 401  
433 402 if (srp_rport_set_state(rport, SRP_RPORT_FAIL_FAST))
434 403 return;
  404 + /*
  405 + * Call scsi_target_block() to wait for ongoing shost->queuecommand()
  406 + * calls before invoking i->f->terminate_rport_io().
  407 + */
  408 + scsi_target_block(rport->dev.parent);
435 409 scsi_target_unblock(rport->dev.parent, SDEV_TRANSPORT_OFFLINE);
436 410  
437 411 /* Involve the LLD if possible to terminate all I/O on the rport. */
438 412 i = to_srp_internal(shost->transportt);
439   - if (i->f->terminate_rport_io) {
440   - srp_wait_for_queuecommand(shost);
  413 + if (i->f->terminate_rport_io)
441 414 i->f->terminate_rport_io(rport);
442   - }
443 415 }
444 416  
445 417 /**
... ... @@ -567,7 +539,6 @@
567 539 if (res)
568 540 goto out;
569 541 scsi_target_block(&shost->shost_gendev);
570   - srp_wait_for_queuecommand(shost);
571 542 res = rport->state != SRP_RPORT_LOST ? i->f->reconnect(rport) : -ENODEV;
572 543 pr_debug("%s (state %d): transport.reconnect() returned %d\n",
573 544 dev_name(&shost->shost_gendev), rport->state, res);