diff options
-rw-r--r-- | drivers/scsi/scsi_transport_fc.c | 124 | ||||
-rw-r--r-- | include/scsi/scsi_transport_fc.h | 7 |
2 files changed, 91 insertions, 40 deletions
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 78486d540652..998c01be3234 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
@@ -53,6 +53,25 @@ static void fc_bsg_remove(struct request_queue *); | |||
53 | static void fc_bsg_goose_queue(struct fc_rport *); | 53 | static void fc_bsg_goose_queue(struct fc_rport *); |
54 | 54 | ||
55 | /* | 55 | /* |
56 | * Module Parameters | ||
57 | */ | ||
58 | |||
59 | /* | ||
60 | * dev_loss_tmo: the default number of seconds that the FC transport | ||
61 | * should insulate the loss of a remote port. | ||
62 | * The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT. | ||
63 | */ | ||
64 | static unsigned int fc_dev_loss_tmo = 60; /* seconds */ | ||
65 | |||
66 | module_param_named(dev_loss_tmo, fc_dev_loss_tmo, uint, S_IRUGO|S_IWUSR); | ||
67 | MODULE_PARM_DESC(dev_loss_tmo, | ||
68 | "Maximum number of seconds that the FC transport should" | ||
69 | " insulate the loss of a remote port. Once this value is" | ||
70 | " exceeded, the scsi target is removed. Value should be" | ||
71 | " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT if" | ||
72 | " fast_io_fail_tmo is not set."); | ||
73 | |||
74 | /* | ||
56 | * Redefine so that we can have same named attributes in the | 75 | * Redefine so that we can have same named attributes in the |
57 | * sdev/starget/host objects. | 76 | * sdev/starget/host objects. |
58 | */ | 77 | */ |
@@ -408,6 +427,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev, | |||
408 | if (!fc_host->work_q) | 427 | if (!fc_host->work_q) |
409 | return -ENOMEM; | 428 | return -ENOMEM; |
410 | 429 | ||
430 | fc_host->dev_loss_tmo = fc_dev_loss_tmo; | ||
411 | snprintf(fc_host->devloss_work_q_name, | 431 | snprintf(fc_host->devloss_work_q_name, |
412 | sizeof(fc_host->devloss_work_q_name), | 432 | sizeof(fc_host->devloss_work_q_name), |
413 | "fc_dl_%d", shost->host_no); | 433 | "fc_dl_%d", shost->host_no); |
@@ -462,25 +482,6 @@ static DECLARE_TRANSPORT_CLASS(fc_vport_class, | |||
462 | NULL); | 482 | NULL); |
463 | 483 | ||
464 | /* | 484 | /* |
465 | * Module Parameters | ||
466 | */ | ||
467 | |||
468 | /* | ||
469 | * dev_loss_tmo: the default number of seconds that the FC transport | ||
470 | * should insulate the loss of a remote port. | ||
471 | * The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT. | ||
472 | */ | ||
473 | static unsigned int fc_dev_loss_tmo = 60; /* seconds */ | ||
474 | |||
475 | module_param_named(dev_loss_tmo, fc_dev_loss_tmo, uint, S_IRUGO|S_IWUSR); | ||
476 | MODULE_PARM_DESC(dev_loss_tmo, | ||
477 | "Maximum number of seconds that the FC transport should" | ||
478 | " insulate the loss of a remote port. Once this value is" | ||
479 | " exceeded, the scsi target is removed. Value should be" | ||
480 | " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT if" | ||
481 | " fast_io_fail_tmo is not set."); | ||
482 | |||
483 | /* | ||
484 | * Netlink Infrastructure | 485 | * Netlink Infrastructure |
485 | */ | 486 | */ |
486 | 487 | ||
@@ -830,24 +831,32 @@ static FC_DEVICE_ATTR(rport, supported_classes, S_IRUGO, | |||
830 | /* | 831 | /* |
831 | * dev_loss_tmo attribute | 832 | * dev_loss_tmo attribute |
832 | */ | 833 | */ |
833 | fc_rport_show_function(dev_loss_tmo, "%d\n", 20, ) | 834 | static int fc_str_to_dev_loss(const char *buf, unsigned long *val) |
834 | static ssize_t | 835 | { |
835 | store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr, | 836 | char *cp; |
836 | const char *buf, size_t count) | 837 | |
838 | *val = simple_strtoul(buf, &cp, 0); | ||
839 | if ((*cp && (*cp != '\n')) || (*val < 0)) | ||
840 | return -EINVAL; | ||
841 | /* | ||
842 | * Check for overflow; dev_loss_tmo is u32 | ||
843 | */ | ||
844 | if (*val > UINT_MAX) | ||
845 | return -EINVAL; | ||
846 | |||
847 | return 0; | ||
848 | } | ||
849 | |||
850 | static int fc_rport_set_dev_loss_tmo(struct fc_rport *rport, | ||
851 | unsigned long val) | ||
837 | { | 852 | { |
838 | unsigned long val; | ||
839 | struct fc_rport *rport = transport_class_to_rport(dev); | ||
840 | struct Scsi_Host *shost = rport_to_shost(rport); | 853 | struct Scsi_Host *shost = rport_to_shost(rport); |
841 | struct fc_internal *i = to_fc_internal(shost->transportt); | 854 | struct fc_internal *i = to_fc_internal(shost->transportt); |
842 | char *cp; | 855 | |
843 | if ((rport->port_state == FC_PORTSTATE_BLOCKED) || | 856 | if ((rport->port_state == FC_PORTSTATE_BLOCKED) || |
844 | (rport->port_state == FC_PORTSTATE_DELETED) || | 857 | (rport->port_state == FC_PORTSTATE_DELETED) || |
845 | (rport->port_state == FC_PORTSTATE_NOTPRESENT)) | 858 | (rport->port_state == FC_PORTSTATE_NOTPRESENT)) |
846 | return -EBUSY; | 859 | return -EBUSY; |
847 | val = simple_strtoul(buf, &cp, 0); | ||
848 | if ((*cp && (*cp != '\n')) || (val < 0)) | ||
849 | return -EINVAL; | ||
850 | |||
851 | /* | 860 | /* |
852 | * Check for overflow; dev_loss_tmo is u32 | 861 | * Check for overflow; dev_loss_tmo is u32 |
853 | */ | 862 | */ |
@@ -863,6 +872,25 @@ store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr, | |||
863 | return -EINVAL; | 872 | return -EINVAL; |
864 | 873 | ||
865 | i->f->set_rport_dev_loss_tmo(rport, val); | 874 | i->f->set_rport_dev_loss_tmo(rport, val); |
875 | return 0; | ||
876 | } | ||
877 | |||
878 | fc_rport_show_function(dev_loss_tmo, "%d\n", 20, ) | ||
879 | static ssize_t | ||
880 | store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr, | ||
881 | const char *buf, size_t count) | ||
882 | { | ||
883 | struct fc_rport *rport = transport_class_to_rport(dev); | ||
884 | unsigned long val; | ||
885 | int rc; | ||
886 | |||
887 | rc = fc_str_to_dev_loss(buf, &val); | ||
888 | if (rc) | ||
889 | return rc; | ||
890 | |||
891 | rc = fc_rport_set_dev_loss_tmo(rport, val); | ||
892 | if (rc) | ||
893 | return rc; | ||
866 | return count; | 894 | return count; |
867 | } | 895 | } |
868 | static FC_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR, | 896 | static FC_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR, |
@@ -1608,8 +1636,35 @@ store_fc_private_host_issue_lip(struct device *dev, | |||
1608 | static FC_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL, | 1636 | static FC_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL, |
1609 | store_fc_private_host_issue_lip); | 1637 | store_fc_private_host_issue_lip); |
1610 | 1638 | ||
1611 | fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20); | 1639 | static ssize_t |
1640 | store_fc_private_host_dev_loss_tmo(struct device *dev, | ||
1641 | struct device_attribute *attr, | ||
1642 | const char *buf, size_t count) | ||
1643 | { | ||
1644 | struct Scsi_Host *shost = transport_class_to_shost(dev); | ||
1645 | struct fc_host_attrs *fc_host = shost_to_fc_host(shost); | ||
1646 | struct fc_rport *rport; | ||
1647 | unsigned long val, flags; | ||
1648 | int rc; | ||
1649 | |||
1650 | rc = fc_str_to_dev_loss(buf, &val); | ||
1651 | if (rc) | ||
1652 | return rc; | ||
1653 | |||
1654 | fc_host_dev_loss_tmo(shost) = val; | ||
1655 | spin_lock_irqsave(shost->host_lock, flags); | ||
1656 | list_for_each_entry(rport, &fc_host->rports, peers) | ||
1657 | fc_rport_set_dev_loss_tmo(rport, val); | ||
1658 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1659 | return count; | ||
1660 | } | ||
1612 | 1661 | ||
1662 | fc_private_host_show_function(dev_loss_tmo, "%d\n", 20, ); | ||
1663 | static FC_DEVICE_ATTR(host, dev_loss_tmo, S_IRUGO | S_IWUSR, | ||
1664 | show_fc_host_dev_loss_tmo, | ||
1665 | store_fc_private_host_dev_loss_tmo); | ||
1666 | |||
1667 | fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20); | ||
1613 | 1668 | ||
1614 | /* | 1669 | /* |
1615 | * Host Statistics Management | 1670 | * Host Statistics Management |
@@ -2165,6 +2220,7 @@ fc_attach_transport(struct fc_function_template *ft) | |||
2165 | SETUP_HOST_ATTRIBUTE_RW(system_hostname); | 2220 | SETUP_HOST_ATTRIBUTE_RW(system_hostname); |
2166 | 2221 | ||
2167 | /* Transport-managed attributes */ | 2222 | /* Transport-managed attributes */ |
2223 | SETUP_PRIVATE_HOST_ATTRIBUTE_RW(dev_loss_tmo); | ||
2168 | SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type); | 2224 | SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type); |
2169 | if (ft->issue_fc_host_lip) | 2225 | if (ft->issue_fc_host_lip) |
2170 | SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip); | 2226 | SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip); |
@@ -2525,11 +2581,7 @@ fc_rport_create(struct Scsi_Host *shost, int channel, | |||
2525 | 2581 | ||
2526 | rport->maxframe_size = -1; | 2582 | rport->maxframe_size = -1; |
2527 | rport->supported_classes = FC_COS_UNSPECIFIED; | 2583 | rport->supported_classes = FC_COS_UNSPECIFIED; |
2528 | if (fci->f->get_host_def_dev_loss_tmo) { | 2584 | rport->dev_loss_tmo = fc_host->dev_loss_tmo; |
2529 | fci->f->get_host_def_dev_loss_tmo(shost); | ||
2530 | rport->dev_loss_tmo = fc_host_def_dev_loss_tmo(shost); | ||
2531 | } else | ||
2532 | rport->dev_loss_tmo = fc_dev_loss_tmo; | ||
2533 | memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name)); | 2585 | memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name)); |
2534 | memcpy(&rport->port_name, &ids->port_name, sizeof(rport->port_name)); | 2586 | memcpy(&rport->port_name, &ids->port_name, sizeof(rport->port_name)); |
2535 | rport->port_id = ids->port_id; | 2587 | rport->port_id = ids->port_id; |
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 9f98fca9b763..59816fe31e68 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h | |||
@@ -496,7 +496,7 @@ struct fc_host_attrs { | |||
496 | u64 fabric_name; | 496 | u64 fabric_name; |
497 | char symbolic_name[FC_SYMBOLIC_NAME_SIZE]; | 497 | char symbolic_name[FC_SYMBOLIC_NAME_SIZE]; |
498 | char system_hostname[FC_SYMBOLIC_NAME_SIZE]; | 498 | char system_hostname[FC_SYMBOLIC_NAME_SIZE]; |
499 | u32 def_dev_loss_tmo; | 499 | u32 dev_loss_tmo; |
500 | 500 | ||
501 | /* Private (Transport-managed) Attributes */ | 501 | /* Private (Transport-managed) Attributes */ |
502 | enum fc_tgtid_binding_type tgtid_bind_type; | 502 | enum fc_tgtid_binding_type tgtid_bind_type; |
@@ -581,8 +581,8 @@ struct fc_host_attrs { | |||
581 | (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q_name) | 581 | (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q_name) |
582 | #define fc_host_devloss_work_q(x) \ | 582 | #define fc_host_devloss_work_q(x) \ |
583 | (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q) | 583 | (((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q) |
584 | #define fc_host_def_dev_loss_tmo(x) \ | 584 | #define fc_host_dev_loss_tmo(x) \ |
585 | (((struct fc_host_attrs *)(x)->shost_data)->def_dev_loss_tmo) | 585 | (((struct fc_host_attrs *)(x)->shost_data)->dev_loss_tmo) |
586 | 586 | ||
587 | 587 | ||
588 | struct fc_bsg_buffer { | 588 | struct fc_bsg_buffer { |
@@ -643,7 +643,6 @@ struct fc_function_template { | |||
643 | void (*get_host_fabric_name)(struct Scsi_Host *); | 643 | void (*get_host_fabric_name)(struct Scsi_Host *); |
644 | void (*get_host_symbolic_name)(struct Scsi_Host *); | 644 | void (*get_host_symbolic_name)(struct Scsi_Host *); |
645 | void (*set_host_system_hostname)(struct Scsi_Host *); | 645 | void (*set_host_system_hostname)(struct Scsi_Host *); |
646 | void (*get_host_def_dev_loss_tmo)(struct Scsi_Host *); | ||
647 | 646 | ||
648 | struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *); | 647 | struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *); |
649 | void (*reset_fc_host_stats)(struct Scsi_Host *); | 648 | void (*reset_fc_host_stats)(struct Scsi_Host *); |