diff options
author | Sue Gleeson <Susan.Gleeson@Sun.COM> | 2010-04-05 15:20:40 -0400 |
---|---|---|
committer | Sue Gleeson <Susan.Gleeson@Sun.COM> | 2010-04-05 15:20:40 -0400 |
commit | c3a558e7c77127215b010652905be7916ec5a080 (patch) | |
tree | 4f5c95cd7be43ee57cfe8981c5e9052edea7a5bb | |
parent | 9adc5a4e4d9ae99cc46988904fa0509938a2133d (diff) | |
download | illumos-joyent-c3a558e7c77127215b010652905be7916ec5a080.tar.gz |
6879350 RFE: Add ability to enable/disable SRPT on specific HCAs
23 files changed, 2097 insertions, 172 deletions
diff --git a/usr/src/Makefile.lint b/usr/src/Makefile.lint index baaf43922c..6eb4120f27 100644 --- a/usr/src/Makefile.lint +++ b/usr/src/Makefile.lint @@ -20,8 +20,7 @@ # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. # # include global definitions @@ -274,6 +273,8 @@ COMMON_SUBDIRS = \ cmd/smserverd \ cmd/sort \ cmd/split \ + cmd/srptadm \ + cmd/srptsvc \ cmd/ssh \ cmd/stat \ cmd/stmfadm \ @@ -423,6 +424,7 @@ COMMON_SUBDIRS = \ lib/libsmbfs \ lib/libsmbios \ lib/libsmedia \ + lib/libsrpt \ lib/libstmf \ lib/libsun_ima \ lib/libthread \ diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile index b493fa6ef1..a17a96695e 100644 --- a/usr/src/cmd/Makefile +++ b/usr/src/cmd/Makefile @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. # include ../Makefile.master @@ -372,6 +371,7 @@ COMMON_SUBDIRS= \ split \ sqlite \ srchtxt \ + srptadm \ srptsvc \ ssh \ stat \ @@ -689,6 +689,7 @@ MSGSUBDIRS= \ smbsrv \ sort \ split \ + srptadm \ ssh \ stat \ stmfadm \ diff --git a/usr/src/cmd/srptadm/Makefile b/usr/src/cmd/srptadm/Makefile new file mode 100644 index 0000000000..b35c3a90e4 --- /dev/null +++ b/usr/src/cmd/srptadm/Makefile @@ -0,0 +1,42 @@ +# +# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +PROG= srptadm + +include ../Makefile.cmd + +LDLIBS += -lsecdb -lscf -lstmf -lsrpt + +.KEEP_STATE: + +all: $(PROG) + +install: all $(ROOTUSRSBINPROG) + +clean: + +lint: lint_PROG + +include ../Makefile.targ diff --git a/usr/src/cmd/srptadm/srptadm.c b/usr/src/cmd/srptadm/srptadm.c new file mode 100644 index 0000000000..90b248a12d --- /dev/null +++ b/usr/src/cmd/srptadm/srptadm.c @@ -0,0 +1,582 @@ +/* + * 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 (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <getopt.h> +#include <strings.h> +#include <ctype.h> +#include <libnvpair.h> +#include <libintl.h> +#include <libgen.h> +#include <pwd.h> +#include <auth_attr.h> +#include <secdb.h> +#include <libscf.h> +#include <limits.h> +#include <locale.h> +#include <dirent.h> + +#include <libstmf.h> +#include <libsrpt.h> + +/* SMF service info */ +#define STMF_SVC "svc:/system/stmf:default" + +#define STMF_STALE(ret) {\ + if (ret == STMF_ERROR_PROV_DATA_STALE) {\ + (void) fprintf(stderr, "%s\n",\ + gettext("Configuration changed during processing. "\ + "Check the configuration, then retry this command "\ + "if appropriate."));\ + }\ +} + +#define SRPTADM_CHKAUTH(sec) {\ + if (!chkauthattr(sec, srptadm_uname)) {\ + (void) fprintf(stderr,\ + gettext("Error, operation requires authorization %s"),\ + sec);\ + (void) fprintf(stderr, "\n");\ + return (1);\ + }\ +} + +#define PROPS_FORMAT " %-20s: " + +static struct option srptadm_long[] = { + {"enable", no_argument, NULL, 'e'}, + {"disable", no_argument, NULL, 'd'}, + {"reset", no_argument, NULL, 'r'}, + {"help", no_argument, NULL, '?'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} +}; + +static char m_def[] = "srptadm modify-defaults [-e] [-d]"; +static char l_def[] = "srptadm list-defaults"; +static char s_tgt[] = "srptadm modify-target [-e] [-d] [-r] <hca>"; +static char l_tgt[] = "srptadm list-target [<hca>]"; + +/* keep the order of this enum in the same order as the 'subcmds' struct */ +typedef enum { + MODIFY_DEFAULT, + LIST_DEFAULT, + MODIFY_TARGET, + LIST_TARGET, + NULL_SUBCMD /* must always be last! */ +} srptadm_sub_t; + +typedef struct { + char *name; + char *shortopts; + char *usemsg; +} srptadm_subcmds_t; + +static srptadm_subcmds_t subcmds[] = { + {"modify-defaults", "edh?", m_def}, + {"list-defaults", "h?", l_def}, + {"modify-target", "edrh?", s_tgt}, + {"list-target", "h?", l_tgt}, + {NULL, ":h?", NULL}, +}; + +/* used for checking if user is authorized */ +static char *srptadm_uname = NULL; + +/* prototypes */ +static int get_local_hcas(char **hcaArray, int count); +static int print_target_props(char *hca); +static int list_target(char *hca); +static int disable_target(char *hca); +static int reset_target(char *hca); +static int list_defaults(void); +static int enable_target(char *hca); +static int set_default_state(boolean_t enabled); + +int +main(int argc, char *argv[]) +{ + int ret = 0; + int idx = NULL_SUBCMD; + char c; + int newargc = argc; + char **newargv = NULL; + char *objp; + int srptind = 0; + struct passwd *pwd = NULL; + char *smfstate = NULL; + boolean_t reset = B_FALSE; + int dflag = 0; + int eflag = 0; + + (void) setlocale(LC_ALL, ""); + (void) textdomain(TEXT_DOMAIN); + + if (argc < 2) { + ret = 1; + goto usage_error; + } + + for (idx = 0; subcmds[idx].name != NULL; idx++) { + if (strcmp(argv[1], subcmds[idx].name) == 0) { + break; + } + } + + /* get the caller's user name for subsequent chkauthattr() calls */ + pwd = getpwuid(getuid()); + if (pwd == NULL) { + (void) fprintf(stderr, "%s\n", + gettext("Could not determine callers user name.")); + return (1); + } + + srptadm_uname = strdup(pwd->pw_name); + + /* increment past command & subcommand */ + newargc--; + newargv = &(argv[1]); + + while ((ret == 0) && (newargv)) { + c = getopt_long(newargc, newargv, subcmds[idx].shortopts, + srptadm_long, &srptind); + if (c == -1) { + break; + } + + switch (c) { + case 0: + /* flag set by getopt */ + break; + case 'd': + dflag++; + break; + case 'e': + eflag++; + break; + case 'r': + reset = B_TRUE; + break; + case '?': + /* + * '?' is returned for both unrecognized + * options and if explicitly provided on + * the command line. The latter should + * be handled the same as -h. + */ + if (strcmp(newargv[optind-1], "-?") != 0) { + (void) fprintf(stderr, + gettext("Unrecognized option %s"), + newargv[optind-1]); + (void) fprintf(stderr, "\n"); + ret = 1; + } + goto usage_error; + case 'h': + goto usage_error; + case ':': + (void) fprintf(stderr, + gettext("Option %s requires an operand."), + newargv[optind-1]); + (void) fprintf(stderr, "\n"); + + /* fall through to default */ + default: + ret = 1; + break; + } + } + + if (ret != 0) { + goto usage_error; + } + + /* after getopt() to allow handling of -h option */ + if ((srptadm_sub_t)idx == NULL_SUBCMD) { + (void) fprintf(stderr, "%s\n", + gettext("Error, no subcommand specified")); + ret = 1; + goto usage_error; + } + + newargc -= optind; + if (newargc == 0) { + newargv = NULL; + objp = NULL; + } else { + newargv = &(newargv[optind]); + objp = newargv[0]; + } + + if (objp == NULL) { + switch ((srptadm_sub_t)idx) { + case MODIFY_TARGET: + /* These subcommands need operands */ + ret = 1; + goto usage_error; + default: + break; + } + } + + if (newargc > 1) { + switch ((srptadm_sub_t)idx) { + case MODIFY_TARGET: + case LIST_TARGET: + /* These subcommands should have at most one operand */ + ret = 1; + goto usage_error; + + default: + break; + } + } + + + /* + * Make sure STMF service is enabled before proceeding. + */ + smfstate = smf_get_state(STMF_SVC); + if (!smfstate || + (strcmp(smfstate, SCF_STATE_STRING_ONLINE) != 0)) { + (void) fprintf(stderr, "%s\n", + gettext("The STMF service must be online " + "before running this command.")); + (void) fprintf(stderr, + gettext("Use 'svcadm enable -r %s'"), STMF_SVC); + (void) fprintf(stderr, "\n"); + (void) fprintf(stderr, "%s\n", + gettext("to enable the service and its prerequisite " + "services and/or")); + (void) fprintf(stderr, + gettext("'svcs -x %s' to determine why it is not online."), + STMF_SVC); + (void) fprintf(stderr, "\n"); + + return (1); + } + + switch ((srptadm_sub_t)idx) { + case MODIFY_DEFAULT: + if (eflag) { + ret = set_default_state(B_TRUE); + } else if (dflag) { + ret = set_default_state(B_FALSE); + } else { + ret = 1; + goto usage_error; + } + break; + case LIST_DEFAULT: + ret = list_defaults(); + break; + case MODIFY_TARGET: + if (reset) { + ret = reset_target(objp); + } else if (eflag) { + ret = enable_target(objp); + } else if (dflag) { + ret = disable_target(objp); + } else { + ret = 1; + goto usage_error; + } + break; + case LIST_TARGET: + ret = list_target(objp); + break; + default: + ret = 1; + goto usage_error; + } + + if (ret != 0) { + (void) fprintf(stderr, + gettext("srptadm %s failed with error %d"), + subcmds[idx].name, ret); + (void) fprintf(stderr, "\n"); + } + return (ret); + +usage_error: + if (subcmds[idx].name) { + (void) printf("%s\n", gettext(subcmds[idx].usemsg)); + } else { + /* overall usage */ + (void) printf("%s\n\n", gettext("srptadm usage:")); + for (idx = 0; subcmds[idx].name != NULL; idx++) { + if (!subcmds[idx].usemsg) { + continue; + } + (void) printf("\t%s\n", gettext(subcmds[idx].usemsg)); + } + } + + return (ret); +} + +static int +set_default_state(boolean_t enabled) +{ + int ret; + char *sec = "solaris.smf.modify.stmf"; + + SRPTADM_CHKAUTH(sec); + + ret = srpt_SetDefaultState(enabled); + + return (ret); +} + +static int +enable_target(char *hca) +{ + int ret; + char *sec = "solaris.smf.modify.stmf"; + + SRPTADM_CHKAUTH(sec); + + ret = srpt_SetTargetState(hca, B_TRUE); + + return (ret); +} + +static int +disable_target(char *hca) +{ + int ret; + char *sec = "solaris.smf.modify.stmf"; + + SRPTADM_CHKAUTH(sec); + + ret = srpt_SetTargetState(hca, B_FALSE); + + return (ret); +} + +static int +reset_target(char *hca) +{ + int ret; + char *sec = "solaris.smf.modify.stmf"; + + SRPTADM_CHKAUTH(sec); + + ret = srpt_ResetTarget(hca); + + return (ret); +} + +static int +list_defaults(void) +{ + int ret; + char *sec = "solaris.smf.read.stmf"; + boolean_t enabled; + + SRPTADM_CHKAUTH(sec); + + /* only state set as default for now */ + ret = srpt_GetDefaultState(&enabled); + + if (ret == 0) { + (void) printf("%s:\n\n", + gettext("SRP Target Service Default Properties")); + + (void) printf(" %s:\t", + gettext("Target creation enabled by default")); + + if (enabled) { + (void) printf("%s\n", gettext("true")); + } else { + (void) printf("%s\n", gettext("false")); + } + } + + return (ret); +} + +static int +list_target(char *hca) +{ + int ret; + char *sec = "solaris.smf.read.stmf"; + char *hcaArr[1024]; /* way bigger than we'll ever see */ + int i; + + SRPTADM_CHKAUTH(sec); + + if (hca != NULL) { + ret = print_target_props(hca); + return (ret); + } + + /* get list of HCAs configured on this system, from /dev/cfg */ + (void) memset(&hcaArr, 0, 1024 * sizeof (char *)); + + ret = get_local_hcas(hcaArr, sizeof (hcaArr)); + if (ret == ETOOMANYREFS) { + (void) fprintf(stderr, "Internal error: too many HCAs\n"); + goto done; + } else if (ret != 0) { + (void) fprintf(stderr, "Error getting list of HCAs: %d\n", ret); + goto done; + } + + for (i = 0; i < 1024; i++) { + if (hcaArr[i] == NULL) { + break; + } + ret = print_target_props(hcaArr[i]); + } + +done: + for (i = 0; i < 1024; i++) { + if (hcaArr[i] == NULL) { + break; + } + free(hcaArr[i]); + } + + return (ret); +} + +static int +print_target_props(char *hca) +{ + int ret; + boolean_t enabled; + char buf[32]; + char euibuf[64]; + uint64_t hcaguid; + stmfDevid devid; + stmfTargetProperties props; + char *state; + + ret = srpt_NormalizeGuid(hca, buf, sizeof (buf), &hcaguid); + if (ret != 0) { + (void) fprintf(stderr, "Invalid target HCA: %s\n", + hca); + return (ret); + } + + /* only property set is enabled */ + ret = srpt_GetTargetState(buf, &enabled); + if (ret != 0) { + (void) fprintf(stderr, + "Could not get enabled state for %s: %d\n", + buf, ret); + return (ret); + } + + (void) printf("Target HCA %s:\n", buf); + + (void) printf(PROPS_FORMAT, gettext("Enabled")); + + if (enabled) { + (void) printf("%s\n", gettext("true")); + } else { + (void) printf("%s\n", gettext("false")); + } + + state = "-"; + + (void) snprintf(euibuf, sizeof (euibuf), "eui.%016llX", hcaguid); + + ret = stmfDevidFromIscsiName(euibuf, &devid); + if (ret == STMF_STATUS_SUCCESS) { + ret = stmfGetTargetProperties(&devid, &props); + if (ret == STMF_STATUS_SUCCESS) { + if (props.status == STMF_TARGET_PORT_ONLINE) { + state = "online"; + } else { + state = "offline"; + } + } + } + + (void) printf(PROPS_FORMAT, gettext("SRP Target Name")); + (void) printf("%s\n", euibuf); + (void) printf(PROPS_FORMAT, gettext("Operational Status")); + (void) printf("%s\n", state); + + (void) printf("\n"); + + return (0); +} + + +static int +get_local_hcas(char **hcaArray, int count) +{ + int ret = 0; + char *cfgdir = "/dev/cfg"; + DIR *dirp = NULL; + struct dirent *entry; + int idx = 0; + char *bufp; + + if ((hcaArray == NULL) || (count == 0)) { + return (EINVAL); + } + + dirp = opendir(cfgdir); + + if (dirp == NULL) { + ret = errno; + (void) fprintf(stderr, "Could not open %s: errno %d\n", + cfgdir, ret); + return (ret); + } + + while ((entry = readdir(dirp)) != NULL) { + bufp = &entry->d_name[0]; + + if (strncmp(bufp, "hca:", 4) != 0) { + continue; + } + + bufp += 4; + + hcaArray[idx] = strdup(bufp); + if (hcaArray[idx] == NULL) { + ret = ENOMEM; + break; + } + idx++; + + if (idx >= count) { + ret = ETOOMANYREFS; + break; + } + } + + return (ret); +} diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile index 2ed5c76543..a458acba3a 100644 --- a/usr/src/lib/Makefile +++ b/usr/src/lib/Makefile @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. # include ../Makefile.master @@ -154,6 +153,7 @@ SUBDIRS += \ krb5 .WAIT \ libsmbfs \ libfcoe \ + libsrpt \ libstmf \ libstmfproxy \ libnsctl \ @@ -460,6 +460,7 @@ HDRSUBDIRS= \ libsocket \ libsqlite \ libfcoe \ + libsrpt \ libstmf \ libstmfproxy \ libsum \ diff --git a/usr/src/lib/libsrpt/Makefile b/usr/src/lib/libsrpt/Makefile new file mode 100644 index 0000000000..4e049e0fe5 --- /dev/null +++ b/usr/src/lib/libsrpt/Makefile @@ -0,0 +1,53 @@ +# +# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +include $(SRC)/lib/Makefile.lib + +HDRS = libsrpt.h +HDRDIR = common + +SUBDIRS = $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) + +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +install := TARGET= install +install_h := TARGET= install_h +lint := TARGET= lint + +.KEEP_STATE: + +all clean clobber install lint: $(SUBDIRS) + +install_h: $(ROOTHDRS) + +check: $(CHECKHDRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include $(SRC)/lib/Makefile.targ diff --git a/usr/src/lib/libsrpt/Makefile.com b/usr/src/lib/libsrpt/Makefile.com new file mode 100644 index 0000000000..4cc7d1d599 --- /dev/null +++ b/usr/src/lib/libsrpt/Makefile.com @@ -0,0 +1,51 @@ +# +# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +LIBRARY = libsrpt.a +VERS = .1 +OBJECTS = libsrpt.o + +include ../../Makefile.lib + +LIBS = $(DYNLIB) $(LINTLIB) + +SRCDIR = ../common +$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) + +SRPTMODDIR = ../../../uts/common/io/comstar/port/srpt + +INCS += -I$(SRCDIR) -I$(SRPTMODDIR) + +C99MODE = -xc99=%all +C99LMODE = -Xc99=%all +LDLIBS += -lc -lnvpair -lstmf +CPPFLAGS += $(INCS) -D_REENTRANT + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +include ../../Makefile.targ diff --git a/usr/src/lib/libsrpt/amd64/Makefile b/usr/src/lib/libsrpt/amd64/Makefile new file mode 100644 index 0000000000..644e6b23da --- /dev/null +++ b/usr/src/lib/libsrpt/amd64/Makefile @@ -0,0 +1,29 @@ +# +# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +all: $(LIBS) + +install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT) diff --git a/usr/src/lib/libsrpt/common/libsrpt.c b/usr/src/lib/libsrpt/common/libsrpt.c new file mode 100644 index 0000000000..5a89f88568 --- /dev/null +++ b/usr/src/lib/libsrpt/common/libsrpt.c @@ -0,0 +1,493 @@ +/* + * 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 (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <limits.h> +#include <ctype.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <strings.h> +#include <libintl.h> +#include <libscf.h> +#include <libnvpair.h> + +#include <libstmf.h> +#include <libsrpt.h> + +#include "srpt_common.h" + +#define SRPT_PROV_NAME "srpt" + +/* + * Function: srpt_GetConfig() + * + * Parameters: + * cfg Current SRPT configuration in nvlist form + * token Configuration generation number. Use this token + * if updating the configuration with srpt_SetConfig. + * + * Return Values: + * 0 Success + * ENOMEM Could not allocate resources + * EINVAL Invalid parameter + */ +int +srpt_GetConfig(nvlist_t **cfg, uint64_t *token) +{ + int ret = 0; + nvlist_t *cfg_nv = NULL; + uint64_t stmf_token = 0; + nvlist_t *hcanv = NULL; + + if (!cfg) { + return (EINVAL); + } + + *cfg = NULL; + + ret = stmfGetProviderDataProt(SRPT_PROV_NAME, &cfg_nv, + STMF_PORT_PROVIDER_TYPE, &stmf_token); + + if (ret == STMF_STATUS_SUCCESS) { + ret = 0; + } else if (ret == STMF_ERROR_NOT_FOUND) { + /* Not initialized yet */ + ret = nvlist_alloc(&cfg_nv, NV_UNIQUE_NAME, 0); + if (ret != 0) { + return (ret); + } + /* create the HCA list */ + ret = nvlist_alloc(&hcanv, NV_UNIQUE_NAME, 0); + if (ret == 0) { + ret = nvlist_add_nvlist(cfg_nv, SRPT_PROP_HCALIST, + hcanv); + if (ret != 0) { + nvlist_free(hcanv); + } + } + if (ret != 0) { + nvlist_free(cfg_nv); + cfg_nv = NULL; + } + } else if (ret == STMF_ERROR_NOMEM) { + ret = ENOMEM; + } else { + ret = EINVAL; + } + + *cfg = cfg_nv; + *token = stmf_token; + + return (ret); +} + +/* + * Function: srpt_SetConfig() + * + * Parameters: + * cfg SRPT configuration in nvlist form + * token Configuration generation number from srpt_GetConfig. + * Use this token to ensure the configuration hasn't been + * updated by another user since the time it was fetched. + * + * Return Values: + * 0 Success + * ENOMEM Could not allocate resources + * EINVAL Invalid parameter + * ECANCELED Configuration updated by another user + */ +int +srpt_SetConfig(nvlist_t *cfg, uint64_t token) +{ + int ret = 0; + + ret = stmfSetProviderDataProt(SRPT_PROV_NAME, cfg, + STMF_PORT_PROVIDER_TYPE, &token); + + if (ret == STMF_STATUS_SUCCESS) { + ret = 0; + } else if (ret == STMF_ERROR_NOMEM) { + ret = ENOMEM; + } else if (ret == STMF_ERROR_PROV_DATA_STALE) { + ret = ECANCELED; /* could be a better errno */ + } else { + ret = EINVAL; + } + + return (ret); +} + +/* + * Function: srpt_GetDefaultState() + * + * Parameters: + * enabled If B_TRUE, indicates that targets will be created for all + * discovered HCAs that have not been specifically disabled. + * If B_FALSE, targets will not be created unless the HCA has + * been specifically enabled. See also srpt_SetDefaultState(). + * + * Return Values: + * 0 Success + * ENOMEM Could not allocate resources + * EINVAL Invalid parameter + */ +int +srpt_GetDefaultState(boolean_t *enabled) +{ + int ret; + nvlist_t *cfgnv; + uint64_t token; + boolean_t val = B_TRUE; + + if (enabled == NULL) { + return (EINVAL); + } + + ret = srpt_GetConfig(&cfgnv, &token); + if (ret != 0) { + return (ret); + } + + if (cfgnv != NULL) { + ret = nvlist_lookup_boolean_value(cfgnv, + SRPT_PROP_DEFAULT_ENABLED, &val); + + if (ret == ENOENT) { + ret = 0; + } + } + + *enabled = val; + return (ret); +} + +/* + * Function: srpt_SetDefaultState() + * + * Parameters: + * enabled If B_TRUE, indicates that targets will be created for all + * discovered HCAs that have not been specifically disabled. + * If B_FALSE, targets will not be created unless the HCA has + * been specifically enabled. See also srpt_SetDefaultState(). + * + * Return Values: + * 0 Success + * ENOMEM Could not allocate resources + * EINVAL Invalid parameter + */ +int +srpt_SetDefaultState(boolean_t enabled) +{ + int ret; + nvlist_t *cfgnv; + uint64_t token; + + ret = srpt_GetConfig(&cfgnv, &token); + if (ret != 0) { + return (ret); + } + + if (cfgnv == NULL) { + ret = nvlist_alloc(&cfgnv, NV_UNIQUE_NAME, 0); + if (ret != 0) { + return (ret); + } + } + + ret = nvlist_add_boolean_value(cfgnv, SRPT_PROP_DEFAULT_ENABLED, + enabled); + + if (ret == 0) { + ret = srpt_SetConfig(cfgnv, token); + } + + nvlist_free(cfgnv); + + return (ret); +} + +/* + * Function: srpt_SetTargetState() + * + * Parameters: + * hca_guid HCA GUID. See description of srpt_NormalizeGuid + * enabled If B_TRUE, indicates that a target will be created for + * this HCA when the SRPT SMF service is enabled. If B_FALSE, + * a target will not be created + * + * Return Values: + * 0 Success + * ENOMEM Could not allocate resources + * EINVAL Invalid parameter + */ +int +srpt_SetTargetState(char *hca_guid, boolean_t enabled) +{ + int ret; + nvlist_t *cfgnv; + uint64_t token; + nvlist_t *hcalist; + nvlist_t *hcanv; + char guid[32]; + uint64_t hcaguid; + + if (hca_guid == NULL) { + return (EINVAL); + } + + ret = srpt_NormalizeGuid(hca_guid, guid, sizeof (guid), &hcaguid); + if (ret != 0) { + return (ret); + } + + ret = srpt_GetConfig(&cfgnv, &token); + if (ret != 0) { + return (ret); + } + + /* get the list of HCAs */ + ret = nvlist_lookup_nvlist(cfgnv, SRPT_PROP_HCALIST, &hcalist); + if (ret != 0) { + nvlist_free(cfgnv); + return (ret); + } + + ret = nvlist_lookup_nvlist(hcalist, guid, &hcanv); + if (ret == ENOENT) { + /* no entry yet */ + ret = nvlist_alloc(&hcanv, NV_UNIQUE_NAME, 0); + if (ret == 0) { + ret = nvlist_add_uint64(hcanv, SRPT_PROP_GUID, hcaguid); + } + } + + if (ret == 0) { + ret = nvlist_add_boolean_value(hcanv, SRPT_PROP_ENABLED, + enabled); + } + + if (ret == 0) { + ret = nvlist_add_nvlist(hcalist, guid, hcanv); + } + + if (ret == 0) { + ret = srpt_SetConfig(cfgnv, token); + } + + nvlist_free(cfgnv); + + return (ret); +} + +/* + * Function: srpt_GetTargetState() + * + * Parameters: + * hca_guid HCA GUID. See description of srpt_NormalizeGuid + * enabled If B_TRUE, indicates that a target will be created for + * this HCA when the SRPT SMF service is enabled. If B_FALSE, + * a target will not be created + * + * Return Values: + * 0 Success + * ENOMEM Could not allocate resources + * EINVAL Invalid parameter + */ +int +srpt_GetTargetState(char *hca_guid, boolean_t *enabled) +{ + int ret; + nvlist_t *cfgnv; + uint64_t token; + nvlist_t *hcalist; + nvlist_t *hcanv; + boolean_t defaultState = B_TRUE; + char guid[32]; + + if (hca_guid == NULL) { + return (EINVAL); + } + + ret = srpt_NormalizeGuid(hca_guid, guid, sizeof (guid), NULL); + if (ret != 0) { + return (ret); + } + + ret = srpt_GetConfig(&cfgnv, &token); + if (ret != 0) { + return (ret); + } + + /* get the list of HCAs */ + ret = nvlist_lookup_nvlist(cfgnv, SRPT_PROP_HCALIST, &hcalist); + if (ret != 0) { + nvlist_free(cfgnv); + return (ret); + } + + /* + * Find the default, for the likely case that this HCA isn't + * explicitly set. + */ + (void) nvlist_lookup_boolean_value(cfgnv, SRPT_PROP_DEFAULT_ENABLED, + &defaultState); + + ret = nvlist_lookup_nvlist(hcalist, guid, &hcanv); + if (ret == 0) { + ret = nvlist_lookup_boolean_value(hcanv, SRPT_PROP_ENABLED, + enabled); + } + + if (ret == ENOENT) { + /* not explicitly set, use the default */ + *enabled = defaultState; + ret = 0; + } + + nvlist_free(cfgnv); + + return (ret); + +} + +/* + * Function: srpt_ResetTarget() + * + * Clears the HCA-specific configuration. Target creation will revert to + * the default. + * + * Parameters: + * hca_guid HCA GUID. See description of srpt_NormalizeGuid + * + * Return Values: + * 0 Success + * ENOMEM Could not allocate resources + * EINVAL Invalid parameter + */ +int +srpt_ResetTarget(char *hca_guid) +{ + int ret; + nvlist_t *cfgnv; + nvlist_t *hcalist; + uint64_t token; + char guid[32]; + + if (hca_guid == NULL) { + return (EINVAL); + } + + ret = srpt_NormalizeGuid(hca_guid, guid, sizeof (guid), NULL); + if (ret != 0) { + return (ret); + } + + ret = srpt_GetConfig(&cfgnv, &token); + if (ret != 0) { + return (ret); + } + + /* get the list of HCAs */ + ret = nvlist_lookup_nvlist(cfgnv, SRPT_PROP_HCALIST, &hcalist); + if (ret != 0) { + nvlist_free(cfgnv); + return (ret); + } + + /* don't set config if we don't actually change anything */ + if (nvlist_exists(hcalist, guid)) { + (void) nvlist_remove_all(hcalist, guid); + + if (ret == 0) { + ret = srpt_SetConfig(cfgnv, token); + } + } + + nvlist_free(cfgnv); + + return (ret); +} + +/* + * srpt_NormalizeGuid() + * + * Parameters: + * in HCA GUID. Must be in one of the following forms: + * 3BA000100CD18 - base hex form + * 0003BA000100CD18 - base hex form with leading zeroes + * hca:3BA000100CD18 - form from cfgadm and/or /dev/cfg + * eui.0003BA000100CD18 - EUI form + * + * buf Buffer to hold normalized guid string. Must be at least + * 17 chars long. + * buflen Length of provided buffer + * int_guid Optional. If not NULL, the integer form of the GUID will also + * be returned. + * Return Values: + * 0 Success + * EINVAL Invalid HCA GUID or invalid parameter. + */ +int +srpt_NormalizeGuid(char *in, char *buf, size_t buflen, uint64_t *int_guid) +{ + uint64_t guid; + char *bufp = in; + char *end = NULL; + + if ((in == NULL) || (buf == NULL)) { + return (EINVAL); + } + + if (strncasecmp(bufp, "eui.", 4) == 0) { + /* EUI form */ + bufp += 4; + } else if (strncasecmp(bufp, "hca:", 4) == 0) { + /* cfgadm and /dev/hca form */ + bufp += 4; + } + + /* + * strtoull() does not return EINVAL as documented. Lucky + * for us, neither 0 nor ULLONG_MAX will be valid. Trap on + * those and fail. + */ + guid = strtoull(bufp, &end, 16); + if ((guid == 0) || (guid == ULLONG_MAX) || + ((end != NULL) && (strlen(end) > 0))) { + return (EINVAL); + } + +#if 0 + (void) snprintf(buf, buflen, "%llX", guid); +#endif + SRPT_FORMAT_HCAKEY(buf, buflen, guid); + + if (int_guid) { + *int_guid = guid; + } + + return (0); +} diff --git a/usr/src/lib/libsrpt/common/libsrpt.h b/usr/src/lib/libsrpt/common/libsrpt.h new file mode 100644 index 0000000000..8b5d1fe26e --- /dev/null +++ b/usr/src/lib/libsrpt/common/libsrpt.h @@ -0,0 +1,180 @@ +/* + * 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 (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +#ifndef _LIBSRPT_H +#define _LIBSRPT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> +#include <libnvpair.h> + +/* + * Function: srpt_GetConfig() + * + * Parameters: + * cfg Current SRPT configuration in nvlist form + * token Configuration generation number. Use this token + * if updating the configuration with srpt_SetConfig. + * + * Return Values: + * 0 Success + * ENOMEM Could not allocate resources + * EINVAL Invalid parameter + */ +int +srpt_GetConfig(nvlist_t **cfg, uint64_t *token); + +/* + * Function: srpt_SetConfig() + * + * Parameters: + * cfg SRPT configuration in nvlist form + * token Configuration generation number from srpt_GetConfig. + * Use this token to ensure the configuration hasn't been + * updated by another user since the time it was fetched. + * + * Return Values: + * 0 Success + * ENOMEM Could not allocate resources + * EINVAL Invalid parameter + * ECANCELED Configuration updated by another user + */ +int +srpt_SetConfig(nvlist_t *cfg, uint64_t token); + +/* + * Function: srpt_GetDefaultState() + * + * Parameters: + * enabled If B_TRUE, indicates that targets will be created for all + * discovered HCAs that have not been specifically disabled. + * If B_FALSE, targets will not be created unless the HCA has + * been specifically enabled. See also srpt_SetDefaultState(). + * + * Return Values: + * 0 Success + * ENOMEM Could not allocate resources + * EINVAL Invalid parameter + */ +int +srpt_GetDefaultState(boolean_t *enabled); + +/* + * Function: srpt_SetDefaultState() + * + * Parameters: + * enabled If B_TRUE, indicates that targets will be created for all + * discovered HCAs that have not been specifically disabled. + * If B_FALSE, targets will not be created unless the HCA has + * been specifically enabled. See also srpt_SetDefaultState(). + * + * Return Values: + * 0 Success + * ENOMEM Could not allocate resources + * EINVAL Invalid parameter + */ +int +srpt_SetDefaultState(boolean_t enabled); + +/* + * Function: srpt_SetTargetState() + * + * Parameters: + * hca_guid HCA GUID. See description of srpt_NormalizeGuid + * enabled If B_TRUE, indicates that a target will be created for + * this HCA when the SRPT SMF service is enabled. If B_FALSE, + * a target will not be created + * + * Return Values: + * 0 Success + * ENOMEM Could not allocate resources + * EINVAL Invalid parameter + */ +int +srpt_SetTargetState(char *hca_guid, boolean_t enabled); + +/* + * Function: srpt_GetTargetState() + * + * Parameters: + * hca_guid HCA GUID. See description of srpt_NormalizeGuid + * enabled If B_TRUE, indicates that a target will be created for + * this HCA when the SRPT SMF service is enabled. If B_FALSE, + * a target will not be created + * + * Return Values: + * 0 Success + * ENOMEM Could not allocate resources + * EINVAL Invalid parameter + */ +int +srpt_GetTargetState(char *hca_guid, boolean_t *enabled); + +/* + * Function: srpt_ResetTarget() + * + * Clears the HCA-specific configuration. Target creation will revert to + * the default. + * + * Parameters: + * hca_guid HCA GUID. See description of srpt_NormalizeGuid + * + * Return Values: + * 0 Success + * ENOMEM Could not allocate resources + * EINVAL Invalid parameter + */ +int +srpt_ResetTarget(char *hca_guid); + +/* + * srpt_NormalizeGuid() + * + * Parameters: + * in HCA GUID. Must be in one of the following forms: + * 3BA000100CD18 - base hex form + * 0003BA000100CD18 - base hex form with leading zeroes + * hca:3BA000100CD18 - form from cfgadm and/or /dev/cfg + * eui.0003BA000100CD18 - EUI form + * + * buf Buffer to hold normalized guid string. Must be at least + * 17 chars long. + * buflen Length of provided buffer + * int_guid Optional. If not NULL, the integer form of the GUID will also + * be returned. + * Return Values: + * 0 Success + * EINVAL Invalid HCA GUID or invalid parameter. + */ +int +srpt_NormalizeGuid(char *in, char *buf, size_t buflen, uint64_t *int_guid); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBSRPT_H */ diff --git a/usr/src/lib/libsrpt/common/llib-lsrpt b/usr/src/lib/libsrpt/common/llib-lsrpt new file mode 100644 index 0000000000..c807a7d9f5 --- /dev/null +++ b/usr/src/lib/libsrpt/common/llib-lsrpt @@ -0,0 +1,28 @@ +/* + * 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 (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +/*LINTLIBRARY*/ +/*PROTOLIB1*/ + +#include <libsrpt.h> diff --git a/usr/src/lib/libsrpt/common/mapfile-vers b/usr/src/lib/libsrpt/common/mapfile-vers new file mode 100644 index 0000000000..8be8e62a75 --- /dev/null +++ b/usr/src/lib/libsrpt/common/mapfile-vers @@ -0,0 +1,56 @@ +# +# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +# +# MAPFILE HEADER START +# +# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. +# Object versioning must comply with the rules detailed in +# +# usr/src/lib/README.mapfiles +# +# You should not be making modifications here until you've read the most current +# copy of that file. If you need help, contact a gatekeeper for guidance. +# +# MAPFILE HEADER END +# +SUNW_1.1 { + global: + srpt_GetConfig; + srpt_SetConfig; + srpt_GetDefaultState; + srpt_SetDefaultState; + srpt_SetTargetState; + srpt_GetTargetState; + srpt_ResetTarget; + srpt_NormalizeGuid; + local: + *; +}; + +SUNWprivate { + global: + local: + *; +}; + diff --git a/usr/src/lib/libsrpt/i386/Makefile b/usr/src/lib/libsrpt/i386/Makefile new file mode 100644 index 0000000000..f9373d2096 --- /dev/null +++ b/usr/src/lib/libsrpt/i386/Makefile @@ -0,0 +1,26 @@ +# +# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libsrpt/sparc/Makefile b/usr/src/lib/libsrpt/sparc/Makefile new file mode 100644 index 0000000000..3f74bc6793 --- /dev/null +++ b/usr/src/lib/libsrpt/sparc/Makefile @@ -0,0 +1,27 @@ +# +# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved. +# +include ../Makefile.com + +all: $(LIBS) + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libsrpt/sparcv9/Makefile b/usr/src/lib/libsrpt/sparcv9/Makefile new file mode 100644 index 0000000000..8f83585151 --- /dev/null +++ b/usr/src/lib/libsrpt/sparcv9/Makefile @@ -0,0 +1,32 @@ +# +# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +LIBS = $(DYNLIB) $(LINTLIB) + +all: $(LIBS) + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/pkg/manifests/driver-network-srpt.mf b/usr/src/pkg/manifests/driver-network-srpt.mf index b1d28be2be..31dd8c8edf 100644 --- a/usr/src/pkg/manifests/driver-network-srpt.mf +++ b/usr/src/pkg/manifests/driver-network-srpt.mf @@ -20,8 +20,7 @@ # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # set name=pkg.fmri value=pkg:/driver/network/srpt@$(PKGVERS) @@ -44,10 +43,13 @@ dir path=lib opensolaris.zone=global variant.opensolaris.zone=global dir path=lib/svc opensolaris.zone=global variant.opensolaris.zone=global dir path=lib/svc/method opensolaris.zone=global variant.opensolaris.zone=global dir path=usr group=sys +dir path=usr/include dir path=usr/lib +dir path=usr/lib/$(ARCH64) dir path=usr/lib/mdb group=sys dir path=usr/lib/mdb/kvm group=sys dir path=usr/lib/mdb/kvm/$(ARCH64) group=sys +dir path=usr/sbin dir path=lib/svc/manifest group=sys opensolaris.zone=global \ variant.opensolaris.zone=global dir path=lib/svc/manifest/system group=sys opensolaris.zone=global \ @@ -67,10 +69,19 @@ $(i386_ONLY)file path=kernel/kmdb/srpt group=sys mode=0555 \ opensolaris.zone=global reboot-needed=true variant.opensolaris.zone=global file path=lib/svc/method/svc-srpt mode=0555 opensolaris.zone=global \ variant.opensolaris.zone=global +file path=usr/include/libsrpt.h +file path=usr/lib/$(ARCH64)/libsrpt.so.1 +file path=usr/lib/$(ARCH64)/llib-lsrpt.ln +file path=usr/lib/libsrpt.so.1 +file path=usr/lib/llib-lsrpt +file path=usr/lib/llib-lsrpt.ln file path=usr/lib/mdb/kvm/$(ARCH64)/srpt.so group=sys mode=0555 $(i386_ONLY)file path=usr/lib/mdb/kvm/srpt.so group=sys mode=0555 +file path=usr/sbin/srptadm mode=0555 file path=lib/svc/manifest/system/ibsrp/target.xml group=sys mode=0444 \ opensolaris.zone=global variant.opensolaris.zone=global +link path=usr/lib/libsrpt.so target=libsrpt.so.1 +link path=usr/lib/$(ARCH64)/libsrpt.so target=libsrpt.so.1 legacy pkg=SUNWsrptr arch=$(ARCH) category=system \ desc="Sun SRP COMSTAR Port Provider (Root)" \ hotline="Please contact your local service provider" \ diff --git a/usr/src/uts/common/io/comstar/port/srpt/srpt_common.h b/usr/src/uts/common/io/comstar/port/srpt/srpt_common.h new file mode 100644 index 0000000000..fa8a688a3a --- /dev/null +++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_common.h @@ -0,0 +1,54 @@ +/* + * 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 (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +#ifndef _SRPT_COMMON_H_ +#define _SRPT_COMMON_H_ + +/* + * Definitions common to both the SRP Target kernel module and the + * user-space library and administrative command. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Configuration nvlist keys */ + +#define SRPT_PROP_HCALIST "HCAs" +#define SRPT_PROP_DEFAULT_ENABLED "default_enabled" +#define SRPT_PROP_GUID "guid" +#define SRPT_PROP_ENABLED "enabled" + +/* Format the HCA key */ +#define SRPT_FORMAT_HCAKEY(b, l, g) \ + ((void) snprintf(b, l, "%llX", g)) + + +#ifdef __cplusplus +} +#endif + +#endif /* _SRPT_COMMON_H_ */ diff --git a/usr/src/uts/common/io/comstar/port/srpt/srpt_impl.h b/usr/src/uts/common/io/comstar/port/srpt/srpt_impl.h index 864513595a..ebb7d7a8eb 100644 --- a/usr/src/uts/common/io/comstar/port/srpt/srpt_impl.h +++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_impl.h @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SRPT_IMPL_H_ @@ -446,6 +445,12 @@ typedef struct srpt_ctxt_s { /* IBDMA entry points */ srpt_ibdma_ops_t sc_ibdma_ops; + + /* + * List of explicitly configured HCAs and their configurable + * attributes. + */ + nvlist_t *sc_cfg_hca_nv; } srpt_ctxt_t; typedef struct srpt_iu_data_s { diff --git a/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.c b/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.c index 3b5f48c388..edd06e7ddd 100644 --- a/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.c +++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -43,15 +42,17 @@ #include "srpt_ioc.h" #include "srpt_stp.h" #include "srpt_ch.h" +#include "srpt_common.h" /* * srpt_ioc_srq_size - Tunable parameter that specifies the number * of receive WQ entries that can be posted to the IOC shared * receive queue. */ -uint32_t srpt_ioc_srq_size = SRPT_DEFAULT_IOC_SRQ_SIZE; -extern uint16_t srpt_send_msg_depth; -extern uint32_t srpt_iu_size; +uint32_t srpt_ioc_srq_size = SRPT_DEFAULT_IOC_SRQ_SIZE; +extern uint16_t srpt_send_msg_depth; +extern uint32_t srpt_iu_size; +extern boolean_t srpt_enable_by_default; /* IOC profile capabilities mask must be big-endian */ typedef struct srpt_ioc_opcap_bits_s { @@ -115,6 +116,7 @@ static struct ibt_clnt_modinfo_s srpt_ibt_modinfo = { static srpt_ioc_t *srpt_ioc_init(ib_guid_t guid); static void srpt_ioc_fini(srpt_ioc_t *ioc); +static boolean_t srpt_check_hca_cfg_enabled(ib_guid_t hca_guid); static srpt_vmem_pool_t *srpt_vmem_create(const char *name, srpt_ioc_t *ioc, ib_memlen_t chunksize, uint64_t maxsize, ibt_mr_flags_t flags); @@ -144,7 +146,6 @@ srpt_ioc_attach() int hca_cnt; int hca_ndx; ib_guid_t *guid; - srpt_ioc_t *ioc; ASSERT(srpt_ctxt != NULL); @@ -171,19 +172,9 @@ srpt_ioc_attach() } for (hca_ndx = 0; hca_ndx < hca_cnt; hca_ndx++) { - SRPT_DPRINTF_L2("ioc_attach, adding I/O" - " Controller (%016llx)", (u_longlong_t)guid[hca_ndx]); - - ioc = srpt_ioc_init(guid[hca_ndx]); - if (ioc == NULL) { - SRPT_DPRINTF_L1("ioc_attach, ioc_init GUID(%016llx)" - " failed", (u_longlong_t)guid[hca_ndx]); - continue; - } - list_insert_tail(&srpt_ctxt->sc_ioc_list, ioc); - SRPT_DPRINTF_L2("ioc_attach, I/O Controller ibt HCA hdl (%p)", - (void *)ioc->ioc_ibt_hdl); - srpt_ctxt->sc_num_iocs++; + SRPT_DPRINTF_L2("ioc_attach, attaching HCA %016llx", + (u_longlong_t)guid[hca_ndx]); + srpt_ioc_attach_hca(guid[hca_ndx], B_FALSE); } ibt_free_hca_list(guid, hca_cnt); @@ -193,6 +184,156 @@ srpt_ioc_attach() } /* + * Initialize I/O Controllers. sprt_ctxt->sc_rwlock must be locked by the + * caller. + * + * 'checked' indicates no need to lookup the hca in the HCA configuration + * list. + */ +void +srpt_ioc_attach_hca(ib_guid_t hca_guid, boolean_t checked) +{ + boolean_t enable_hca = B_TRUE; + srpt_ioc_t *ioc; + + if (!checked) { + enable_hca = srpt_check_hca_cfg_enabled(hca_guid); + + if (!enable_hca) { + /* nothing to do */ + SRPT_DPRINTF_L2( + "ioc_attach_hca, HCA %016llx disabled " + "by srpt config", + (u_longlong_t)hca_guid); + return; + } + } + + SRPT_DPRINTF_L2("ioc_attach_hca, adding I/O" + " Controller (%016llx)", (u_longlong_t)hca_guid); + + ioc = srpt_ioc_init(hca_guid); + if (ioc == NULL) { + /* + * IOC already exists or an error occurred. Already + * logged by srpt_ioc_init() + */ + return; + } + + /* + * Create the COMSTAR SRP Target for this IOC. If this fails, + * remove the IOC. + */ + rw_enter(&ioc->ioc_rwlock, RW_WRITER); + ioc->ioc_tgt_port = srpt_stp_alloc_port(ioc, ioc->ioc_guid); + if (ioc->ioc_tgt_port == NULL) { + SRPT_DPRINTF_L1("ioc_attach_hca: alloc SCSI" + " Target Port error on GUID(%016llx)", + (u_longlong_t)ioc->ioc_guid); + rw_exit(&ioc->ioc_rwlock); + srpt_ioc_fini(ioc); + return; + } + rw_exit(&ioc->ioc_rwlock); + + /* + * New HCA added with default SCSI Target Port, SRP service + * will be started when SCSI Target Port is brought + * on-line by STMF. + */ + list_insert_tail(&srpt_ctxt->sc_ioc_list, ioc); + SRPT_DPRINTF_L2("ioc_attach_hca, I/O Controller ibt HCA hdl (%p)", + (void *)ioc->ioc_ibt_hdl); + + srpt_ctxt->sc_num_iocs++; +} + +/* + * srpt_check_hca_cfg_enabled() + * + * Function to check the configuration for the enabled status of a given + * HCA. Returns B_TRUE if SRPT services should be activated for this HCA, + * B_FALSE if it should be disabled. + */ +static boolean_t +srpt_check_hca_cfg_enabled(ib_guid_t hca_guid) +{ + int status; + char buf[32]; + nvlist_t *hcanv; + boolean_t enable_hca; + + enable_hca = srpt_enable_by_default; + + SRPT_FORMAT_HCAKEY(buf, sizeof (buf), (u_longlong_t)hca_guid); + + if (srpt_ctxt->sc_cfg_hca_nv != NULL) { + status = nvlist_lookup_nvlist(srpt_ctxt->sc_cfg_hca_nv, + buf, &hcanv); + if (status == 0) { + SRPT_DPRINTF_L3("check_hca_cfg, found guid %s", buf); + (void) nvlist_lookup_boolean_value(hcanv, + SRPT_PROP_ENABLED, &enable_hca); + } else { + SRPT_DPRINTF_L3("check_hca_cfg, did not find guid %s", + buf); + } + } + + return (enable_hca); +} + +/* + * srpt_ioc_update() + * + * Using the configuration nvlist, enables or disables SRP services + * the provided HCAs. srpt_ctxt->sc_rwlock should be held outside of this call. + */ +void +srpt_ioc_update(void) +{ + boolean_t enabled; + nvpair_t *nvp = NULL; + uint64_t hca_guid; + nvlist_t *nvl; + nvlist_t *cfg = srpt_ctxt->sc_cfg_hca_nv; + + if (cfg == NULL) { + SRPT_DPRINTF_L2("ioc_update, no configuration data"); + return; + } + + while ((nvp = nvlist_next_nvpair(cfg, nvp)) != NULL) { + enabled = srpt_enable_by_default; + + if ((nvpair_value_nvlist(nvp, &nvl)) != 0) { + SRPT_DPRINTF_L2("ioc_update, did not find an nvlist"); + continue; + } + + if ((nvlist_lookup_uint64(nvl, SRPT_PROP_GUID, &hca_guid)) + != 0) { + SRPT_DPRINTF_L2("ioc_update, did not find a guid"); + continue; + } + + (void) nvlist_lookup_boolean_value(nvl, SRPT_PROP_ENABLED, + &enabled); + + if (enabled) { + SRPT_DPRINTF_L2("ioc_update, enabling guid %016llx", + (u_longlong_t)hca_guid); + srpt_ioc_attach_hca(hca_guid, B_TRUE); + } else { + SRPT_DPRINTF_L2("ioc_update, disabling guid %016llx", + (u_longlong_t)hca_guid); + srpt_ioc_detach_hca(hca_guid); + } + } +} + +/* * srpt_ioc_detach() - I/O Controller detach * * srpt_ctxt->sc_rwlock should be held outside of this call. @@ -202,23 +343,79 @@ srpt_ioc_detach() { srpt_ioc_t *ioc; - ASSERT(srpt_ctxt != NULL); - + /* + * All SRP targets must be destroyed before calling this + * function. + */ while ((ioc = list_head(&srpt_ctxt->sc_ioc_list)) != NULL) { - list_remove(&srpt_ctxt->sc_ioc_list, ioc); SRPT_DPRINTF_L2("ioc_detach, removing I/O Controller(%p)" " (%016llx), ibt_hdl(%p)", (void *)ioc, ioc ? (u_longlong_t)ioc->ioc_guid : 0x0ll, (void *)ioc->ioc_ibt_hdl); + + list_remove(&srpt_ctxt->sc_ioc_list, ioc); + ASSERT(ioc->ioc_tgt_port != NULL); srpt_ioc_fini(ioc); + srpt_ctxt->sc_num_iocs--; } - (void) ibt_detach(srpt_ctxt->sc_ibt_hdl); srpt_ctxt->sc_ibt_hdl = NULL; } /* + * srpt_ioc_detach_hca() + * + * Stop SRP Target services on this HCA + * + * Note that this is not entirely synchronous with srpt_ioc_attach_hca() + * in that we don't need to check the configuration to know whether to + * disable an HCA. We get here either because the IB framework has told + * us the HCA has been detached, or because the administrator has explicitly + * disabled this HCA. + * + * Must be called with srpt_ctxt->sc_rwlock locked as RW_WRITER. + */ +void +srpt_ioc_detach_hca(ib_guid_t hca_guid) +{ + srpt_ioc_t *ioc; + srpt_target_port_t *tgt; + stmf_status_t stmf_status = STMF_SUCCESS; + + ioc = srpt_ioc_get_locked(hca_guid); + if (ioc == NULL) { + /* doesn't exist, nothing to do */ + return; + } + + rw_enter(&ioc->ioc_rwlock, RW_WRITER); + tgt = ioc->ioc_tgt_port; + + if (tgt != NULL) { + stmf_status = srpt_stp_destroy_port(tgt); + if (stmf_status == STMF_SUCCESS) { + ioc->ioc_tgt_port = NULL; + (void) srpt_stp_free_port(tgt); + } + } + + rw_exit(&ioc->ioc_rwlock); + + if (stmf_status != STMF_SUCCESS) { + /* should never happen */ + return; + } + + list_remove(&srpt_ctxt->sc_ioc_list, ioc); + srpt_ctxt->sc_num_iocs--; + + srpt_ioc_fini(ioc); + SRPT_DPRINTF_L2("ioc_detach_hca, HCA %016llx detached", + (u_longlong_t)hca_guid); +} + +/* * srpt_ioc_init() - I/O Controller initialization * * Requires srpt_ctxt->rw_lock be held outside of call. @@ -248,7 +445,7 @@ srpt_ioc_init(ib_guid_t guid) ioc = srpt_ioc_get_locked(guid); if (ioc != NULL) { - SRPT_DPRINTF_L1("ioc_init, HCA already exists"); + SRPT_DPRINTF_L2("ioc_init, HCA already exists"); return (NULL); } @@ -701,7 +898,6 @@ void srpt_ioc_ib_async_hdlr(void *clnt, ibt_hca_hdl_t hdl, ibt_async_code_t code, ibt_async_event_t *event) { - srpt_ioc_t *ioc; srpt_channel_t *ch; switch (code) { @@ -714,47 +910,26 @@ srpt_ioc_ib_async_hdlr(void *clnt, ibt_hca_hdl_t hdl, break; case IBT_HCA_ATTACH_EVENT: - rw_enter(&srpt_ctxt->sc_rwlock, RW_WRITER); - ioc = srpt_ioc_init(event->ev_hca_guid); - - if (ioc == NULL) { - rw_exit(&srpt_ctxt->sc_rwlock); - SRPT_DPRINTF_L1("ib_async_hdlr, HCA_ATTACH" - " event failed to initialize HCA (0x%016llx)", - (u_longlong_t)event->ev_hca_guid); - return; - } - SRPT_DPRINTF_L2("HCA_ATTACH_EVENT: I/O Controller" - " ibt hdl (%p)", - (void *)ioc->ioc_ibt_hdl); - - rw_enter(&ioc->ioc_rwlock, RW_WRITER); - ioc->ioc_tgt_port = srpt_stp_alloc_port(ioc, ioc->ioc_guid); - if (ioc->ioc_tgt_port == NULL) { - SRPT_DPRINTF_L1("ioc_ib_async_hdlr, alloc SCSI " - "target port error for HCA (0x%016llx)", - (u_longlong_t)event->ev_hca_guid); - rw_exit(&ioc->ioc_rwlock); - srpt_ioc_fini(ioc); - rw_exit(&srpt_ctxt->sc_rwlock); - return; - } - - /* - * New HCA added with default SCSI Target Port, SRP service - * will be started when SCSI Target Port is brought - * on-line by STMF. - */ - srpt_ctxt->sc_num_iocs++; - list_insert_tail(&srpt_ctxt->sc_ioc_list, ioc); + SRPT_DPRINTF_L2( + "ib_async_hdlr, received attach event for HCA 0x%016llx", + (u_longlong_t)event->ev_hca_guid); - rw_exit(&ioc->ioc_rwlock); + rw_enter(&srpt_ctxt->sc_rwlock, RW_WRITER); + srpt_ioc_attach_hca(event->ev_hca_guid, B_FALSE); rw_exit(&srpt_ctxt->sc_rwlock); + break; case IBT_HCA_DETACH_EVENT: SRPT_DPRINTF_L1( - "ioc_iob_async_hdlr, HCA_DETACH_EVENT received."); + "ioc_iob_async_hdlr, received HCA_DETACH_EVENT for " + "HCA 0x%016llx", + (u_longlong_t)event->ev_hca_guid); + + rw_enter(&srpt_ctxt->sc_rwlock, RW_WRITER); + srpt_ioc_detach_hca(event->ev_hca_guid); + rw_exit(&srpt_ctxt->sc_rwlock); + break; case IBT_EVENT_EMPTY_CHAN: @@ -1445,7 +1620,7 @@ srpt_dereg_mem(srpt_ioc_t *ioc, srpt_mr_t *mr) status = ibt_deregister_mr(ioc->ioc_ibt_hdl, mr->mr_hdl); if (status != IBT_SUCCESS) { - SRPT_DPRINTF_L1("ioc_fini, error deregistering MR (%d)", + SRPT_DPRINTF_L1("srpt_dereg_mem, error deregistering MR (%d)", status); } kmem_free(mr, sizeof (srpt_mr_t)); diff --git a/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.h b/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.h index f9c6fab614..20f9392366 100644 --- a/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.h +++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_ioc.h @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SRPT_IOC_H @@ -38,7 +37,10 @@ extern "C" { #include "srpt_impl.h" int srpt_ioc_attach(); +void srpt_ioc_attach_hca(ib_guid_t hca_guid, boolean_t checked); void srpt_ioc_detach(); +void srpt_ioc_detach_hca(ib_guid_t hca_guid); +void srpt_ioc_update(void); void srpt_ioc_init_profile(srpt_ioc_t *ioc); ibt_status_t srpt_ioc_svc_bind(srpt_target_port_t *tgt, uint_t portnum); void srpt_ioc_svc_unbind(srpt_target_port_t *tgt, uint_t portnum); diff --git a/usr/src/uts/common/io/comstar/port/srpt/srpt_mod.c b/usr/src/uts/common/io/comstar/port/srpt/srpt_mod.c index 12d5d0f79e..829d67eca8 100644 --- a/usr/src/uts/common/io/comstar/port/srpt/srpt_mod.c +++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_mod.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -51,10 +50,21 @@ #include "srpt_stp.h" #include "srpt_cm.h" #include "srpt_ioctl.h" +#include "srpt_common.h" #define SRPT_NAME_VERSION "COMSTAR SRP Target" /* + * srpt_enable_by_default - configurable parameter that + * determines whether targets are created automatically for + * all HCAs when the service is enabled. + * + * B_TRUE is the legacy default as srpt originally shipped + * this way. Changing it to false is highly desirable. + */ +boolean_t srpt_enable_by_default = B_TRUE; + +/* * srpt_send_msg_depth - Tunable parameter that specifies the * maximum messages that could be in flight for a channel. */ @@ -166,6 +176,8 @@ _init(void) /* Start-up state is DISABLED. SMF will tell us if we should enable. */ srpt_ctxt->sc_svc_state = SRPT_SVC_DISABLED; + list_create(&srpt_ctxt->sc_ioc_list, sizeof (srpt_ioc_t), + offsetof(srpt_ioc_t, ioc_node)); list_create(&srpt_ctxt->sc_ioc_list, sizeof (srpt_ioc_t), offsetof(srpt_ioc_t, ioc_node)); @@ -294,7 +306,6 @@ static int srpt_enable_srp_services(void) { int status; - srpt_ioc_t *ioc; ASSERT((rw_read_locked(&srpt_ctxt->sc_rwlock)) == 0); @@ -314,7 +325,9 @@ srpt_enable_srp_services(void) } /* - * Initialize IB resources, creating a list of SRP I/O Controllers. + * Initialize IB resources, creating a list of SRP I/O Controllers + * and for each controller, register the SCSI Target Port with STMF + * and prepare profile and services. */ status = srpt_ioc_attach(); if (status != DDI_SUCCESS) { @@ -323,32 +336,17 @@ srpt_enable_srp_services(void) goto err_exit_2; } - /* Not an error if no iocs yet; we will listen for ATTACH events */ + /* + * No configured controllers is not a fatal error. This can happen + * if all HCAs are currently disabled for use by SRP. The service + * should remain running in case the user changes their mind and + * enables an HCA for SRP services. + */ if (srpt_ctxt->sc_num_iocs == 0) { SRPT_DPRINTF_L2("enable_srp: no IB I/O Controllers found"); return (DDI_SUCCESS); } - /* - * For each I/O Controller register the default SCSI Target Port - * with STMF, and prepare profile and services. SRP will not - * start until the associated LPORT is brought on-line. - */ - ioc = list_head(&srpt_ctxt->sc_ioc_list); - - while (ioc != NULL) { - rw_enter(&ioc->ioc_rwlock, RW_WRITER); - ioc->ioc_tgt_port = srpt_stp_alloc_port(ioc, ioc->ioc_guid); - if (ioc->ioc_tgt_port == NULL) { - SRPT_DPRINTF_L1("enable_srp: alloc SCSI" - " Target Port error on GUID(%016llx)", - (u_longlong_t)ioc->ioc_guid); - } - - rw_exit(&ioc->ioc_rwlock); - ioc = list_next(&srpt_ctxt->sc_ioc_list, ioc); - } - return (DDI_SUCCESS); err_exit_2: @@ -383,6 +381,11 @@ srpt_drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) ddi_remove_minor_node(dip, NULL); srpt_ctxt->sc_dip = NULL; + if (srpt_ctxt->sc_cfg_hca_nv != NULL) { + nvlist_free(srpt_ctxt->sc_cfg_hca_nv); + srpt_ctxt->sc_cfg_hca_nv = NULL; + } + rw_exit(&srpt_ctxt->sc_rwlock); break; @@ -407,7 +410,6 @@ static int srpt_disable_srp_services(void) { stmf_status_t stmf_status; - stmf_change_status_t cstatus; srpt_ioc_t *ioc; srpt_target_port_t *tgt; int ret_status = 0; @@ -421,57 +423,17 @@ srpt_disable_srp_services(void) ioc = list_head(&srpt_ctxt->sc_ioc_list); while (ioc != NULL) { - /* - * Notify STMF to take the I/O Controller SCSI Target Port(s) - * off-line after we mark them as disabled so that they will - * stay off-line. - */ rw_enter(&ioc->ioc_rwlock, RW_WRITER); tgt = ioc->ioc_tgt_port; if (tgt != NULL) { - mutex_enter(&tgt->tp_lock); - tgt->tp_drv_disabled = 1; - mutex_exit(&tgt->tp_lock); - - SRPT_DPRINTF_L2("disable_srp: unbind and de-register" - " services for GUID(%016llx)", - (u_longlong_t)ioc->ioc_guid); - - cstatus.st_completion_status = STMF_SUCCESS; - cstatus.st_additional_info = NULL; - - stmf_status = stmf_ctl(STMF_CMD_LPORT_OFFLINE, - tgt->tp_lport, &cstatus); - - /* - * Wait for asynchronous target off-line operation - * to complete and then deregister the target - * port. - */ - mutex_enter(&tgt->tp_lock); - while (tgt->tp_state != SRPT_TGT_STATE_OFFLINE) { - cv_wait(&tgt->tp_offline_complete, - &tgt->tp_lock); - } - mutex_exit(&tgt->tp_lock); - ioc->ioc_tgt_port = NULL; - - SRPT_DPRINTF_L3("disable_srp: IOC (0x%016llx) Target" - " SRP off-line complete", - (u_longlong_t)ioc->ioc_guid); - - stmf_status = srpt_stp_deregister_port(tgt); - if (stmf_status != STMF_SUCCESS) { - /* Fails if I/O is pending */ - if (ret_status == 0) { - ret_status = EBUSY; - } - SRPT_DPRINTF_L1("disable_srp: could not" - " de-register LPORT, err(0x%llx)", - (u_longlong_t)stmf_status); - } else { + stmf_status = srpt_stp_destroy_port(tgt); + if (stmf_status == STMF_SUCCESS) { + ioc->ioc_tgt_port = NULL; (void) srpt_stp_free_port(tgt); + } else { + ret_status = DDI_FAILURE; + break; } } @@ -586,11 +548,90 @@ srpt_drv_ioctl(dev_t drv, int cmd, intptr_t argp, int flag, cred_t *cred, static void srpt_pp_cb(stmf_port_provider_t *pp, int cmd, void *arg, uint32_t flags) { - SRPT_DPRINTF_L3("srpt_pp_cb, invoked (%d)", cmd); + int ret; + nvlist_t *in_nvl = (nvlist_t *)arg; + nvlist_t *nvl = NULL; + nvlist_t *hcalist; + nvlist_t *ctxt_nvl; + boolean_t defaultEnabled = B_TRUE; + boolean_t called_by_reg = B_TRUE; + + SRPT_DPRINTF_L2("srpt_pp_cb, invoked (%d)", cmd); + + if (cmd != STMF_PROVIDER_DATA_UPDATED) { + return; + } + /* - * We don't currently utilize the port provider call-back, in the - * future we might use it to synchronize provider data via STMF. + * If STMF_PCB_PREG_COMPLETE is set in the flags, we're being + * called back during provider registration with STMF. + * (while we're calling stmf_register_port_provider()). + * srpt_enable_service() already holds the sc_wrlock, and will + * make sure the configuration is activated, so we just need to + * set the config and get out. If this function is called at any + * time other than SRPT service start, need to grab the sc_wrlock + * as WRITER. */ + if (!(flags & STMF_PCB_PREG_COMPLETE)) { + SRPT_DPRINTF_L2( + "srpt_pp_cb: called after registration"); + called_by_reg = B_FALSE; + rw_enter(&srpt_ctxt->sc_rwlock, RW_WRITER); + } else { + called_by_reg = B_TRUE; + SRPT_DPRINTF_L2( + "srpt_pp_cb: called as part of registration"); + } + + if (in_nvl != NULL) { + /* copy nvlist */ + ret = nvlist_lookup_nvlist(in_nvl, SRPT_PROP_HCALIST, &hcalist); + if (ret != 0) { + SRPT_DPRINTF_L1( + "srpt_pp_cb: Could not read hca config, err=%d", + ret); + return; + } + + ret = nvlist_dup(hcalist, &nvl, 0); + if (ret != 0) { + SRPT_DPRINTF_L1( + "srpt_pp_cb: Could not copy hca config, err=%d", + ret); + return; + } + if (nvlist_lookup_boolean_value(in_nvl, + SRPT_PROP_DEFAULT_ENABLED, &defaultEnabled) == 0) { + /* set whether targets are created by default */ + SRPT_DPRINTF_L2( + "srpt_pp_cb: setting default enabled = %d\n", + (int)defaultEnabled); + srpt_enable_by_default = defaultEnabled; + } + } else { + SRPT_DPRINTF_L2( + "srpt_pp_cb: null config received"); + } + + /* put list in ctxt and set default state */ + ctxt_nvl = srpt_ctxt->sc_cfg_hca_nv; + + /* set new config, NULL is valid */ + srpt_ctxt->sc_cfg_hca_nv = nvl; + + /* free the old nvlist */ + if (ctxt_nvl != NULL) { + nvlist_free(ctxt_nvl); + } + + if (called_by_reg) { + return; + } + + /* Update the HCA based on the new config */ + srpt_ioc_update(); + + rw_exit(&srpt_ctxt->sc_rwlock); } static int diff --git a/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.c b/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.c index 62fc86c4a6..d7da726086 100644 --- a/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.c +++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -445,39 +444,75 @@ srpt_stp_free_port(srpt_target_port_t *tgt) } /* - * srpt_stp_deregister_port() + * srpt_stp_destroy_port() */ stmf_status_t -srpt_stp_deregister_port(srpt_target_port_t *tgt) +srpt_stp_destroy_port(srpt_target_port_t *tgt) { stmf_status_t status; + stmf_change_status_t cstatus; + uint64_t guid; ASSERT(tgt != NULL); ASSERT(tgt->tp_lport != NULL); - SRPT_DPRINTF_L3("stp_deregister_port, de-register STMF LPORT"); + SRPT_DPRINTF_L3("stp_destroy_port, de-register STMF LPORT"); -retry_deregistration: - status = stmf_deregister_local_port(tgt->tp_lport); - if (status == STMF_SUCCESS) { - SRPT_DPRINTF_L3("stp_deregister_port, LPORT de-register" - " complete"); - return (status); + mutex_enter(&tgt->tp_lock); + if (tgt->tp_drv_disabled != 0) { + /* already being destroyed, get out now - should not happen */ + mutex_exit(&tgt->tp_lock); + return (STMF_ALREADY); } + + tgt->tp_drv_disabled = 1; + guid = tgt->tp_ioc->ioc_guid; + mutex_exit(&tgt->tp_lock); + + SRPT_DPRINTF_L2("stp_destroy_port: unbind and de-register" + " services for GUID(%016llx)", (u_longlong_t)guid); + + cstatus.st_completion_status = STMF_SUCCESS; + cstatus.st_additional_info = NULL; + + status = stmf_ctl(STMF_CMD_LPORT_OFFLINE, tgt->tp_lport, &cstatus); + /* - * This is only done on an administrative thread of - * execution so it is ok to take a while. + * Wait for asynchronous target off-line operation + * to complete and then deregister the target + * port. */ - if (status == STMF_BUSY) { - delay(drv_usectohz(1000000)); - goto retry_deregistration; + mutex_enter(&tgt->tp_lock); + while (tgt->tp_state != SRPT_TGT_STATE_OFFLINE) { + cv_wait(&tgt->tp_offline_complete, &tgt->tp_lock); + } + mutex_exit(&tgt->tp_lock); + + SRPT_DPRINTF_L3("stp_destroy_port: IOC (0x%016llx) Target" + " SRP off-line complete", (u_longlong_t)guid); + + /* loop waiting for all I/O to drain */ + for (;;) { + status = stmf_deregister_local_port(tgt->tp_lport); + if (status == STMF_BUSY) { + delay(drv_usectohz(1000000)); + } else { + break; + } + } + + if (status == STMF_SUCCESS) { + SRPT_DPRINTF_L3("stp_destroy_port, LPORT de-register" + " complete"); + } else { + /* + * Something other than a BUSY error, this should not happen. + */ + SRPT_DPRINTF_L1( + "stp_destroy_port, de-register STMF error(0x%llx)", + (u_longlong_t)status); } - /* - * Something other than a BUSY error, this should not happen. - */ - SRPT_DPRINTF_L1("stp_deregister_port, de-register STMF error(0x%llx)", - (u_longlong_t)status); return (status); } diff --git a/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.h b/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.h index e1bd099b05..f22a44a600 100644 --- a/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.h +++ b/usr/src/uts/common/io/comstar/port/srpt/srpt_stp.h @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SRPT_STP_H @@ -43,7 +42,7 @@ int srpt_stp_start_srp(srpt_target_port_t *tgt); void srpt_stp_stop_srp(srpt_target_port_t *tgt); srpt_target_port_t *srpt_stp_alloc_port(srpt_ioc_t *ioc, ib_guid_t guid); stmf_status_t srpt_stp_free_port(srpt_target_port_t *tgt); -stmf_status_t srpt_stp_deregister_port(srpt_target_port_t *tgt); +stmf_status_t srpt_stp_destroy_port(srpt_target_port_t *tgt); srpt_session_t *srpt_stp_alloc_session(srpt_target_port_t *tgt, uint8_t *i_id, uint8_t *t_id, uint8_t port, |