Skip to content

Commit af92c02

Browse files
Merge patch series "scsi: fixes for targets with many LUNs, and scsi_target_block rework"
Martin Wilck <[email protected]> says: This patch series addresses some issues we saw in a test setup with a large number of SCSI LUNs. The first two patches simply increase the number of available sg and bsg devices. 3-5 fix a large delay we encountered between blocking a Fibre Channel remote port and the dev_loss_tmo. 6 renames scsi_target_block() to scsi_block_targets(), and makes additional changes to this API, as suggested in the review of the v2 series. 7 improves a warning message. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin K. Petersen <[email protected]>
2 parents 20fce50 + 6d7160c commit af92c02

File tree

8 files changed

+50
-49
lines changed

8 files changed

+50
-49
lines changed

block/bsg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ static inline struct bsg_device *to_bsg_device(struct inode *inode)
3636
}
3737

3838
#define BSG_DEFAULT_CMDS 64
39-
#define BSG_MAX_DEVS 32768
39+
#define BSG_MAX_DEVS (1 << MINORBITS)
4040

4141
static DEFINE_IDA(bsg_minor_ida);
4242
static struct class *bsg_class;

drivers/scsi/scsi_lib.c

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2731,24 +2731,16 @@ void scsi_start_queue(struct scsi_device *sdev)
27312731
blk_mq_unquiesce_queue(sdev->request_queue);
27322732
}
27332733

2734-
static void scsi_stop_queue(struct scsi_device *sdev, bool nowait)
2734+
static void scsi_stop_queue(struct scsi_device *sdev)
27352735
{
27362736
/*
27372737
* The atomic variable of ->queue_stopped covers that
27382738
* blk_mq_quiesce_queue* is balanced with blk_mq_unquiesce_queue.
27392739
*
2740-
* However, we still need to wait until quiesce is done
2741-
* in case that queue has been stopped.
2740+
* The caller needs to wait until quiesce is done.
27422741
*/
2743-
if (!cmpxchg(&sdev->queue_stopped, 0, 1)) {
2744-
if (nowait)
2745-
blk_mq_quiesce_queue_nowait(sdev->request_queue);
2746-
else
2747-
blk_mq_quiesce_queue(sdev->request_queue);
2748-
} else {
2749-
if (!nowait)
2750-
blk_mq_wait_quiesce_done(sdev->request_queue->tag_set);
2751-
}
2742+
if (!cmpxchg(&sdev->queue_stopped, 0, 1))
2743+
blk_mq_quiesce_queue_nowait(sdev->request_queue);
27522744
}
27532745

27542746
/**
@@ -2775,37 +2767,46 @@ int scsi_internal_device_block_nowait(struct scsi_device *sdev)
27752767
* request queue.
27762768
*/
27772769
if (!ret)
2778-
scsi_stop_queue(sdev, true);
2770+
scsi_stop_queue(sdev);
27792771
return ret;
27802772
}
27812773
EXPORT_SYMBOL_GPL(scsi_internal_device_block_nowait);
27822774

