aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_iscsi.c
diff options
context:
space:
mode:
authorNilesh Javali <nilesh.javali@qlogic.com>2012-02-27 06:08:51 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-29 17:55:59 -0500
commit6260a5d221225f4e6befd98c6001325a3007a8c4 (patch)
tree710ae4cf58f56124fba9b6781b87745ec1dba9fa /drivers/scsi/scsi_transport_iscsi.c
parent8270ee2abb78c73b73e04f2909b0de15540c9017 (diff)
[SCSI] iscsi_transport: Add support to display CHAP list and delete CHAP entry
For offload iSCSI like qla4xxx CHAP entries are stored in FLASH. This patch adds support to list CHAP entries stored in FLASH and delete specified CHAP entry from FLASH using iscsi tools. Signed-off-by: Nilesh Javali <nilesh.javali@qlogic.com> Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/scsi_transport_iscsi.c')
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c101
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
730static int iscsi_is_session_dev(const struct device *dev) 730int 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}
734EXPORT_SYMBOL_GPL(iscsi_is_session_dev);
734 735
735static int iscsi_iter_session_fn(struct device *dev, void *data) 736static 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
2004static int 2005static int
2006iscsi_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
2069exit_get_chap:
2070 scsi_host_put(shost);
2071 return err;
2072}
2073
2074static 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
2095static int
2005iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) 2096iscsi_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);