diff options
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 68 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 262 | ||||
-rw-r--r-- | include/scsi/iscsi_if.h | 64 | ||||
-rw-r--r-- | include/scsi/scsi_transport_iscsi.h | 24 |
4 files changed, 342 insertions, 76 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 6ecb4baa37e2..6e510f3cfbf6 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -3536,7 +3536,7 @@ iscsi_session_get_param(struct iscsi_cls_session *cls_session, | |||
3536 | *value = session->ofmarker_en; | 3536 | *value = session->ofmarker_en; |
3537 | break; | 3537 | break; |
3538 | default: | 3538 | default: |
3539 | return ISCSI_ERR_PARAM_NOT_FOUND; | 3539 | return -EINVAL; |
3540 | } | 3540 | } |
3541 | 3541 | ||
3542 | return 0; | 3542 | return 0; |
@@ -3547,6 +3547,7 @@ iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, | |||
3547 | enum iscsi_param param, uint32_t *value) | 3547 | enum iscsi_param param, uint32_t *value) |
3548 | { | 3548 | { |
3549 | struct iscsi_conn *conn = cls_conn->dd_data; | 3549 | struct iscsi_conn *conn = cls_conn->dd_data; |
3550 | struct inet_sock *inet; | ||
3550 | 3551 | ||
3551 | switch(param) { | 3552 | switch(param) { |
3552 | case ISCSI_PARAM_MAX_RECV_DLENGTH: | 3553 | case ISCSI_PARAM_MAX_RECV_DLENGTH: |
@@ -3561,13 +3562,61 @@ iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, | |||
3561 | case ISCSI_PARAM_DATADGST_EN: | 3562 | case ISCSI_PARAM_DATADGST_EN: |
3562 | *value = conn->datadgst_en; | 3563 | *value = conn->datadgst_en; |
3563 | break; | 3564 | break; |
3565 | case ISCSI_PARAM_CONN_PORT: | ||
3566 | mutex_lock(&conn->xmitmutex); | ||
3567 | if (!conn->sock) { | ||
3568 | mutex_unlock(&conn->xmitmutex); | ||
3569 | return -EINVAL; | ||
3570 | } | ||
3571 | |||
3572 | inet = inet_sk(conn->sock->sk); | ||
3573 | *value = be16_to_cpu(inet->dport); | ||
3574 | mutex_unlock(&conn->xmitmutex); | ||
3564 | default: | 3575 | default: |
3565 | return ISCSI_ERR_PARAM_NOT_FOUND; | 3576 | return -EINVAL; |
3566 | } | 3577 | } |
3567 | 3578 | ||
3568 | return 0; | 3579 | return 0; |
3569 | } | 3580 | } |
3570 | 3581 | ||
3582 | static int | ||
3583 | iscsi_conn_get_str_param(struct iscsi_cls_conn *cls_conn, | ||
3584 | enum iscsi_param param, char *buf) | ||
3585 | { | ||
3586 | struct iscsi_conn *conn = cls_conn->dd_data; | ||
3587 | struct sock *sk; | ||
3588 | struct inet_sock *inet; | ||
3589 | struct ipv6_pinfo *np; | ||
3590 | int len = 0; | ||
3591 | |||
3592 | switch (param) { | ||
3593 | case ISCSI_PARAM_CONN_ADDRESS: | ||
3594 | mutex_lock(&conn->xmitmutex); | ||
3595 | if (!conn->sock) { | ||
3596 | mutex_unlock(&conn->xmitmutex); | ||
3597 | return -EINVAL; | ||
3598 | } | ||
3599 | |||
3600 | sk = conn->sock->sk; | ||
3601 | if (sk->sk_family == PF_INET) { | ||
3602 | inet = inet_sk(sk); | ||
3603 | len = sprintf(buf, "%u.%u.%u.%u\n", | ||
3604 | NIPQUAD(inet->daddr)); | ||
3605 | } else { | ||
3606 | np = inet6_sk(sk); | ||
3607 | len = sprintf(buf, | ||
3608 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
3609 | NIP6(np->daddr)); | ||
3610 | } | ||
3611 | mutex_unlock(&conn->xmitmutex); | ||
3612 | break; | ||
3613 | default: | ||
3614 | return -EINVAL; | ||
3615 | } | ||
3616 | |||
3617 | return len; | ||
3618 | } | ||
3619 | |||
3571 | static void | 3620 | static void |
3572 | iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) | 3621 | iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) |
3573 | { | 3622 | { |
@@ -3610,6 +3659,20 @@ static struct iscsi_transport iscsi_tcp_transport = { | |||
3610 | .name = "tcp", | 3659 | .name = "tcp", |
3611 | .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST | 3660 | .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST |
3612 | | CAP_DATADGST, | 3661 | | CAP_DATADGST, |
3662 | .param_mask = ISCSI_MAX_RECV_DLENGTH | | ||
3663 | ISCSI_MAX_XMIT_DLENGTH | | ||
3664 | ISCSI_HDRDGST_EN | | ||
3665 | ISCSI_DATADGST_EN | | ||
3666 | ISCSI_INITIAL_R2T_EN | | ||
3667 | ISCSI_MAX_R2T | | ||
3668 | ISCSI_IMM_DATA_EN | | ||
3669 | ISCSI_FIRST_BURST | | ||
3670 | ISCSI_MAX_BURST | | ||
3671 | ISCSI_PDU_INORDER_EN | | ||
3672 | ISCSI_DATASEQ_INORDER_EN | | ||
3673 | ISCSI_ERL | | ||
3674 | ISCSI_CONN_PORT | | ||
3675 | ISCSI_CONN_ADDRESS, | ||
3613 | .host_template = &iscsi_sht, | 3676 | .host_template = &iscsi_sht, |
3614 | .hostdata_size = sizeof(struct iscsi_session), | 3677 | .hostdata_size = sizeof(struct iscsi_session), |
3615 | .conndata_size = sizeof(struct iscsi_conn), | 3678 | .conndata_size = sizeof(struct iscsi_conn), |
@@ -3622,6 +3685,7 @@ static struct iscsi_transport iscsi_tcp_transport = { | |||
3622 | .destroy_conn = iscsi_conn_destroy, | 3685 | .destroy_conn = iscsi_conn_destroy, |
3623 | .set_param = iscsi_conn_set_param, | 3686 | .set_param = iscsi_conn_set_param, |
3624 | .get_conn_param = iscsi_conn_get_param, | 3687 | .get_conn_param = iscsi_conn_get_param, |
3688 | .get_conn_str_param = iscsi_conn_get_str_param, | ||
3625 | .get_session_param = iscsi_session_get_param, | 3689 | .get_session_param = iscsi_session_get_param, |
3626 | .start_conn = iscsi_conn_start, | 3690 | .start_conn = iscsi_conn_start, |
3627 | .stop_conn = iscsi_conn_stop, | 3691 | .stop_conn = iscsi_conn_stop, |
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 10ff0f0210ba..72a71ebc9d03 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -31,21 +31,13 @@ | |||
31 | #include <scsi/scsi_transport_iscsi.h> | 31 | #include <scsi/scsi_transport_iscsi.h> |
32 | #include <scsi/iscsi_if.h> | 32 | #include <scsi/iscsi_if.h> |
33 | 33 | ||
34 | #define ISCSI_SESSION_ATTRS 8 | 34 | #define ISCSI_SESSION_ATTRS 10 |
35 | #define ISCSI_CONN_ATTRS 6 | 35 | #define ISCSI_CONN_ATTRS 10 |
36 | 36 | ||
37 | struct iscsi_internal { | 37 | struct iscsi_internal { |
38 | struct scsi_transport_template t; | 38 | struct scsi_transport_template t; |
39 | struct iscsi_transport *iscsi_transport; | 39 | struct iscsi_transport *iscsi_transport; |
40 | struct list_head list; | 40 | struct list_head list; |
41 | /* | ||
42 | * based on transport capabilities, at register time we set these | ||
43 | * bits to tell the transport class it wants attributes displayed | ||
44 | * in sysfs or that it can support different iSCSI Data-Path | ||
45 | * capabilities | ||
46 | */ | ||
47 | uint32_t param_mask; | ||
48 | |||
49 | struct class_device cdev; | 41 | struct class_device cdev; |
50 | /* | 42 | /* |
51 | * We do not have any private or other attrs. | 43 | * We do not have any private or other attrs. |
@@ -223,6 +215,7 @@ static void iscsi_session_release(struct device *dev) | |||
223 | 215 | ||
224 | shost = iscsi_session_to_shost(session); | 216 | shost = iscsi_session_to_shost(session); |
225 | scsi_host_put(shost); | 217 | scsi_host_put(shost); |
218 | kfree(session->targetname); | ||
226 | kfree(session); | 219 | kfree(session); |
227 | module_put(transport->owner); | 220 | module_put(transport->owner); |
228 | } | 221 | } |
@@ -304,6 +297,7 @@ static void iscsi_conn_release(struct device *dev) | |||
304 | struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev); | 297 | struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev); |
305 | struct device *parent = conn->dev.parent; | 298 | struct device *parent = conn->dev.parent; |
306 | 299 | ||
300 | kfree(conn->persistent_address); | ||
307 | kfree(conn); | 301 | kfree(conn); |
308 | put_device(parent); | 302 | put_device(parent); |
309 | } | 303 | } |
@@ -870,6 +864,67 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev | |||
870 | return 0; | 864 | return 0; |
871 | } | 865 | } |
872 | 866 | ||
867 | static void | ||
868 | iscsi_copy_param(struct iscsi_uevent *ev, uint32_t *value, char *data) | ||
869 | { | ||
870 | if (ev->u.set_param.len != sizeof(uint32_t)) | ||
871 | BUG(); | ||
872 | memcpy(value, data, min_t(uint32_t, sizeof(uint32_t), | ||
873 | ev->u.set_param.len)); | ||
874 | } | ||
875 | |||
876 | static int | ||
877 | iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev) | ||
878 | { | ||
879 | char *data = (char*)ev + sizeof(*ev); | ||
880 | struct iscsi_cls_conn *conn; | ||
881 | struct iscsi_cls_session *session; | ||
882 | int err = 0; | ||
883 | uint32_t value = 0; | ||
884 | |||
885 | session = iscsi_session_lookup(ev->u.set_param.sid); | ||
886 | conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid); | ||
887 | if (!conn || !session) | ||
888 | return -EINVAL; | ||
889 | |||
890 | switch (ev->u.set_param.param) { | ||
891 | case ISCSI_PARAM_TARGET_NAME: | ||
892 | /* this should not change between logins */ | ||
893 | if (session->targetname) | ||
894 | return 0; | ||
895 | |||
896 | session->targetname = kstrdup(data, GFP_KERNEL); | ||
897 | if (!session->targetname) | ||
898 | return -ENOMEM; | ||
899 | break; | ||
900 | case ISCSI_PARAM_TPGT: | ||
901 | iscsi_copy_param(ev, &value, data); | ||
902 | session->tpgt = value; | ||
903 | break; | ||
904 | case ISCSI_PARAM_PERSISTENT_PORT: | ||
905 | iscsi_copy_param(ev, &value, data); | ||
906 | conn->persistent_port = value; | ||
907 | break; | ||
908 | case ISCSI_PARAM_PERSISTENT_ADDRESS: | ||
909 | /* | ||
910 | * this is the address returned in discovery so it should | ||
911 | * not change between logins. | ||
912 | */ | ||
913 | if (conn->persistent_address) | ||
914 | return 0; | ||
915 | |||
916 | conn->persistent_address = kstrdup(data, GFP_KERNEL); | ||
917 | if (!conn->persistent_address) | ||
918 | return -ENOMEM; | ||
919 | break; | ||
920 | default: | ||
921 | iscsi_copy_param(ev, &value, data); | ||
922 | err = transport->set_param(conn, ev->u.set_param.param, value); | ||
923 | } | ||
924 | |||
925 | return err; | ||
926 | } | ||
927 | |||
873 | static int | 928 | static int |
874 | iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 929 | iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
875 | { | 930 | { |
@@ -917,12 +972,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
917 | err = -EINVAL; | 972 | err = -EINVAL; |
918 | break; | 973 | break; |
919 | case ISCSI_UEVENT_SET_PARAM: | 974 | case ISCSI_UEVENT_SET_PARAM: |
920 | conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid); | 975 | err = iscsi_set_param(transport, ev); |
921 | if (conn) | ||
922 | ev->r.retcode = transport->set_param(conn, | ||
923 | ev->u.set_param.param, ev->u.set_param.value); | ||
924 | else | ||
925 | err = -EINVAL; | ||
926 | break; | 976 | break; |
927 | case ISCSI_UEVENT_START_CONN: | 977 | case ISCSI_UEVENT_START_CONN: |
928 | conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid); | 978 | conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid); |
@@ -1028,6 +1078,10 @@ free_skb: | |||
1028 | #define iscsi_cdev_to_conn(_cdev) \ | 1078 | #define iscsi_cdev_to_conn(_cdev) \ |
1029 | iscsi_dev_to_conn(_cdev->dev) | 1079 | iscsi_dev_to_conn(_cdev->dev) |
1030 | 1080 | ||
1081 | #define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store) \ | ||
1082 | struct class_device_attribute class_device_attr_##_prefix##_##_name = \ | ||
1083 | __ATTR(_name,_mode,_show,_store) | ||
1084 | |||
1031 | /* | 1085 | /* |
1032 | * iSCSI connection attrs | 1086 | * iSCSI connection attrs |
1033 | */ | 1087 | */ |
@@ -1045,7 +1099,8 @@ show_conn_int_param_##param(struct class_device *cdev, char *buf) \ | |||
1045 | 1099 | ||
1046 | #define iscsi_conn_int_attr(field, param, format) \ | 1100 | #define iscsi_conn_int_attr(field, param, format) \ |
1047 | iscsi_conn_int_attr_show(param, format) \ | 1101 | iscsi_conn_int_attr_show(param, format) \ |
1048 | static CLASS_DEVICE_ATTR(field, S_IRUGO, show_conn_int_param_##param, NULL); | 1102 | static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_int_param_##param, \ |
1103 | NULL); | ||
1049 | 1104 | ||
1050 | iscsi_conn_int_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH, "%u"); | 1105 | iscsi_conn_int_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH, "%u"); |
1051 | iscsi_conn_int_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH, "%u"); | 1106 | iscsi_conn_int_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH, "%u"); |
@@ -1053,6 +1108,25 @@ iscsi_conn_int_attr(header_digest, ISCSI_PARAM_HDRDGST_EN, "%d"); | |||
1053 | iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d"); | 1108 | iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d"); |
1054 | iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d"); | 1109 | iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d"); |
1055 | iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d"); | 1110 | iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d"); |
1111 | iscsi_conn_int_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT, "%d"); | ||
1112 | iscsi_conn_int_attr(port, ISCSI_PARAM_CONN_PORT, "%d"); | ||
1113 | |||
1114 | #define iscsi_conn_str_attr_show(param) \ | ||
1115 | static ssize_t \ | ||
1116 | show_conn_str_param_##param(struct class_device *cdev, char *buf) \ | ||
1117 | { \ | ||
1118 | struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \ | ||
1119 | struct iscsi_transport *t = conn->transport; \ | ||
1120 | return t->get_conn_str_param(conn, param, buf); \ | ||
1121 | } | ||
1122 | |||
1123 | #define iscsi_conn_str_attr(field, param) \ | ||
1124 | iscsi_conn_str_attr_show(param) \ | ||
1125 | static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_str_param_##param, \ | ||
1126 | NULL); | ||
1127 | |||
1128 | iscsi_conn_str_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS); | ||
1129 | iscsi_conn_str_attr(address, ISCSI_PARAM_CONN_ADDRESS); | ||
1056 | 1130 | ||
1057 | #define iscsi_cdev_to_session(_cdev) \ | 1131 | #define iscsi_cdev_to_session(_cdev) \ |
1058 | iscsi_dev_to_session(_cdev->dev) | 1132 | iscsi_dev_to_session(_cdev->dev) |
@@ -1074,7 +1148,8 @@ show_session_int_param_##param(struct class_device *cdev, char *buf) \ | |||
1074 | 1148 | ||
1075 | #define iscsi_session_int_attr(field, param, format) \ | 1149 | #define iscsi_session_int_attr(field, param, format) \ |
1076 | iscsi_session_int_attr_show(param, format) \ | 1150 | iscsi_session_int_attr_show(param, format) \ |
1077 | static CLASS_DEVICE_ATTR(field, S_IRUGO, show_session_int_param_##param, NULL); | 1151 | static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_int_param_##param, \ |
1152 | NULL); | ||
1078 | 1153 | ||
1079 | iscsi_session_int_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, "%d"); | 1154 | iscsi_session_int_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, "%d"); |
1080 | iscsi_session_int_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, "%hu"); | 1155 | iscsi_session_int_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, "%hu"); |
@@ -1084,18 +1159,88 @@ iscsi_session_int_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, "%u"); | |||
1084 | iscsi_session_int_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, "%d"); | 1159 | iscsi_session_int_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, "%d"); |
1085 | iscsi_session_int_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, "%d"); | 1160 | iscsi_session_int_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, "%d"); |
1086 | iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d"); | 1161 | iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d"); |
1162 | iscsi_session_int_attr(tpgt, ISCSI_PARAM_TPGT, "%d"); | ||
1087 | 1163 | ||
1088 | #define SETUP_SESSION_RD_ATTR(field, param) \ | 1164 | #define iscsi_session_str_attr_show(param) \ |
1089 | if (priv->param_mask & (1 << param)) { \ | 1165 | static ssize_t \ |
1090 | priv->session_attrs[count] = &class_device_attr_##field;\ | 1166 | show_session_str_param_##param(struct class_device *cdev, char *buf) \ |
1091 | count++; \ | 1167 | { \ |
1092 | } | 1168 | struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \ |
1169 | struct iscsi_transport *t = session->transport; \ | ||
1170 | return t->get_session_str_param(session, param, buf); \ | ||
1171 | } | ||
1172 | |||
1173 | #define iscsi_session_str_attr(field, param) \ | ||
1174 | iscsi_session_str_attr_show(param) \ | ||
1175 | static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_str_param_##param, \ | ||
1176 | NULL); | ||
1177 | |||
1178 | iscsi_session_str_attr(targetname, ISCSI_PARAM_TARGET_NAME); | ||
1093 | 1179 | ||
1094 | #define SETUP_CONN_RD_ATTR(field, param) \ | 1180 | /* |
1095 | if (priv->param_mask & (1 << param)) { \ | 1181 | * Private session and conn attrs. userspace uses several iscsi values |
1096 | priv->conn_attrs[count] = &class_device_attr_##field; \ | 1182 | * to identify each session between reboots. Some of these values may not |
1183 | * be present in the iscsi_transport/LLD driver becuase userspace handles | ||
1184 | * login (and failback for login redirect) so for these type of drivers | ||
1185 | * the class manages the attrs and values for the iscsi_transport/LLD | ||
1186 | */ | ||
1187 | #define iscsi_priv_session_attr_show(field, format) \ | ||
1188 | static ssize_t \ | ||
1189 | show_priv_session_##field(struct class_device *cdev, char *buf) \ | ||
1190 | { \ | ||
1191 | struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \ | ||
1192 | return sprintf(buf, format"\n", session->field); \ | ||
1193 | } | ||
1194 | |||
1195 | #define iscsi_priv_session_attr(field, format) \ | ||
1196 | iscsi_priv_session_attr_show(field, format) \ | ||
1197 | static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \ | ||
1198 | NULL) | ||
1199 | iscsi_priv_session_attr(targetname, "%s"); | ||
1200 | iscsi_priv_session_attr(tpgt, "%d"); | ||
1201 | |||
1202 | #define iscsi_priv_conn_attr_show(field, format) \ | ||
1203 | static ssize_t \ | ||
1204 | show_priv_conn_##field(struct class_device *cdev, char *buf) \ | ||
1205 | { \ | ||
1206 | struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \ | ||
1207 | return sprintf(buf, format"\n", conn->field); \ | ||
1208 | } | ||
1209 | |||
1210 | #define iscsi_priv_conn_attr(field, format) \ | ||
1211 | iscsi_priv_conn_attr_show(field, format) \ | ||
1212 | static ISCSI_CLASS_ATTR(priv_conn, field, S_IRUGO, show_priv_conn_##field, \ | ||
1213 | NULL) | ||
1214 | iscsi_priv_conn_attr(persistent_address, "%s"); | ||
1215 | iscsi_priv_conn_attr(persistent_port, "%d"); | ||
1216 | |||
1217 | #define SETUP_PRIV_SESSION_RD_ATTR(field) \ | ||
1218 | do { \ | ||
1219 | priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \ | ||
1220 | count++; \ | ||
1221 | } while (0) | ||
1222 | |||
1223 | #define SETUP_SESSION_RD_ATTR(field, param_flag) \ | ||
1224 | do { \ | ||
1225 | if (tt->param_mask & param_flag) { \ | ||
1226 | priv->session_attrs[count] = &class_device_attr_sess_##field; \ | ||
1097 | count++; \ | 1227 | count++; \ |
1098 | } | 1228 | } \ |
1229 | } while (0) | ||
1230 | |||
1231 | #define SETUP_PRIV_CONN_RD_ATTR(field) \ | ||
1232 | do { \ | ||
1233 | priv->conn_attrs[count] = &class_device_attr_priv_conn_##field; \ | ||
1234 | count++; \ | ||
1235 | } while (0) | ||
1236 | |||
1237 | #define SETUP_CONN_RD_ATTR(field, param_flag) \ | ||
1238 | do { \ | ||
1239 | if (tt->param_mask & param_flag) { \ | ||
1240 | priv->conn_attrs[count] = &class_device_attr_conn_##field; \ | ||
1241 | count++; \ | ||
1242 | } \ | ||
1243 | } while (0) | ||
1099 | 1244 | ||
1100 | static int iscsi_session_match(struct attribute_container *cont, | 1245 | static int iscsi_session_match(struct attribute_container *cont, |
1101 | struct device *dev) | 1246 | struct device *dev) |
@@ -1173,31 +1318,30 @@ iscsi_register_transport(struct iscsi_transport *tt) | |||
1173 | if (err) | 1318 | if (err) |
1174 | goto unregister_cdev; | 1319 | goto unregister_cdev; |
1175 | 1320 | ||
1176 | /* setup parameters mask */ | ||
1177 | priv->param_mask = 0xFFFFFFFF; | ||
1178 | if (!(tt->caps & CAP_MULTI_R2T)) | ||
1179 | priv->param_mask &= ~(1 << ISCSI_PARAM_MAX_R2T); | ||
1180 | if (!(tt->caps & CAP_HDRDGST)) | ||
1181 | priv->param_mask &= ~(1 << ISCSI_PARAM_HDRDGST_EN); | ||
1182 | if (!(tt->caps & CAP_DATADGST)) | ||
1183 | priv->param_mask &= ~(1 << ISCSI_PARAM_DATADGST_EN); | ||
1184 | if (!(tt->caps & CAP_MARKERS)) { | ||
1185 | priv->param_mask &= ~(1 << ISCSI_PARAM_IFMARKER_EN); | ||
1186 | priv->param_mask &= ~(1 << ISCSI_PARAM_OFMARKER_EN); | ||
1187 | } | ||
1188 | |||
1189 | /* connection parameters */ | 1321 | /* connection parameters */ |
1190 | priv->conn_cont.ac.attrs = &priv->conn_attrs[0]; | 1322 | priv->conn_cont.ac.attrs = &priv->conn_attrs[0]; |
1191 | priv->conn_cont.ac.class = &iscsi_connection_class.class; | 1323 | priv->conn_cont.ac.class = &iscsi_connection_class.class; |
1192 | priv->conn_cont.ac.match = iscsi_conn_match; | 1324 | priv->conn_cont.ac.match = iscsi_conn_match; |
1193 | transport_container_register(&priv->conn_cont); | 1325 | transport_container_register(&priv->conn_cont); |
1194 | 1326 | ||
1195 | SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH); | 1327 | SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_MAX_RECV_DLENGTH); |
1196 | SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH); | 1328 | SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_MAX_XMIT_DLENGTH); |
1197 | SETUP_CONN_RD_ATTR(header_digest, ISCSI_PARAM_HDRDGST_EN); | 1329 | SETUP_CONN_RD_ATTR(header_digest, ISCSI_HDRDGST_EN); |
1198 | SETUP_CONN_RD_ATTR(data_digest, ISCSI_PARAM_DATADGST_EN); | 1330 | SETUP_CONN_RD_ATTR(data_digest, ISCSI_DATADGST_EN); |
1199 | SETUP_CONN_RD_ATTR(ifmarker, ISCSI_PARAM_IFMARKER_EN); | 1331 | SETUP_CONN_RD_ATTR(ifmarker, ISCSI_IFMARKER_EN); |
1200 | SETUP_CONN_RD_ATTR(ofmarker, ISCSI_PARAM_OFMARKER_EN); | 1332 | SETUP_CONN_RD_ATTR(ofmarker, ISCSI_OFMARKER_EN); |
1333 | SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS); | ||
1334 | SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT); | ||
1335 | |||
1336 | if (tt->param_mask & ISCSI_PERSISTENT_ADDRESS) | ||
1337 | SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS); | ||
1338 | else | ||
1339 | SETUP_PRIV_CONN_RD_ATTR(persistent_address); | ||
1340 | |||
1341 | if (tt->param_mask & ISCSI_PERSISTENT_PORT) | ||
1342 | SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT); | ||
1343 | else | ||
1344 | SETUP_PRIV_CONN_RD_ATTR(persistent_port); | ||
1201 | 1345 | ||
1202 | BUG_ON(count > ISCSI_CONN_ATTRS); | 1346 | BUG_ON(count > ISCSI_CONN_ATTRS); |
1203 | priv->conn_attrs[count] = NULL; | 1347 | priv->conn_attrs[count] = NULL; |
@@ -1209,14 +1353,24 @@ iscsi_register_transport(struct iscsi_transport *tt) | |||
1209 | priv->session_cont.ac.match = iscsi_session_match; | 1353 | priv->session_cont.ac.match = iscsi_session_match; |
1210 | transport_container_register(&priv->session_cont); | 1354 | transport_container_register(&priv->session_cont); |
1211 | 1355 | ||
1212 | SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN); | 1356 | SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_INITIAL_R2T_EN); |
1213 | SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T); | 1357 | SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_MAX_R2T); |
1214 | SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_PARAM_IMM_DATA_EN); | 1358 | SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_IMM_DATA_EN); |
1215 | SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_PARAM_FIRST_BURST); | 1359 | SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_FIRST_BURST); |
1216 | SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_PARAM_MAX_BURST); | 1360 | SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_MAX_BURST); |
1217 | SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN); | 1361 | SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN); |
1218 | SETUP_SESSION_RD_ATTR(data_seq_in_order,ISCSI_PARAM_DATASEQ_INORDER_EN) | 1362 | SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN); |
1219 | SETUP_SESSION_RD_ATTR(erl, ISCSI_PARAM_ERL); | 1363 | SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL); |
1364 | |||
1365 | if (tt->param_mask & ISCSI_TARGET_NAME) | ||
1366 | SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME); | ||
1367 | else | ||
1368 | SETUP_PRIV_SESSION_RD_ATTR(targetname); | ||
1369 | |||
1370 | if (tt->param_mask & ISCSI_TPGT) | ||
1371 | SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT); | ||
1372 | else | ||
1373 | SETUP_PRIV_SESSION_RD_ATTR(tpgt); | ||
1220 | 1374 | ||
1221 | BUG_ON(count > ISCSI_SESSION_ATTRS); | 1375 | BUG_ON(count > ISCSI_SESSION_ATTRS); |
1222 | priv->session_attrs[count] = NULL; | 1376 | priv->session_attrs[count] = NULL; |
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 933a91b1474e..2c3a89b64e71 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h | |||
@@ -86,7 +86,7 @@ struct iscsi_uevent { | |||
86 | uint32_t sid; | 86 | uint32_t sid; |
87 | uint32_t cid; | 87 | uint32_t cid; |
88 | uint32_t param; /* enum iscsi_param */ | 88 | uint32_t param; /* enum iscsi_param */ |
89 | uint32_t value; | 89 | uint32_t len; |
90 | } set_param; | 90 | } set_param; |
91 | struct msg_start_conn { | 91 | struct msg_start_conn { |
92 | uint32_t sid; | 92 | uint32_t sid; |
@@ -155,22 +155,54 @@ enum iscsi_err { | |||
155 | * iSCSI Parameters (RFC3720) | 155 | * iSCSI Parameters (RFC3720) |
156 | */ | 156 | */ |
157 | enum iscsi_param { | 157 | enum iscsi_param { |
158 | ISCSI_PARAM_MAX_RECV_DLENGTH = 0, | 158 | /* passed in using netlink set param */ |
159 | ISCSI_PARAM_MAX_XMIT_DLENGTH = 1, | 159 | ISCSI_PARAM_MAX_RECV_DLENGTH, |
160 | ISCSI_PARAM_HDRDGST_EN = 2, | 160 | ISCSI_PARAM_MAX_XMIT_DLENGTH, |
161 | ISCSI_PARAM_DATADGST_EN = 3, | 161 | ISCSI_PARAM_HDRDGST_EN, |
162 | ISCSI_PARAM_INITIAL_R2T_EN = 4, | 162 | ISCSI_PARAM_DATADGST_EN, |
163 | ISCSI_PARAM_MAX_R2T = 5, | 163 | ISCSI_PARAM_INITIAL_R2T_EN, |
164 | ISCSI_PARAM_IMM_DATA_EN = 6, | 164 | ISCSI_PARAM_MAX_R2T, |
165 | ISCSI_PARAM_FIRST_BURST = 7, | 165 | ISCSI_PARAM_IMM_DATA_EN, |
166 | ISCSI_PARAM_MAX_BURST = 8, | 166 | ISCSI_PARAM_FIRST_BURST, |
167 | ISCSI_PARAM_PDU_INORDER_EN = 9, | 167 | ISCSI_PARAM_MAX_BURST, |
168 | ISCSI_PARAM_DATASEQ_INORDER_EN = 10, | 168 | ISCSI_PARAM_PDU_INORDER_EN, |
169 | ISCSI_PARAM_ERL = 11, | 169 | ISCSI_PARAM_DATASEQ_INORDER_EN, |
170 | ISCSI_PARAM_IFMARKER_EN = 12, | 170 | ISCSI_PARAM_ERL, |
171 | ISCSI_PARAM_OFMARKER_EN = 13, | 171 | ISCSI_PARAM_IFMARKER_EN, |
172 | ISCSI_PARAM_OFMARKER_EN, | ||
173 | ISCSI_PARAM_TARGET_NAME, | ||
174 | ISCSI_PARAM_TPGT, | ||
175 | ISCSI_PARAM_PERSISTENT_ADDRESS, | ||
176 | ISCSI_PARAM_PERSISTENT_PORT, | ||
177 | |||
178 | /* pased in through bind conn using transport_fd */ | ||
179 | ISCSI_PARAM_CONN_PORT, | ||
180 | ISCSI_PARAM_CONN_ADDRESS, | ||
181 | |||
182 | /* must always be last */ | ||
183 | ISCSI_PARAM_MAX, | ||
172 | }; | 184 | }; |
173 | #define ISCSI_PARAM_MAX 14 | 185 | |
186 | #define ISCSI_MAX_RECV_DLENGTH (1 << ISCSI_PARAM_MAX_RECV_DLENGTH) | ||
187 | #define ISCSI_MAX_XMIT_DLENGTH (1 << ISCSI_PARAM_MAX_XMIT_DLENGTH) | ||
188 | #define ISCSI_HDRDGST_EN (1 << ISCSI_PARAM_HDRDGST_EN) | ||
189 | #define ISCSI_DATADGST_EN (1 << ISCSI_PARAM_DATADGST_EN) | ||
190 | #define ISCSI_INITIAL_R2T_EN (1 << ISCSI_PARAM_INITIAL_R2T_EN) | ||
191 | #define ISCSI_MAX_R2T (1 << ISCSI_PARAM_MAX_R2T) | ||
192 | #define ISCSI_IMM_DATA_EN (1 << ISCSI_PARAM_IMM_DATA_EN) | ||
193 | #define ISCSI_FIRST_BURST (1 << ISCSI_PARAM_FIRST_BURST) | ||
194 | #define ISCSI_MAX_BURST (1 << ISCSI_PARAM_MAX_BURST) | ||
195 | #define ISCSI_PDU_INORDER_EN (1 << ISCSI_PARAM_PDU_INORDER_EN) | ||
196 | #define ISCSI_DATASEQ_INORDER_EN (1 << ISCSI_PARAM_DATASEQ_INORDER_EN) | ||
197 | #define ISCSI_ERL (1 << ISCSI_PARAM_ERL) | ||
198 | #define ISCSI_IFMARKER_EN (1 << ISCSI_PARAM_IFMARKER_EN) | ||
199 | #define ISCSI_OFMARKER_EN (1 << ISCSI_PARAM_OFMARKER_EN) | ||
200 | #define ISCSI_TARGET_NAME (1 << ISCSI_PARAM_TARGET_NAME) | ||
201 | #define ISCSI_TPGT (1 << ISCSI_PARAM_TPGT) | ||
202 | #define ISCSI_PERSISTENT_ADDRESS (1 << ISCSI_PARAM_PERSISTENT_ADDRESS) | ||
203 | #define ISCSI_PERSISTENT_PORT (1 << ISCSI_PARAM_PERSISTENT_PORT) | ||
204 | #define ISCSI_CONN_PORT (1 << ISCSI_PARAM_CONN_PORT) | ||
205 | #define ISCSI_CONN_ADDRESS (1 << ISCSI_PARAM_CONN_ADDRESS) | ||
174 | 206 | ||
175 | #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle) | 207 | #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle) |
176 | #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr) | 208 | #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr) |
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 631463cd4892..4b200645c84b 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h | |||
@@ -53,11 +53,11 @@ struct iscsi_transport { | |||
53 | struct module *owner; | 53 | struct module *owner; |
54 | char *name; | 54 | char *name; |
55 | unsigned int caps; | 55 | unsigned int caps; |
56 | /* LLD sets this to indicate what values it can export to sysfs */ | ||
57 | unsigned int param_mask; | ||
56 | struct scsi_host_template *host_template; | 58 | struct scsi_host_template *host_template; |
57 | /* LLD session/scsi_host data size */ | 59 | /* LLD session/scsi_host data size */ |
58 | int hostdata_size; | 60 | int hostdata_size; |
59 | /* LLD iscsi_host data size */ | ||
60 | int ihostdata_size; | ||
61 | /* LLD connection data size */ | 61 | /* LLD connection data size */ |
62 | int conndata_size; | 62 | int conndata_size; |
63 | /* LLD session data size */ | 63 | /* LLD session data size */ |
@@ -79,10 +79,13 @@ struct iscsi_transport { | |||
79 | int (*set_param) (struct iscsi_cls_conn *conn, enum iscsi_param param, | 79 | int (*set_param) (struct iscsi_cls_conn *conn, enum iscsi_param param, |
80 | uint32_t value); | 80 | uint32_t value); |
81 | int (*get_conn_param) (struct iscsi_cls_conn *conn, | 81 | int (*get_conn_param) (struct iscsi_cls_conn *conn, |
82 | enum iscsi_param param, | 82 | enum iscsi_param param, uint32_t *value); |
83 | uint32_t *value); | ||
84 | int (*get_session_param) (struct iscsi_cls_session *session, | 83 | int (*get_session_param) (struct iscsi_cls_session *session, |
85 | enum iscsi_param param, uint32_t *value); | 84 | enum iscsi_param param, uint32_t *value); |
85 | int (*get_conn_str_param) (struct iscsi_cls_conn *conn, | ||
86 | enum iscsi_param param, char *buf); | ||
87 | int (*get_session_str_param) (struct iscsi_cls_session *session, | ||
88 | enum iscsi_param param, char *buf); | ||
86 | int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, | 89 | int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, |
87 | char *data, uint32_t data_size); | 90 | char *data, uint32_t data_size); |
88 | void (*get_stats) (struct iscsi_cls_conn *conn, | 91 | void (*get_stats) (struct iscsi_cls_conn *conn, |
@@ -107,6 +110,14 @@ struct iscsi_cls_conn { | |||
107 | void *dd_data; /* LLD private data */ | 110 | void *dd_data; /* LLD private data */ |
108 | struct iscsi_transport *transport; | 111 | struct iscsi_transport *transport; |
109 | uint32_t cid; /* connection id */ | 112 | uint32_t cid; /* connection id */ |
113 | |||
114 | /* portal/group values we got during discovery */ | ||
115 | char *persistent_address; | ||
116 | int persistent_port; | ||
117 | /* portal/group values we are currently using */ | ||
118 | char *address; | ||
119 | int port; | ||
120 | |||
110 | int active; /* must be accessed with the connlock */ | 121 | int active; /* must be accessed with the connlock */ |
111 | struct device dev; /* sysfs transport/container device */ | 122 | struct device dev; /* sysfs transport/container device */ |
112 | struct mempool_zone *z_error; | 123 | struct mempool_zone *z_error; |
@@ -120,6 +131,11 @@ struct iscsi_cls_conn { | |||
120 | struct iscsi_cls_session { | 131 | struct iscsi_cls_session { |
121 | struct list_head sess_list; /* item in session_list */ | 132 | struct list_head sess_list; /* item in session_list */ |
122 | struct iscsi_transport *transport; | 133 | struct iscsi_transport *transport; |
134 | |||
135 | /* iSCSI values used as unique id by userspace. */ | ||
136 | char *targetname; | ||
137 | int tpgt; | ||
138 | |||
123 | int sid; /* session id */ | 139 | int sid; /* session id */ |
124 | void *dd_data; /* LLD private data */ | 140 | void *dd_data; /* LLD private data */ |
125 | struct device dev; /* sysfs transport/container device */ | 141 | struct device dev; /* sysfs transport/container device */ |