27832775
/**
2784-
* scsi_internal_device_block - try to transition to the SDEV_BLOCK state
2776+
* scsi_device_block - try to transition to the SDEV_BLOCK state
27852777
* @sdev: device to block
2778+
* @data: dummy argument, ignored
27862779
*
2787-
* Pause SCSI command processing on the specified device and wait until all
2788-
* ongoing scsi_request_fn() / scsi_queue_rq() calls have finished. May sleep.
2789-
*
2790-
* Returns zero if successful or a negative error code upon failure.
2780+
* Pause SCSI command processing on the specified device. Callers must wait
2781+
* until all ongoing scsi_queue_rq() calls have finished after this function
2782+
* returns.
27912783
*
27922784
* Note:
27932785
* This routine transitions the device to the SDEV_BLOCK state (which must be
27942786
* a legal transition). When the device is in this state, command processing
27952787
* is paused until the device leaves the SDEV_BLOCK state. See also
27962788
* scsi_internal_device_unblock().
27972789
*/
2798-
static int scsi_internal_device_block(struct scsi_device *sdev)
2790+
static void scsi_device_block(struct scsi_device *sdev, void *data)
27992791
{
28002792
int err;
2793+
enum scsi_device_state state;
28012794

28022795
mutex_lock(&sdev->state_mutex);
28032796
err = __scsi_internal_device_block_nowait(sdev);
2797+
state = sdev->sdev_state;
28042798
if (err == 0)
2805-
scsi_stop_queue(sdev, false);
2799+
/*
2800+
* scsi_stop_queue() must be called with the state_mutex
2801+
* held. Otherwise a simultaneous scsi_start_queue() call
2802+
* might unquiesce the queue before we quiesce it.
2803+
*/
2804+
scsi_stop_queue(sdev);
2805+
28062806
mutex_unlock(&sdev->state_mutex);
28072807

2808-
return err;
2808+
WARN_ONCE(err, "%s: failed to block %s in state %d\n",
2809+
__func__, dev_name(&sdev->sdev_gendev), state);
28092810
}
28102811

28112812
/**
@@ -2888,36 +2889,35 @@ static int scsi_internal_device_unblock(struct scsi_device *sdev,
28882889
return ret;
28892890
}
28902891

2891-
static void
2892-
device_block(struct scsi_device *sdev, void *data)
2893-
{
2894-
int ret;
2895-
2896-
ret = scsi_internal_device_block(sdev);
2897-
2898-
WARN_ONCE(ret, "scsi_internal_device_block(%s) failed: ret = %d\n",
2899-
dev_name(&sdev->sdev_gendev), ret);
2900-
}
2901-
29022892
static int
29032893
target_block(struct device *dev, void *data)
29042894
{
29052895
if (scsi_is_target_device(dev))
29062896
starget_for_each_device(to_scsi_target(dev), NULL,
2907-
device_block);
2897+
scsi_device_block);
29082898
return 0;
29092899
}
29102900

2901+
/**
2902+
* scsi_block_targets - transition all SCSI child devices to SDEV_BLOCK state
2903+
* @dev: a parent device of one or more scsi_target devices
2904+
* @shost: the Scsi_Host to which this device belongs
2905+
*
2906+
* Iterate over all children of @dev, which should be scsi_target devices,
2907+
* and switch all subordinate scsi devices to SDEV_BLOCK state. Wait for
2908+
* ongoing scsi_queue_rq() calls to finish. May sleep.
2909+
*
2910+
* Note:
2911+
* @dev must not itself be a scsi_target device.
2912+
*/
29112913
void
2912-
scsi_target_block(struct device *dev)
2914+
scsi_block_targets(struct Scsi_Host *shost, struct device *dev)
29132915
{
2914-
if (scsi_is_target_device(dev))
2915-
starget_for_each_device(to_scsi_target(dev), NULL,
2916-
device_block);
2917-
else
2918-
device_for_each_child(dev, NULL, target_block);
2916+
WARN_ON_ONCE(scsi_is_target_device(dev));
2917+
device_for_each_child(dev, NULL, target_block);
2918+
blk_mq_wait_quiesce_done(&shost->tag_set);
29192919
}
2920-
EXPORT_SYMBOL_GPL(scsi_target_block);
2920+
EXPORT_SYMBOL_GPL(scsi_block_targets);
29212921

29222922
static void
29232923
device_unblock(struct scsi_device *sdev, void *data)

drivers/scsi/scsi_transport_fc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3451,7 +3451,7 @@ fc_remote_port_delete(struct fc_rport *rport)
34513451

34523452
spin_unlock_irqrestore(shost->host_lock, flags);
34533453

3454-
scsi_target_block(&rport->dev);
3454+
scsi_block_targets(shost, &rport->dev);
34553455

