diff options
Diffstat (limited to 'drivers/scsi/scsi_transport_iscsi.c')
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 101 |
1 files changed, 100 insertions, 1 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index a20f1813cb51..7bf0dec46271 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -727,10 +727,11 @@ static void iscsi_session_release(struct device *dev) | |||
727 | kfree(session); | 727 | kfree(session); |
728 | } | 728 | } |
729 | 729 | ||
730 | static int iscsi_is_session_dev(const struct device *dev) | 730 | int iscsi_is_session_dev(const struct device *dev) |
731 | { | 731 | { |
732 | return dev->release == iscsi_session_release; | 732 | return dev->release == iscsi_session_release; |
733 | } | 733 | } |
734 | EXPORT_SYMBOL_GPL(iscsi_is_session_dev); | ||
734 | 735 | ||
735 | static int iscsi_iter_session_fn(struct device *dev, void *data) | 736 | static int iscsi_iter_session_fn(struct device *dev, void *data) |
736 | { | 737 | { |
@@ -2002,6 +2003,96 @@ iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev) | |||
2002 | } | 2003 | } |
2003 | 2004 | ||
2004 | static int | 2005 | static int |
2006 | iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh) | ||
2007 | { | ||
2008 | struct iscsi_uevent *ev = NLMSG_DATA(nlh); | ||
2009 | struct Scsi_Host *shost = NULL; | ||
2010 | struct iscsi_chap_rec *chap_rec; | ||
2011 | struct iscsi_internal *priv; | ||
2012 | struct sk_buff *skbchap; | ||
2013 | struct nlmsghdr *nlhchap; | ||
2014 | struct iscsi_uevent *evchap; | ||
2015 | uint32_t chap_buf_size; | ||
2016 | int len, err = 0; | ||
2017 | char *buf; | ||
2018 | |||
2019 | if (!transport->get_chap) | ||
2020 | return -EINVAL; | ||
2021 | |||
2022 | priv = iscsi_if_transport_lookup(transport); | ||
2023 | if (!priv) | ||
2024 | return -EINVAL; | ||
2025 | |||
2026 | chap_buf_size = (ev->u.get_chap.num_entries * sizeof(*chap_rec)); | ||
2027 | len = NLMSG_SPACE(sizeof(*ev) + chap_buf_size); | ||
2028 | |||
2029 | shost = scsi_host_lookup(ev->u.get_chap.host_no); | ||
2030 | if (!shost) { | ||
2031 | printk(KERN_ERR "%s: failed. Cound not find host no %u\n", | ||
2032 | __func__, ev->u.get_chap.host_no); | ||
2033 | return -ENODEV; | ||
2034 | } | ||
2035 | |||
2036 | do { | ||
2037 | int actual_size; | ||
2038 | |||
2039 | skbchap = alloc_skb(len, GFP_KERNEL); | ||
2040 | if (!skbchap) { | ||
2041 | printk(KERN_ERR "can not deliver chap: OOM\n"); | ||
2042 | err = -ENOMEM; | ||
2043 | goto exit_get_chap; | ||
2044 | } | ||
2045 | |||
2046 | nlhchap = __nlmsg_put(skbchap, 0, 0, 0, | ||
2047 | (len - sizeof(*nlhchap)), 0); | ||
2048 | evchap = NLMSG_DATA(nlhchap); | ||
2049 | memset(evchap, 0, sizeof(*evchap)); | ||
2050 | evchap->transport_handle = iscsi_handle(transport); | ||
2051 | evchap->type = nlh->nlmsg_type; | ||
2052 | evchap->u.get_chap.host_no = ev->u.get_chap.host_no; | ||
2053 | evchap->u.get_chap.chap_tbl_idx = ev->u.get_chap.chap_tbl_idx; | ||
2054 | evchap->u.get_chap.num_entries = ev->u.get_chap.num_entries; | ||
2055 | buf = (char *) ((char *)evchap + sizeof(*evchap)); | ||
2056 | memset(buf, 0, chap_buf_size); | ||
2057 | |||
2058 | err = transport->get_chap(shost, ev->u.get_chap.chap_tbl_idx, | ||
2059 | &evchap->u.get_chap.num_entries, buf); | ||
2060 | |||
2061 | actual_size = NLMSG_SPACE(sizeof(*ev) + chap_buf_size); | ||
2062 | skb_trim(skbchap, NLMSG_ALIGN(actual_size)); | ||
2063 | nlhchap->nlmsg_len = actual_size; | ||
2064 | |||
2065 | err = iscsi_multicast_skb(skbchap, ISCSI_NL_GRP_ISCSID, | ||
2066 | GFP_KERNEL); | ||
2067 | } while (err < 0 && err != -ECONNREFUSED); | ||
2068 | |||
2069 | exit_get_chap: | ||
2070 | scsi_host_put(shost); | ||
2071 | return err; | ||
2072 | } | ||
2073 | |||
2074 | static int iscsi_delete_chap(struct iscsi_transport *transport, | ||
2075 | struct iscsi_uevent *ev) | ||
2076 | { | ||
2077 | struct Scsi_Host *shost; | ||
2078 | int err = 0; | ||
2079 | |||
2080 | if (!transport->delete_chap) | ||
2081 | return -ENOSYS; | ||
2082 | |||
2083 | shost = scsi_host_lookup(ev->u.delete_chap.host_no); | ||
2084 | if (!shost) { | ||
2085 | printk(KERN_ERR "%s could not find host no %u\n", | ||
2086 | __func__, ev->u.delete_chap.host_no); | ||
2087 | return -ENODEV; | ||
2088 | } | ||
2089 | |||
2090 | err = transport->delete_chap(shost, ev->u.delete_chap.chap_tbl_idx); | ||
2091 | scsi_host_put(shost); | ||
2092 | return err; | ||
2093 | } | ||
2094 | |||
2095 | static int | ||
2005 | iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) | 2096 | iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) |
2006 | { | 2097 | { |
2007 | int err = 0; | 2098 | int err = 0; |
@@ -2149,6 +2240,12 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) | |||
2149 | case ISCSI_UEVENT_PING: | 2240 | case ISCSI_UEVENT_PING: |
2150 | err = iscsi_send_ping(transport, ev); | 2241 | err = iscsi_send_ping(transport, ev); |
2151 | break; | 2242 | break; |
2243 | case ISCSI_UEVENT_GET_CHAP: | ||
2244 | err = iscsi_get_chap(transport, nlh); | ||
2245 | break; | ||
2246 | case ISCSI_UEVENT_DELETE_CHAP: | ||
2247 | err = iscsi_delete_chap(transport, ev); | ||
2248 | break; | ||
2152 | default: | 2249 | default: |
2153 | err = -ENOSYS; | 2250 | err = -ENOSYS; |
2154 | break; | 2251 | break; |
@@ -2198,6 +2295,8 @@ iscsi_if_rx(struct sk_buff *skb) | |||
2198 | */ | 2295 | */ |
2199 | if (ev->type == ISCSI_UEVENT_GET_STATS && !err) | 2296 | if (ev->type == ISCSI_UEVENT_GET_STATS && !err) |
2200 | break; | 2297 | break; |
2298 | if (ev->type == ISCSI_UEVENT_GET_CHAP && !err) | ||
2299 | break; | ||
2201 | err = iscsi_if_send_reply(group, nlh->nlmsg_seq, | 2300 | err = iscsi_if_send_reply(group, nlh->nlmsg_seq, |
2202 | nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); | 2301 | nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); |
2203 | } while (err < 0 && err != -ECONNREFUSED && err != -ESRCH); | 2302 | } while (err < 0 && err != -ECONNREFUSED && err != -ESRCH); |