summaryrefslogtreecommitdiff
path: root/usr/src/uts/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common')
-rw-r--r--usr/src/uts/common/Makefile.files3
-rw-r--r--usr/src/uts/common/Makefile.rules7
-rw-r--r--usr/src/uts/common/fs/sockfs/socksubr.c15
-rw-r--r--usr/src/uts/common/fs/vfs.c34
-rw-r--r--usr/src/uts/common/inet/kifconf/kifconf.c238
-rw-r--r--usr/src/uts/common/io/scsi/adapters/iscsi/iscsi.c172
-rw-r--r--usr/src/uts/common/io/scsi/adapters/iscsi/iscsi.h12
-rw-r--r--usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_conn.c46
-rw-r--r--usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_ioctl.c32
-rw-r--r--usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_lun.c48
-rw-r--r--usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_net.c250
-rw-r--r--usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_sess.c237
-rw-r--r--usr/src/uts/common/io/scsi/adapters/iscsi/iscsid.c867
-rw-r--r--usr/src/uts/common/io/scsi/adapters/iscsi/nvfile.c19
-rw-r--r--usr/src/uts/common/io/strplumb.c45
-rw-r--r--usr/src/uts/common/os/iscsiboot_prop.c269
-rw-r--r--usr/src/uts/common/os/main.c10
-rw-r--r--usr/src/uts/common/os/space.c10
-rw-r--r--usr/src/uts/common/sys/bootprops.h84
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/iscsi_if.h23
20 files changed, 2178 insertions, 243 deletions
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index 1d28772d6d..ca6ce67df3 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -47,6 +47,7 @@ COMMON_CORE_OBJS += \
disp.o \
group.o \
kstat_fr.o \
+ iscsiboot_prop.o \
lgrp.o \
lgrp_topo.o \
mutex.o \
@@ -1797,7 +1798,7 @@ ISCSI_INITIATOR_OBJS = chap.o iscsi_io.o iscsi_thread.o \
iscsi_queue.o persistent.o iscsi_conn.o \
iscsi_sess.o radius_auth.o iscsi_crc.o \
iscsi_stats.o radius_packet.o iscsi_doorclt.o \
- iscsi_targetparam.o utils.o
+ iscsi_targetparam.o utils.o kifconf.o
#
# ntxn 10Gb/1Gb NIC driver module
diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules
index d1678f46cb..0035b502b9 100644
--- a/usr/src/uts/common/Makefile.rules
+++ b/usr/src/uts/common/Makefile.rules
@@ -1109,6 +1109,10 @@ $(OBJS_DIR)/%.o: $(COMMONBASE)/iscsi/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
+$(OBJS_DIR)/%.o: $(UTSBASE)/common/inet/kifconf/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
#
# krtld must refer to its own bzero/bcopy until the kernel is fully linked
#
@@ -2118,6 +2122,9 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/scsi/adapters/iscsi/%.c
$(LINTS_DIR)/%.ln: $(COMMONBASE)/iscsi/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
+$(LINTS_DIR)/%.ln: $(UTSBASE)/common/inet/kifconf/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
ZMODLINTFLAGS = -erroff=E_CONSTANT_CONDITION
$(LINTS_DIR)/%.ln: $(UTSBASE)/common/zmod/%.c
diff --git a/usr/src/uts/common/fs/sockfs/socksubr.c b/usr/src/uts/common/fs/sockfs/socksubr.c
index d8b69aef5e..33a6841f16 100644
--- a/usr/src/uts/common/fs/sockfs/socksubr.c
+++ b/usr/src/uts/common/fs/sockfs/socksubr.c
@@ -92,7 +92,7 @@ static struct kmem_cache *socktpi_cache, *socktpi_unix_cache;
struct kmem_cache *socktpi_sod_cache;
dev_t sockdev; /* For fsid in getattr */
-
+int sockfs_defer_nl7c_init = 0;
struct sockparams *sphead;
krwlock_t splist_lock;
@@ -107,6 +107,8 @@ extern void nl7c_init(void);
extern int sostr_init();
+extern int modrootloaded;
+
#define ADRSTRLEN (2 * sizeof (void *) + 1)
/*
* kernel structure for passing the sockinfo data back up to the user.
@@ -195,6 +197,11 @@ soconfig(int domain, int type, int protocol,
dprint(0, ("soconfig(%d,%d,%d,%s,%d)\n",
domain, type, protocol, devpath, devpathlen));
+ if (sockfs_defer_nl7c_init) {
+ nl7c_init();
+ sockfs_defer_nl7c_init = 0;
+ }
+
/*
* Look for an existing match.
*/
@@ -769,7 +776,11 @@ sockinit(int fstype, char *name)
mutex_init(&socklist.sl_lock, NULL, MUTEX_DEFAULT, NULL);
sendfile_init();
- nl7c_init();
+ if (!modrootloaded) {
+ sockfs_defer_nl7c_init = 1;
+ } else {
+ nl7c_init();
+ }
return (0);
diff --git a/usr/src/uts/common/fs/vfs.c b/usr/src/uts/common/fs/vfs.c
index 30e9cf7430..bf9d325048 100644
--- a/usr/src/uts/common/fs/vfs.c
+++ b/usr/src/uts/common/fs/vfs.c
@@ -36,7 +36,6 @@
* contributors.
*/
-
#include <sys/types.h>
#include <sys/t_lock.h>
#include <sys/param.h>
@@ -84,11 +83,11 @@
#include <sys/attr.h>
#include <sys/spa.h>
#include <sys/lofi.h>
+#include <sys/bootprops.h>
#include <vm/page.h>
#include <fs/fs_subr.h>
-
/* Private interfaces to create vopstats-related data structures */
extern void initialize_vopstats(vopstats_t *);
extern vopstats_t *get_fstype_vopstats(struct vfs *, struct vfssw *);
@@ -4489,6 +4488,9 @@ vfs_root_redev(vfs_t *vfsp, dev_t ndev, int fstype)
extern int hvmboot_rootconf();
#endif /* __x86 */
+extern ib_boot_prop_t *iscsiboot_prop;
+extern void iscsi_boot_prop_free();
+
int
rootconf()
{
@@ -4496,6 +4498,7 @@ rootconf()
struct vfssw *vsw;
extern void pm_init();
char *fstyp, *fsmod;
+ int ret = -1;
getrootfs(&fstyp, &fsmod);
@@ -4533,8 +4536,31 @@ rootconf()
pm_init();
- if (netboot)
- (void) strplumb();
+ if (netboot && iscsiboot_prop) {
+ cmn_err(CE_WARN, "NFS boot and iSCSI boot"
+ " shouldn't happen in the same time");
+ return (EINVAL);
+ }
+
+ if (netboot || iscsiboot_prop)
+ ret = strplumb();
+
+ if ((ret == 0) && iscsiboot_prop) {
+ ret = modload("drv", "iscsi");
+ /* -1 indicates fail */
+ if (ret == -1) {
+ cmn_err(CE_WARN, "Failed to load iscsi module");
+ iscsi_boot_prop_free();
+ return (EINVAL);
+ } else {
+ if (!i_ddi_attach_pseudo_node("iscsi")) {
+ cmn_err(CE_WARN,
+ "Failed to attach iscsi driver");
+ iscsi_boot_prop_free();
+ return (ENODEV);
+ }
+ }
+ }
error = VFS_MOUNTROOT(rootvfs, ROOT_INIT);
vfs_unrefvfssw(vsw);
diff --git a/usr/src/uts/common/inet/kifconf/kifconf.c b/usr/src/uts/common/inet/kifconf/kifconf.c
new file mode 100644
index 0000000000..90c0ebdcd5
--- /dev/null
+++ b/usr/src/uts/common/inet/kifconf/kifconf.c
@@ -0,0 +1,238 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/t_kuser.h>
+#include <sys/netconfig.h>
+#include <netinet/in.h>
+#include <net/route.h>
+#include <net/if.h>
+#include <sys/kstr.h>
+#include <rpc/clnt.h>
+#include <sys/stropts.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/bootprops.h>
+
+static int
+kivoid_to_sock(int af, void *source, void *dest)
+{
+ struct sockaddr_in *sin = NULL;
+ struct sockaddr_in6 *sin6 = NULL;
+
+ if (source == NULL || dest == NULL) {
+ return (-1);
+ }
+ if (af == AF_INET) {
+ sin = (struct sockaddr_in *)dest;
+ (void) bcopy(source, &sin->sin_addr,
+ sizeof (struct in_addr));
+ sin->sin_family = af;
+ } else if (af == AF_INET6) {
+ sin6 = (struct sockaddr_in6 *)dest;
+ (void) bcopy(source, &sin6->sin6_addr,
+ sizeof (struct in6_addr));
+ sin6->sin6_family = af;
+ } else {
+ return (-1);
+ }
+ return (0);
+}
+
+int
+kdlifconfig(TIUSER *tiptr, int af, void *myIPaddr, void *mymask,
+ struct in_addr *mybraddr, struct in_addr *gateway, char *ifname)
+{
+ int rc;
+ struct netbuf sbuf;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ struct rtentry route;
+ struct sockaddr_in *rt_sin;
+
+ if (myIPaddr == NULL || mymask == NULL) {
+ return (-1);
+ }
+
+ if (af == AF_INET) {
+ rc = kivoid_to_sock(af, mymask, &sin);
+ if (rc != 0) {
+ return (rc);
+ }
+ sbuf.buf = (caddr_t)&sin;
+ sbuf.maxlen = sbuf.len = sizeof (sin);
+ } else {
+ rc = kivoid_to_sock(af, mymask, &sin6);
+ if (rc != 0) {
+ return (rc);
+ }
+ sbuf.buf = (caddr_t)&sin6;
+ sbuf.maxlen = sbuf.len = sizeof (sin6);
+ }
+ if (rc = kifioctl(tiptr, SIOCSLIFNETMASK, &sbuf, ifname)) {
+ return (rc);
+ }
+
+ if (af == AF_INET) {
+ rc = kivoid_to_sock(af, myIPaddr, &sin);
+ if (rc != 0) {
+ return (rc);
+ }
+ sbuf.buf = (caddr_t)&sin;
+ sbuf.maxlen = sbuf.len = sizeof (sin);
+ } else {
+ rc = kivoid_to_sock(af, myIPaddr, &sin6);
+ if (rc != 0) {
+ return (rc);
+ }
+ sbuf.buf = (caddr_t)&sin6;
+ sbuf.maxlen = sbuf.len = sizeof (sin6);
+ }
+
+ if (rc = kifioctl(tiptr, SIOCSLIFADDR, &sbuf, ifname)) {
+ return (rc);
+ }
+ /*
+ * Only IPv4 has brocadcast address.
+ */
+ if (af == AF_INET && mybraddr != NULL) {
+ if (mybraddr->s_addr != INADDR_BROADCAST) {
+ rc = kivoid_to_sock(af, mybraddr, &sin);
+ if (rc != 0) {
+ return (rc);
+ }
+ sbuf.buf = (caddr_t)&sin;
+ sbuf.maxlen = sbuf.len = sizeof (sin);
+ if (rc = kifioctl(tiptr, SIOCSLIFBRDADDR, &sbuf,
+ ifname)) {
+ return (rc);
+ }
+ }
+ }
+
+ /*
+ * Now turn on the interface.
+ */
+ if (rc = ksetifflags(tiptr, IFF_UP, ifname)) {
+ return (rc);
+ }
+
+ /*
+ * Set the default gateway.
+ */
+ if (af == AF_INET && gateway != NULL) {
+ (void) memset(&route, 0, sizeof (route));
+ rt_sin = (struct sockaddr_in *)&route.rt_dst;
+ rt_sin->sin_family = AF_INET;
+
+ rt_sin = (struct sockaddr_in *)&route.rt_gateway;
+ rt_sin->sin_addr.s_addr = gateway->s_addr;
+ route.rt_flags = RTF_GATEWAY | RTF_UP;
+ sbuf.buf = (caddr_t)&route;
+ sbuf.maxlen = sbuf.len = sizeof (route);
+ if (rc = kifioctl(tiptr, SIOCADDRT, &sbuf, ifname)) {
+ return (rc);
+ }
+ }
+ return (0);
+}
+
+int
+kifioctl(TIUSER *tiptr, int cmd, struct netbuf *nbuf, char *ifname)
+{
+ struct strioctl iocb;
+ struct lifreq lifr;
+ vnode_t *vp = NULL;
+ char *buf = NULL;
+ int rc = 0;
+
+ (void) memset(&lifr, 0, sizeof (lifr));
+ /*
+ * Now do the one requested.
+ */
+ if (nbuf->len) {
+ if (nbuf->len == sizeof (struct rtentry)) {
+ if (cmd != SIOCADDRT) {
+ return (-1);
+ }
+ /*
+ * Set up gateway parameters.
+ */
+ iocb.ic_len = nbuf->len;
+ iocb.ic_dp = nbuf->buf;
+ } else {
+ if (nbuf->len != sizeof (struct sockaddr_in) &&
+ nbuf->len != sizeof (struct sockaddr_in6)) {
+ return (-1);
+ }
+ buf = (char *)&lifr.lifr_addr;
+ bcopy(nbuf->buf, buf, nbuf->len);
+ iocb.ic_len = sizeof (lifr);
+ iocb.ic_dp = (caddr_t)&lifr;
+ }
+ } else {
+ iocb.ic_len = sizeof (lifr);
+ iocb.ic_dp = (caddr_t)&lifr;
+ }
+ (void) strncpy((caddr_t)&lifr.lifr_name, ifname,
+ sizeof (lifr.lifr_name));
+ iocb.ic_cmd = cmd;
+ iocb.ic_timout = 0;
+
+ vp = tiptr->fp->f_vnode;
+ rc = kstr_ioctl(vp, I_STR, (intptr_t)&iocb);
+ if (rc) {
+ return (rc);
+ }
+
+ return (0);
+}
+
+int
+ksetifflags(TIUSER *tiptr, uint_t value, char *ifname)
+{
+ int rc;
+ struct strioctl iocb;
+ struct lifreq lifr;
+
+ if (ifname == NULL) {
+ return (-1);
+ }
+
+ (void) memset(&lifr, 0, sizeof (lifr));
+
+ (void) strncpy((caddr_t)&lifr.lifr_name, ifname,
+ sizeof (lifr.lifr_name));
+ iocb.ic_cmd = SIOCGLIFFLAGS;
+ iocb.ic_timout = 0;
+ iocb.ic_len = sizeof (lifr);
+ iocb.ic_dp = (caddr_t)&lifr;
+ if (rc = kstr_ioctl(tiptr->fp->f_vnode, I_STR, (intptr_t)&iocb))
+ return (rc);
+
+ lifr.lifr_flags |= value;
+ iocb.ic_cmd = SIOCSLIFFLAGS;
+ return (kstr_ioctl(tiptr->fp->f_vnode, I_STR, (intptr_t)&iocb));
+}
diff --git a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi.c b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi.c
index 0bef2b1892..d638c24459 100644
--- a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi.c
+++ b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi.c
@@ -41,6 +41,7 @@
#include <sys/utsname.h>
#include "isns_client.h"
#include "isns_protocol.h"
+#include <sys/bootprops.h>
#define ISCSI_NAME_VERSION "iSCSI Initiator v-1.55"
@@ -60,6 +61,8 @@ int iscsi_nop_delay = ISCSI_DEFAULT_NOP_DELAY;
int iscsi_rx_window = ISCSI_DEFAULT_RX_WINDOW;
int iscsi_rx_max_window = ISCSI_DEFAULT_RX_MAX_WINDOW;
+extern ib_boot_prop_t *iscsiboot_prop;
+
/*
* +--------------------------------------------------------------------+
* | iscsi.c prototypes |
@@ -140,6 +143,7 @@ static int iscsi_i_commoncap(struct scsi_address *ap, char *cap,
int val, int lunonly, int doset);
static void iscsi_get_name_to_iqn(char *name, int name_max_len);
static void iscsi_get_name_from_iqn(char *name, int name_max_len);
+static boolean_t iscsi_cmp_boot_sess_oid(iscsi_hba_t *ihp, uint32_t oid);
/* struct helpers prototypes */
@@ -530,6 +534,7 @@ iscsi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
* initialize the discovery processes and
* persistent store.
*/
+ ihp->persistent_loaded = B_FALSE;
if (iscsid_init(ihp, B_FALSE) == B_FALSE) {
goto iscsi_attach_failed0;
}
@@ -1410,6 +1415,7 @@ iscsi_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
boolean_t rval;
char init_port_name[MAX_NAME_PROP_SIZE];
iscsi_sockaddr_t addr_dsc;
+ iscsi_boot_property_t *bootProp;
instance = getminor(dev);
ihp = (iscsi_hba_t *)ddi_get_soft_state(iscsi_state, instance);
@@ -1747,6 +1753,20 @@ iscsi_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
break;
}
rtn = iscsi_set_params(ils, ihp, B_TRUE);
+ if (iscsiboot_prop) {
+ if (iscsi_cmp_boot_sess_oid(ihp, ils->s_oid)) {
+ /*
+ * found active session for this object
+ * or this is initiator's object
+ * with mpxio enabled
+ */
+ if (!iscsi_reconfig_boot_sess(ihp)) {
+ rtn = EINVAL;
+ kmem_free(ils, sizeof (*ils));
+ break;
+ }
+ }
+ }
kmem_free(ils, sizeof (*ils));
break;
@@ -1874,7 +1894,14 @@ iscsi_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
hba_params),
&(isp->sess_params),
sizeof (isp->sess_params));
-
+ if (iscsiboot_prop &&
+ isp->sess_boot) {
+ /*
+ * reconfig boot
+ * session later
+ */
+ continue;
+ }
/*
* Notify the session that the
* login parameters have
@@ -1892,6 +1919,19 @@ iscsi_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
kmem_free(ics, sizeof (*ics));
kmem_free(name, ISCSI_MAX_NAME_LEN);
rw_exit(&ihp->hba_sess_list_rwlock);
+ if (iscsiboot_prop) {
+ if (iscsi_cmp_boot_sess_oid(ihp, e.e_oid)) {
+ /*
+ * found active session for this object
+ * or this is initiator object
+ * with mpxio enabled
+ */
+ if (!iscsi_reconfig_boot_sess(ihp)) {
+ rtn = EINVAL;
+ break;
+ }
+ }
+ }
}
break;
@@ -3936,9 +3976,109 @@ iscsi_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
} else {
/* set */
rtn = iscsi_ioctl_set_config_sess(ihp, ics);
+ if (iscsiboot_prop) {
+ if (iscsi_cmp_boot_sess_oid(ihp,
+ ics->ics_oid)) {
+ /*
+ * found active session for this object
+ * or this is initiator object
+ * with mpxio enabled
+ */
+ if (!iscsi_reconfig_boot_sess(ihp)) {
+ rtn = EINVAL;
+ break;
+ }
+ }
+ }
}
break;
+ case ISCSI_IS_ACTIVE:
+ /*
+ * dhcpagent calls here to check if there are
+ * active iSCSI sessions
+ */
+ instance = 0;
+ if (iscsiboot_prop) {
+ instance = 1;
+ }
+ if (!instance) {
+ rw_enter(&ihp->hba_sess_list_rwlock,
+ RW_READER);
+ for (isp = ihp->hba_sess_list; isp;
+ isp = isp->sess_next) {
+ if ((isp->sess_state ==
+ ISCSI_SESS_STATE_LOGGED_IN) &&
+ (isp->sess_lun_list !=
+ NULL)) {
+ instance = 1;
+ break;
+ }
+ }
+ rw_exit(&ihp->hba_sess_list_rwlock);
+ }
+ size = sizeof (instance);
+ if (ddi_copyout(&instance, (caddr_t)arg, size,
+ mode) != 0) {
+ rtn = EFAULT;
+ }
+ break;
+
+ case ISCSI_BOOTPROP_GET:
+ size = sizeof (*bootProp);
+ bootProp = iscsi_ioctl_copyin((caddr_t)arg, mode, size);
+ if (bootProp == NULL) {
+ rtn = EFAULT;
+ break;
+ }
+ bootProp->hba_mpxio_enabled =
+ iscsi_chk_bootlun_mpxio(ihp);
+ if (iscsiboot_prop == NULL) {
+ bootProp->iscsiboot = 0;
+ rtn = iscsi_ioctl_copyout(bootProp, size,
+ (caddr_t)arg, mode);
+ break;
+ } else {
+ bootProp->iscsiboot = 1;
+ }
+
+ if (iscsiboot_prop->boot_init.ini_name != NULL) {
+ (void) strncpy((char *)bootProp->ini_name.n_name,
+ (char *)iscsiboot_prop->boot_init.ini_name,
+ ISCSI_MAX_NAME_LEN);
+ }
+ if (iscsiboot_prop->boot_init.ini_chap_name != NULL) {
+ bootProp->auth.a_auth_method = authMethodCHAP;
+ (void) strncpy((char *)bootProp->ini_chap.c_user,
+ (char *)iscsiboot_prop->boot_init.ini_chap_name,
+ ISCSI_MAX_NAME_LEN);
+ (void) strncpy((char *)bootProp->ini_chap.c_secret,
+ (char *)iscsiboot_prop->boot_init.ini_chap_sec,
+ ISCSI_CHAP_SECRET_LEN);
+ if (iscsiboot_prop->boot_tgt.tgt_chap_name !=
+ NULL) {
+ bootProp->auth.a_bi_auth = B_TRUE;
+ } else {
+ bootProp->auth.a_bi_auth = B_FALSE;
+ }
+ }
+ if (iscsiboot_prop->boot_tgt.tgt_name != NULL) {
+ (void) strncpy((char *)bootProp->tgt_name.n_name,
+ (char *)iscsiboot_prop->boot_tgt.tgt_name,
+ ISCSI_MAX_NAME_LEN);
+ }
+ if (iscsiboot_prop->boot_tgt.tgt_chap_name != NULL) {
+ (void) strncpy((char *)bootProp->tgt_chap.c_user,
+ (char *)iscsiboot_prop->boot_tgt.tgt_chap_name,
+ ISCSI_MAX_NAME_LEN);
+ (void) strncpy((char *)bootProp->tgt_chap.c_secret,
+ (char *)iscsiboot_prop->boot_tgt.tgt_chap_sec,
+ ISCSI_CHAP_SECRET_LEN);
+ }
+
+ rtn = iscsi_ioctl_copyout(bootProp, size, (caddr_t)arg, mode);
+ break;
+
default:
rtn = ENOTTY;
cmn_err(CE_NOTE, "unrecognized ioctl 0x%x", cmd);
@@ -4726,3 +4866,33 @@ iscsi_override_target_default(iscsi_hba_t *ihp, iscsi_param_get_t *ipg)
}
kmem_free(pp, sizeof (*pp));
}
+
+static boolean_t
+iscsi_cmp_boot_sess_oid(iscsi_hba_t *ihp, uint32_t oid)
+{
+ iscsi_sess_t *isp = NULL;
+
+ if (iscsi_chk_bootlun_mpxio(ihp)) {
+ for (isp = ihp->hba_sess_list; isp; isp = isp->sess_next) {
+ if ((isp->sess_oid == oid) && isp->sess_boot) {
+ /* oid is session object */
+ break;
+ }
+ if ((isp->sess_target_oid == oid) && isp->sess_boot) {
+ /*
+ * oid is target object while
+ * this session is boot session
+ */
+ break;
+ }
+ }
+ if (oid == ihp->hba_oid) {
+ /* oid is initiator object id */
+ return (B_TRUE);
+ } else if ((isp != NULL) && (isp->sess_boot)) {
+ /* oid is boot session object id */
+ return (B_TRUE);
+ }
+ }
+ return (B_FALSE);
+}
diff --git a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi.h b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi.h
index 5c7ef0719f..6258ff9d5b 100644
--- a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi.h
+++ b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi.h
@@ -228,6 +228,12 @@ extern int iscsi_rx_window;
extern int iscsi_rx_max_window;
/*
+ * During iscsi boot, if the boot session has been created, the
+ * initiator hasn't changed the boot lun to be online, we will wait
+ * 180s here for lun online by default.
+ */
+#define ISCSI_BOOT_DEFAULT_MAX_DELAY 180 /* seconds */
+/*
* +--------------------------------------------------------------------+
* | iSCSI Driver Structures |
* +--------------------------------------------------------------------+
@@ -812,6 +818,7 @@ typedef struct iscsi_sess {
iscsi_thread_t *sess_ic_thread;
boolean_t sess_window_open;
+ boolean_t sess_boot;
iscsi_sess_type_t sess_type;
boolean_t sess_enum_in_progress;
@@ -914,6 +921,7 @@ typedef struct iscsi_hba {
boolean_t hba_discovery_in_progress;
boolean_t hba_mpxio_enabled; /* mpxio-enabled */
+ boolean_t persistent_loaded; /* persistent_loaded */
/*
* Ensures only one SendTargets operation occurs at a time
@@ -1084,6 +1092,10 @@ boolean_t iscsid_login_tgt(iscsi_hba_t *ihp, char *target_name,
iSCSIDiscoveryMethod_t method, struct sockaddr *addr_dsc);
void iscsid_addr_to_sockaddr(int src_insize, void *src_addr, int src_port,
struct sockaddr *dst_addr);
+boolean_t iscsi_reconfig_boot_sess(iscsi_hba_t *ihp);
+boolean_t iscsi_chk_bootlun_mpxio(iscsi_hba_t *ihp);
+boolean_t iscsi_cmp_boot_ini_name(char *name);
+boolean_t iscsi_cmp_boot_tgt_name(char *name);
extern void bcopy(const void *s1, void *s2, size_t n);
extern void bzero(void *s, size_t n);
diff --git a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_conn.c b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_conn.c
index 5e26452da5..c1d8a3f6c2 100644
--- a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_conn.c
+++ b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_conn.c
@@ -27,6 +27,9 @@
#include "iscsi.h"
#include "persistent.h"
+#include <sys/bootprops.h>
+
+extern ib_boot_prop_t *iscsiboot_prop;
/* interface connection interfaces */
static iscsi_status_t iscsi_conn_state_free(iscsi_conn_t *icp,
@@ -51,6 +54,7 @@ static void iscsi_conn_retry(iscsi_sess_t *isp,
#define SHUTDOWN_TIMEOUT 180 /* seconds */
+extern int modrootloaded;
/*
* +--------------------------------------------------------------------+
* | External Connection Interfaces |
@@ -543,9 +547,22 @@ iscsi_conn_sync_params(iscsi_conn_t *icp)
(void) persistent_param_get((char *)isp->sess_name, &pp);
for (param_id = 0; param_id < ISCSI_NUM_LOGIN_PARAM;
param_id++) {
+ if (iscsiboot_prop && modrootloaded &&
+ !iscsi_chk_bootlun_mpxio(ihp) && isp->sess_boot) {
+ /*
+ * iscsi boot with mpxio disabled
+ * while iscsi booting target's parameter overriden
+ * do no update target's parameters.
+ */
+ if (pp.p_bitmap) {
+ cmn_err(CE_NOTE, "Adopting "
+ " default login parameters in"
+ " boot session as MPxIO is disabled");
+ }
+ break;
+ }
if (pp.p_bitmap & (1 << param_id)) {
-
- switch (param_id) {
+ switch (param_id) {
/*
* Boolean parameters
*/
@@ -644,13 +661,38 @@ iscsi_conn_sync_params(iscsi_conn_t *icp)
}
}
+ if (iscsiboot_prop && (ics->ics_out > 1) && isp->sess_boot &&
+ !iscsi_chk_bootlun_mpxio(ihp)) {
+ /*
+ * iscsi booting session with mpxio disabled,
+ * no need set multiple sessions for booting session
+ */
+ ics->ics_out = 1;
+ ics->ics_bound = B_FALSE;
+ cmn_err(CE_NOTE, "MPxIO is disabled,"
+ " no need to configure multiple boot sessions");
+ }
+
/*
* Check to make sure this session is still a configured
* session. The user might have decreased the session
* count. (NOTE: byte 5 of the sess_isid is the session
* count (via MS/T). This counter starts at 0.)
*/
+
+
idx = isp->sess_isid[5];
+
+ if (iscsiboot_prop && (idx == ISCSI_MAX_CONFIG_SESSIONS)) {
+ /*
+ * This is temporary session for boot session propose
+ * no need to bound IP for this session
+ */
+ icp->conn_bound = B_FALSE;
+ kmem_free(ics, sizeof (iscsi_config_sess_t));
+ return (ISCSI_STATUS_SUCCESS);
+ }
+
if (ics->ics_out <= idx) {
/*
* No longer a configured session. Return a
diff --git a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_ioctl.c b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_ioctl.c
index 7ef9c9f0f8..e5967dab8c 100644
--- a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_ioctl.c
+++ b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_ioctl.c
@@ -37,6 +37,9 @@
#include "iscsi_targetparam.h"
#include <sys/strsubr.h>
#include <sys/socketvar.h>
+#include <sys/bootprops.h>
+
+extern ib_boot_prop_t *iscsiboot_prop;
static iscsi_status_t iscsi_create_sendtgts_list(iscsi_conn_t *icp,
char *data, int data_len, iscsi_sendtgts_list_t *stl);
@@ -869,14 +872,26 @@ iscsi_set_params(iscsi_param_set_t *ils, iscsi_hba_t *ihp, boolean_t persist)
}
/*
- * We may have multiple sessions with different
- * tpgt values. So we need to loop through
+ * Here may have multiple sessions with different
+ * tpgt values. So it is needed to loop through
* the sessions and update all sessions.
*/
if (rtn == 0) {
rw_enter(&ihp->hba_sess_list_rwlock, RW_READER);
for (isp = ihp->hba_sess_list; isp;
isp = isp->sess_next) {
+ if (iscsiboot_prop &&
+ isp->sess_boot &&
+ iscsi_chk_bootlun_mpxio(ihp)) {
+ /*
+ * MPxIO is enabled so capable
+ * of changing. All changes
+ * will be applied later,
+ * after this function
+ */
+ continue;
+ }
+
if (strncmp((char *)isp->sess_name,
(char *)name,
ISCSI_MAX_NAME_LEN) == 0) {
@@ -917,16 +932,25 @@ mutex_exit(&isp->sess_state_mutex);
rw_enter(&ihp->hba_sess_list_rwlock, RW_READER);
for (isp = ihp->hba_sess_list; isp;
isp = isp->sess_next) {
-
ilg->g_param = ils->s_param;
params = &isp->sess_params;
if (iscsi_get_persisted_param(
isp->sess_name, ilg, params) != 0) {
-
rtn = iscsi_set_param(params, ils);
if (rtn != 0) {
break;
}
+ if (iscsiboot_prop &&
+ isp->sess_boot &&
+ iscsi_chk_bootlun_mpxio(ihp)) {
+ /*
+ * MPxIO is enabled so capable
+ * of changing. Changes will
+ * be applied later, right
+ * after this function
+ */
+ continue;
+ }
/*
* Notify the session that
diff --git a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_lun.c b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_lun.c
index 6a89c238c4..a757790ef0 100644
--- a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_lun.c
+++ b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_lun.c
@@ -27,6 +27,7 @@
#include "iscsi.h"
#include <sys/fs/dv_node.h> /* devfs_clean */
+#include <sys/bootprops.h>
/* tpgt bytes in string form */
#define TPGT_EXT_SIZE 5
@@ -47,6 +48,7 @@ static iscsi_status_t iscsi_lun_phys_create(iscsi_sess_t *isp,
uint16_t lun_num, iscsi_lun_t *ilp, struct scsi_inquiry *inq);
extern dev_info_t *scsi_vhci_dip;
+extern ib_boot_prop_t *iscsiboot_prop;
/*
* +--------------------------------------------------------------------+
@@ -69,6 +71,8 @@ iscsi_lun_create(iscsi_sess_t *isp, uint16_t lun_num, uint8_t lun_addr_type,
iscsi_lun_t *ilp = NULL;
iscsi_lun_t *ilp_tmp = NULL;
char *addr = NULL;
+ uint16_t boot_lun_num = 0;
+ uint64_t *lun_num_ptr = NULL;
ASSERT(isp != NULL);
ihp = isp->sess_hba;
@@ -81,7 +85,7 @@ iscsi_lun_create(iscsi_sess_t *isp, uint16_t lun_num, uint8_t lun_addr_type,
ADDR_EXT_SIZE + 1),
"%02X%02X%s%04X,%d", isp->sess_isid[4],
isp->sess_isid[5], isp->sess_name,
- isp->sess_tpgt_conf & 0xFFFF, lun_num);
+ isp->sess_tpgt_nego & 0xFFFF, lun_num);
/* allocate space for lun struct */
ilp = kmem_zalloc(sizeof (iscsi_lun_t), KM_SLEEP);
@@ -168,13 +172,27 @@ iscsi_lun_create(iscsi_sess_t *isp, uint16_t lun_num, uint8_t lun_addr_type,
} else {
ilp->lun_state = ISCSI_LUN_STATE_ONLINE;
ilp->lun_time_online = ddi_get_time();
+
+ /* Check whether this is the required LUN for iscsi boot */
+ if (iscsiboot_prop != NULL && isp->sess_boot == B_TRUE &&
+ iscsiboot_prop->boot_tgt.lun_online == 0) {
+ lun_num_ptr =
+ (uint64_t *)iscsiboot_prop->boot_tgt.tgt_boot_lun;
+ boot_lun_num = (uint16_t)(*lun_num_ptr);
+ if (boot_lun_num == ilp->lun_num) {
+ /*
+ * During iscsi boot, the boot lun has been
+ * online, we should set the "online flag".
+ */
+ iscsiboot_prop->boot_tgt.lun_online = 1;
+ }
+ }
}
rw_exit(&isp->sess_lun_list_rwlock);
return (rtn);
}
-
/*
* iscsi_lun_destroy - offline and remove lun
*
@@ -490,13 +508,15 @@ phys_create_done:
void
iscsi_lun_online(iscsi_hba_t *ihp, iscsi_lun_t *ilp)
{
- int circ = 0;
- int rval;
+ int circ = 0;
+ int rval = 0;
+ uint64_t *lun_num_ptr = NULL;
+ uint16_t boot_lun_num = 0;
+ iscsi_sess_t *isp = NULL;
ASSERT(ilp != NULL);
ASSERT((ilp->lun_pip != NULL) || (ilp->lun_dip != NULL));
-
if (ilp->lun_pip != NULL) {
ndi_devi_enter(scsi_vhci_dip, &circ);
rval = mdi_pi_online(ilp->lun_pip, 0);
@@ -515,6 +535,24 @@ iscsi_lun_online(iscsi_hba_t *ihp, iscsi_lun_t *ilp)
ilp->lun_time_online = ddi_get_time();
}
}
+
+ /* Check whether this is the required LUN for iscsi boot */
+ if (iscsiboot_prop != NULL &&
+ iscsiboot_prop->boot_tgt.lun_online == 0) {
+ isp = ilp->lun_sess;
+ if (isp->sess_boot == B_TRUE) {
+ lun_num_ptr =
+ (uint64_t *)iscsiboot_prop->boot_tgt.tgt_boot_lun;
+ boot_lun_num = (uint16_t)(*lun_num_ptr);
+ if (boot_lun_num == ilp->lun_num) {
+ /*
+ * During iscsi boot, the boot lun has been
+ * online, we should set the "online flag".
+ */
+ iscsiboot_prop->boot_tgt.lun_online = 1;
+ }
+ }
+ }
}
/*
diff --git a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_net.c b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_net.c
index d02c8efc1a..23e64684a1 100644
--- a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_net.c
+++ b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_net.c
@@ -32,7 +32,9 @@
#include <sys/pathname.h> /* declares: lookupname */
#include <sys/fs/snode.h> /* defines: VTOS */
#include <sys/fs/dv_node.h> /* declares: devfs_lookupname */
-#include <netinet/in.h>
+#include <sys/bootconf.h>
+#include <sys/bootprops.h>
+
#include "iscsi.h"
/*
@@ -142,8 +144,27 @@ const int is_incoming_opcode_invalid[256] = {
/* 0xEX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 0xFX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
+/*
+ * Define macros to manipulate snode, vnode, and open device flags
+ */
+#define VTYP_VALID(i) (((i) == VCHR) || ((i) == VBLK))
+#define STYP_VALID(i) (((i) == S_IFCHR) || ((i) == S_IFBLK))
+#define STYP_TO_VTYP(i) (((i) == S_IFCHR) ? VCHR : VBLK)
+
+#define IP_4_BITS 32
+#define IP_6_BITS 128
+
+extern int modrootloaded;
+extern ib_boot_prop_t *iscsiboot_prop;
/* prototypes */
+
+/* for iSCSI boot */
+static int net_up = 0;
+static iscsi_status_t iscsi_net_interface();
+static int iscsi_ldi_vp_from_name(char *path, vnode_t **vpp);
+/* boot prototypes end */
+
static void * iscsi_net_socket(int domain, int type, int protocol);
static int iscsi_net_bind(void *socket, struct sockaddr *
name, int name_len, int backlog, int flags);
@@ -282,6 +303,11 @@ iscsi_net_socket(int domain, int type, int protocol)
int err = 0;
major_t maj;
+ if (!modrootloaded && !net_up && iscsiboot_prop) {
+ if (iscsi_net_interface() == ISCSI_STATUS_SUCCESS)
+ net_up = 1;
+ }
+
/* ---- solookup: start ---- */
if ((vp = solookup(domain, type, protocol, NULL, &err)) == NULL) {
@@ -291,10 +317,16 @@ iscsi_net_socket(int domain, int type, int protocol)
* to use USERSPACE and declared static we'll do the
* work here instead.
*/
- err = lookupname(type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp",
- UIO_SYSSPACE, FOLLOW, NULLVPP, &vp);
- if (err)
+ if (!modrootloaded) {
+ err = iscsi_ldi_vp_from_name("/devices/pseudo/tcp@0:"
+ "tcp", &vp);
+ } else {
+ err = lookupname(type == SOCK_STREAM ? "/dev/tcp" :
+ "/dev/udp", UIO_SYSSPACE, FOLLOW, NULLVPP, &vp);
+ }
+ if (err) {
return (NULL);
+ }
/* ---- check that it is the correct vnode ---- */
if (vp->v_type != VCHR) {
@@ -905,3 +937,213 @@ iscsi_net_recvdata(void *socket, iscsi_hdr_t *ihp, char *data,
}
return (ISCSI_STATUS_SUCCESS);
}
+
+/*
+ * Convert a prefix length to a mask.
+ */
+static iscsi_status_t
+iscsi_prefixlentomask(int prefixlen, int maxlen, uchar_t *mask)
+{
+ if (prefixlen < 0 || prefixlen > maxlen || mask == NULL) {
+ return (ISCSI_STATUS_INTERNAL_ERROR);
+ }
+
+ while (prefixlen > 0) {
+ if (prefixlen >= 8) {
+ *mask = 0xff;
+ mask++;
+ prefixlen = prefixlen - 8;
+ continue;
+ }
+ *mask = *mask | (1 << (8 - prefixlen));
+ prefixlen--;
+ }
+ return (ISCSI_STATUS_SUCCESS);
+}
+
+static iscsi_status_t
+iscsi_net_interface()
+{
+ struct in_addr braddr;
+ struct in_addr subnet;
+ struct in_addr myaddr;
+ struct in_addr defgateway;
+ struct in6_addr myaddr6;
+ struct in6_addr subnet6;
+ uchar_t mask_prefix = 0;
+ int mask_bits = 1;
+ TIUSER *tiptr;
+ TIUSER *tiptr6;
+ char ifname[16] = {0};
+ iscsi_status_t status;
+
+ struct knetconfig dl_udp_netconf = {
+ NC_TPI_CLTS,
+ NC_INET,
+ NC_UDP,
+ 0, };
+ struct knetconfig dl_udp6_netconf = {
+ NC_TPI_CLTS,
+ NC_INET6,
+ NC_UDP,
+ 0, };
+
+ (void) strlcpy(ifname, rootfs.bo_ifname, sizeof (ifname));
+
+ if (iscsiboot_prop->boot_nic.sin_family == AF_INET) {
+ /*
+ * Assumes only one linkage array element.
+ */
+ dl_udp_netconf.knc_rdev =
+ makedevice(clone_major, ddi_name_to_major("udp"));
+
+ myaddr.s_addr =
+ iscsiboot_prop->boot_nic.nic_ip_u.u_in4.s_addr;
+
+ mask_prefix = iscsiboot_prop->boot_nic.sub_mask_prefix;
+ (void) memset(&subnet.s_addr, 0, sizeof (subnet));
+ status = iscsi_prefixlentomask(mask_prefix, IP_4_BITS,
+ (uchar_t *)&subnet.s_addr);
+ if (status != ISCSI_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ mask_bits = mask_bits << (IP_4_BITS - mask_prefix);
+ mask_bits = mask_bits - 1;
+ /*
+ * Set the last mask bits of the ip address with 1, then
+ * we can get the broadcast address.
+ */
+ braddr.s_addr = myaddr.s_addr | mask_bits;
+
+ defgateway.s_addr =
+ iscsiboot_prop->boot_nic.nic_gw_u.u_in4.s_addr;
+
+ /* initialize interface */
+ if (t_kopen((file_t *)NULL, dl_udp_netconf.knc_rdev,
+ FREAD|FWRITE, &tiptr, CRED()) == 0) {
+ if (kdlifconfig(tiptr, AF_INET, &myaddr, &subnet,
+ &braddr, &defgateway, ifname)) {
+ cmn_err(CE_WARN, "Failed to configure"
+ " iSCSI boot nic");
+ (void) t_kclose(tiptr, 0);
+ return (ISCSI_STATUS_INTERNAL_ERROR);
+ }
+ } else {
+ cmn_err(CE_WARN, "Failed to configure"
+ " iSCSI boot nic");
+ return (ISCSI_STATUS_INTERNAL_ERROR);
+ }
+ return (ISCSI_STATUS_SUCCESS);
+ } else {
+ dl_udp6_netconf.knc_rdev =
+ makedevice(clone_major, ddi_name_to_major("udp6"));
+
+ bcopy(&iscsiboot_prop->boot_nic.nic_ip_u.u_in6.s6_addr,
+ &myaddr6.s6_addr, 16);
+
+ (void) memset(&subnet6, 0, sizeof (subnet6));
+ mask_prefix = iscsiboot_prop->boot_nic.sub_mask_prefix;
+ status = iscsi_prefixlentomask(mask_prefix, IP_6_BITS,
+ (uchar_t *)&subnet6.s6_addr);
+ if (status != ISCSI_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ if (t_kopen((file_t *)NULL, dl_udp6_netconf.knc_rdev,
+ FREAD|FWRITE, &tiptr6, CRED()) == 0) {
+ if (kdlifconfig(tiptr6, AF_INET6, &myaddr6,
+ &subnet6, NULL, NULL, ifname)) {
+ cmn_err(CE_WARN, "Failed to configure"
+ " iSCSI boot nic");
+ (void) t_kclose(tiptr, 0);
+ return (ISCSI_STATUS_INTERNAL_ERROR);
+ }
+ } else {
+ cmn_err(CE_WARN, "Failed to configure"
+ " iSCSI boot nic");
+ return (ISCSI_STATUS_INTERNAL_ERROR);
+ }
+ return (ISCSI_STATUS_SUCCESS);
+ }
+}
+
+/*
+ * vp is needed to create the socket for the time being.
+ */
+static int
+iscsi_ldi_vp_from_name(char *path, vnode_t **vpp)
+{
+ vnode_t *vp = NULL;
+ int ret;
+
+ /* sanity check required input parameters */
+ if ((path == NULL) || (vpp == NULL))
+ return (EINVAL);
+
+ if (modrootloaded) {
+ cred_t *saved_cred = curthread->t_cred;
+
+ /* we don't want lookupname to fail because of credentials */
+ curthread->t_cred = kcred;
+
+ /*
+ * all lookups should be done in the global zone. but
+ * lookupnameat() won't actually do this if an absolute
+ * path is passed in. since the ldi interfaces require an
+ * absolute path we pass lookupnameat() a pointer to
+ * the character after the leading '/' and tell it to
+ * start searching at the current system root directory.
+ */
+ ASSERT(*path == '/');
+ ret = lookupnameat(path + 1, UIO_SYSSPACE, FOLLOW, NULLVPP,
+ &vp, rootdir);
+
+ /* restore this threads credentials */
+ curthread->t_cred = saved_cred;
+
+ if (ret == 0) {
+ if (!vn_matchops(vp, spec_getvnodeops()) ||
+ !VTYP_VALID(vp->v_type)) {
+ VN_RELE(vp);
+ return (ENXIO);
+ }
+ }
+ }
+
+ if (vp == NULL) {
+ dev_info_t *dip;
+ dev_t dev;
+ int spec_type;
+
+ /*
+ * Root is not mounted, the minor node is not specified,
+ * or an OBP path has been specified.
+ */
+
+ /*
+ * Determine if path can be pruned to produce an
+ * OBP or devfs path for resolve_pathname.
+ */
+ if (strncmp(path, "/devices/", 9) == 0)
+ path += strlen("/devices");
+
+ /*
+ * if no minor node was specified the DEFAULT minor node
+ * will be returned. if there is no DEFAULT minor node
+ * one will be fabricated of type S_IFCHR with the minor
+ * number equal to the instance number.
+ */
+ ret = resolve_pathname(path, &dip, &dev, &spec_type);
+ if (ret != 0)
+ return (ENODEV);
+
+ ASSERT(STYP_VALID(spec_type));
+ vp = makespecvp(dev, STYP_TO_VTYP(spec_type));
+ spec_assoc_vp_with_devi(vp, dip);
+ ddi_release_devi(dip);
+ }
+
+ *vpp = vp;
+ return (0);
+}
diff --git a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_sess.c b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_sess.c
index c69239272f..a1b2dcd92f 100644
--- a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_sess.c
+++ b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_sess.c
@@ -25,6 +25,7 @@
* iSCSI session interfaces
*/
+#include <sys/bootprops.h>
#include "iscsi.h"
#include "persistent.h"
#include "iscsi_targetparam.h"
@@ -140,7 +141,16 @@ iscsi_sess_create(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method,
(uchar_t *)target_name);
}
+ if (method & iSCSIDiscoveryMethodBoot) {
+ /* This is boot session. */
+ isp->sess_boot = B_TRUE;
+ } else {
+ isp->sess_boot = B_FALSE;
+ }
+
/* Associate session with this discovery method */
+ method = method & ~(iSCSIDiscoveryMethodBoot);
+
isp->sess_discovered_by = method;
if (addr_dsc == NULL) {
bzero(&isp->sess_discovered_addr,
@@ -530,6 +540,7 @@ iscsi_sess_destroy(iscsi_sess_t *isp)
return (rval);
}
+extern ib_boot_prop_t *iscsiboot_prop;
/*
* static iscsi_sess_set_auth -
*
@@ -540,6 +551,7 @@ iscsi_sess_set_auth(iscsi_sess_t *isp)
char *init_name;
iscsi_chap_props_t *chap = NULL;
iscsi_auth_props_t *auth = NULL;
+ uchar_t *tmp = NULL;
if (isp == (iscsi_sess_t *)NULL) {
return (B_FALSE);
@@ -549,100 +561,175 @@ iscsi_sess_set_auth(iscsi_sess_t *isp)
if (isp->sess_hba == (iscsi_hba_t *)NULL) {
return (B_FALSE);
}
+
init_name = (char *)isp->sess_hba->hba_name;
- auth = (iscsi_auth_props_t *)kmem_zalloc
- (sizeof (iscsi_auth_props_t), KM_SLEEP);
- /* Obtain target's authentication settings. */
- if (persistent_auth_get((char *)isp->sess_name, auth) != B_TRUE) {
- /*
- * If no target authentication settings found, try to obtain
- * system wide configuration (from the initiator).
- */
- bzero(auth, sizeof (*auth));
- if (persistent_auth_get(init_name, auth) != B_TRUE) {
+ /* Zero out the session authentication structure */
+ bzero(&isp->sess_auth, sizeof (iscsi_auth_t));
+
+ if (isp->sess_boot == B_FALSE) {
+
+ auth = (iscsi_auth_props_t *)kmem_zalloc
+ (sizeof (iscsi_auth_props_t), KM_SLEEP);
+ /* Obtain target's authentication settings. */
+ if (persistent_auth_get((char *)isp->sess_name, auth)
+ != B_TRUE) {
+ /*
+ * If no target authentication settings found,
+ * try to obtain system wide configuration
+ * (from the initiator).
+ */
bzero(auth, sizeof (*auth));
- auth->a_auth_method = authMethodNone;
- }
+ if (persistent_auth_get(init_name, auth) != B_TRUE) {
+ bzero(auth, sizeof (*auth));
+ auth->a_auth_method = authMethodNone;
+ }
- /* We do not support system wide bi-directional auth flag. */
- auth->a_bi_auth = B_FALSE;
- }
+ /*
+ * We do not support system wide bi-directional
+ * auth flag.
+ */
+ auth->a_bi_auth = B_FALSE;
+ }
- /* Zero out the session authentication structure */
- bzero(&isp->sess_auth, sizeof (iscsi_auth_t));
+ chap = (iscsi_chap_props_t *)kmem_zalloc
+ (sizeof (iscsi_chap_props_t), KM_SLEEP);
- chap = (iscsi_chap_props_t *)kmem_zalloc
- (sizeof (iscsi_chap_props_t), KM_SLEEP);
+ /*
+ * Initialize the target-side chap name to the session name
+ * if no chap settings have been saved for the current session.
+ */
+ if (persistent_chap_get((char *)isp->sess_name, chap)
+ == B_FALSE) {
+ int name_len = strlen((char *)isp->sess_name);
+ bcopy((char *)isp->sess_name, chap->c_user, name_len);
+ chap->c_user_len = name_len;
+ (void) (persistent_chap_set((char *)isp->sess_name,
+ chap));
+ bzero(chap, sizeof (*chap));
+ }
- /*
- * Initialize the target-side chap name to the session name if no chap
- * settings have been saved for the current session.
- */
- if (persistent_chap_get((char *)isp->sess_name, chap) == B_FALSE) {
- int name_len = strlen((char *)isp->sess_name);
- bcopy((char *)isp->sess_name, chap->c_user, name_len);
- chap->c_user_len = name_len;
- (void) (persistent_chap_set((char *)isp->sess_name, chap));
- bzero(chap, sizeof (*chap));
- }
+ if (auth->a_auth_method & authMethodCHAP) {
+ /* Obtain initiator's CHAP settings. */
+ if (persistent_chap_get(init_name, chap) == B_FALSE) {
+ /* No initiator secret defined. */
+ kmem_free(chap, sizeof (iscsi_chap_props_t));
+ /* Set authentication method to NONE */
+ isp->sess_auth.password_length = 0;
+ kmem_free(auth, sizeof (iscsi_auth_props_t));
+ return (B_FALSE);
+ }
- if (auth->a_auth_method & authMethodCHAP) {
- /* Obtain initiator's CHAP settings. */
- if (persistent_chap_get(init_name, chap) == B_FALSE) {
- /* No initiator secret defined. */
- kmem_free(chap, sizeof (iscsi_chap_props_t));
+ bcopy(chap->c_user, isp->sess_auth.username,
+ sizeof (chap->c_user));
+ bcopy(chap->c_secret, isp->sess_auth.password,
+ sizeof (chap->c_secret));
+ isp->sess_auth.password_length = chap->c_secret_len;
+ } else {
/* Set authentication method to NONE */
isp->sess_auth.password_length = 0;
+ }
+
+ /*
+ * Consider enabling bidirectional authentication only if
+ * authentication method is not NONE.
+ */
+ if (auth->a_auth_method & authMethodCHAP &&
+ auth->a_bi_auth == B_TRUE) {
+ /* Enable bi-directional authentication. */
+ isp->sess_auth.bidirectional_auth = 1;
+
+ bzero(chap, sizeof (*chap));
+ /* Obtain target's CHAP settings. */
+ if (persistent_chap_get((char *)isp->sess_name, chap)
+ == B_TRUE) {
+ bcopy(chap->c_secret,
+ isp->sess_auth.password_in,
+ sizeof (chap->c_secret));
+ bcopy(chap->c_user, isp->sess_auth.username_in,
+ strlen((char *)chap->c_user));
+ isp->sess_auth.password_length_in =
+ chap->c_secret_len;
+ } else {
+ /*
+ * No target secret defined.
+ * RADIUS server should have been enabled.
+ */
+ /* EMPTY */
+ }
+ } else {
+ /* Disable bi-directional authentication */
+ isp->sess_auth.bidirectional_auth = 0;
+ }
+
+ if (auth != NULL) {
kmem_free(auth, sizeof (iscsi_auth_props_t));
+ }
+ if (chap != NULL) {
+ kmem_free(chap, sizeof (iscsi_chap_props_t));
+ }
+ } else {
+ /*
+ * This session is boot session. We will use the CHAP and
+ * the user name got from the boot property structure instead
+ * of persistent sotre.
+ */
+ if (iscsiboot_prop == NULL) {
return (B_FALSE);
}
- bcopy(chap->c_user, isp->sess_auth.username,
- sizeof (chap->c_user));
- bcopy(chap->c_secret, isp->sess_auth.password,
- sizeof (chap->c_secret));
- isp->sess_auth.password_length = chap->c_secret_len;
- } else {
- /* Set authentication method to NONE */
- isp->sess_auth.password_length = 0;
- }
+ if (iscsiboot_prop->boot_init.ini_chap_sec == NULL) {
+ return (B_FALSE);
+ }
- /*
- * Consider enabling bidirectional authentication only if
- * authentication method is not NONE.
- */
- if (auth->a_auth_method & authMethodCHAP &&
- auth->a_bi_auth == B_TRUE) {
- /* Enable bi-directional authentication. */
- isp->sess_auth.bidirectional_auth = 1;
-
- bzero(chap, sizeof (*chap));
- /* Obtain target's CHAP settings. */
- if (persistent_chap_get((char *)isp->sess_name, chap) ==
- B_TRUE) {
- bcopy(chap->c_secret, isp->sess_auth.password_in,
- sizeof (chap->c_secret));
- bcopy(chap->c_user, isp->sess_auth.username_in,
- strlen((char *)chap->c_user));
- isp->sess_auth.password_length_in = chap->c_secret_len;
+ /* CHAP secret */
+ (void) bcopy(iscsiboot_prop->boot_init.ini_chap_sec,
+ isp->sess_auth.password,
+ strlen((char *)iscsiboot_prop->boot_init.ini_chap_sec));
+
+ /*
+ * If chap name is not set,
+ * we will use initiator name instead.
+ */
+ if (iscsiboot_prop->boot_init.ini_chap_name == NULL) {
+ (void) bcopy(init_name, isp->sess_auth.username,
+ strlen(init_name));
} else {
+ tmp = iscsiboot_prop->boot_init.ini_chap_name;
+ (void) bcopy(tmp,
+ isp->sess_auth.username, strlen((char *)tmp));
+ }
+
+ isp->sess_auth.password_length =
+ strlen((char *)iscsiboot_prop->boot_init.ini_chap_sec);
+
+ if (iscsiboot_prop->boot_tgt.tgt_chap_sec != NULL) {
/*
- * No target secret defined.
- * RADIUS server should have been enabled.
+ * Bidirectional authentication is required.
*/
- /* EMPTY */
- }
- } else {
- /* Disable bi-directional authentication */
- isp->sess_auth.bidirectional_auth = 0;
- }
+ tmp = iscsiboot_prop->boot_tgt.tgt_chap_sec;
+ (void) bcopy(tmp,
+ isp->sess_auth.password_in, strlen((char *)tmp));
- if (auth != NULL) {
- kmem_free(auth, sizeof (iscsi_auth_props_t));
- }
- if (chap != NULL) {
- kmem_free(chap, sizeof (iscsi_chap_props_t));
+ /*
+ * If the target's chap name is not set, we will use
+ * session name instead.
+ */
+ if (iscsiboot_prop->boot_tgt.tgt_chap_name == NULL) {
+ (void) bcopy(isp->sess_name,
+ isp->sess_auth.username_in,
+ isp->sess_name_length);
+ } else {
+ tmp = iscsiboot_prop->boot_tgt.tgt_chap_name;
+ (void) bcopy(tmp,
+ isp->sess_auth.username_in,
+ strlen((char *)tmp));
+ }
+ tmp = iscsiboot_prop->boot_tgt.tgt_chap_sec;
+ isp->sess_auth.password_length_in =
+ strlen((char *)tmp);
+ isp->sess_auth.bidirectional_auth = 1;
+ }
}
/* Set up authentication buffers only if configured */
diff --git a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsid.c b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsid.c
index dc89313b96..b7b0db9205 100644
--- a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsid.c
+++ b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsid.c
@@ -41,6 +41,7 @@
#include "persistent.h"
#include "iscsi.h"
#include <sys/ethernet.h>
+#include <sys/bootprops.h>
/*
* local function prototypes
@@ -51,6 +52,7 @@ static void iscsid_thread_static(iscsi_thread_t *thread, void *p);
static void iscsid_thread_sendtgts(iscsi_thread_t *thread, void *p);
static void iscsid_thread_isns(iscsi_thread_t *thread, void *p);
static void iscsid_thread_slp(iscsi_thread_t *thread, void *p);
+static void iscsid_thread_boot_wd(iscsi_thread_t *thread, void *p);
static void iscsid_threads_create(iscsi_hba_t *ihp);
static void iscsid_threads_destroy(void);
static int iscsid_copyto_param_set(uint32_t param_id,
@@ -62,11 +64,19 @@ static void iscsid_remove_target_param(char *name);
static boolean_t iscsid_add(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method,
struct sockaddr *addr_dsc, char *target_name, int tpgt,
struct sockaddr *addr_tgt);
-
static void iscsi_discovery_event(iscsi_hba_t *ihp,
iSCSIDiscoveryMethod_t m, boolean_t start);
static void iscsi_send_sysevent(iscsi_hba_t *ihp,
char *subclass, nvlist_t *np);
+static boolean_t iscsid_boot_init_config(iscsi_hba_t *ihp);
+static iscsi_sess_t *iscsi_add_boot_sess(iscsi_hba_t *ihp, int isid);
+static boolean_t iscsid_make_entry(ib_boot_prop_t *boot_prop_entry,
+ entry_t *entry);
+
+extern int modrootloaded;
+int iscsi_configroot_retry = 20;
+static boolean_t iscsi_configroot_printed = FALSE;
+extern ib_boot_prop_t *iscsiboot_prop;
/*
* iSCSI target discovery thread table
@@ -96,7 +106,6 @@ static iscsid_thr_table iscsid_thr[] = {
NULL }
};
-
/*
* discovery method event table
*/
@@ -109,13 +118,130 @@ iSCSIDiscoveryMethod_t for_failure[] = {
};
/*
+ * The following private tunable, set in /etc/system, e.g.,
+ * set iscsi:iscsi_boot_max_delay = 360
+ * , provides with customer a max wait time in
+ * seconds to wait for boot lun online during iscsi boot.
+ * Defaults to 180s.
+ */
+int iscsi_boot_max_delay = ISCSI_BOOT_DEFAULT_MAX_DELAY;
+
+/*
* discovery configuration semaphore
*/
ksema_t iscsid_config_semaphore;
+static iscsi_thread_t *iscsi_boot_wd_handle = NULL;
+
#define CHECK_METHOD(v) ((dm & v) ? B_TRUE : B_FALSE)
/*
+ * Check if IP is valid
+ */
+static boolean_t
+iscsid_ip_check(char *ip)
+{
+ int i = 0;
+
+ if (!ip)
+ return (B_FALSE);
+ for (; (ip[i] == 0) && (i < IB_IP_BUFLEN); i++) {}
+ if (i == IB_IP_BUFLEN) {
+ /* invalid IP address */
+ return (B_FALSE);
+ }
+ return (B_TRUE);
+}
+
+/*
+ * Make an entry for the boot target.
+ * return B_TRUE upon success
+ * B_FALSE if fail
+ */
+static boolean_t
+iscsid_make_entry(ib_boot_prop_t *boot_prop_entry, entry_t *entry)
+{
+ if (entry == NULL || boot_prop_entry == NULL) {
+ return (B_FALSE);
+ }
+
+ if (!iscsid_ip_check(
+ (char *)&boot_prop_entry->boot_tgt.tgt_ip_u))
+ return (B_FALSE);
+
+ if (boot_prop_entry->boot_tgt.sin_family != AF_INET &&
+ boot_prop_entry->boot_tgt.sin_family != AF_INET6)
+ return (B_FALSE);
+
+ entry->e_vers = ISCSI_INTERFACE_VERSION;
+
+ mutex_enter(&iscsi_oid_mutex);
+ entry->e_oid = iscsi_oid++;
+ mutex_exit(&iscsi_oid_mutex);
+
+ entry->e_tpgt = ISCSI_DEFAULT_TPGT;
+
+ if (boot_prop_entry->boot_tgt.sin_family == AF_INET) {
+ entry->e_u.u_in4.s_addr =
+ boot_prop_entry->boot_tgt.tgt_ip_u.u_in4.s_addr;
+ entry->e_insize = sizeof (struct in_addr);
+ } else {
+ (void) bcopy(
+ &boot_prop_entry->boot_tgt.tgt_ip_u.u_in6.s6_addr,
+ entry->e_u.u_in6.s6_addr, 16);
+ entry->e_insize = sizeof (struct in6_addr);
+ }
+
+ entry->e_port = boot_prop_entry->boot_tgt.tgt_port;
+ entry->e_boot = B_TRUE;
+ return (B_TRUE);
+}
+
+/*
+ * Create the boot session
+ */
+static void
+iscsi_boot_session_create(iscsi_hba_t *ihp,
+ ib_boot_prop_t *boot_prop_table)
+{
+ iSCSIDiscoveryMethod_t dm;
+ entry_t e;
+ iscsi_sockaddr_t addr_dsc;
+
+ if (ihp == NULL || boot_prop_table == NULL) {
+ return;
+ }
+
+ if (!iscsid_ip_check(
+ (char *)&boot_prop_table->boot_tgt.tgt_ip_u)) {
+ return;
+ }
+
+ if (boot_prop_table->boot_tgt.tgt_name != NULL) {
+ dm = iSCSIDiscoveryMethodStatic |
+ iSCSIDiscoveryMethodBoot;
+ if (!iscsid_make_entry(boot_prop_table, &e))
+ return;
+ iscsid_addr_to_sockaddr(e.e_insize, &e.e_u,
+ e.e_port, &addr_dsc.sin);
+
+ (void) iscsid_add(ihp, dm, &addr_dsc.sin,
+ (char *)boot_prop_table->boot_tgt.tgt_name,
+ e.e_tpgt, &addr_dsc.sin);
+ } else {
+ dm = iSCSIDiscoveryMethodSendTargets |
+ iSCSIDiscoveryMethodBoot;
+ if (!iscsid_make_entry(boot_prop_table, &e))
+ return;
+ iscsid_addr_to_sockaddr(e.e_insize, &e.e_u,
+ e.e_port, &addr_dsc.sin);
+ iscsid_do_sendtgts(&e);
+ (void) iscsid_login_tgt(ihp, NULL, dm,
+ &addr_dsc.sin);
+ }
+}
+
+/*
* iscsid_init -- load data from persistent storage and start discovery threads
*
* If restart is B_TRUE than someone has issued an ISCSI_DB_RELOAD ioctl.
@@ -132,40 +258,74 @@ iscsid_init(iscsi_hba_t *ihp, boolean_t restart)
sema_init(&iscsid_config_semaphore, 1, NULL,
SEMA_DRIVER, NULL);
- rval = persistent_init(restart);
- if (rval == B_TRUE) {
- rval = iscsid_init_config(ihp);
- if (rval == B_TRUE) {
- rval = iscsid_init_targets(ihp);
+ if (iscsiboot_prop) {
+ if (ihp->persistent_loaded) {
+ rval = persistent_init(B_TRUE);
+ } else {
+ rval = persistent_init(B_FALSE);
+ if (rval)
+ ihp->persistent_loaded = B_TRUE;
}
- }
-
- if (rval == B_TRUE) {
+ } else {
+ rval = persistent_init(restart);
if (restart == B_FALSE) {
- iscsid_threads_create(ihp);
+ ihp->persistent_loaded = B_TRUE;
}
+ }
- dm = persistent_disc_meth_get();
- rval = iscsid_enable_discovery(ihp, dm, B_FALSE);
+ if ((modrootloaded == 0) && (iscsiboot_prop != NULL) && rval) {
+ if (!iscsid_boot_init_config(ihp)) {
+ rval = B_FALSE;
+ } else {
+ iscsi_boot_session_create(ihp, iscsiboot_prop);
+ iscsi_boot_wd_handle =
+ iscsi_thread_create(ihp->hba_dip,
+ "BootWD", iscsid_thread_boot_wd, ihp);
+ if (iscsi_boot_wd_handle) {
+ rval = iscsi_thread_start(
+ iscsi_boot_wd_handle);
+ } else {
+ rval = B_FALSE;
+ }
+ }
+ if (!rval) {
+ cmn_err(CE_NOTE, "Initializaton of iscsi initiator"
+ " partially failed");
+ }
+ } else {
if (rval == B_TRUE) {
- rval = iscsid_disable_discovery(ihp, ~dm);
+ rval = iscsid_init_config(ihp);
+ if (rval == B_TRUE) {
+ rval = iscsid_init_targets(ihp);
+ }
}
- }
- if (rval == B_FALSE) {
- /*
- * In case of failure the events still need to be sent
- * because the door daemon will pause until all these
- * events have occurred.
- */
- for (fdm = &for_failure[0]; *fdm != iSCSIDiscoveryMethodUnknown;
- fdm++) {
- /* ---- Send both start and end events ---- */
- iscsi_discovery_event(ihp, *fdm, B_TRUE);
- iscsi_discovery_event(ihp, *fdm, B_FALSE);
+ if (rval == B_TRUE) {
+ if (restart == B_FALSE) {
+ iscsid_threads_create(ihp);
+ }
+
+ dm = persistent_disc_meth_get();
+ rval = iscsid_enable_discovery(ihp, dm, B_FALSE);
+ if (rval == B_TRUE) {
+ rval = iscsid_disable_discovery(ihp, ~dm);
+ }
+
+ }
+ if (rval == B_FALSE) {
+ /*
+ * In case of failure the events still need to be sent
+ * because the door daemon will pause until all these
+ * events have occurred.
+ */
+ for (fdm = &for_failure[0]; *fdm !=
+ iSCSIDiscoveryMethodUnknown; fdm++) {
+ /* ---- Send both start and end events ---- */
+ iscsi_discovery_event(ihp, *fdm, B_TRUE);
+ iscsi_discovery_event(ihp, *fdm, B_FALSE);
+ }
}
}
-
return (rval);
}
@@ -177,6 +337,10 @@ void
iscsid_fini()
{
iscsid_threads_destroy();
+ if (iscsi_boot_wd_handle != NULL) {
+ iscsi_thread_destroy(iscsi_boot_wd_handle);
+ iscsi_boot_wd_handle = NULL;
+ }
persistent_fini();
sema_destroy(&iscsid_config_semaphore);
}
@@ -369,7 +533,8 @@ iscsid_do_sendtgts(entry_t *disc_addr)
const char *ip;
int ctr;
int rc;
- iscsi_hba_t *ihp;
+ iscsi_hba_t *ihp;
+ iSCSIDiscoveryMethod_t dm = iSCSIDiscoveryMethodSendTargets;
/* allocate and initialize sendtargets list header */
stl_sz = sizeof (*stl_hdr) + ((stl_num_tgts - 1) *
@@ -436,8 +601,10 @@ retry_sendtgts:
&(stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_addr),
stl_hdr->stl_list[ctr].ste_ipaddr.a_port,
&addr_tgt.sin);
-
- (void) iscsid_add(ihp, iSCSIDiscoveryMethodSendTargets,
+ if (disc_addr->e_boot == B_TRUE) {
+ dm = dm | iSCSIDiscoveryMethodBoot;
+ }
+ (void) iscsid_add(ihp, dm,
&addr_dsc.sin, (char *)stl_hdr->stl_list[ctr].ste_name,
stl_hdr->stl_list[ctr].ste_tpgt,
&addr_tgt.sin);
@@ -528,29 +695,73 @@ iscsid_do_isns_query(iscsi_hba_t *ihp)
void
iscsid_config_one(iscsi_hba_t *ihp, char *name, boolean_t protect)
{
- boolean_t rc;
-
- rc = iscsid_login_tgt(ihp, name,
- iSCSIDiscoveryMethodUnknown, NULL);
- /*
- * If we didn't login to the device we might have
- * to update our discovery information and attempt
- * the login again.
- */
- if (rc == B_FALSE) {
+ boolean_t rc = B_FALSE;
+ int retry = 0;
+ int lun_online = 0;
+ int cur_sec = 0;
+
+ if (!modrootloaded && (iscsiboot_prop != NULL)) {
+ if (!iscsi_configroot_printed) {
+ cmn_err(CE_NOTE, "Configuring"
+ " iSCSI boot session...");
+ iscsi_configroot_printed = B_TRUE;
+ }
+ while (rc == B_FALSE && retry <
+ iscsi_configroot_retry) {
+ rc = iscsid_login_tgt(ihp, name,
+ iSCSIDiscoveryMethodBoot, NULL);
+ if (rc == B_FALSE) {
+ /*
+ * create boot session
+ */
+ iscsi_boot_session_create(ihp,
+ iscsiboot_prop);
+ } else {
+ /*
+ * The boot session has been created, if
+ * the target lun has not been online,
+ * we should wait here for a while
+ */
+ do {
+ lun_online =
+ iscsiboot_prop->boot_tgt.lun_online;
+ if (lun_online == 0) {
+ delay(SEC_TO_TICK(1));
+ cur_sec++;
+ }
+ } while ((lun_online == 0) &&
+ (cur_sec < iscsi_boot_max_delay));
+ }
+ retry++;
+ }
+ if (!rc) {
+ cmn_err(CE_WARN, "Failed to configure iSCSI"
+ " boot session");
+ }
+ } else {
+ rc = iscsid_login_tgt(ihp, name, iSCSIDiscoveryMethodUnknown,
+ NULL);
/*
- * Stale /dev links can cause us to get floods
- * of config requests. Prevent these repeated
- * requests from causing unneeded discovery updates
- * if ISCSI_CONFIG_STORM_PROTECT is set.
+ * If we didn't login to the device we might have
+ * to update our discovery information and attempt
+ * the login again.
*/
- if ((protect == B_FALSE) ||
- (ddi_get_lbolt() > ihp->hba_config_lbolt +
- SEC_TO_TICK(ihp->hba_config_storm_delay))) {
- ihp->hba_config_lbolt = ddi_get_lbolt();
- iscsid_poke_discovery(ihp, iSCSIDiscoveryMethodUnknown);
- (void) iscsid_login_tgt(ihp, name,
- iSCSIDiscoveryMethodUnknown, NULL);
+ if (rc == B_FALSE) {
+ /*
+ * Stale /dev links can cause us to get floods
+ * of config requests. Prevent these repeated
+ * requests from causing unneeded discovery updates
+ * if ISCSI_CONFIG_STORM_PROTECT is set.
+ */
+ if ((protect == B_FALSE) ||
+ (ddi_get_lbolt() > ihp->hba_config_lbolt +
+ SEC_TO_TICK(ihp->hba_config_storm_delay))) {
+ ihp->hba_config_lbolt = ddi_get_lbolt();
+ iscsid_poke_discovery(ihp,
+ iSCSIDiscoveryMethodUnknown);
+ (void) iscsid_login_tgt(ihp, name,
+ iSCSIDiscoveryMethodUnknown, NULL);
+ }
}
}
}
@@ -565,20 +776,68 @@ iscsid_config_one(iscsi_hba_t *ihp, char *name, boolean_t protect)
void
iscsid_config_all(iscsi_hba_t *ihp, boolean_t protect)
{
- /*
- * Stale /dev links can cause us to get floods
- * of config requests. Prevent these repeated
- * requests from causing unneeded discovery updates
- * if ISCSI_CONFIG_STORM_PROTECT is set.
- */
- if ((protect == B_FALSE) ||
- (ddi_get_lbolt() > ihp->hba_config_lbolt +
- SEC_TO_TICK(ihp->hba_config_storm_delay))) {
- ihp->hba_config_lbolt = ddi_get_lbolt();
- iscsid_poke_discovery(ihp, iSCSIDiscoveryMethodUnknown);
- }
- (void) iscsid_login_tgt(ihp, NULL,
- iSCSIDiscoveryMethodUnknown, NULL);
+ boolean_t rc = B_FALSE;
+ int retry = 0;
+ int lun_online = 0;
+ int cur_sec = 0;
+
+ if (!modrootloaded && iscsiboot_prop != NULL) {
+ if (!iscsi_configroot_printed) {
+ cmn_err(CE_NOTE, "Configuring"
+ " iSCSI boot session...");
+ iscsi_configroot_printed = B_TRUE;
+ }
+ while (rc == B_FALSE && retry <
+ iscsi_configroot_retry) {
+ rc = iscsid_login_tgt(ihp, NULL,
+ iSCSIDiscoveryMethodBoot, NULL);
+ if (rc == B_FALSE) {
+ /*
+ * No boot session has been created.
+ * We would like to create the boot
+ * Session first.
+ */
+ iscsi_boot_session_create(ihp,
+ iscsiboot_prop);
+ } else {
+ /*
+ * The boot session has been created, if
+ * the target lun has not been online,
+ * we should wait here for a while
+ */
+ do {
+ lun_online =
+ iscsiboot_prop->boot_tgt.lun_online;
+ if (lun_online == 0) {
+ delay(SEC_TO_TICK(1));
+ cur_sec++;
+ }
+ } while ((lun_online == 0) &&
+ (cur_sec < iscsi_boot_max_delay));
+ }
+ retry++;
+ }
+ if (!rc) {
+ cmn_err(CE_WARN, "Failed to configure"
+ " boot session");
+ }
+ } else {
+ /*
+ * Stale /dev links can cause us to get floods
+ * of config requests. Prevent these repeated
+ * requests from causing unneeded discovery updates
+ * if ISCSI_CONFIG_STORM_PROTECT is set.
+ */
+ if ((protect == B_FALSE) ||
+ (ddi_get_lbolt() > ihp->hba_config_lbolt +
+ SEC_TO_TICK(ihp->hba_config_storm_delay))) {
+ ihp->hba_config_lbolt = ddi_get_lbolt();
+ iscsid_poke_discovery(ihp,
+ iSCSIDiscoveryMethodUnknown);
+ }
+ (void) iscsid_login_tgt(ihp, NULL,
+ iSCSIDiscoveryMethodUnknown, NULL);
+ }
}
/*
@@ -754,6 +1013,19 @@ iscsid_add(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method,
}
}
+ if (iscsiboot_prop && (ics->ics_out > 1) &&
+ !iscsi_chk_bootlun_mpxio(ihp)) {
+ /*
+ * iscsi boot with mpxio disabled
+ * no need to search configured boot session
+ */
+
+ if (iscsi_cmp_boot_ini_name(tmp) ||
+ iscsi_cmp_boot_tgt_name(tmp)) {
+ ics->ics_out = 1;
+ ics->ics_bound = B_FALSE;
+ }
+ }
/* Check to see if we need to get more information */
if (ics->ics_out > 1) {
/* record new size and free last buffer */
@@ -866,7 +1138,8 @@ iscsid_del(iscsi_hba_t *ihp, char *target_name,
try_destroy = B_TRUE;
}
- if (try_destroy == B_TRUE) {
+ if (try_destroy == B_TRUE &&
+ isp->sess_boot == B_FALSE) {
(void) strcpy(name, (char *)isp->sess_name);
status = iscsi_sess_destroy(isp);
if (ISCSI_SUCCESS(status)) {
@@ -914,44 +1187,58 @@ iscsid_login_tgt(iscsi_hba_t *ihp, char *target_name,
isp = ihp->hba_sess_list;
while (isp != NULL) {
boolean_t try_online;
-
- if (target_name == NULL) {
- if (method == iSCSIDiscoveryMethodUnknown) {
- /* unknown method mean login to all */
- try_online = B_TRUE;
- } else if (isp->sess_discovered_by & method) {
- if ((method == iSCSIDiscoveryMethodISNS) ||
- (method ==
- iSCSIDiscoveryMethodSendTargets)) {
- if ((addr_dsc == NULL) ||
- (bcmp(&isp->sess_discovered_addr,
- addr_dsc, SIZEOF_SOCKADDR(
- &isp->sess_discovered_addr.sin))
- == 0)) {
- /*
- * iSNS or sendtarget
- * discovery and discovery
- * address is NULL or match
- */
- try_online = B_TRUE;
- } else {
+ if (!(method & iSCSIDiscoveryMethodBoot)) {
+ if (target_name == NULL) {
+ if (method == iSCSIDiscoveryMethodUnknown) {
+ /* unknown method mean login to all */
+ try_online = B_TRUE;
+ } else if (isp->sess_discovered_by & method) {
+ if ((method ==
+ iSCSIDiscoveryMethodISNS) ||
+ (method ==
+ iSCSIDiscoveryMethodSendTargets)) {
+#define SESS_DISC_ADDR isp->sess_discovered_addr.sin
+ if ((addr_dsc == NULL) ||
+ (bcmp(
+ &isp->sess_discovered_addr,
+ addr_dsc, SIZEOF_SOCKADDR(
+ &SESS_DISC_ADDR))
+ == 0)) {
+ /*
+ * iSNS or sendtarget
+ * discovery and
+ * discovery address
+ * is NULL or match
+ */
+ try_online = B_TRUE;
+ } else {
/* addr_dsc not a match */
- try_online = B_FALSE;
+ try_online = B_FALSE;
+ }
+#undef SESS_DISC_ADDR
+ } else {
+ /* static configuration */
+ try_online = B_TRUE;
}
} else {
- /* static configuration */
- try_online = B_TRUE;
+ /* method not a match */
+ try_online = B_FALSE;
}
+ } else if (strcmp(target_name,
+ (char *)isp->sess_name) == 0) {
+ /* target_name match */
+ try_online = B_TRUE;
} else {
- /* method not a match */
+ /* target_name not a match */
try_online = B_FALSE;
}
- } else if (strcmp(target_name, (char *)isp->sess_name) == 0) {
- /* target_name match */
- try_online = B_TRUE;
} else {
- /* target_name not a match */
- try_online = B_FALSE;
+ /*
+ * online the boot session.
+ */
+ if (isp->sess_boot == B_TRUE) {
+ try_online = B_TRUE;
+ }
}
if (try_online == B_TRUE) {
@@ -993,22 +1280,36 @@ iscsid_init_config(iscsi_hba_t *ihp)
bzero(&ips, sizeof (ips));
if (persistent_initiator_name_get(initiatorName,
ISCSI_MAX_NAME_LEN) == B_TRUE) {
- (void) strncpy((char *)ips.s_value.v_name, initiatorName,
- sizeof (ips.s_value.v_name));
-
ips.s_vers = ISCSI_INTERFACE_VERSION;
ips.s_param = ISCSI_LOGIN_PARAM_INITIATOR_NAME;
- (void) iscsi_set_params(&ips, ihp, B_FALSE);
+ if (iscsiboot_prop && !iscsi_cmp_boot_ini_name(initiatorName)) {
+ (void) strncpy(initiatorName,
+ (const char *)iscsiboot_prop->boot_init.ini_name,
+ ISCSI_MAX_NAME_LEN);
+ (void) strncpy((char *)ips.s_value.v_name,
+ (const char *)iscsiboot_prop->boot_init.ini_name,
+ sizeof (ips.s_value.v_name));
+ (void) iscsi_set_params(&ips, ihp, B_TRUE);
+ cmn_err(CE_NOTE, "Set initiator's name"
+ " from firmware");
+ } else {
+ (void) strncpy((char *)ips.s_value.v_name,
+ initiatorName, sizeof (ips.s_value.v_name));
+
+ (void) iscsi_set_params(&ips, ihp, B_FALSE);
+ }
} else {
/*
- * if we don't have an initiator-node name it's most
- * likely because this is a fresh install (or we
- * couldn't read the persistent store properly). Set
- * a default initiator name so the initiator can
+ * if no initiator-node name available it is most
+ * likely due to a fresh install, or the persistent
+ * store is not working correctly. Set
+ * a default initiator name so that the initiator can
* be brought up properly.
*/
iscsid_set_default_initiator_node_settings(ihp);
+ (void) strncpy(initiatorName, (const char *)ihp->hba_name,
+ ISCSI_MAX_NAME_LEN);
}
/*
@@ -1052,6 +1353,10 @@ iscsid_init_config(iscsi_hba_t *ihp)
}
}
} /* END for() */
+ if (iscsiboot_prop &&
+ iscsi_chk_bootlun_mpxio(ihp)) {
+ (void) iscsi_reconfig_boot_sess(ihp);
+ }
break;
}
} /* END while() */
@@ -1114,6 +1419,15 @@ iscsid_init_targets(iscsi_hba_t *ihp)
continue;
}
+ if (iscsiboot_prop && iscsi_cmp_boot_tgt_name(name) &&
+ !iscsi_chk_bootlun_mpxio(ihp)) {
+ /*
+ * boot target is not mpxio enabled
+ * simply ignore these overriden parameters
+ */
+ continue;
+ }
+
ips.s_oid = iscsi_targetparam_get_oid((unsigned char *)name);
for (param_id = 0; param_id < ISCSI_NUM_LOGIN_PARAM;
@@ -1133,6 +1447,10 @@ iscsid_init_targets(iscsi_hba_t *ihp)
}
}
} /* END for() */
+ if (iscsiboot_prop && iscsi_cmp_boot_tgt_name(name) &&
+ iscsi_chk_bootlun_mpxio(ihp)) {
+ (void) iscsi_reconfig_boot_sess(ihp);
+ }
} /* END while() */
persistent_param_unlock();
@@ -1463,28 +1781,37 @@ iscsid_set_default_initiator_node_settings(iscsi_hba_t *ihp)
iscsi_chap_props_t *chap = NULL;
/* Set default initiator-node name */
- (void) snprintf((char *)ihp->hba_name,
- ISCSI_MAX_NAME_LEN,
- "iqn.1986-03.com.sun:01:");
-
- (void) localetheraddr(NULL, &eaddr);
- for (i = 0; i < ETHERADDRL; i++) {
- (void) snprintf(val, sizeof (val), "%02x",
- eaddr.ether_addr_octet[i]);
+ if (iscsiboot_prop && iscsiboot_prop->boot_init.ini_name != NULL) {
+ (void) strncpy((char *)ihp->hba_name,
+ (const char *)iscsiboot_prop->boot_init.ini_name,
+ ISCSI_MAX_NAME_LEN);
+ } else {
+ (void) snprintf((char *)ihp->hba_name,
+ ISCSI_MAX_NAME_LEN,
+ "iqn.1986-03.com.sun:01:");
+
+ (void) localetheraddr(NULL, &eaddr);
+ for (i = 0; i < ETHERADDRL; i++) {
+ (void) snprintf(val, sizeof (val), "%02x",
+ eaddr.ether_addr_octet[i]);
+ (void) strncat((char *)ihp->hba_name, val,
+ ISCSI_MAX_NAME_LEN);
+ }
+
+ /* Set default initiator-node alias */
+ x = ddi_get_time();
+ (void) snprintf(val, sizeof (val), ".%lx", x);
(void) strncat((char *)ihp->hba_name, val, ISCSI_MAX_NAME_LEN);
- }
- /* Set default initiator-node alias */
- x = ddi_get_time();
- (void) snprintf(val, sizeof (val), ".%lx", x);
- (void) strncat((char *)ihp->hba_name, val, ISCSI_MAX_NAME_LEN);
- (void) persistent_initiator_name_set((char *)ihp->hba_name);
- if (ihp->hba_alias[0] == '\0') {
- (void) strncpy((char *)ihp->hba_alias,
- utsname.nodename, ISCSI_MAX_NAME_LEN);
- ihp->hba_alias_length = strlen((char *)ihp->hba_alias);
- (void) persistent_alias_name_set((char *)ihp->hba_alias);
+ if (ihp->hba_alias[0] == '\0') {
+ (void) strncpy((char *)ihp->hba_alias,
+ utsname.nodename, ISCSI_MAX_NAME_LEN);
+ ihp->hba_alias_length = strlen((char *)ihp->hba_alias);
+ (void) persistent_alias_name_set(
+ (char *)ihp->hba_alias);
+ }
}
+ (void) persistent_initiator_name_set((char *)ihp->hba_name);
/* Set default initiator-node CHAP settings */
if (persistent_initiator_name_get((char *)ihp->hba_name,
@@ -1633,3 +1960,297 @@ iscsi_send_sysevent(iscsi_hba_t *ihp, char *subclass, nvlist_t *np)
(void) ddi_log_sysevent(ihp->hba_dip, DDI_VENDOR_SUNW, EC_ISCSI,
subclass, np, NULL, DDI_SLEEP);
}
+
+static boolean_t
+iscsid_boot_init_config(iscsi_hba_t *ihp)
+{
+ if (strlen((const char *)iscsiboot_prop->boot_init.ini_name) != 0) {
+ bcopy(iscsiboot_prop->boot_init.ini_name,
+ ihp->hba_name,
+ strlen((const char *)iscsiboot_prop->boot_init.ini_name));
+ }
+ /* or using default login param for boot session */
+ return (B_TRUE);
+}
+
+boolean_t
+iscsi_reconfig_boot_sess(iscsi_hba_t *ihp)
+{
+ iscsi_config_sess_t *ics;
+ int idx;
+ iscsi_sess_t *isp, *t_isp;
+ int isid, size;
+ char *name;
+ boolean_t rtn = B_TRUE;
+
+ if (iscsiboot_prop == NULL) {
+ return (B_FALSE);
+ }
+ size = sizeof (*ics);
+ ics = kmem_zalloc(size, KM_SLEEP);
+ ics->ics_in = 1;
+
+ /* get information of number of sessions to be configured */
+ name = (char *)iscsiboot_prop->boot_tgt.tgt_name;
+ if (persistent_get_config_session(name, ics) == B_FALSE) {
+ /*
+ * No target information available to check
+ * initiator information. Assume one session
+ * by default.
+ */
+ name = (char *)iscsiboot_prop->boot_init.ini_name;
+ if (persistent_get_config_session(name, ics) == B_FALSE) {
+ ics->ics_out = 1;
+ ics->ics_bound = B_TRUE;
+ }
+ }
+
+ /* get necessary information */
+ if (ics->ics_out > 1) {
+ idx = ics->ics_out;
+ size = ISCSI_SESSION_CONFIG_SIZE(ics->ics_out);
+ kmem_free(ics, sizeof (*ics));
+
+ ics = kmem_zalloc(size, KM_SLEEP);
+ ics->ics_in = idx;
+
+ /* get configured sessions information */
+ if (persistent_get_config_session((char *)name,
+ ics) != B_TRUE) {
+ cmn_err(CE_NOTE, "session(%s) - "
+ "failed to setup multiple sessions",
+ name);
+ kmem_free(ics, size);
+ return (B_FALSE);
+ }
+ }
+
+ /* create a temporary session to keep boot session connective */
+ t_isp = iscsi_add_boot_sess(ihp, ISCSI_MAX_CONFIG_SESSIONS);
+ if (t_isp == NULL) {
+ cmn_err(CE_NOTE, "session(%s) - "
+ "failed to setup multiple sessions", name);
+ rw_exit(&ihp->hba_sess_list_rwlock);
+ kmem_free(ics, size);
+ return (B_FALSE);
+ }
+
+ /* destroy all old boot sessions */
+ rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
+ isp = ihp->hba_sess_list;
+ while (isp != NULL) {
+ if (iscsi_chk_bootlun_mpxio(ihp) && isp->sess_boot) {
+ if (isp->sess_isid[5] != ISCSI_MAX_CONFIG_SESSIONS) {
+ /*
+ * destroy all stale sessions
+ * except temporary boot session
+ */
+ if (ISCSI_SUCCESS(iscsi_sess_destroy(
+ isp))) {
+ isp = ihp->hba_sess_list;
+ } else {
+ /*
+ * couldn't destroy stale sessions
+ * at least poke it to disconnect
+ */
+ mutex_enter(&isp->sess_state_mutex);
+ iscsi_sess_state_machine(isp,
+ ISCSI_SESS_EVENT_N7);
+ mutex_exit(&isp->sess_state_mutex);
+ isp = isp->sess_next;
+ cmn_err(CE_NOTE, "session(%s) - "
+ "failed to setup multiple"
+ " sessions", name);
+ }
+ } else {
+ isp = isp->sess_next;
+ }
+ } else {
+ isp = isp->sess_next;
+ }
+ }
+ rw_exit(&ihp->hba_sess_list_rwlock);
+
+ for (isid = 0; isid < ics->ics_out; isid++) {
+ isp = iscsi_add_boot_sess(ihp, isid);
+ if (isp == NULL) {
+ cmn_err(CE_NOTE, "session(%s) - failed to setup"
+ " multiple sessions", name);
+ rtn = B_FALSE;
+ break;
+ }
+ }
+ if (!rtn && (isid == 0)) {
+ /*
+ * fail to create any new boot session
+ * so only the temporary session is alive
+ * quit without destroying it
+ */
+ kmem_free(ics, size);
+ return (rtn);
+ }
+
+ rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
+ if (!ISCSI_SUCCESS(iscsi_sess_destroy(t_isp))) {
+ /* couldn't destroy temp boot session */
+ cmn_err(CE_NOTE, "session(%s) - "
+ "failed to setup multiple sessions", name);
+ rw_exit(&ihp->hba_sess_list_rwlock);
+ rtn = B_FALSE;
+ }
+ rw_exit(&ihp->hba_sess_list_rwlock);
+
+ kmem_free(ics, size);
+ return (rtn);
+}
+
+static iscsi_sess_t *
+iscsi_add_boot_sess(iscsi_hba_t *ihp, int isid)
+{
+ iscsi_sess_t *isp;
+ iscsi_conn_t *icp;
+ uint_t oid;
+
+ iscsi_sockaddr_t addr_dst;
+
+ addr_dst.sin.sa_family = iscsiboot_prop->boot_tgt.sin_family;
+ if (addr_dst.sin.sa_family == AF_INET) {
+ bcopy(&iscsiboot_prop->boot_tgt.tgt_ip_u.u_in4.s_addr,
+ &addr_dst.sin4.sin_addr.s_addr, sizeof (struct in_addr));
+ addr_dst.sin4.sin_port =
+ htons(iscsiboot_prop->boot_tgt.tgt_port);
+ } else {
+ bcopy(&iscsiboot_prop->boot_tgt.tgt_ip_u.u_in6.s6_addr,
+ &addr_dst.sin6.sin6_addr.s6_addr,
+ sizeof (struct in6_addr));
+ addr_dst.sin6.sin6_port =
+ htons(iscsiboot_prop->boot_tgt.tgt_port);
+ }
+
+ rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
+ isp = iscsi_sess_create(ihp,
+ iSCSIDiscoveryMethodBoot|iSCSIDiscoveryMethodStatic,
+ (struct sockaddr *)&addr_dst,
+ (char *)iscsiboot_prop->boot_tgt.tgt_name,
+ ISCSI_DEFAULT_TPGT, isid, ISCSI_SESS_TYPE_NORMAL, &oid);
+ if (isp == NULL) {
+ /* create temp booting session failed */
+ rw_exit(&ihp->hba_sess_list_rwlock);
+ return (NULL);
+ }
+ isp->sess_boot = B_TRUE;
+
+ if (!ISCSI_SUCCESS(iscsi_conn_create((struct sockaddr *)&addr_dst,
+ isp, &icp))) {
+ rw_exit(&ihp->hba_sess_list_rwlock);
+ return (NULL);
+ }
+
+ rw_exit(&ihp->hba_sess_list_rwlock);
+ /* now online created session */
+ if (iscsid_login_tgt(ihp, (char *)iscsiboot_prop->boot_tgt.tgt_name,
+ iSCSIDiscoveryMethodBoot|iSCSIDiscoveryMethodStatic,
+ (struct sockaddr *)&addr_dst) == B_FALSE) {
+ return (NULL);
+ }
+
+ return (isp);
+}
+
+static void
+iscsid_thread_boot_wd(iscsi_thread_t *thread, void *p)
+{
+ int rc = 1;
+ iscsi_hba_t *ihp = (iscsi_hba_t *)p;
+
+ while (rc != 0) {
+ if (iscsiboot_prop && (modrootloaded == 1) &&
+ (ihp->persistent_loaded == B_TRUE)) {
+ (void) iscsid_init(ihp, B_FALSE);
+ (void) iscsi_reconfig_boot_sess(ihp);
+ iscsid_poke_discovery(ihp, iSCSIDiscoveryMethodUnknown);
+ (void) iscsid_login_tgt(ihp, NULL,
+ iSCSIDiscoveryMethodUnknown, NULL);
+ break;
+ }
+ rc = iscsi_thread_wait(thread, SEC_TO_TICK(1));
+ }
+}
+
+boolean_t
+iscsi_cmp_boot_tgt_name(char *name)
+{
+ if (iscsiboot_prop && (strncmp((const char *)name,
+ (const char *)iscsiboot_prop->boot_tgt.tgt_name,
+ ISCSI_MAX_NAME_LEN) == 0)) {
+ return (B_TRUE);
+ } else {
+ return (B_FALSE);
+ }
+}
+
+boolean_t
+iscsi_cmp_boot_ini_name(char *name)
+{
+ if (iscsiboot_prop && (strncmp((const char *)name,
+ (const char *)iscsiboot_prop->boot_init.ini_name,
+ ISCSI_MAX_NAME_LEN) == 0)) {
+ return (B_TRUE);
+ } else {
+ return (B_FALSE);
+ }
+}
+
+boolean_t
+iscsi_chk_bootlun_mpxio(iscsi_hba_t *ihp)
+{
+ iscsi_sess_t *isp;
+ iscsi_lun_t *ilp;
+ isp = ihp->hba_sess_list;
+ boolean_t tgt_mpxio_enabled = B_FALSE;
+ boolean_t bootlun_found = B_FALSE;
+ uint16_t lun_num;
+
+ if (iscsiboot_prop == NULL) {
+ return (B_FALSE);
+ }
+
+ if (!ihp->hba_mpxio_enabled) {
+ return (B_FALSE);
+ }
+
+ lun_num = *((uint64_t *)(iscsiboot_prop->boot_tgt.tgt_boot_lun));
+
+ while (isp != NULL) {
+ if ((strncmp((char *)isp->sess_name,
+ (const char *)iscsiboot_prop->boot_tgt.tgt_name,
+ ISCSI_MAX_NAME_LEN) == 0) &&
+ (isp->sess_boot == B_TRUE)) {
+ /*
+ * found boot session.
+ * check its mdi path info is null or not
+ */
+ ilp = isp->sess_lun_list;
+ while (ilp != NULL) {
+ if (lun_num == ilp->lun_num) {
+ if (ilp->lun_pip) {
+ tgt_mpxio_enabled = B_TRUE;
+ }
+ bootlun_found = B_TRUE;
+ }
+ ilp = ilp->lun_next;
+ }
+ }
+ isp = isp->sess_next;
+ }
+ if (bootlun_found) {
+ return (tgt_mpxio_enabled);
+ } else {
+ /*
+ * iscsiboot_prop not NULL while no boot lun found
+ * in most cases this is none iscsi boot while iscsiboot_prop
+ * is not NULL, in this scenario return iscsi HBA's mpxio config
+ */
+ return (ihp->hba_mpxio_enabled);
+ }
+}
diff --git a/usr/src/uts/common/io/scsi/adapters/iscsi/nvfile.c b/usr/src/uts/common/io/scsi/adapters/iscsi/nvfile.c
index 0ff155693d..f7d6028783 100644
--- a/usr/src/uts/common/io/scsi/adapters/iscsi/nvfile.c
+++ b/usr/src/uts/common/io/scsi/adapters/iscsi/nvfile.c
@@ -26,10 +26,12 @@
#include "iscsi.h"
#include "nvfile.h"
#include <sys/file.h> /* defines: FKIOCTL */
+#include <sys/kobj.h>
#define NVF_GETF 16
static kmutex_t nvf_getf_lock;
static file_t *nvf_fd[NVF_GETF];
+extern int modrootloaded;
/*
* file names
@@ -208,7 +210,12 @@ nvf_load(void)
/*
* try to load current file
*/
- rval = nvf_parse(nvf_curr_filename);
+ if (!modrootloaded) {
+ mutex_exit(&nvf_lock);
+ return (B_TRUE);
+ } else {
+ rval = nvf_parse(nvf_curr_filename);
+ }
if (rval == B_TRUE) {
mutex_exit(&nvf_lock);
return (rval);
@@ -224,7 +231,13 @@ nvf_load(void)
/*
* try to load previous file
*/
- rval = nvf_parse(nvf_prev_filename);
+ if (!modrootloaded) {
+ mutex_exit(&nvf_lock);
+ return (B_TRUE);
+ } else {
+ rval = nvf_parse(nvf_curr_filename);
+ }
+
if (rval == B_TRUE) {
mutex_exit(&nvf_lock);
return (rval);
@@ -837,7 +850,7 @@ nvf_thread(void *arg)
/*
* check whether its time to write to file. If not, reschedule self
*/
- if (nticks > NVF_RESCHED_MIN_TICKS) {
+ if ((nticks > NVF_RESCHED_MIN_TICKS) || !modrootloaded) {
if (NVF_IS_ACTIVE(nvf_flags)) {
mutex_exit(&nvf_lock);
nvf_thread_id = timeout(nvf_thread, NULL, nticks);
diff --git a/usr/src/uts/common/io/strplumb.c b/usr/src/uts/common/io/strplumb.c
index 4eaf8e20ac..ffb7753e09 100644
--- a/usr/src/uts/common/io/strplumb.c
+++ b/usr/src/uts/common/io/strplumb.c
@@ -23,8 +23,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/types.h>
#include <sys/user.h>
@@ -78,6 +76,8 @@
*/
int strplumbdebug = 0;
+extern ib_boot_prop_t *iscsiboot_prop;
+
#define DBG0(_f) \
if (strplumbdebug != 0) \
printf("strplumb: " _f)
@@ -143,6 +143,7 @@ _info(struct modinfo *modinfop)
#define UDPDEV "/devices/pseudo/udp@0:udp"
#define TCP6DEV "/devices/pseudo/tcp6@0:tcp6"
+#define UDP6DEV "/devices/pseudo/udp6@0:udp6"
#define SCTP6DEV "/devices/pseudo/sctp6@0:sctp6"
#define IP6DEV "/devices/pseudo/ip6@0:ip6"
@@ -424,6 +425,8 @@ setifname(ldi_handle_t lh, struct lifreq *lifrp)
return (ldi_ioctl(lh, I_STR, (intptr_t)&iocb, FKIOCTL, CRED(), &rval));
}
+extern ib_boot_prop_t *iscsiboot_prop;
+
static int
strplumb_dev(ldi_ident_t li)
{
@@ -433,10 +436,16 @@ strplumb_dev(ldi_ident_t li)
struct lifreq lifr;
struct ifreq ifr;
int rval;
+ int af = 0;
+ char *name = NULL;
bzero(&lifr, sizeof (struct lifreq));
bzero(&ifr, sizeof (ifr));
+ if (iscsiboot_prop != NULL) {
+ af = iscsiboot_prop->boot_nic.sin_family;
+ }
+
/*
* Now set up the links. Ultimately, we should have two streams
* permanently linked underneath UDP (which is actually IP with UDP
@@ -474,9 +483,18 @@ strplumb_dev(ldi_ident_t li)
if ((err = getifflags(lh, &lifr)) != 0)
goto done;
- lifr.lifr_flags |= IFF_IPV4;
- lifr.lifr_flags &= ~IFF_IPV6;
-
+ if (af == 0 || af == AF_INET) {
+ lifr.lifr_flags |= IFF_IPV4;
+ lifr.lifr_flags &= ~IFF_IPV6;
+ name = UDPDEV;
+ } else {
+ /*
+ * iscsi boot is used with ipv6 enabled
+ */
+ lifr.lifr_flags |= IFF_IPV6;
+ lifr.lifr_flags &= ~IFF_IPV4;
+ name = UDP6DEV;
+ }
if ((err = ldi_ioctl(lh, I_PUSH, (intptr_t)ARP, FKIOCTL, CRED(),
&rval)) != 0) {
printf("strplumb: push ARP failed: %d\n", err);
@@ -498,7 +516,7 @@ strplumb_dev(ldi_ident_t li)
}
/* Pop out ARP if not needed */
- if (lifr.lifr_flags & IFF_NOARP) {
+ if (lifr.lifr_flags & (IFF_NOARP | IFF_IPV6)) {
err = ldi_ioctl(lh, I_POP, (intptr_t)0, FKIOCTL, CRED(),
&rval);
if (err != 0) {
@@ -507,9 +525,9 @@ strplumb_dev(ldi_ident_t li)
}
}
- if ((err = ldi_open_by_name(UDPDEV, FREAD|FWRITE, CRED(), &mux_lh,
+ if ((err = ldi_open_by_name(name, FREAD|FWRITE, CRED(), &mux_lh,
li)) != 0) {
- printf("strplumb: open of UDPDEV failed: %d\n", err);
+ printf("strplumb: open of %s failed: %d\n", name, err);
goto done;
}
@@ -521,6 +539,10 @@ strplumb_dev(ldi_ident_t li)
goto done;
}
+ if (af == AF_INET6) {
+ goto done;
+ }
+
DBG2("UDP-ARP-IP-%s muxid: %d\n", rootfs.bo_ifname, ifr.ifr_ip_muxid);
(void) ldi_close(lh, FREAD|FWRITE, CRED());
@@ -681,8 +703,13 @@ strplumb_get_netdev_path(void)
dhcacklen = bootp_len;
ddi_prop_free(bootp);
- } else
+ } else if (iscsiboot_prop != NULL) {
+ bcopy(iscsiboot_prop->boot_nic.nic_mac,
+ boot_macaddr, IB_BOOT_MACLEN);
+ boot_maclen = IB_BOOT_MACLEN;
+ } else {
return (NULL);
+ }
ddi_walk_devs(ddi_root_node(), matchmac, (void *)&devpath);
return (devpath);
diff --git a/usr/src/uts/common/os/iscsiboot_prop.c b/usr/src/uts/common/os/iscsiboot_prop.c
new file mode 100644
index 0000000000..28b0566d34
--- /dev/null
+++ b/usr/src/uts/common/os/iscsiboot_prop.c
@@ -0,0 +1,269 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Commmon routines, handling iscsi boot props
+ */
+
+#include <sys/types.h>
+#include <sys/bootprops.h>
+#include <sys/cmn_err.h>
+#include <sys/socket.h>
+#include <sys/kmem.h>
+#include <netinet/in.h>
+
+extern void *memset(void *s, int c, size_t n);
+extern int memcmp(const void *s1, const void *s2, size_t n);
+extern void bcopy(const void *s1, void *s2, size_t n);
+extern size_t strlen(const char *s);
+static void kinet_ntoa(char *buf, void *in, int af);
+extern ib_boot_prop_t *iscsiboot_prop;
+
+int iscsi_print_bootprop = 0;
+
+#define ISCSI_BOOTPROP_BUFLEN 256
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+static void
+iscsi_bootprop_print(int level, char *str)
+{
+ if (str == NULL) {
+ return;
+ }
+ if (iscsi_print_bootprop == 1) {
+ cmn_err(level, "%s", str);
+ }
+}
+
+static void
+iscsi_print_initiator_property(ib_ini_prop_t *ibinitp)
+{
+ char outbuf[ISCSI_BOOTPROP_BUFLEN] = {0};
+
+ if (ibinitp == NULL) {
+ return;
+ }
+
+ if (ibinitp->ini_name != NULL) {
+ (void) sprintf(outbuf,
+ "Initiator Name : %s\n",
+ ibinitp->ini_name);
+ iscsi_bootprop_print(CE_CONT, outbuf);
+ }
+
+ if (ibinitp->ini_chap_name != NULL) {
+ (void) memset(outbuf, 0, ISCSI_BOOTPROP_BUFLEN);
+ (void) sprintf(outbuf,
+ "Initiator CHAP Name : %s\n",
+ ibinitp->ini_chap_name);
+
+ iscsi_bootprop_print(CE_CONT, outbuf);
+ }
+}
+
+static void
+iscsi_print_nic_property(ib_nic_prop_t *nicp)
+{
+ char outbuf[ISCSI_BOOTPROP_BUFLEN] = {0};
+ char ipaddr[50] = {0};
+ int n = 0;
+
+ if (nicp == NULL) {
+ return;
+ }
+
+ kinet_ntoa(ipaddr, &nicp->nic_ip_u, nicp->sin_family);
+ n = snprintf(outbuf, ISCSI_BOOTPROP_BUFLEN,
+ "Local IP addr : %s\n", ipaddr);
+
+ (void) memset(ipaddr, 0, 50);
+ kinet_ntoa(ipaddr, &nicp->nic_gw_u, nicp->sin_family);
+ n = n + snprintf(outbuf + n, ISCSI_BOOTPROP_BUFLEN - n,
+ "Local gateway : %s\n", ipaddr);
+
+ (void) memset(ipaddr, 0, 50);
+ kinet_ntoa(ipaddr, &nicp->nic_dhcp_u, nicp->sin_family);
+ n = n + snprintf(outbuf + n, ISCSI_BOOTPROP_BUFLEN - n,
+ "Local DHCP : %s\n", ipaddr);
+
+ (void) snprintf(outbuf + n, ISCSI_BOOTPROP_BUFLEN - n,
+ "Local MAC : %02x:%02x:%02x:%02x:%02x:%02x\n",
+ nicp->nic_mac[0],
+ nicp->nic_mac[1],
+ nicp->nic_mac[2],
+ nicp->nic_mac[3],
+ nicp->nic_mac[4],
+ nicp->nic_mac[5]);
+
+ iscsi_bootprop_print(CE_CONT, outbuf);
+}
+
+static void
+iscsi_print_tgt_property(ib_tgt_prop_t *itgtp)
+{
+ char outbuf[ISCSI_BOOTPROP_BUFLEN] = {0};
+ char ipaddr[50] = {0};
+
+ if (itgtp == NULL) {
+ return;
+ }
+
+ if (itgtp->tgt_name != NULL) {
+ (void) memset(outbuf, 0, ISCSI_BOOTPROP_BUFLEN);
+ (void) sprintf(outbuf,
+ "Target Name : %s\n",
+ itgtp->tgt_name);
+ iscsi_bootprop_print(CE_CONT, outbuf);
+ }
+
+ kinet_ntoa(ipaddr, &itgtp->tgt_ip_u, itgtp->sin_family);
+ (void) sprintf(outbuf,
+ "Target IP : %s\n"
+ "Target Port : %d\n"
+ "Boot LUN : %02x%02x-%02x%02x-%02x%02x-%02x%02x\n",
+ ipaddr,
+ itgtp->tgt_port,
+ itgtp->tgt_boot_lun[0],
+ itgtp->tgt_boot_lun[1],
+ itgtp->tgt_boot_lun[2],
+ itgtp->tgt_boot_lun[3],
+ itgtp->tgt_boot_lun[4],
+ itgtp->tgt_boot_lun[5],
+ itgtp->tgt_boot_lun[6],
+ itgtp->tgt_boot_lun[7]);
+ iscsi_bootprop_print(CE_CONT, outbuf);
+
+ if (itgtp->tgt_chap_name != NULL) {
+ (void) memset(outbuf, 0, ISCSI_BOOTPROP_BUFLEN);
+ (void) sprintf(outbuf,
+ "CHAP Name : %s\n",
+ itgtp->tgt_chap_name);
+ iscsi_bootprop_print(CE_CONT, outbuf);
+ }
+}
+
+void
+iscsi_print_boot_property()
+{
+ if (iscsiboot_prop == NULL) {
+ return;
+ }
+
+ iscsi_print_initiator_property(
+ &iscsiboot_prop->boot_init);
+
+ iscsi_print_nic_property(&iscsiboot_prop->boot_nic);
+
+ iscsi_print_tgt_property(&iscsiboot_prop->boot_tgt);
+}
+
+void
+iscsi_boot_free_ini(ib_ini_prop_t *init)
+{
+ if (init == NULL) {
+ return;
+ }
+
+ if (init->ini_name != NULL) {
+ kmem_free(init->ini_name, strlen((char *)init->ini_name) + 1);
+ init->ini_name = NULL;
+ }
+ if (init->ini_chap_name != NULL) {
+ kmem_free(init->ini_chap_name,
+ strlen((char *)init->ini_chap_name) + 1);
+ init->ini_chap_name = NULL;
+ }
+ if (init->ini_chap_sec != NULL) {
+ kmem_free(init->ini_chap_sec,
+ strlen((char *)init->ini_chap_sec) + 1);
+ init->ini_chap_sec = NULL;
+ }
+}
+
+void
+iscsi_boot_free_tgt(ib_tgt_prop_t *target)
+{
+ if (target == NULL) {
+ return;
+ }
+
+ if (target->tgt_name != NULL) {
+ kmem_free(target->tgt_name,
+ strlen((char *)target->tgt_name) + 1);
+ target->tgt_name = NULL;
+ }
+ if (target->tgt_chap_name != NULL) {
+ kmem_free(target->tgt_chap_name,
+ strlen((char *)target->tgt_chap_name) + 1);
+ target->tgt_chap_name = NULL;
+ }
+ if (target->tgt_chap_sec != NULL) {
+ kmem_free(target->tgt_chap_sec,
+ strlen((char *)target->tgt_chap_sec) + 1);
+ target->tgt_chap_sec = NULL;
+ }
+}
+
+/*
+ * Free the memory used by boot property.
+ */
+void
+iscsi_boot_prop_free()
+{
+ ib_boot_prop_t *tmp;
+
+ if (iscsiboot_prop == NULL) {
+ return;
+ }
+ tmp = iscsiboot_prop;
+ iscsiboot_prop = NULL;
+ iscsi_boot_free_ini(&(tmp->boot_init));
+ iscsi_boot_free_tgt(&(tmp->boot_tgt));
+}
+
+static void
+kinet_ntoa(char *buf, void *in, int af)
+{
+ unsigned char *p = NULL;
+ int i = 0;
+
+ if (buf == NULL || in == NULL) {
+ return;
+ }
+ p = (unsigned char *)in;
+ if (af == AF_INET) {
+ (void) sprintf(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+ } else {
+ for (i = 0; i < 14; i = i + 2) {
+ (void) sprintf(buf, "%02x%02x:", p[i], p[i+1]);
+ buf = buf + 5;
+ }
+ (void) sprintf(buf, "%02x%02x", p[i], p[i+1]);
+ }
+}
diff --git a/usr/src/uts/common/os/main.c b/usr/src/uts/common/os/main.c
index 5b3d8d5d03..7d0cf27d8e 100644
--- a/usr/src/uts/common/os/main.c
+++ b/usr/src/uts/common/os/main.c
@@ -26,7 +26,6 @@
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysmacros.h>
@@ -76,6 +75,7 @@
#include <sys/dc_ki.h>
#include <c2/audit.h>
+#include <sys/bootprops.h>
/* well known processes */
proc_t *proc_sched; /* memory scheduler */
@@ -361,6 +361,7 @@ main(void)
extern id_t syscid, defaultcid;
extern int swaploaded;
extern int netboot;
+ extern ib_boot_prop_t *iscsiboot_prop;
extern void vm_init(void);
extern void cbe_init_pre(void);
extern void cbe_init(void);
@@ -429,7 +430,10 @@ main(void)
*/
for (initptr = &init_tbl[0]; *initptr; initptr++)
(**initptr)();
-
+ /*
+ * Load iSCSI boot properties
+ */
+ ld_ib_prop();
/*
* initialize vm related stuff.
*/
@@ -474,7 +478,7 @@ main(void)
* Plumb the protocol modules and drivers only if we are not
* networked booted, in this case we already did it in rootconf().
*/
- if (netboot == 0)
+ if (netboot == 0 && iscsiboot_prop == NULL)
(void) strplumb();
gethrestime(&PTOU(curproc)->u_start);
diff --git a/usr/src/uts/common/os/space.c b/usr/src/uts/common/os/space.c
index 08384fab47..6edebecdfe 100644
--- a/usr/src/uts/common/os/space.c
+++ b/usr/src/uts/common/os/space.c
@@ -20,12 +20,10 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* The intent of this file is to contain any data that must remain
* resident in the kernel.
@@ -61,6 +59,7 @@
#include <sys/kbio.h>
#include <sys/consdev.h>
#include <sys/wscons.h>
+#include <sys/bootprops.h>
struct buf bfreelist; /* Head of the free list of buffers */
@@ -377,3 +376,8 @@ uint_t ip_threads_per_cpu = NUMBER_OF_THREADS_PER_CPU;
/* Global flag to enable/disable soft ring facility */
boolean_t ip_squeue_soft_ring = B_FALSE;
+
+/*
+ * Global iscsi boot prop
+ */
+ib_boot_prop_t *iscsiboot_prop = NULL;
diff --git a/usr/src/uts/common/sys/bootprops.h b/usr/src/uts/common/sys/bootprops.h
index f337777172..ed6dd8bd7a 100644
--- a/usr/src/uts/common/sys/bootprops.h
+++ b/usr/src/uts/common/sys/bootprops.h
@@ -19,16 +19,16 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _BOOTPROPS_H
#define _BOOTPROPS_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/t_kuser.h>
#ifdef __cplusplus
extern "C" {
@@ -48,6 +48,84 @@ extern "C" {
#define BP_BOOTP_RESPONSE "bootp-response"
#define BP_NETWORK_INTERFACE "network-interface"
+/*
+ * kifconf prototypes
+ */
+int
+kdlifconfig(TIUSER *tiptr, int af, void *myIPaddr, void *mymask,
+ struct in_addr *mybraddr, struct in_addr *gateway, char *ifname);
+int
+ksetifflags(TIUSER *tiptr, uint_t value, char *ifname);
+int
+kifioctl(TIUSER *tiptr, int cmd, struct netbuf *nbuf, char *ifname);
+
+/*
+ * Boot properties related to iscsi boot:
+ */
+#define IB_BOOT_MACLEN 6
+#define IB_IP_BUFLEN 16
+
+/*
+ * iSCSI boot initiator's properties
+ */
+typedef struct _ib_ini_prop {
+ uchar_t *ini_name;
+ uchar_t *ini_chap_name;
+ uchar_t *ini_chap_sec;
+} ib_ini_prop_t;
+
+/*
+ * iSCSI boot nic's properties
+ */
+typedef struct _ib_nic_prop {
+ uchar_t nic_mac[6];
+ uchar_t nic_vlan[2];
+ union {
+ struct in_addr u_in4;
+ struct in6_addr u_in6;
+ } nic_ip_u;
+ union {
+ struct in_addr u_in4;
+ struct in6_addr u_in6;
+ } nic_gw_u;
+ union {
+ struct in_addr u_in4;
+ struct in6_addr u_in6;
+ } nic_dhcp_u;
+ int sin_family;
+ uchar_t sub_mask_prefix;
+
+} ib_nic_prop_t;
+
+/*
+ * iSCSI boot target's properties
+ */
+typedef struct _ib_tgt_prop {
+ union {
+ struct in_addr u_in4;
+ struct in6_addr u_in6;
+ }tgt_ip_u;
+ int sin_family;
+ uint32_t tgt_port;
+ uchar_t tgt_boot_lun[8];
+ uchar_t *tgt_name;
+ uchar_t *tgt_chap_name;
+ uchar_t *tgt_chap_sec;
+ int lun_online;
+} ib_tgt_prop_t;
+
+/*
+ * iSCSI boot properties
+ */
+typedef struct _ib_boot_prop {
+ ib_ini_prop_t boot_init;
+ ib_nic_prop_t boot_nic;
+ ib_tgt_prop_t boot_tgt;
+} ib_boot_prop_t;
+
+void
+ld_ib_prop();
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/common/sys/scsi/adapters/iscsi_if.h b/usr/src/uts/common/sys/scsi/adapters/iscsi_if.h
index f56e67fd76..dd5f72a5c0 100644
--- a/usr/src/uts/common/sys/scsi/adapters/iscsi_if.h
+++ b/usr/src/uts/common/sys/scsi/adapters/iscsi_if.h
@@ -145,6 +145,8 @@ extern "C" {
#define ISCSI_GET_CONFIG_SESSIONS (ISCSI_IOCTL | 44)
#define ISCSI_SET_CONFIG_SESSIONS (ISCSI_IOCTL | 45)
#define ISCSI_INIT_NODE_NAME_SET (ISCSI_IOCTL | 46)
+#define ISCSI_IS_ACTIVE (ISCSI_IOCTL | 47)
+#define ISCSI_BOOTPROP_GET (ISCSI_IOCTL | 48)
#define ISCSI_DB_DUMP (ISCSI_IOCTL | 100) /* DBG */
/*
@@ -180,7 +182,13 @@ typedef enum iSCSIDiscoveryMethod {
iSCSIDiscoveryMethodStatic = 1,
iSCSIDiscoveryMethodSLP = 2,
iSCSIDiscoveryMethodISNS = 4,
- iSCSIDiscoveryMethodSendTargets = 8
+ iSCSIDiscoveryMethodSendTargets = 8,
+ /*
+ * Since there is no specification about boot discovery method,
+ * we should leave a value gap in case of other discovery
+ * methods added.
+ */
+ iSCSIDiscoveryMethodBoot = 128
} iSCSIDiscoveryMethod_t;
#define ISCSI_ALL_DISCOVERY_METHODS (iSCSIDiscoveryMethodStatic | \
iSCSIDiscoveryMethodSLP | \
@@ -246,6 +254,8 @@ typedef struct entry {
int e_insize;
int e_port;
int e_tpgt;
+ /* e_boot should be true if a boot session is created. */
+ boolean_t e_boot;
} entry_t;
/*
@@ -601,6 +611,17 @@ typedef struct iscsi_config_sess {
iscsi_ipaddr_t ics_bindings[1];
} iscsi_config_sess_t;
+/* iscsi booting prop */
+typedef struct _iSCSIBootProperties {
+ node_name_t ini_name;
+ node_name_t tgt_name;
+ iscsi_auth_props_t auth;
+ iscsi_chap_props_t ini_chap;
+ iscsi_chap_props_t tgt_chap;
+ int iscsiboot;
+ boolean_t hba_mpxio_enabled;
+} iscsi_boot_property_t;
+
#define ISCSI_SESSION_CONFIG_SIZE(SIZE) \
(sizeof (iscsi_config_sess_t) + \
((SIZE - 1) * sizeof (iscsi_ipaddr_t)))