34563456
/* see if we need to kill io faster than waiting for device loss */
34573457
if ((rport->fast_io_fail_tmo != -1) &&

drivers/scsi/scsi_transport_iscsi.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1943,13 +1943,14 @@ static void __iscsi_block_session(struct work_struct *work)
19431943
struct iscsi_cls_session *session =
19441944
container_of(work, struct iscsi_cls_session,
19451945
block_work);
1946+
struct Scsi_Host *shost = iscsi_session_to_shost(session);
19461947
unsigned long flags;
19471948

19481949
ISCSI_DBG_TRANS_SESSION(session, "Blocking session\n");
19491950
spin_lock_irqsave(&session->lock, flags);
19501951
session->state = ISCSI_SESSION_FAILED;
19511952
spin_unlock_irqrestore(&session->lock, flags);
1952-
scsi_target_block(&session->dev);
1953+
scsi_block_targets(shost, &session->dev);
19531954
ISCSI_DBG_TRANS_SESSION(session, "Completed SCSI target blocking\n");
19541955
if (session->recovery_tmo >= 0)
19551956
queue_delayed_work(session->workq,

drivers/scsi/scsi_transport_srp.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ static void srp_reconnect_work(struct work_struct *work)
396396
}
397397

398398
/*
399-
* scsi_target_block() must have been called before this function is
399+
* scsi_block_targets() must have been called before this function is
400400
* called to guarantee that no .queuecommand() calls are in progress.
401401
*/
402402
static void __rport_fail_io_fast(struct srp_rport *rport)
@@ -480,7 +480,7 @@ static void __srp_start_tl_fail_timers(struct srp_rport *rport)
480480
srp_rport_set_state(rport, SRP_RPORT_BLOCKED) == 0) {
481481
pr_debug("%s new state: %d\n", dev_name(&shost->shost_gendev),
482482
rport->state);
483-
scsi_target_block(&shost->shost_gendev);
483+
scsi_block_targets(shost, &shost->shost_gendev);
484484
if (fast_io_fail_tmo >= 0)
485485
queue_delayed_work(system_long_wq,
486486
&rport->fast_io_fail_work,
@@ -548,7 +548,7 @@ int srp_reconnect_rport(struct srp_rport *rport)
548548
* later is ok though, scsi_internal_device_unblock_nowait()
549549
* treats SDEV_TRANSPORT_OFFLINE like SDEV_BLOCK.
550550
*/
551-
scsi_target_block(&shost->shost_gendev);
551+
scsi_block_targets(shost, &shost->shost_gendev);
552552
res = rport->state != SRP_RPORT_LOST ? i->f->reconnect(rport) : -ENODEV;
553553
pr_debug("%s (state %d): transport.reconnect() returned %d\n",
554554
dev_name(&shost->shost_gendev), rport->state, res);

drivers/scsi/sg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ static int sg_proc_init(void);
7171

7272
#define SG_ALLOW_DIO_DEF 0
7373

74-
#define SG_MAX_DEVS 32768
74+
#define SG_MAX_DEVS (1 << MINORBITS)
7575

7676
/* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type
7777
* of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater

drivers/scsi/snic/snic_disc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ snic_tgt_del(struct work_struct *work)
214214
scsi_flush_work(shost);
215215

216216
/* Block IOs on child devices, stops new IOs */
217-
scsi_target_block(&tgt->dev);
217+
scsi_block_targets(shost, &tgt->dev);
218218

219219
/* Cleanup IOs */
220220
snic_tgt_scsi_abort_io(tgt);

include/scsi/scsi_device.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ extern void scsi_scan_target(struct device *parent, unsigned int channel,
456456
unsigned int id, u64 lun,
457457
enum scsi_scan_mode rescan);
458458
extern void scsi_target_reap(struct scsi_target *);
459-
extern void scsi_target_block(struct device *);
459+
void scsi_block_targets(struct Scsi_Host *shost, struct device *dev);
460460
extern void scsi_target_unblock(struct device *, enum scsi_device_state);
461461
extern void scsi_remove_target(struct device *);
462462
extern const char *scsi_device_state_name(enum scsi_device_state);

0 commit comments

Comments
 (0)