Skip to content

Commit 25236d4

Browse files
Ewan D. Milnemartinkpetersen
authored andcommitted
scsi: scsi_transport_fc: Change to use per-rport devloss_work_q
Configurations with large numbers of FC rports per host instance are taking a very long time to complete all devloss work. Increase potential parallelism by using a per-rport devloss_work_q for dev_loss_work and fast_io_fail_work. Signed-off-by: Ewan D. Milne <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Hannes Reinecke <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 01aad16 commit 25236d4

File tree

2 files changed

+42
-33
lines changed

2 files changed

+42
-33
lines changed

drivers/scsi/scsi_transport_fc.c

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -446,13 +446,6 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
446446
return -ENOMEM;
447447

448448
fc_host->dev_loss_tmo = fc_dev_loss_tmo;
449-
fc_host->devloss_work_q = alloc_workqueue("fc_dl_%d", 0, 0,
450-
shost->host_no);
451-
if (!fc_host->devloss_work_q) {
452-
destroy_workqueue(fc_host->work_q);
453-
fc_host->work_q = NULL;
454-
return -ENOMEM;
455-
}
456449

457450
fc_bsg_hostadd(shost, fc_host);
458451
/* ignore any bsg add error - we just can't do sgio */
@@ -2821,10 +2814,10 @@ fc_flush_work(struct Scsi_Host *shost)
28212814
* 1 on success / 0 already queued / < 0 for error
28222815
*/
28232816
static int
2824-
fc_queue_devloss_work(struct Scsi_Host *shost, struct delayed_work *work,
2825-
unsigned long delay)
2817+
fc_queue_devloss_work(struct Scsi_Host *shost, struct fc_rport *rport,
2818+
struct delayed_work *work, unsigned long delay)
28262819
{
2827-
if (unlikely(!fc_host_devloss_work_q(shost))) {
2820+
if (unlikely(!rport->devloss_work_q)) {
28282821
printk(KERN_ERR
28292822
"ERROR: FC host '%s' attempted to queue work, "
28302823
"when no workqueue created.\n", shost->hostt->name);
@@ -2833,25 +2826,25 @@ fc_queue_devloss_work(struct Scsi_Host *shost, struct delayed_work *work,
28332826
return -EINVAL;
28342827
}
28352828

2836-
return queue_delayed_work(fc_host_devloss_work_q(shost), work, delay);
2829+
return queue_delayed_work(rport->devloss_work_q, work, delay);
28372830
}
28382831

28392832
/**
28402833
* fc_flush_devloss - Flush a fc_host's devloss workqueue.
28412834
* @shost: Pointer to Scsi_Host bound to fc_host.
28422835
*/
28432836
static void
2844-
fc_flush_devloss(struct Scsi_Host *shost)
2837+
fc_flush_devloss(struct Scsi_Host *shost, struct fc_rport *rport)
28452838
{
2846-
if (!fc_host_devloss_work_q(shost)) {
2839+
if (unlikely(!rport->devloss_work_q)) {
28472840
printk(KERN_ERR
28482841
"ERROR: FC host '%s' attempted to flush work, "
28492842
"when no workqueue created.\n", shost->hostt->name);
28502843
dump_stack();
28512844
return;
28522845
}
28532846

2854-
flush_workqueue(fc_host_devloss_work_q(shost));
2847+
flush_workqueue(rport->devloss_work_q);
28552848
}
28562849

28572850

@@ -2913,13 +2906,6 @@ fc_remove_host(struct Scsi_Host *shost)
29132906
fc_host->work_q = NULL;
29142907
destroy_workqueue(work_q);
29152908
}
2916-
2917-
/* flush all devloss work items, then kill it */
2918-
if (fc_host->devloss_work_q) {
2919-
work_q = fc_host->devloss_work_q;
2920-
fc_host->devloss_work_q = NULL;
2921-
destroy_workqueue(work_q);
2922-
}
29232909
}
29242910
EXPORT_SYMBOL(fc_remove_host);
29252911

@@ -2967,6 +2953,7 @@ fc_rport_final_delete(struct work_struct *work)
29672953
struct device *dev = &rport->dev;
29682954
struct Scsi_Host *shost = rport_to_shost(rport);
29692955
struct fc_internal *i = to_fc_internal(shost->transportt);
2956+
struct workqueue_struct *work_q;
29702957
unsigned long flags;
29712958
int do_callback = 0;
29722959

@@ -2988,9 +2975,9 @@ fc_rport_final_delete(struct work_struct *work)
29882975
if (rport->flags & FC_RPORT_DEVLOSS_PENDING) {
29892976
spin_unlock_irqrestore(shost->host_lock, flags);
29902977
if (!cancel_delayed_work(&rport->fail_io_work))
2991-
fc_flush_devloss(shost);
2978+
fc_flush_devloss(shost, rport);
29922979
if (!cancel_delayed_work(&rport->dev_loss_work))
2993-
fc_flush_devloss(shost);
2980+
fc_flush_devloss(shost, rport);
29942981
cancel_work_sync(&rport->scan_work);
29952982
spin_lock_irqsave(shost->host_lock, flags);
29962983
rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
@@ -3021,6 +3008,12 @@ fc_rport_final_delete(struct work_struct *work)
30213008

30223009
fc_bsg_remove(rport->rqst_q);
30233010

3011+
if (rport->devloss_work_q) {
3012+
work_q = rport->devloss_work_q;
3013+
rport->devloss_work_q = NULL;
3014+
destroy_workqueue(work_q);
3015+
}
3016+
30243017
transport_remove_device(dev);
30253018
device_del(dev);
30263019
transport_destroy_device(dev);
@@ -3093,6 +3086,22 @@ fc_remote_port_create(struct Scsi_Host *shost, int channel,
30933086

30943087
spin_unlock_irqrestore(shost->host_lock, flags);
30953088

3089+
rport->devloss_work_q = alloc_workqueue("fc_dl_%d_%d", 0, 0,
3090+
shost->host_no, rport->number);
3091+
if (!rport->devloss_work_q) {
3092+
printk(KERN_ERR "FC Remote Port alloc_workqueue failed\n");
3093+
/*
3094+
* Note that we have not yet called device_initialize() / get_device()
3095+
* Cannot reclaim incremented rport->number because we released host_lock
3096+
*/
3097+
spin_lock_irqsave(shost->host_lock, flags);
3098+
list_del(&rport->peers);
3099+
scsi_host_put(shost); /* for fc_host->rport list */
3100+
spin_unlock_irqrestore(shost->host_lock, flags);
3101+
kfree(rport);
3102+
return NULL;
3103+
}
3104+
30963105
dev = &rport->dev;
30973106
device_initialize(dev); /* takes self reference */
30983107
dev->parent = get_device(&shost->shost_gendev); /* parent reference */
@@ -3255,9 +3264,9 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
32553264
* be checked and will NOOP the function.
32563265
*/
32573266
if (!cancel_delayed_work(&rport->fail_io_work))
3258-
fc_flush_devloss(shost);
3267+
fc_flush_devloss(shost, rport);
32593268
if (!cancel_delayed_work(&rport->dev_loss_work))
3260-
fc_flush_devloss(shost);
3269+
fc_flush_devloss(shost, rport);
32613270

32623271
spin_lock_irqsave(shost->host_lock, flags);
32633272

@@ -3451,11 +3460,12 @@ fc_remote_port_delete(struct fc_rport *rport)
34513460
/* see if we need to kill io faster than waiting for device loss */
34523461
if ((rport->fast_io_fail_tmo != -1) &&
34533462
(rport->fast_io_fail_tmo < timeout))
3454-
fc_queue_devloss_work(shost, &rport->fail_io_work,
3455-
rport->fast_io_fail_tmo * HZ);
3463+
fc_queue_devloss_work(shost, rport, &rport->fail_io_work,
3464+
rport->fast_io_fail_tmo * HZ);
34563465

34573466
/* cap the length the devices can be blocked until they are deleted */
3458-
fc_queue_devloss_work(shost, &rport->dev_loss_work, timeout * HZ);
3467+
fc_queue_devloss_work(shost, rport, &rport->dev_loss_work,
3468+
timeout * HZ);
34593469
}
34603470
EXPORT_SYMBOL(fc_remote_port_delete);
34613471

@@ -3514,9 +3524,9 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
35143524
* transaction.
35153525
*/
35163526
if (!cancel_delayed_work(&rport->fail_io_work))
3517-
fc_flush_devloss(shost);
3527+
fc_flush_devloss(shost, rport);
35183528
if (!cancel_delayed_work(&rport->dev_loss_work))
3519-
fc_flush_devloss(shost);
3529+
fc_flush_devloss(shost, rport);
35203530

35213531
spin_lock_irqsave(shost->host_lock, flags);
35223532
rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT |

include/scsi/scsi_transport_fc.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,8 @@ struct fc_rport { /* aka fc_starget_attrs */
383383
struct work_struct stgt_delete_work;
384384
struct work_struct rport_delete_work;
385385
struct request_queue *rqst_q; /* bsg support */
386+
387+
struct workqueue_struct *devloss_work_q;
386388
} __attribute__((aligned(sizeof(unsigned long))));
387389

388390
/* bit field values for struct fc_rport "flags" field: */
@@ -576,7 +578,6 @@ struct fc_host_attrs {
576578

577579
/* work queues for rport state manipulation */
578580
struct workqueue_struct *work_q;
579-
struct workqueue_struct *devloss_work_q;
580581

581582
/* bsg support */
582583
struct request_queue *rqst_q;
@@ -654,8 +655,6 @@ struct fc_host_attrs {
654655
(((struct fc_host_attrs *)(x)->shost_data)->npiv_vports_inuse)
655656
#define fc_host_work_q(x) \
656657
(((struct fc_host_attrs *)(x)->shost_data)->work_q)
657-
#define fc_host_devloss_work_q(x) \
658-
(((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q)
659658
#define fc_host_dev_loss_tmo(x) \
660659
(((struct fc_host_attrs *)(x)->shost_data)->dev_loss_tmo)
661660
#define fc_host_max_ct_payload(x) \

0 commit comments

Comments
 (0)