aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_srp.c
diff options
context:
space:
mode:
authorBart Van Assche <bvanassche@acm.org>2013-10-26 08:35:59 -0400
committerRoland Dreier <roland@purestorage.com>2013-11-08 17:43:16 -0500
commit8c64e4531c3c3bedf11d723196270d4a7553db45 (patch)
tree4cdd251177d7b981139f729e658fccdeb1b1ffd9 /drivers/scsi/scsi_transport_srp.c
parentc1120f8981fe8ac8dd21092afaf664ba030a76cd (diff)
scsi_transport_srp: Add periodic reconnect support
Add support for periodically reconnecting to an SRP target until the dev_loss timer expires. After the tenth reconnection attempt, gradually slow down subsequent reconnect attempts. Signed-off-by: Bart Van Assche <bvanassche@acm.org> Acked-by: David Dillow <dillowda@ornl.gov> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/scsi/scsi_transport_srp.c')
-rw-r--r--drivers/scsi/scsi_transport_srp.c106
1 files changed, 99 insertions, 7 deletions
diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c
index 2696e26b3423..2700a5a09bd4 100644
--- a/drivers/scsi/scsi_transport_srp.c
+++ b/drivers/scsi/scsi_transport_srp.c
@@ -41,7 +41,7 @@ struct srp_host_attrs {
41#define to_srp_host_attrs(host) ((struct srp_host_attrs *)(host)->shost_data) 41#define to_srp_host_attrs(host) ((struct srp_host_attrs *)(host)->shost_data)
42 42
43#define SRP_HOST_ATTRS 0 43#define SRP_HOST_ATTRS 0
44#define SRP_RPORT_ATTRS 6 44#define SRP_RPORT_ATTRS 8
45 45
46struct srp_internal { 46struct srp_internal {
47 struct scsi_transport_template t; 47 struct scsi_transport_template t;
@@ -69,11 +69,13 @@ static inline struct Scsi_Host *rport_to_shost(struct srp_rport *r)
69 * are finished in a reasonable time. Hence do not allow the fast I/O fail 69 * are finished in a reasonable time. Hence do not allow the fast I/O fail
70 * timeout to exceed SCSI_DEVICE_BLOCK_MAX_TIMEOUT. Furthermore, these 70 * timeout to exceed SCSI_DEVICE_BLOCK_MAX_TIMEOUT. Furthermore, these
71 * parameters must be such that multipath can detect failed paths timely. 71 * parameters must be such that multipath can detect failed paths timely.
72 * Hence do not allow both parameters to be disabled simultaneously. 72 * Hence do not allow all three parameters to be disabled simultaneously.
73 */ 73 */
74int srp_tmo_valid(int fast_io_fail_tmo, int dev_loss_tmo) 74int srp_tmo_valid(int reconnect_delay, int fast_io_fail_tmo, int dev_loss_tmo)
75{ 75{
76 if (fast_io_fail_tmo < 0 && dev_loss_tmo < 0) 76 if (reconnect_delay < 0 && fast_io_fail_tmo < 0 && dev_loss_tmo < 0)
77 return -EINVAL;
78 if (reconnect_delay == 0)
77 return -EINVAL; 79 return -EINVAL;
78 if (fast_io_fail_tmo > SCSI_DEVICE_BLOCK_MAX_TIMEOUT) 80 if (fast_io_fail_tmo > SCSI_DEVICE_BLOCK_MAX_TIMEOUT)
79 return -EINVAL; 81 return -EINVAL;
@@ -202,6 +204,56 @@ static int srp_parse_tmo(int *tmo, const char *buf)
202 return res; 204 return res;
203} 205}
204 206
207static ssize_t show_reconnect_delay(struct device *dev,
208 struct device_attribute *attr, char *buf)
209{
210 struct srp_rport *rport = transport_class_to_srp_rport(dev);
211
212 return srp_show_tmo(buf, rport->reconnect_delay);
213}
214
215static ssize_t store_reconnect_delay(struct device *dev,
216 struct device_attribute *attr,
217 const char *buf, const size_t count)
218{
219 struct srp_rport *rport = transport_class_to_srp_rport(dev);
220 int res, delay;
221
222 res = srp_parse_tmo(&delay, buf);
223 if (res)
224 goto out;
225 res = srp_tmo_valid(delay, rport->fast_io_fail_tmo,
226 rport->dev_loss_tmo);
227 if (res)
228 goto out;
229
230 if (rport->reconnect_delay <= 0 && delay > 0 &&
231 rport->state != SRP_RPORT_RUNNING) {
232 queue_delayed_work(system_long_wq, &rport->reconnect_work,
233 delay * HZ);
234 } else if (delay <= 0) {
235 cancel_delayed_work(&rport->reconnect_work);
236 }
237 rport->reconnect_delay = delay;
238 res = count;
239
240out:
241 return res;
242}
243
244static DEVICE_ATTR(reconnect_delay, S_IRUGO | S_IWUSR, show_reconnect_delay,
245 store_reconnect_delay);
246
247static ssize_t show_failed_reconnects(struct device *dev,
248 struct device_attribute *attr, char *buf)
249{
250 struct srp_rport *rport = transport_class_to_srp_rport(dev);
251
252 return sprintf(buf, "%d\n", rport->failed_reconnects);
253}
254
255static DEVICE_ATTR(failed_reconnects, S_IRUGO, show_failed_reconnects, NULL);
256
205static ssize_t show_srp_rport_fast_io_fail_tmo(struct device *dev, 257static ssize_t show_srp_rport_fast_io_fail_tmo(struct device *dev,
206 struct device_attribute *attr, 258 struct device_attribute *attr,
207 char *buf) 259 char *buf)
@@ -222,7 +274,8 @@ static ssize_t store_srp_rport_fast_io_fail_tmo(struct device *dev,
222 res = srp_parse_tmo(&fast_io_fail_tmo, buf); 274 res = srp_parse_tmo(&fast_io_fail_tmo, buf);
223 if (res) 275 if (res)
224 goto out; 276 goto out;
225 res = srp_tmo_valid(fast_io_fail_tmo, rport->dev_loss_tmo); 277 res = srp_tmo_valid(rport->reconnect_delay, fast_io_fail_tmo,
278 rport->dev_loss_tmo);
226 if (res) 279 if (res)
227 goto out; 280 goto out;
228 rport->fast_io_fail_tmo = fast_io_fail_tmo; 281 rport->fast_io_fail_tmo = fast_io_fail_tmo;
@@ -256,7 +309,8 @@ static ssize_t store_srp_rport_dev_loss_tmo(struct device *dev,
256 res = srp_parse_tmo(&dev_loss_tmo, buf); 309 res = srp_parse_tmo(&dev_loss_tmo, buf);
257 if (res) 310 if (res)
258 goto out; 311 goto out;
259 res = srp_tmo_valid(rport->fast_io_fail_tmo, dev_loss_tmo); 312 res = srp_tmo_valid(rport->reconnect_delay, rport->fast_io_fail_tmo,
313 dev_loss_tmo);
260 if (res) 314 if (res)
261 goto out; 315 goto out;
262 rport->dev_loss_tmo = dev_loss_tmo; 316 rport->dev_loss_tmo = dev_loss_tmo;
@@ -312,6 +366,29 @@ invalid:
312 return -EINVAL; 366 return -EINVAL;
313} 367}
314 368
369/**
370 * srp_reconnect_work() - reconnect and schedule a new attempt if necessary
371 */
372static void srp_reconnect_work(struct work_struct *work)
373{
374 struct srp_rport *rport = container_of(to_delayed_work(work),
375 struct srp_rport, reconnect_work);
376 struct Scsi_Host *shost = rport_to_shost(rport);
377 int delay, res;
378
379 res = srp_reconnect_rport(rport);
380 if (res != 0) {
381 shost_printk(KERN_ERR, shost,
382 "reconnect attempt %d failed (%d)\n",
383 ++rport->failed_reconnects, res);
384 delay = rport->reconnect_delay *
385 min(100, max(1, rport->failed_reconnects - 10));
386 if (delay > 0)
387 queue_delayed_work(system_long_wq,
388 &rport->reconnect_work, delay * HZ);
389 }
390}
391
315static void __rport_fail_io_fast(struct srp_rport *rport) 392static void __rport_fail_io_fast(struct srp_rport *rport)
316{ 393{
317 struct Scsi_Host *shost = rport_to_shost(rport); 394 struct Scsi_Host *shost = rport_to_shost(rport);
@@ -371,16 +448,21 @@ static void rport_dev_loss_timedout(struct work_struct *work)
371static void __srp_start_tl_fail_timers(struct srp_rport *rport) 448static void __srp_start_tl_fail_timers(struct srp_rport *rport)
372{ 449{
373 struct Scsi_Host *shost = rport_to_shost(rport); 450 struct Scsi_Host *shost = rport_to_shost(rport);
374 int fast_io_fail_tmo, dev_loss_tmo; 451 int delay, fast_io_fail_tmo, dev_loss_tmo;
375 452
376 lockdep_assert_held(&rport->mutex); 453 lockdep_assert_held(&rport->mutex);
377 454
378 if (!rport->deleted) { 455 if (!rport->deleted) {
456 delay = rport->reconnect_delay;
379 fast_io_fail_tmo = rport->fast_io_fail_tmo; 457 fast_io_fail_tmo = rport->fast_io_fail_tmo;
380 dev_loss_tmo = rport->dev_loss_tmo; 458 dev_loss_tmo = rport->dev_loss_tmo;
381 pr_debug("%s current state: %d\n", 459 pr_debug("%s current state: %d\n",
382 dev_name(&shost->shost_gendev), rport->state); 460 dev_name(&shost->shost_gendev), rport->state);
383 461
462 if (delay > 0)
463 queue_delayed_work(system_long_wq,
464 &rport->reconnect_work,
465 1UL * delay * HZ);
384 if (fast_io_fail_tmo >= 0 && 466 if (fast_io_fail_tmo >= 0 &&
385 srp_rport_set_state(rport, SRP_RPORT_BLOCKED) == 0) { 467 srp_rport_set_state(rport, SRP_RPORT_BLOCKED) == 0) {
386 pr_debug("%s new state: %d\n", 468 pr_debug("%s new state: %d\n",
@@ -481,6 +563,7 @@ int srp_reconnect_rport(struct srp_rport *rport)
481 cancel_delayed_work(&rport->fast_io_fail_work); 563 cancel_delayed_work(&rport->fast_io_fail_work);
482 cancel_delayed_work(&rport->dev_loss_work); 564 cancel_delayed_work(&rport->dev_loss_work);
483 565
566 rport->failed_reconnects = 0;
484 srp_rport_set_state(rport, SRP_RPORT_RUNNING); 567 srp_rport_set_state(rport, SRP_RPORT_RUNNING);
485 scsi_target_unblock(&shost->shost_gendev, SDEV_RUNNING); 568 scsi_target_unblock(&shost->shost_gendev, SDEV_RUNNING);
486 /* 569 /*
@@ -539,6 +622,7 @@ static void srp_rport_release(struct device *dev)
539{ 622{
540 struct srp_rport *rport = dev_to_rport(dev); 623 struct srp_rport *rport = dev_to_rport(dev);
541 624
625 cancel_delayed_work_sync(&rport->reconnect_work);
542 cancel_delayed_work_sync(&rport->fast_io_fail_work); 626 cancel_delayed_work_sync(&rport->fast_io_fail_work);
543 cancel_delayed_work_sync(&rport->dev_loss_work); 627 cancel_delayed_work_sync(&rport->dev_loss_work);
544 628
@@ -635,6 +719,10 @@ struct srp_rport *srp_rport_add(struct Scsi_Host *shost,
635 memcpy(rport->port_id, ids->port_id, sizeof(rport->port_id)); 719 memcpy(rport->port_id, ids->port_id, sizeof(rport->port_id));
636 rport->roles = ids->roles; 720 rport->roles = ids->roles;
637 721
722 if (i->f->reconnect)
723 rport->reconnect_delay = i->f->reconnect_delay ?
724 *i->f->reconnect_delay : 10;
725 INIT_DELAYED_WORK(&rport->reconnect_work, srp_reconnect_work);
638 rport->fast_io_fail_tmo = i->f->fast_io_fail_tmo ? 726 rport->fast_io_fail_tmo = i->f->fast_io_fail_tmo ?
639 *i->f->fast_io_fail_tmo : 15; 727 *i->f->fast_io_fail_tmo : 15;
640 rport->dev_loss_tmo = i->f->dev_loss_tmo ? *i->f->dev_loss_tmo : 60; 728 rport->dev_loss_tmo = i->f->dev_loss_tmo ? *i->f->dev_loss_tmo : 60;
@@ -773,6 +861,10 @@ srp_attach_transport(struct srp_function_template *ft)
773 i->rport_attrs[count++] = &dev_attr_fast_io_fail_tmo; 861 i->rport_attrs[count++] = &dev_attr_fast_io_fail_tmo;
774 i->rport_attrs[count++] = &dev_attr_dev_loss_tmo; 862 i->rport_attrs[count++] = &dev_attr_dev_loss_tmo;
775 } 863 }
864 if (ft->reconnect) {
865 i->rport_attrs[count++] = &dev_attr_reconnect_delay;
866 i->rport_attrs[count++] = &dev_attr_failed_reconnects;
867 }
776 if (ft->rport_delete) 868 if (ft->rport_delete)
777 i->rport_attrs[count++] = &dev_attr_delete; 869 i->rport_attrs[count++] = &dev_attr_delete;
778 i->rport_attrs[count++] = NULL; 870 i->rport_attrs[count++] = NULL;