summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorJohn Sonnenschein <johns@joyent.com>2012-01-12 21:43:07 +0000
committerJohn Sonnenschein <johns@joyent.com>2012-01-12 21:43:07 +0000
commitffd3d51cda0d52ac103aaa51865ea8b99ce2bc39 (patch)
treecaccc892b2859e382f40b29bf961281341b6e99c /usr/src
parent1636e739ebc2ac80c49a1e69f71fda812db48850 (diff)
parent9aac36a25d67d80901ad3284d1c2045d3d1a6d64 (diff)
downloadillumos-joyent-ffd3d51cda0d52ac103aaa51865ea8b99ce2bc39.tar.gz
Merge branch 'master' into gcc4
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/boot/bootadm/bootadm_upgrade.c1
-rw-r--r--usr/src/cmd/prtconf/prtconf.c48
-rw-r--r--usr/src/cmd/prtconf/prtconf.h2
-rw-r--r--usr/src/cmd/sendmail/src/Makefile10
-rw-r--r--usr/src/cmd/sendmail/src/sasl.c287
-rw-r--r--usr/src/cmd/tr/str.c6
-rw-r--r--usr/src/cmd/zoneadmd/Makefile43
-rw-r--r--usr/src/cmd/zoneadmd/Makefile.com68
-rw-r--r--usr/src/cmd/zoneadmd/amd64/Makefile31
-rw-r--r--usr/src/cmd/zoneadmd/i386/Makefile30
-rw-r--r--usr/src/cmd/zoneadmd/mcap.c58
-rw-r--r--usr/src/cmd/zoneadmd/vplat.c20
-rw-r--r--usr/src/lib/brand/joyent/zone/statechange.ksh81
-rwxr-xr-xusr/src/lib/brand/kvm/zone/statechange.ksh67
-rw-r--r--usr/src/lib/libzfs/common/libzfs_pool.c2
-rw-r--r--usr/src/man/man1m/prtconf.1m13
-rw-r--r--usr/src/man/man1m/zfs.1m40
-rw-r--r--usr/src/man/man3tecla/gl_get_line.3tecla2
-rw-r--r--usr/src/uts/common/disp/cmt.c6
-rw-r--r--usr/src/uts/common/disp/cpucaps.c229
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_tree.c2
-rw-r--r--usr/src/uts/common/inet/tcp/tcp_timers.c6
-rw-r--r--usr/src/uts/common/io/dld/dld_proto.c35
-rw-r--r--usr/src/uts/common/io/dls/dls.c66
-rw-r--r--usr/src/uts/common/io/igb/igb_82575.c286
-rw-r--r--usr/src/uts/common/io/igb/igb_82575.h4
-rw-r--r--usr/src/uts/common/io/igb/igb_api.c6
-rw-r--r--usr/src/uts/common/io/igb/igb_defines.h16
-rw-r--r--usr/src/uts/common/io/igb/igb_hw.h5
-rw-r--r--usr/src/uts/common/io/igb/igb_main.c41
-rw-r--r--usr/src/uts/common/io/igb/igb_regs.h10
-rw-r--r--usr/src/uts/common/io/mac/mac_sched.c17
-rw-r--r--usr/src/uts/common/io/sata/impl/sata.c2
-rw-r--r--usr/src/uts/common/os/timer.c23
-rw-r--r--usr/src/uts/common/os/zone.c84
-rw-r--r--usr/src/uts/common/sys/cpucaps.h5
-rw-r--r--usr/src/uts/common/sys/cpucaps_impl.h6
-rw-r--r--usr/src/uts/common/sys/vm_usage.h4
-rw-r--r--usr/src/uts/common/vm/vm_usage.c87
39 files changed, 1527 insertions, 222 deletions
diff --git a/usr/src/cmd/boot/bootadm/bootadm_upgrade.c b/usr/src/cmd/boot/bootadm/bootadm_upgrade.c
index ddf28c4a25..92156bf877 100644
--- a/usr/src/cmd/boot/bootadm/bootadm_upgrade.c
+++ b/usr/src/cmd/boot/bootadm/bootadm_upgrade.c
@@ -124,7 +124,6 @@ get_boot_cap(const char *osroot)
}
if (!is_grub(osroot)) {
- bam_error(NOT_GRUB_ROOT, osroot);
return (BAM_ERROR);
}
diff --git a/usr/src/cmd/prtconf/prtconf.c b/usr/src/cmd/prtconf/prtconf.c
index 4ff967fffb..ab41e8ede7 100644
--- a/usr/src/cmd/prtconf/prtconf.c
+++ b/usr/src/cmd/prtconf/prtconf.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011, Joyent, Inc. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -168,7 +169,7 @@ cleanup_path(const char *input_path, char *path)
#ifdef DEBUG
static const char *optstring = "abcdDvVxpPFf:M:dLuC";
#else
-static const char *optstring = "abcdDvVxpPFf:uC";
+static const char *optstring = "abcdDvVxmpPFf:uC";
#endif /* DEBUG */
int
@@ -201,6 +202,9 @@ main(int argc, char *argv[])
case 'v':
++opts.o_verbose;
break;
+ case 'm':
+ ++opts.o_memory;
+ break;
case 'p':
++opts.o_prominfo;
break;
@@ -338,35 +342,43 @@ main(int argc, char *argv[])
return (0);
}
- ret = sysinfo(SI_HW_PROVIDER, hw_provider, sizeof (hw_provider));
- /*
- * If 0 bytes are returned (the system returns '1', for the \0),
- * we're probably on x86, and there has been no si-hw-provider
- * set in /etc/bootrc, default to Joyent.
- */
- if (ret <= 1) {
- (void) strncpy(hw_provider, "Joyent",
+ if (!opts.o_memory) {
+ ret = sysinfo(SI_HW_PROVIDER, hw_provider,
sizeof (hw_provider));
+ /*
+ * If 0 bytes are returned (the system returns '1', for the \0),
+ * we're probably on x86, and there has been no si-hw-provider
+ * set in /etc/bootrc, default to Joyent.
+ */
+ if (ret <= 1) {
+ (void) strncpy(hw_provider, "Joyent",
+ sizeof (hw_provider));
+ }
+ (void) printf("System Configuration: %s %s\n", hw_provider,
+ opts.o_uts.machine);
}
- (void) printf("System Configuration: %s %s\n", hw_provider,
- opts.o_uts.machine);
pagesize = sysconf(_SC_PAGESIZE);
npages = sysconf(_SC_PHYS_PAGES);
- (void) printf("Memory size: ");
if (pagesize == -1 || npages == -1)
- (void) printf("unable to determine\n");
+ if (opts.o_memory) {
+ (void) printf("0\n");
+ return (1);
+ } else {
+ (void) printf("Memory size: unable to determine\n");
+ }
else {
const int64_t kbyte = 1024;
const int64_t mbyte = 1024 * 1024;
int64_t ii = (int64_t)pagesize * npages;
- if (ii >= mbyte)
- (void) printf("%ld Megabytes\n",
+ if (opts.o_memory) {
+ (void) printf("%ld\n", (long)((ii+mbyte-1) / mbyte));
+ return (0);
+ } else {
+ (void) printf("Memory size: %ld Megabytes\n",
(long)((ii+mbyte-1) / mbyte));
- else
- (void) printf("%ld Kilobytes\n",
- (long)((ii+kbyte-1) / kbyte));
+ }
}
if (opts.o_prominfo) {
diff --git a/usr/src/cmd/prtconf/prtconf.h b/usr/src/cmd/prtconf/prtconf.h
index 366e5e0351..2e48fef0a5 100644
--- a/usr/src/cmd/prtconf/prtconf.h
+++ b/usr/src/cmd/prtconf/prtconf.h
@@ -21,6 +21,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2011 Joyent, Inc. All rights reserved.
*/
#ifndef _PRT_CONF_H
@@ -52,6 +53,7 @@ struct prt_opts {
int o_drv_name;
int o_pseudodevs;
int o_fbname;
+ int o_memory;
int o_noheader;
int o_prominfo;
int o_productinfo;
diff --git a/usr/src/cmd/sendmail/src/Makefile b/usr/src/cmd/sendmail/src/Makefile
index 31513f702f..e171e139d3 100644
--- a/usr/src/cmd/sendmail/src/Makefile
+++ b/usr/src/cmd/sendmail/src/Makefile
@@ -19,6 +19,8 @@
# CDDL HEADER END
#
+# Copyright (c) 2011 Gary Mills
+
#
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
@@ -34,8 +36,8 @@ include ../Makefile.cmd
OBJS= alias.o arpadate.o bf.o collect.o conf.o control.o convtime.o daemon.o \
deliver.o domain.o envelope.o err.o headers.o macro.o main.o map.o \
mci.o milter.o mime.o parseaddr.o queue.o ratectrl.o readcf.o \
- recipient.o savemail.o sfsasl.o sm_resolve.o srvrsmtp.o stab.o stats.o \
- sysexits.o tls.o trace.o udb.o usersmtp.o util.o version.o
+ recipient.o sasl.o savemail.o sfsasl.o sm_resolve.o srvrsmtp.o stab.o \
+ stats.o sysexits.o tls.o trace.o udb.o usersmtp.o util.o version.o
SRCS= $(OBJS:%.o=%.c)
@@ -43,7 +45,7 @@ MAPFILES = $(MAPFILE.INT) $(MAPFILE.NGB)
LDFLAGS += $(MAPFILES:%=-M%)
# EXPORT DELETE START
-CRYPTOLIBS= -lssl -lcrypto
+CRYPTOLIBS= -lssl -lcrypto -lsasl
# EXPORT DELETE END
LDLIBS += ../libsmutil/libsmutil.a ../libsm/libsm.a -lresolv -lsocket \
-lnsl ../db/libdb.a -lldap -lsldap -lwrap -lumem \
@@ -52,7 +54,7 @@ LDLIBS += ../libsmutil/libsmutil.a ../libsm/libsm.a -lresolv -lsocket \
INCPATH= -I. -I../include -I../db
# EXPORT DELETE START
-CRYPTOENVDEF= -DSTARTTLS
+CRYPTOENVDEF= -DSTARTTLS -DSASL=20115
# EXPORT DELETE END
ENVDEF= -DNETINET6 -DTCPWRAPPERS $(CRYPTOENVDEF)
SUNENVDEF= -DSUN_EXTENSIONS -DVENDOR_DEFAULT=VENDOR_SUN \
diff --git a/usr/src/cmd/sendmail/src/sasl.c b/usr/src/cmd/sendmail/src/sasl.c
new file mode 100644
index 0000000000..6f9e4a50df
--- /dev/null
+++ b/usr/src/cmd/sendmail/src/sasl.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set
+ * forth in the LICENSE file which can be found at the top level of
+ * the sendmail distribution.
+ *
+ */
+
+#include <sm/gen.h>
+SM_RCSID("@(#)$Id: sasl.c,v 8.22 2006/08/15 23:24:57 ca Exp $")
+
+#if SASL
+# include <stdlib.h>
+# include <sendmail.h>
+# include <errno.h>
+
+/*
+** In order to ensure that storage leaks are tracked, and to prevent
+** conflicts between the sm_heap package and sasl, we tell sasl to
+** use the following heap allocation functions. Unfortunately,
+** the sasl package incorrectly specifies the size of a block
+** using unsigned long: for portability, it should be size_t.
+*/
+
+void *sm_sasl_malloc __P((unsigned long));
+static void *sm_sasl_calloc __P((unsigned long, unsigned long));
+static void *sm_sasl_realloc __P((void *, unsigned long));
+void sm_sasl_free __P((void *));
+
+/*
+** SASLv1:
+** We can't use an rpool for Cyrus-SASL memory management routines,
+** since the encryption/decryption routines in Cyrus-SASL
+** allocate/deallocate a buffer each time. Since rpool
+** don't release memory until the very end, memory consumption is
+** proportional to the size of an e-mail, which is unacceptable.
+*/
+
+/*
+** SM_SASL_MALLOC -- malloc() for SASL
+**
+** Parameters:
+** size -- size of requested memory.
+**
+** Returns:
+** pointer to memory.
+*/
+
+void *
+sm_sasl_malloc(size)
+ unsigned long size;
+{
+ return sm_malloc((size_t) size);
+}
+
+/*
+** SM_SASL_CALLOC -- calloc() for SASL
+**
+** Parameters:
+** nelem -- number of elements.
+** elemsize -- size of each element.
+**
+** Returns:
+** pointer to memory.
+**
+** Notice:
+** this isn't currently used by SASL.
+*/
+
+static void *
+sm_sasl_calloc(nelem, elemsize)
+ unsigned long nelem;
+ unsigned long elemsize;
+{
+ size_t size;
+ void *p;
+
+ size = (size_t) nelem * (size_t) elemsize;
+ p = sm_malloc(size);
+ if (p == NULL)
+ return NULL;
+ memset(p, '\0', size);
+ return p;
+}
+
+/*
+** SM_SASL_REALLOC -- realloc() for SASL
+**
+** Parameters:
+** p -- pointer to old memory.
+** size -- size of requested memory.
+**
+** Returns:
+** pointer to new memory.
+*/
+
+static void *
+sm_sasl_realloc(o, size)
+ void *o;
+ unsigned long size;
+{
+ return sm_realloc(o, (size_t) size);
+}
+
+/*
+** SM_SASL_FREE -- free() for SASL
+**
+** Parameters:
+** p -- pointer to free.
+**
+** Returns:
+** none
+*/
+
+void
+sm_sasl_free(p)
+ void *p;
+{
+ sm_free(p);
+}
+
+/*
+** SM_SASL_INIT -- sendmail specific SASL initialization
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none
+**
+** Side Effects:
+** installs memory management routines for SASL.
+*/
+
+void
+sm_sasl_init()
+{
+ sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc,
+ sm_sasl_realloc, sm_sasl_free);
+}
+/*
+** INTERSECT -- create the intersection between two lists
+**
+** Parameters:
+** s1, s2 -- lists of items (separated by single blanks).
+** rpool -- resource pool from which result is allocated.
+**
+** Returns:
+** the intersection of both lists.
+*/
+
+char *
+intersect(s1, s2, rpool)
+ char *s1, *s2;
+ SM_RPOOL_T *rpool;
+{
+ char *hr, *h1, *h, *res;
+ int l1, l2, rl;
+
+ if (s1 == NULL || s2 == NULL) /* NULL string(s) -> NULL result */
+ return NULL;
+ l1 = strlen(s1);
+ l2 = strlen(s2);
+ rl = SM_MIN(l1, l2);
+ res = (char *) sm_rpool_malloc(rpool, rl + 1);
+ if (res == NULL)
+ return NULL;
+ *res = '\0';
+ if (rl == 0) /* at least one string empty? */
+ return res;
+ hr = res;
+ h1 = s1;
+ h = s1;
+
+ /* walk through s1 */
+ while (h != NULL && *h1 != '\0')
+ {
+ /* is there something after the current word? */
+ if ((h = strchr(h1, ' ')) != NULL)
+ *h = '\0';
+ l1 = strlen(h1);
+
+ /* does the current word appear in s2 ? */
+ if (iteminlist(h1, s2, " ") != NULL)
+ {
+ /* add a blank if not first item */
+ if (hr != res)
+ *hr++ = ' ';
+
+ /* copy the item */
+ memcpy(hr, h1, l1);
+
+ /* advance pointer in result list */
+ hr += l1;
+ *hr = '\0';
+ }
+ if (h != NULL)
+ {
+ /* there are more items */
+ *h = ' ';
+ h1 = h + 1;
+ }
+ }
+ return res;
+}
+# if SASL >= 20000
+/*
+** IPTOSTRING -- create string for SASL_IP*PORT property
+** (borrowed from lib/iptostring.c in Cyrus-IMAP)
+**
+** Parameters:
+** addr -- (pointer to) socket address
+** addrlen -- length of socket address
+** out -- output string (result)
+** outlen -- maximum length of output string
+**
+** Returns:
+** true iff successful.
+**
+** Side Effects:
+** creates output string if successful.
+** sets errno if unsuccessful.
+*/
+
+# include <arpa/inet.h>
+
+# ifndef NI_MAXHOST
+# define NI_MAXHOST 1025
+# endif
+# ifndef NI_MAXSERV
+# define NI_MAXSERV 32
+# endif
+
+bool
+iptostring(addr, addrlen, out, outlen)
+ SOCKADDR *addr;
+ SOCKADDR_LEN_T addrlen;
+ char *out;
+ unsigned outlen;
+{
+ char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
+# if NETINET6
+ int niflags;
+# endif /* NETINET6 */
+
+ if (addr == NULL || out == NULL)
+ {
+ errno = EINVAL;
+ return false;
+ }
+
+# if NETINET6
+ niflags = (NI_NUMERICHOST | NI_NUMERICSERV);
+# ifdef NI_WITHSCOPEID
+ if (addr->sa.sa_family == AF_INET6)
+ niflags |= NI_WITHSCOPEID;
+# endif /* NI_WITHSCOPEID */
+ if (getnameinfo((struct sockaddr *) addr, addrlen,
+ hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), niflags) != 0)
+ return false;
+# else /* NETINET6 */
+ if (addr->sa.sa_family != AF_INET)
+ {
+ errno = EINVAL;
+ return false;
+ }
+ if (sm_strlcpy(hbuf, inet_ntoa(addr->sin.sin_addr), sizeof(hbuf))
+ >= sizeof(hbuf))
+ {
+ errno = ENOMEM;
+ return false;
+ }
+ sm_snprintf(pbuf, sizeof(pbuf), "%d", ntohs(addr->sin.sin_port));
+# endif /* NETINET6 */
+
+ if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
+ {
+ errno = ENOMEM;
+ return false;
+ }
+ sm_snprintf(out, outlen, "%s;%s", hbuf, pbuf);
+ return true;
+}
+# endif /* SASL >= 20000 */
+#endif /* SASL */
diff --git a/usr/src/cmd/tr/str.c b/usr/src/cmd/tr/str.c
index 6219e7819c..40d8ae44ad 100644
--- a/usr/src/cmd/tr/str.c
+++ b/usr/src/cmd/tr/str.c
@@ -82,10 +82,8 @@ next(s)
default:
clen = mbrtowc(&wch, s->str, MB_LEN_MAX, NULL);
if (clen == (size_t)-1 || clen == (size_t)-2 ||
- clen == 0) {
- (void) fprintf(stderr, "Illegal seqeunce.\n");
- exit(1);
- }
+ clen == 0)
+ errx(1, "illegal sequence");
is_octal = 0;
s->lastch = wch;
s->str += clen;
diff --git a/usr/src/cmd/zoneadmd/Makefile b/usr/src/cmd/zoneadmd/Makefile
index f8810c46ef..4c3c697a9d 100644
--- a/usr/src/cmd/zoneadmd/Makefile
+++ b/usr/src/cmd/zoneadmd/Makefile
@@ -18,9 +18,6 @@
#
# CDDL HEADER END
-
-#
-
#
# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, Joyent, Inc. All rights reserved.
@@ -30,41 +27,43 @@ PROG= zoneadmd
include ../Makefile.cmd
-ROOTCMDDIR= $(ROOTLIB)/zones
+$(64ONLY)SUBDIRS= $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
-OBJS= zoneadmd.o zcons.o vplat.o mcap.o
-SRCS = $(OBJS:.o=.c)
-POFILE=zoneadmd_all.po
-POFILES= $(OBJS:%.o=%.po)
+all := TARGET = all
+install := TARGET = install
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
-CFLAGS += $(CCVERBOSE)
-LDLIBS += -lsocket -lzonecfg -lnsl -ldevinfo -ldevice -lnvpair \
- -lgen -lbsm -lcontract -lzfs -luuid -lbrand -ldladm -ltsnet -ltsol \
- -linetutil -lproc
XGETFLAGS += -a -x zoneadmd.xcl
+ROOTUSRLIBZONES = $(ROOT)/usr/lib/zones
+
.KEEP_STATE:
.PARALLEL:
-all: $(PROG)
+all: $(SUBDIRS)
$(PROG): $(OBJS)
$(LINK.c) -o $@ $(OBJS) $(LDLIBS)
$(POST_PROCESS)
-install: all $(ROOTCMD)
+install: $(SUBDIRS)
+ -$(RM) $(ROOTUSRLIBZONES)/$(PROG)
+ -$(LN) $(ISAEXEC) $(ROOTUSRLIBZONES)/$(PROG)
-$(POFILE): $(POFILES)
- $(RM) $@
- $(CAT) $(POFILES) > $@
+$(POFILE):
-clean:
- $(RM) $(OBJS)
-
-lint: lint_SRCS
+clean clobebr lint: $(SUBDIRS)
check:
- $(CSTYLE) -p -P $(SRCS:%=%)
+ $(CSTYLE) -p -P *.c
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
include ../Makefile.targ
diff --git a/usr/src/cmd/zoneadmd/Makefile.com b/usr/src/cmd/zoneadmd/Makefile.com
new file mode 100644
index 0000000000..ae00564d95
--- /dev/null
+++ b/usr/src/cmd/zoneadmd/Makefile.com
@@ -0,0 +1,68 @@
+#
+# 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.
+# Copyright (c) 2011, Joyent, Inc. All rights reserved.
+#
+
+PROG= zoneadmd
+
+include ../../Makefile.cmd
+
+ROOTCMDDIR= $(ROOTLIB)/zones
+
+OBJS= zoneadmd.o zcons.o vplat.o mcap.o
+
+CFLAGS += $(CCVERBOSE)
+LDLIBS += -lsocket -lzonecfg -lnsl -ldevinfo -ldevice -lnvpair \
+ -lgen -lbsm -lcontract -lzfs -luuid -lbrand -ldladm -ltsnet -ltsol \
+ -linetutil -lproc
+
+.KEEP_STATE:
+
+%.o: ../%.c
+ $(COMPILE.c) $<
+
+ROOTUSRLIBZONES = $(ROOT)/usr/lib/zones
+ROOTUSRLIBZONES32 = $(ROOTUSRLIBZONES)/$(MACH32)
+ROOTUSRLIBZONES64 = $(ROOTUSRLIBZONES)/$(MACH64)
+ROOTUSRLIBZONESPROG32 = $(ROOTUSRLIBZONES32)/$(PROG)
+ROOTUSRLIBZONESPROG64 = $(ROOTUSRLIBZONES64)/$(PROG)
+$(ROOTUSRLIBZONES32)/%: $(ROOTUSRLIBZONES32) %
+ $(INS.file)
+$(ROOTUSRLIBZONES64)/%: $(ROOTUSRLIBZONES64) %
+ $(INS.file)
+$(ROOTUSRLIBZONES32):
+ $(INS.dir)
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(LINK.c) -o $@ $(OBJS) $(LDLIBS)
+ $(POST_PROCESS)
+
+clean:
+ $(RM) $(OBJS)
+
+lint:
+ $(LINT.c) ../*.c $(LDLIBS)
+
+include ../../Makefile.targ
diff --git a/usr/src/cmd/zoneadmd/amd64/Makefile b/usr/src/cmd/zoneadmd/amd64/Makefile
new file mode 100644
index 0000000000..75ac51db32
--- /dev/null
+++ b/usr/src/cmd/zoneadmd/amd64/Makefile
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (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) 2011, Joyent, Inc. All rights reserved.
+#
+
+.KEEP_STATE:
+
+include ../Makefile.com
+include ../../Makefile.cmd.64
+
+install: all $(ROOTUSRLIBZONES64) $(ROOTUSRLIBZONESPROG64)
diff --git a/usr/src/cmd/zoneadmd/i386/Makefile b/usr/src/cmd/zoneadmd/i386/Makefile
new file mode 100644
index 0000000000..a8764e0638
--- /dev/null
+++ b/usr/src/cmd/zoneadmd/i386/Makefile
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (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) 2011, Joyent, Inc. All rights reserved.
+#
+
+.KEEP_STATE:
+
+include ../Makefile.com
+
+install: all $(ROOTUSRLIBZONES32) $(ROOTUSRLIBZONESPROG32)
diff --git a/usr/src/cmd/zoneadmd/mcap.c b/usr/src/cmd/zoneadmd/mcap.c
index 3330da3197..9e0fba65e2 100644
--- a/usr/src/cmd/zoneadmd/mcap.c
+++ b/usr/src/cmd/zoneadmd/mcap.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Copyright 2011 Joyent, Inc. All rights reserved.
+ * Copyright 2011, 2012, Joyent, Inc. All rights reserved.
*/
/*
@@ -563,52 +563,34 @@ done:
static uint64_t
get_mem_info(int age)
{
- uint64_t n = 400; /* Initial guess on number of zones */
- uint64_t got = n;
- int i;
- zsd_vmusage64_t *buf = NULL;
- size_t size = sizeof (zsd_vmusage64_t) * n;
- uint64_t zone_rss = 0;
-
- /* Preallocate to try to get all zone mem data with only 1 syscall. */
- if ((buf = (zsd_vmusage64_t *)malloc(size)) == NULL) {
- debug("get_mem_info malloc failed\n");
- return (0);
- }
+ uint64_t n = 1;
+ zsd_vmusage64_t buf;
+ uint64_t zone_rss;
-again:
- if (syscall(SYS_rusagesys, _RUSAGESYS_GETVMUSAGE, VMUSAGE_ALL_ZONES,
- age, (uintptr_t)buf, (uintptr_t)&n) != 0) {
+ buf.vmu_id = zid;
+
+ if (syscall(SYS_rusagesys, _RUSAGESYS_GETVMUSAGE, VMUSAGE_A_ZONE,
+ age, (uintptr_t)&buf, (uintptr_t)&n) != 0) {
debug("vmusage failed\n");
(void) sleep_shutdown(1);
- if (shutting_down) {
- free(buf);
- return (0);
- }
+ return (0);
}
- if (n > got) {
- size_t size = sizeof (zsd_vmusage64_t) * n;
-
- if (buf != NULL)
- free(buf);
- buf = (zsd_vmusage64_t *)malloc(size);
- if (buf == NULL) {
- debug("get_mem_info malloc failed\n");
- return (0);
- }
- got = n;
- goto again;
+ if (n > 1) {
+ /* This should never happen */
+ debug("vmusage returned more than one result\n");
+ (void) sleep_shutdown(1);
+ return (0);
}
- for (i = 0; i < n; i++) {
- if (buf[i].vmu_id == zid) {
- zone_rss = buf[i].vmu_rss_all / 1024;
- break;
- }
+ if (buf.vmu_id != zid) {
+ /* This should never happen */
+ debug("vmusage returned the incorrect zone\n");
+ (void) sleep_shutdown(1);
+ return (0);
}
- free(buf);
+ zone_rss = buf.vmu_rss_all / 1024;
return (zone_rss);
}
diff --git a/usr/src/cmd/zoneadmd/vplat.c b/usr/src/cmd/zoneadmd/vplat.c
index b09f124dea..d0b85f3c18 100644
--- a/usr/src/cmd/zoneadmd/vplat.c
+++ b/usr/src/cmd/zoneadmd/vplat.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent Inc. All rights reserved.
+ * Copyright (c) 2011, 2012, Joyent Inc. All rights reserved.
*/
/*
@@ -710,6 +710,7 @@ unmount_filesystems(zlog_t *zlogp, zoneid_t zoneid, boolean_t unmount_cmd)
if (umount2(path, MS_FORCE) == 0) {
unmounted = B_TRUE;
stuck = B_FALSE;
+ fail = 0;
} else {
/*
* We may hit a failure here if there
@@ -723,12 +724,27 @@ unmount_filesystems(zlog_t *zlogp, zoneid_t zoneid, boolean_t unmount_cmd)
* this case, we will wait and retry
* a few times before we give up.
*/
- if (fail++ < 15) {
+ fail++;
+ if (fail < 16) {
zerror(zlogp, B_FALSE,
"unable to unmount '%s', "
"retrying in 1 second",
path);
(void) sleep(1);
+ } else if (fail == 16) {
+ char cmdbuf[MAXPATHLEN + 21];
+
+ zerror(zlogp, B_FALSE,
+ "unable to unmount '%s', "
+ "trying to kill GZ "
+ "processes",
+ path);
+ (void) snprintf(cmdbuf,
+ sizeof (cmdbuf),
+ "/usr/sbin/fuser -ck %s",
+ path);
+ (void) system(cmdbuf);
+ (void) sleep(2);
} else {
error++;
zerror(zlogp, B_FALSE,
diff --git a/usr/src/lib/brand/joyent/zone/statechange.ksh b/usr/src/lib/brand/joyent/zone/statechange.ksh
index ba4df02b99..70be7819b4 100644
--- a/usr/src/lib/brand/joyent/zone/statechange.ksh
+++ b/usr/src/lib/brand/joyent/zone/statechange.ksh
@@ -19,7 +19,7 @@
#
# CDDL HEADER END
#
-# Copyright 2010, 2011 Joyent, Inc. All rights reserved.
+# Copyright 2010, 2012 Joyent, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -385,6 +385,69 @@ setup_snapshots()
done
}
+#
+# If the zone has a CPU cap, calculate the CPU baseline and set it so we can
+# track when we're bursting. There are many ways that the baseline can be
+# calculated based on the other settings in the zones (e.g. a simple way would
+# be as a precentage of the cap).
+#
+# For SmartMachines, our CPU baseline is calculated off of the system's
+# provisionable memory and the memory cap of the zone. We assume that 83% of
+# the system's memory is usable by zones (the rest is for the OS) and we assume
+# that the zone memory cap is set so that we're proportional to how many zones
+# we can provision on the system (i.e. we don't overprovision memory). Using
+# these assumptions, we calculate the proportion of CPU for the zone based on
+# its proportion of memory. Thus, the zone's CPU baseline is calculated using:
+# ((zone capped memsize in MB) * 100) / (MB/core).
+# Uncapped zones have no baseline (i.e. infrastructure zones).
+#
+# Remember that the cpu-cap rctl and the baseline are expressed in units of
+# a percent of a CPU, so 100 is 1 full CPU.
+#
+setup_cpu_baseline()
+{
+ # If there is already a baseline, don't set one heuristically
+ curr_base=`prctl -P -n zone.cpu-baseline -i zone $ZONENAME | nawk '{
+ if ($2 == "privileged") print $3
+ }'`
+ [ -n "$curr_base" ] && return
+
+ # Get current cap and convert from zonecfg format into rctl format
+ cap=`zonecfg -z $ZONENAME info capped-cpu | nawk '{
+ if ($1 == "[ncpus:") print (substr($2, 1, length($2) - 1) * 100)
+ }'`
+ [ -z "$cap" ] && return
+
+ # Get zone's memory cap in MB times 100
+ zmem=`zonecfg -z $ZONENAME info capped-memory | nawk '{
+ if ($1 == "[physical:") {
+ val = substr($2, 1, length($2) - 2)
+ units = substr($2, length($2) - 1, 1)
+
+ # convert GB to MB
+ if (units == "G")
+ val *= 1024
+ print (val * 100)
+ }
+ }'`
+ [ -z "$zmem" ] && return
+
+ # Get system's total memory in MB
+ smem=`prtconf -m`
+ # provisionable memory is 83% of total memory (bash can't do floats)
+ prov_mem=$((($smem * 83) / 100))
+ nprocs=`psrinfo -v | \
+ nawk '/virtual processor/ {cnt++} END {print cnt}'`
+
+ mb_per_core=$(($prov_mem / $nprocs))
+
+ baseline=$(($zmem / $mb_per_core))
+ [[ $baseline == 0 ]] && baseline=1
+ [[ $baseline -gt $cap ]] && baseline=$cap
+
+ prctl -n zone.cpu-baseline -v $baseline -t priv -i zone $ZONENAME
+}
+
cleanup_snapshots()
{
#
@@ -431,10 +494,18 @@ load_sdc_sysinfo
load_sdc_config
[[ "$subcommand" == "pre" && $cmd == 0 ]] && setup_fs
-[[ "$subcommand" == "post" && $cmd == 0 ]] && setup_snapshots
-[[ "$subcommand" == "pre" && $cmd == 4 ]] && cleanup_snapshots
-[[ "$subcommand" == "post" && $cmd == 0 ]] && setup_net
-[[ "$subcommand" == "pre" && $cmd == 4 ]] && cleanup_net
+if [[ "$subcommand" == "post" && $cmd == 0 ]]; then
+ setup_snapshots
+ setup_net
+fi
+
+# We can't set a rctl until we have a process in the zone to grab
+[[ "$subcommand" == "post" && $cmd == 1 ]] && setup_cpu_baseline
+
+if [[ "$subcommand" == "pre" && $cmd == 4 ]]; then
+ cleanup_snapshots
+ cleanup_net
+fi
exit 0
diff --git a/usr/src/lib/brand/kvm/zone/statechange.ksh b/usr/src/lib/brand/kvm/zone/statechange.ksh
index 7c08ce6ea9..22f647775a 100755
--- a/usr/src/lib/brand/kvm/zone/statechange.ksh
+++ b/usr/src/lib/brand/kvm/zone/statechange.ksh
@@ -19,7 +19,7 @@
#
# CDDL HEADER END
#
-# Copyright 2010, 2011 Joyent, Inc. All rights reserved.
+# Copyright 2010, 2012 Joyent, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -318,6 +318,69 @@ setup_fs()
}
#
+# If the zone has a CPU cap, calculate the CPU baseline and set it so we can
+# track when we're bursting. There are many ways that the baseline can be
+# calculated based on the other settings in the zones (e.g. a simple way would
+# be as a precentage of the cap).
+#
+# For SmartMachines, our CPU baseline is calculated off of the system's
+# provisionable memory and the memory cap of the zone. We assume that 83% of
+# the system's memory is usable by zones (the rest is for the OS) and we assume
+# that the zone memory cap is set so that we're proportional to how many zones
+# we can provision on the system (i.e. we don't overprovision memory). Using
+# these assumptions, we calculate the proportion of CPU for the zone based on
+# its proportion of memory. Thus, the zone's CPU baseline is calculated using:
+# ((zone capped memsize in MB) * 100) / (MB/core).
+# Uncapped zones have no baseline (i.e. infrastructure zones).
+#
+# Remember that the cpu-cap rctl and the baseline are expressed in units of
+# a percent of a CPU, so 100 is 1 full CPU.
+#
+setup_cpu_baseline()
+{
+ # If there is already a baseline, don't set one heuristically
+ curr_base=`prctl -P -n zone.cpu-baseline -i zone $ZONENAME | nawk '{
+ if ($2 == "privileged") print $3
+ }'`
+ [ -n "$curr_base" ] && return
+
+ # Get current cap and convert from zonecfg format into rctl format
+ cap=`zonecfg -z $ZONENAME info capped-cpu | nawk '{
+ if ($1 == "[ncpus:") print (substr($2, 1, length($2) - 1) * 100)
+ }'`
+ [ -z "$cap" ] && return
+
+ # Get zone's memory cap in MB times 100
+ zmem=`zonecfg -z $ZONENAME info capped-memory | nawk '{
+ if ($1 == "[physical:") {
+ val = substr($2, 1, length($2) - 2)
+ units = substr($2, length($2) - 1, 1)
+
+ # convert GB to MB
+ if (units == "G")
+ val *= 1024
+ print (val * 100)
+ }
+ }'`
+ [ -z "$zmem" ] && return
+
+ # Get system's total memory in MB
+ smem=`prtconf -m`
+ # provisionable memory is 83% of total memory (bash can't do floats)
+ prov_mem=$((($smem * 83) / 100))
+ nprocs=`psrinfo -v | \
+ nawk '/virtual processor/ {cnt++} END {print cnt}'`
+
+ mb_per_core=$(($prov_mem / $nprocs))
+
+ baseline=$(($zmem / $mb_per_core))
+ [[ $baseline == 0 ]] && baseline=1
+ [[ $baseline -gt $cap ]] && baseline=$cap
+
+ prctl -n zone.cpu-baseline -v $baseline -t priv -i zone $ZONENAME
+}
+
+#
# We're halting the zone, perform network cleanup.
#
cleanup_net()
@@ -351,5 +414,7 @@ echo "statechange $subcommand $cmd" >>/tmp/kvm.log
[[ "$subcommand" == "pre" && $cmd == 0 ]] && setup_fs
[[ "$subcommand" == "pre" && $cmd == 4 ]] && cleanup_net
[[ "$subcommand" == "post" && $cmd == 0 ]] && setup_net
+# We can't set a rctl until we have a process in the zone to grab
+[[ "$subcommand" == "post" && $cmd == 1 ]] && setup_cpu_baseline
exit 0
diff --git a/usr/src/lib/libzfs/common/libzfs_pool.c b/usr/src/lib/libzfs/common/libzfs_pool.c
index 8eb7e2ca15..bf833d1bdd 100644
--- a/usr/src/lib/libzfs/common/libzfs_pool.c
+++ b/usr/src/lib/libzfs/common/libzfs_pool.c
@@ -270,7 +270,7 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
case PROP_TYPE_NUMBER:
intval = zpool_get_prop_int(zhp, prop, &src);
- if (literal) {
+ if (literal && prop != ZPOOL_PROP_HEALTH) {
(void) snprintf(buf, len, "%llu",
(u_longlong_t)intval);
break;
diff --git a/usr/src/man/man1m/prtconf.1m b/usr/src/man/man1m/prtconf.1m
index bd93c39ec6..2f47637796 100644
--- a/usr/src/man/man1m/prtconf.1m
+++ b/usr/src/man/man1m/prtconf.1m
@@ -1,5 +1,6 @@
'\" te
.\" Copyright 1989 AT&T Copyright (c) 2003, Sun Microsystems, Inc. All Rights Reserved
+.\" Copyright 2011, Joyent, Inc. All Rights Reserved
.\" 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]
@@ -9,7 +10,7 @@ prtconf \- print system configuration
.SH SYNOPSIS
.LP
.nf
-\fB/usr/sbin/prtconf\fR [\fB-V\fR] | [\fB-F\fR] | [\fB-x\fR] | [\fB-bpv\fR] | [\fB-acdDPv\fR]
+\fB/usr/sbin/prtconf\fR [\fB-V\fR] | [\fB-F\fR] | [\fB-m\fr] | [\fB-x\fR] | [\fB-bpv\fR] | [\fB-acdDPv\fR]
[\fIdev_path\fR]
.fi
@@ -98,6 +99,16 @@ console frame buffer on a SUNW,Ultra-30 is \fBffb\fR, the command returns:
.sp
.ne 2
.na
+\fB\fB-m\fR\fR
+.ad
+.RS 6n
+Displays the amount system memory in megabytes.
+This flag must be used by itself.
+.RE
+
+.sp
+.ne 2
+.na
\fB\fB-p\fR\fR
.ad
.RS 6n
diff --git a/usr/src/man/man1m/zfs.1m b/usr/src/man/man1m/zfs.1m
index 8a8e9e59ca..1548d0b148 100644
--- a/usr/src/man/man1m/zfs.1m
+++ b/usr/src/man/man1m/zfs.1m
@@ -7,6 +7,7 @@
.\" the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
.\" Copyright 2011 Nexenta Systems, Inc. All rights reserved.
.\" Copyright 2011 by Delphix. All rights reserved.
+.\" Copyright 2011 Joshua M. Clulow <josh@sysmgr.org>
.TH ZFS 1M "28 Jul 2011"
.SH NAME
zfs \- configures ZFS file systems
@@ -154,7 +155,7 @@ zfs \- configures ZFS file systems
.LP
.nf
-\fBzfs\fR \fBreceive\fR [\fB-vnFu\fR] \fB-d\fR \fIfilesystem\fR
+\fBzfs\fR \fBreceive\fR [\fB-vnFu\fR] [\fB-d\fR|\fB-e\fR] \fIfilesystem\fR
.fi
.LP
@@ -2862,7 +2863,7 @@ on future versions of \fBZFS\fR.
.ad
.br
.na
-\fB\fBzfs receive\fR [\fB-vnFu\fR] \fB-d\fR \fIfilesystem\fR\fR
+\fB\fBzfs receive\fR [\fB-vnFu\fR] [\fB-d\fR|\fB-e\fR] \fIfilesystem\fR\fR
.ad
.sp .6
.RS 4n
@@ -2884,15 +2885,23 @@ on the sending location are destroyed by using the \fBzfs destroy\fR \fB-d\fR
command.
.sp
The name of the snapshot (and file system, if a full stream is received) that
-this subcommand creates depends on the argument type and the \fB-d\fR option.
+this subcommand creates depends on the argument type and the use of the
+\fB-d\fR or \fB-e\fR options.
.sp
If the argument is a snapshot name, the specified \fIsnapshot\fR is created. If
the argument is a file system or volume name, a snapshot with the same name as
the sent snapshot is created within the specified \fIfilesystem\fR or
-\fIvolume\fR. If the \fB-d\fR option is specified, the snapshot name is
-determined by appending the sent snapshot's name to the specified
-\fIfilesystem\fR. If the \fB-d\fR option is specified, any required file
-systems within the specified one are created.
+\fIvolume\fR. If neither of the \fB-d\fR or \fB-e\fR options are specified,
+the provided target snapshot name is used exactly as provided.
+.sp
+The \fB-d\fR and \fB-e\fR options cause the file system name of the target
+snapshot to be determined by appending a portion of the sent snapshot's name to
+the specified target \fIfilesystem\fR. If the \fB-d\fR option is specified, all
+but the first element of the sent snapshot's file system path (usually the
+pool name) is used and any required intermediate file systems within the
+specified one are created. If the \fB-e\fR option is specified, then only the
+last element of the sent snapshot's file system name (i.e. the name of the
+source file system itself) is used as the target file system name.
.sp
.ne 2
.na
@@ -2900,8 +2909,21 @@ systems within the specified one are created.
.ad
.sp .6
.RS 4n
-Use the name of the sent snapshot to determine the name of the new snapshot as
-described in the paragraph above.
+Discard the first element of the sent snapshot's file system name, using
+the remaining elements to determine the name of the target file system for
+the new snapshot as described in the paragraph above.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fB-e\fR\fR
+.ad
+.sp .6
+.RS 4n
+Discard all but the last element of the sent snapshot's file system name,
+using that element to determine the name of the target file system for
+the new snapshot as described in the paragraph above.
.RE
.sp
diff --git a/usr/src/man/man3tecla/gl_get_line.3tecla b/usr/src/man/man3tecla/gl_get_line.3tecla
index 4d0cfd0e8c..f85a1ed7e6 100644
--- a/usr/src/man/man3tecla/gl_get_line.3tecla
+++ b/usr/src/man/man3tecla/gl_get_line.3tecla
@@ -942,7 +942,7 @@ Resume command-line editing.
.LP
Note that the \fIname\fR argument of \fBgl_register_action()\fR specifies the
name by which a user can refer to the action in their configuration file. This
-allows them to re-bind the action to an alternate key-seqeunce. In order for
+allows them to re-bind the action to an alternate key-sequence. In order for
this to work, it is necessary to call \fBgl_register_action()\fR between
calling \fBnew_GetLine()\fR and the first call to \fBgl_get_line()\fR.
.SS "History Files"
diff --git a/usr/src/uts/common/disp/cmt.c b/usr/src/uts/common/disp/cmt.c
index 3aa3b67e29..7e46509fce 100644
--- a/usr/src/uts/common/disp/cmt.c
+++ b/usr/src/uts/common/disp/cmt.c
@@ -1263,6 +1263,9 @@ cmt_pad_enable(pghw_type_t type)
ASSERT(PGHW_IS_PM_DOMAIN(type));
ASSERT(MUTEX_HELD(&cpu_lock));
+ if (cmt_sched_disabled == 1)
+ return (-1);
+
if ((hwset = pghw_set_lookup(type)) == NULL ||
cmt_hw_blacklisted[type]) {
/*
@@ -1313,6 +1316,9 @@ cmt_pad_disable(pghw_type_t type)
ASSERT(PGHW_IS_PM_DOMAIN(type));
ASSERT(MUTEX_HELD(&cpu_lock));
+ if (cmt_sched_disabled == 1)
+ return (-1);
+
if ((hwset = pghw_set_lookup(type)) == NULL) {
/*
* Unable to find any instances of the specified type of
diff --git a/usr/src/uts/common/disp/cpucaps.c b/usr/src/uts/common/disp/cpucaps.c
index 46f53faab6..26067235a9 100644
--- a/usr/src/uts/common/disp/cpucaps.c
+++ b/usr/src/uts/common/disp/cpucaps.c
@@ -22,6 +22,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2011, 2012 Joyent, Inc. All rights reserved.
*/
#include <sys/disp.h>
@@ -74,6 +75,32 @@
* Putting threads on wait queues in random places while running in the
* kernel might lead to all kinds of locking problems.
*
+ * Bursting
+ * ========
+ *
+ * CPU bursting occurs when the CPU usage is over the baseline but under the
+ * cap. The baseline CPU (zone.cpu-baseline) is set in a multi-tenant
+ * environment so that we know how much CPU is allocated for a tenant under
+ * normal utilization. We can then track how much time a zone is spending
+ * over the "normal" CPU utilization expected for that zone using the
+ * "above_base_sec" kstat. This kstat is cumulative.
+ *
+ * If the zone has a burst limit (zone.cpu-burst-time) then the zone can
+ * burst for that period of time (in seconds) before the effective cap is
+ * lowered to the baseline. Once the effective cap is lowered, the zone
+ * will run at the baseline for the burst limit before the effective cap is
+ * raised again to the full value. This will allow the zone to burst again.
+ * We can watch this behavior using the kstats. The "effective" kstat shows
+ * which cap is being used, the baseline value or the burst value. The
+ * "burst_limit_sec" shows the value of the zone.cpu-burst-time rctl and the
+ * "bursting_sec" kstat shows how many seconds the zone has currently been
+ * bursting. When the CPU load is continuously greater than the baseline,
+ * bursting_sec will increase, up to the burst_limit_sec value, then the
+ * effective kstat will drop to the baseline and the bursting_sec value will
+ * decrease until it hits 0, at which time the effective kstat will return to
+ * the full burst value and the bursting_sec value will begin to increase
+ * again.
+ *
* Accounting
* ==========
*
@@ -203,18 +230,28 @@ static void caps_update();
*/
struct cap_kstat {
kstat_named_t cap_value;
+ kstat_named_t cap_baseline;
+ kstat_named_t cap_effective;
+ kstat_named_t cap_burst_limit;
+ kstat_named_t cap_bursting;
kstat_named_t cap_usage;
kstat_named_t cap_nwait;
kstat_named_t cap_below;
kstat_named_t cap_above;
+ kstat_named_t cap_above_base;
kstat_named_t cap_maxusage;
kstat_named_t cap_zonename;
} cap_kstat = {
{ "value", KSTAT_DATA_UINT64 },
+ { "baseline", KSTAT_DATA_UINT64 },
+ { "effective", KSTAT_DATA_UINT64 },
+ { "burst_limit_sec", KSTAT_DATA_UINT64 },
+ { "bursting_sec", KSTAT_DATA_UINT64 },
{ "usage", KSTAT_DATA_UINT64 },
{ "nwait", KSTAT_DATA_UINT64 },
{ "below_sec", KSTAT_DATA_UINT64 },
{ "above_sec", KSTAT_DATA_UINT64 },
+ { "above_base_sec", KSTAT_DATA_UINT64 },
{ "maxusage", KSTAT_DATA_UINT64 },
{ "zonename", KSTAT_DATA_STRING },
};
@@ -311,7 +348,7 @@ cap_enable(list_t *l, cpucap_t *cap, hrtime_t value)
cap->cap_below = cap->cap_above = 0;
cap->cap_maxusage = 0;
cap->cap_usage = 0;
- cap->cap_value = value;
+ cap->cap_value = cap->cap_chk_value = value;
waitq_unblock(&cap->cap_waitq);
if (CPUCAPS_OFF()) {
cpucaps_enabled = B_TRUE;
@@ -345,7 +382,7 @@ cap_disable(list_t *l, cpucap_t *cap)
cpucaps_enabled = B_FALSE;
cpucaps_clock_callout = NULL;
}
- cap->cap_value = 0;
+ cap->cap_value = cap->cap_chk_value = 0;
cap->cap_project = NULL;
cap->cap_zone = NULL;
if (cap->cap_kstat != NULL) {
@@ -487,6 +524,8 @@ cap_walk(list_t *l, void (*cb)(cpucap_t *, int64_t))
* The waitq_isempty check is performed without the waitq lock. If a new thread
* is placed on the waitq right after the check, it will be picked up during the
* next invocation of cap_poke_waitq().
+ *
+ * Called once per tick for zones.
*/
/* ARGSUSED */
static void
@@ -494,7 +533,45 @@ cap_poke_waitq(cpucap_t *cap, int64_t gen)
{
ASSERT(MUTEX_HELD(&caps_lock));
- if (cap->cap_usage >= cap->cap_value) {
+ if (cap->cap_base != 0) {
+ /*
+ * Because of the way usage is calculated and decayed, its
+ * possible for the zone to be slightly over its cap, but we
+ * don't want to count that after we have reduced the effective
+ * cap to the baseline. That way the zone will be able to
+ * burst again after the burst_limit has expired.
+ */
+ if (cap->cap_usage > cap->cap_base &&
+ cap->cap_chk_value == cap->cap_value) {
+ cap->cap_above_base++;
+
+ /*
+ * If bursting is limited and we've been bursting
+ * longer than we're supposed to, then set the
+ * effective cap to the baseline.
+ */
+ if (cap->cap_burst_limit != 0) {
+ cap->cap_bursting++;
+ if (cap->cap_bursting >= cap->cap_burst_limit)
+ cap->cap_chk_value = cap->cap_base;
+ }
+ } else if (cap->cap_bursting > 0) {
+ /*
+ * We're not bursting now, but we were, decay the
+ * bursting timer.
+ */
+ cap->cap_bursting--;
+ /*
+ * Reset the effective cap once we decay to 0 so we
+ * can burst again.
+ */
+ if (cap->cap_bursting == 0 &&
+ cap->cap_chk_value != cap->cap_value)
+ cap->cap_chk_value = cap->cap_value;
+ }
+ }
+
+ if (cap->cap_usage >= cap->cap_chk_value) {
cap->cap_above++;
} else {
waitq_t *wq = &cap->cap_waitq;
@@ -629,14 +706,14 @@ cap_project_zone_modify_walker(kproject_t *kpj, void *arg)
* Remove all projects in this zone without caps
* from the capped_projects list.
*/
- if (project_cap->cap_value == MAX_USAGE) {
+ if (project_cap->cap_chk_value == MAX_USAGE) {
cap_project_disable(kpj);
}
} else if (CAP_DISABLED(project_cap)) {
/*
* Add the project to capped_projects list.
*/
- ASSERT(project_cap->cap_value == 0);
+ ASSERT(project_cap->cap_chk_value == 0);
cap_project_enable(kpj, MAX_USAGE);
}
mutex_exit(&caps_lock);
@@ -746,7 +823,7 @@ cpucaps_zone_set(zone_t *zone, rctl_qty_t cap_val)
/*
* No state transitions, just change the value
*/
- cap->cap_value = value;
+ cap->cap_value = cap->cap_chk_value = value;
}
ASSERT(MUTEX_HELD(&caps_lock));
@@ -757,6 +834,108 @@ cpucaps_zone_set(zone_t *zone, rctl_qty_t cap_val)
}
/*
+ * Set zone's base cpu value to base_val
+ */
+int
+cpucaps_zone_set_base(zone_t *zone, rctl_qty_t base_val)
+{
+ cpucap_t *cap = NULL;
+ hrtime_t value;
+
+ ASSERT(base_val <= MAXCAP);
+ if (base_val > MAXCAP)
+ base_val = MAXCAP;
+
+ if (CPUCAPS_OFF() || !ZONE_IS_CAPPED(zone))
+ return (0);
+
+ if (zone->zone_cpucap == NULL)
+ cap = cap_alloc();
+
+ mutex_enter(&caps_lock);
+
+ if (cpucaps_busy) {
+ mutex_exit(&caps_lock);
+ return (EBUSY);
+ }
+
+ /*
+ * Double-check whether zone->zone_cpucap is NULL, now with caps_lock
+ * held. If it is still NULL, assign a newly allocated cpucap to it.
+ */
+ if (zone->zone_cpucap == NULL) {
+ zone->zone_cpucap = cap;
+ } else if (cap != NULL) {
+ cap_free(cap);
+ }
+
+ cap = zone->zone_cpucap;
+
+ value = base_val * cap_tick_cost;
+ if (value < 0 || value > cap->cap_value)
+ value = 0;
+
+ cap->cap_base = value;
+
+ mutex_exit(&caps_lock);
+
+ return (0);
+}
+
+/*
+ * Set zone's maximum burst time in seconds. A burst time of 0 means that
+ * the zone can run over its baseline indefinitely.
+ */
+int
+cpucaps_zone_set_burst_time(zone_t *zone, rctl_qty_t base_val)
+{
+ cpucap_t *cap = NULL;
+ hrtime_t value;
+
+ ASSERT(base_val <= INT_MAX);
+ /* Treat the default as 0 - no limit */
+ if (base_val == INT_MAX)
+ base_val = 0;
+ if (base_val > INT_MAX)
+ base_val = INT_MAX;
+
+ if (CPUCAPS_OFF() || !ZONE_IS_CAPPED(zone))
+ return (0);
+
+ if (zone->zone_cpucap == NULL)
+ cap = cap_alloc();
+
+ mutex_enter(&caps_lock);
+
+ if (cpucaps_busy) {
+ mutex_exit(&caps_lock);
+ return (EBUSY);
+ }
+
+ /*
+ * Double-check whether zone->zone_cpucap is NULL, now with caps_lock
+ * held. If it is still NULL, assign a newly allocated cpucap to it.
+ */
+ if (zone->zone_cpucap == NULL) {
+ zone->zone_cpucap = cap;
+ } else if (cap != NULL) {
+ cap_free(cap);
+ }
+
+ cap = zone->zone_cpucap;
+
+ value = SEC_TO_TICK(base_val);
+ if (value < 0)
+ value = 0;
+
+ cap->cap_burst_limit = value;
+
+ mutex_exit(&caps_lock);
+
+ return (0);
+}
+
+/*
* The project is going away so disable its cap.
*/
void
@@ -902,7 +1081,7 @@ cpucaps_project_set(kproject_t *kpj, rctl_qty_t cap_val)
if (CAP_DISABLED(cap))
cap_project_enable(kpj, value);
else
- cap->cap_value = value;
+ cap->cap_value = cap->cap_chk_value = value;
} else if (CAP_ENABLED(cap)) {
/*
* User requested to drop a cap on the project. If it is part of
@@ -910,7 +1089,7 @@ cpucaps_project_set(kproject_t *kpj, rctl_qty_t cap_val)
* otherwise disable the cap.
*/
if (ZONE_IS_CAPPED(kpj->kpj_zone)) {
- cap->cap_value = MAX_USAGE;
+ cap->cap_value = cap->cap_chk_value = MAX_USAGE;
} else {
cap_project_disable(kpj);
}
@@ -948,6 +1127,26 @@ cpucaps_zone_get(zone_t *zone)
}
/*
+ * Get current zone baseline.
+ */
+rctl_qty_t
+cpucaps_zone_get_base(zone_t *zone)
+{
+ return (zone->zone_cpucap != NULL ?
+ (rctl_qty_t)(zone->zone_cpucap->cap_base / cap_tick_cost) : 0);
+}
+
+/*
+ * Get current zone maximum burst time.
+ */
+rctl_qty_t
+cpucaps_zone_get_burst_time(zone_t *zone)
+{
+ return (zone->zone_cpucap != NULL ?
+ (rctl_qty_t)(TICK_TO_SEC(zone->zone_cpucap->cap_burst_limit)) : 0);
+}
+
+/*
* Charge project of thread t the time thread t spent on CPU since previously
* adjusted.
*
@@ -1045,7 +1244,7 @@ cpucaps_charge(kthread_id_t t, caps_sc_t *csc, cpucaps_charge_t charge_type)
project_cap = kpj->kpj_cpucap;
- if (project_cap->cap_usage >= project_cap->cap_value) {
+ if (project_cap->cap_usage >= project_cap->cap_chk_value) {
t->t_schedflag |= TS_PROJWAITQ;
rc = B_TRUE;
} else if (t->t_schedflag & TS_PROJWAITQ) {
@@ -1059,7 +1258,7 @@ cpucaps_charge(kthread_id_t t, caps_sc_t *csc, cpucaps_charge_t charge_type)
} else {
cpucap_t *zone_cap = zone->zone_cpucap;
- if (zone_cap->cap_usage >= zone_cap->cap_value) {
+ if (zone_cap->cap_usage >= zone_cap->cap_chk_value) {
t->t_schedflag |= TS_ZONEWAITQ;
rc = B_TRUE;
} else if (t->t_schedflag & TS_ZONEWAITQ) {
@@ -1133,6 +1332,12 @@ cap_kstat_update(kstat_t *ksp, int rw)
capsp->cap_value.value.ui64 =
ROUND_SCALE(cap->cap_value, cap_tick_cost);
+ capsp->cap_baseline.value.ui64 =
+ ROUND_SCALE(cap->cap_base, cap_tick_cost);
+ capsp->cap_effective.value.ui64 =
+ ROUND_SCALE(cap->cap_chk_value, cap_tick_cost);
+ capsp->cap_burst_limit.value.ui64 =
+ ROUND_SCALE(cap->cap_burst_limit, tick_sec);
capsp->cap_usage.value.ui64 =
ROUND_SCALE(cap->cap_usage, cap_tick_cost);
capsp->cap_maxusage.value.ui64 =
@@ -1140,6 +1345,10 @@ cap_kstat_update(kstat_t *ksp, int rw)
capsp->cap_nwait.value.ui64 = cap->cap_waitq.wq_count;
capsp->cap_below.value.ui64 = ROUND_SCALE(cap->cap_below, tick_sec);
capsp->cap_above.value.ui64 = ROUND_SCALE(cap->cap_above, tick_sec);
+ capsp->cap_above_base.value.ui64 =
+ ROUND_SCALE(cap->cap_above_base, tick_sec);
+ capsp->cap_bursting.value.ui64 =
+ ROUND_SCALE(cap->cap_bursting, tick_sec);
kstat_named_setstr(&capsp->cap_zonename, zonename);
return (0);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree.c b/usr/src/uts/common/fs/smbsrv/smb_tree.c
index 24dd27cdc5..a31b536236 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_tree.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c
@@ -232,7 +232,7 @@ smb_tree_connect_core(smb_request_t *sr)
(void) smb_strlwr(unc_path);
if ((name = smb_tree_get_sharename(unc_path)) == NULL) {
- smb_tree_log(sr, name, "invalid UNC path");
+ smb_tree_log(sr, unc_path, "invalid UNC path");
smbsr_error(sr, 0, ERRSRV, ERRinvnetname);
return (NULL);
}
diff --git a/usr/src/uts/common/inet/tcp/tcp_timers.c b/usr/src/uts/common/inet/tcp/tcp_timers.c
index a18c7dd8b1..6dbf02a9e5 100644
--- a/usr/src/uts/common/inet/tcp/tcp_timers.c
+++ b/usr/src/uts/common/inet/tcp/tcp_timers.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2011 Joyent, Inc. All rights reserved.
*/
#include <sys/types.h>
@@ -250,8 +251,11 @@ tcp_timeout_cancel(conn_t *connp, timeout_id_t id)
/*
* If we were unable to untimeout successfully, it has already
* been enqueued on the squeue; mark the ID with the free
- * bit. This bit can never be set in a valid identifier, and
+ * bit. This bit can never be set in a valid identifier, and
* we'll use it to prevent the timeout from being executed.
+ * And note that we're within the squeue perimeter here, so
+ * we don't need to worry about racing with timer handling
+ * (which also executes within the perimeter).
*/
tcpt->tcpt_tid |= CALLOUT_ID_FREE;
delta = 0;
diff --git a/usr/src/uts/common/io/dld/dld_proto.c b/usr/src/uts/common/io/dld/dld_proto.c
index 2fba6f2a25..3ef3ce1eaf 100644
--- a/usr/src/uts/common/io/dld/dld_proto.c
+++ b/usr/src/uts/common/io/dld/dld_proto.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -573,7 +574,7 @@ proto_promiscon_req(dld_str_t *dsp, mblk_t *mp)
dl_promiscon_req_t *dlp = (dl_promiscon_req_t *)mp->b_rptr;
int err = 0;
t_uscalar_t dl_err;
- uint32_t promisc_saved;
+ uint32_t new_flags, promisc_saved;
queue_t *q = dsp->ds_wq;
mac_perim_handle_t mph;
@@ -588,18 +589,20 @@ proto_promiscon_req(dld_str_t *dsp, mblk_t *mp)
goto failed;
}
- promisc_saved = dsp->ds_promisc;
+ mac_perim_enter_by_mh(dsp->ds_mh, &mph);
+
+ new_flags = promisc_saved = dsp->ds_promisc;
switch (dlp->dl_level) {
case DL_PROMISC_SAP:
- dsp->ds_promisc |= DLS_PROMISC_SAP;
+ new_flags |= DLS_PROMISC_SAP;
break;
case DL_PROMISC_MULTI:
- dsp->ds_promisc |= DLS_PROMISC_MULTI;
+ new_flags |= DLS_PROMISC_MULTI;
break;
case DL_PROMISC_PHYS:
- dsp->ds_promisc |= DLS_PROMISC_PHYS;
+ new_flags |= DLS_PROMISC_PHYS;
break;
default:
@@ -607,10 +610,8 @@ proto_promiscon_req(dld_str_t *dsp, mblk_t *mp)
goto failed;
}
- mac_perim_enter_by_mh(dsp->ds_mh, &mph);
-
if ((promisc_saved == 0) && (err = dls_active_set(dsp)) != 0) {
- dsp->ds_promisc = promisc_saved;
+ ASSERT(dsp->ds_promisc == promisc_saved);
dl_err = DL_SYSERR;
goto failed2;
}
@@ -618,7 +619,7 @@ proto_promiscon_req(dld_str_t *dsp, mblk_t *mp)
/*
* Adjust channel promiscuity.
*/
- err = dls_promisc(dsp, promisc_saved);
+ err = dls_promisc(dsp, new_flags);
if (err != 0) {
dl_err = DL_SYSERR;
@@ -648,7 +649,7 @@ proto_promiscoff_req(dld_str_t *dsp, mblk_t *mp)
dl_promiscoff_req_t *dlp = (dl_promiscoff_req_t *)mp->b_rptr;
int err = 0;
t_uscalar_t dl_err;
- uint32_t promisc_saved;
+ uint32_t new_flags;
queue_t *q = dsp->ds_wq;
mac_perim_handle_t mph;
@@ -663,14 +664,16 @@ proto_promiscoff_req(dld_str_t *dsp, mblk_t *mp)
goto failed;
}
- promisc_saved = dsp->ds_promisc;
+ mac_perim_enter_by_mh(dsp->ds_mh, &mph);
+
+ new_flags = dsp->ds_promisc;
switch (dlp->dl_level) {
case DL_PROMISC_SAP:
if (!(dsp->ds_promisc & DLS_PROMISC_SAP)) {
dl_err = DL_NOTENAB;
goto failed;
}
- dsp->ds_promisc &= ~DLS_PROMISC_SAP;
+ new_flags &= ~DLS_PROMISC_SAP;
break;
case DL_PROMISC_MULTI:
@@ -678,7 +681,7 @@ proto_promiscoff_req(dld_str_t *dsp, mblk_t *mp)
dl_err = DL_NOTENAB;
goto failed;
}
- dsp->ds_promisc &= ~DLS_PROMISC_MULTI;
+ new_flags &= ~DLS_PROMISC_MULTI;
break;
case DL_PROMISC_PHYS:
@@ -686,7 +689,7 @@ proto_promiscoff_req(dld_str_t *dsp, mblk_t *mp)
dl_err = DL_NOTENAB;
goto failed;
}
- dsp->ds_promisc &= ~DLS_PROMISC_PHYS;
+ new_flags &= ~DLS_PROMISC_PHYS;
break;
default:
@@ -694,11 +697,10 @@ proto_promiscoff_req(dld_str_t *dsp, mblk_t *mp)
goto failed;
}
- mac_perim_enter_by_mh(dsp->ds_mh, &mph);
/*
* Adjust channel promiscuity.
*/
- err = dls_promisc(dsp, promisc_saved);
+ err = dls_promisc(dsp, new_flags);
if (err != 0) {
mac_perim_exit(mph);
@@ -706,6 +708,7 @@ proto_promiscoff_req(dld_str_t *dsp, mblk_t *mp)
goto failed;
}
+ ASSERT(dsp->ds_promisc == new_flags);
if (dsp->ds_promisc == 0)
dls_active_clear(dsp, B_FALSE);
diff --git a/usr/src/uts/common/io/dls/dls.c b/usr/src/uts/common/io/dls/dls.c
index e29b1ee6ac..d35c1e4bbf 100644
--- a/usr/src/uts/common/io/dls/dls.c
+++ b/usr/src/uts/common/io/dls/dls.c
@@ -21,6 +21,11 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2012, Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * Copyright 2011 Joyent, Inc. All rights reserved.
*/
/*
@@ -82,7 +87,6 @@ dls_close(dld_str_t *dsp)
dls_link_t *dlp = dsp->ds_dlp;
dls_multicst_addr_t *p;
dls_multicst_addr_t *nextp;
- uint32_t old_flags;
ASSERT(dsp->ds_datathr_cnt == 0);
ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
@@ -119,9 +123,7 @@ dls_close(dld_str_t *dsp)
* If the MAC has been set in promiscuous mode then disable it.
* This needs to be done before resetting ds_rx.
*/
- old_flags = dsp->ds_promisc;
- dsp->ds_promisc = 0;
- (void) dls_promisc(dsp, old_flags);
+ (void) dls_promisc(dsp, 0);
/*
* At this point we have cutoff inbound packet flow from the mac
@@ -234,51 +236,60 @@ dls_unbind(dld_str_t *dsp)
dsp->ds_sap = 0;
}
+/*
+ * In order to prevent promiscuous-mode processing with dsp->ds_promisc
+ * set to inaccurate values, this function sets dsp->ds_promisc with new
+ * flags. For enabling (mac_promisc_add), the flags are set prior to the
+ * actual enabling. For disabling (mac_promisc_remove), the flags are set
+ * after the actual disabling.
+ */
int
-dls_promisc(dld_str_t *dsp, uint32_t old_flags)
+dls_promisc(dld_str_t *dsp, uint32_t new_flags)
{
- int err = 0;
+ int err = 0;
+ uint32_t old_flags = dsp->ds_promisc;
ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
- ASSERT(!(dsp->ds_promisc & ~(DLS_PROMISC_SAP | DLS_PROMISC_MULTI |
+ ASSERT(!(new_flags & ~(DLS_PROMISC_SAP | DLS_PROMISC_MULTI |
DLS_PROMISC_PHYS)));
- if (old_flags == 0 && dsp->ds_promisc != 0) {
+ if (dsp->ds_promisc == 0 && new_flags != 0) {
/*
* If only DLS_PROMISC_SAP, we don't turn on the
* physical promisc mode
*/
+ dsp->ds_promisc = new_flags;
err = mac_promisc_add(dsp->ds_mch, MAC_CLIENT_PROMISC_ALL,
dls_rx_promisc, dsp, &dsp->ds_mph,
- (dsp->ds_promisc != DLS_PROMISC_SAP) ? 0 :
+ (new_flags != DLS_PROMISC_SAP) ? 0 :
MAC_PROMISC_FLAGS_NO_PHYS);
- if (err != 0)
+ if (err != 0) {
+ dsp->ds_promisc = old_flags;
return (err);
+ }
/* Remove vlan promisc handle to avoid sending dup copy up */
if (dsp->ds_vlan_mph != NULL) {
mac_promisc_remove(dsp->ds_vlan_mph);
dsp->ds_vlan_mph = NULL;
}
- } else if (old_flags != 0 && dsp->ds_promisc == 0) {
+ } else if (dsp->ds_promisc != 0 && new_flags == 0) {
ASSERT(dsp->ds_mph != NULL);
mac_promisc_remove(dsp->ds_mph);
+ dsp->ds_promisc = new_flags;
dsp->ds_mph = NULL;
if (dsp->ds_sap == ETHERTYPE_VLAN &&
dsp->ds_dlstate != DL_UNBOUND) {
- int err;
-
if (dsp->ds_vlan_mph != NULL)
return (EINVAL);
err = mac_promisc_add(dsp->ds_mch,
MAC_CLIENT_PROMISC_ALL, dls_rx_vlan_promisc, dsp,
&dsp->ds_vlan_mph, MAC_PROMISC_FLAGS_NO_PHYS);
- return (err);
}
- } else if (old_flags == DLS_PROMISC_SAP && dsp->ds_promisc != 0 &&
- dsp->ds_promisc != old_flags) {
+ } else if (dsp->ds_promisc == DLS_PROMISC_SAP && new_flags != 0 &&
+ new_flags != dsp->ds_promisc) {
/*
* If the old flag is PROMISC_SAP, but the current flag has
* changed to some new non-zero value, we need to turn the
@@ -286,8 +297,15 @@ dls_promisc(dld_str_t *dsp, uint32_t old_flags)
*/
ASSERT(dsp->ds_mph != NULL);
mac_promisc_remove(dsp->ds_mph);
+ /* Honors both after-remove and before-add semantics! */
+ dsp->ds_promisc = new_flags;
err = mac_promisc_add(dsp->ds_mch, MAC_CLIENT_PROMISC_ALL,
dls_rx_promisc, dsp, &dsp->ds_mph, 0);
+ if (err != 0)
+ dsp->ds_promisc = old_flags;
+ } else {
+ /* No adding or removing, but record the new flags anyway. */
+ dsp->ds_promisc = new_flags;
}
return (err);
@@ -596,6 +614,22 @@ boolean_t
dls_accept_promisc(dld_str_t *dsp, mac_header_info_t *mhip, dls_rx_t *ds_rx,
void **ds_rx_arg, boolean_t loopback)
{
+ if (dsp->ds_promisc == 0) {
+ /*
+ * If there are active walkers of the mi_promisc_list when
+ * promiscuousness is disabled, ds_promisc will be cleared,
+ * but the DLS will remain on the mi_promisc_list until the
+ * walk is completed. If we do not recognize this case here,
+ * we won't properly execute the ds_promisc case in the common
+ * accept routine -- and we will potentially accept a packet
+ * that has originated with this DLS (which in turn can
+ * induce recursion and death by stack overflow). If
+ * ds_promisc is zero, we know that we are in this window --
+ * and we refuse to accept the packet.
+ */
+ return (B_FALSE);
+ }
+
return (dls_accept_common(dsp, mhip, ds_rx, ds_rx_arg, B_TRUE,
loopback));
}
diff --git a/usr/src/uts/common/io/igb/igb_82575.c b/usr/src/uts/common/io/igb/igb_82575.c
index 3a3fcc2d4f..462107a49d 100644
--- a/usr/src/uts/common/io/igb/igb_82575.c
+++ b/usr/src/uts/common/io/igb/igb_82575.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright(c) 2007-2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007-2012 Intel Corporation. All rights reserved.
*/
/*
@@ -80,6 +80,15 @@ static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw);
static void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw);
static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw);
+static s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw,
+ u16 offset);
+static s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw,
+ u16 offset);
+static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw);
+static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw);
+static void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value);
+static void e1000_clear_vfta_i350(struct e1000_hw *hw);
+
static const u16 e1000_82580_rxpbs_table[] =
{36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140};
#define E1000_82580_RXPBS_TABLE_SIZE \
@@ -151,6 +160,7 @@ e1000_init_phy_params_82575(struct e1000_hw *hw)
phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
break;
case I82580_I_PHY_ID:
+ case I350_I_PHY_ID:
phy->type = e1000_phy_82580;
phy->ops.check_polarity = e1000_check_polarity_82577;
phy->ops.force_speed_duplex =
@@ -222,6 +232,17 @@ e1000_init_nvm_params_82575(struct e1000_hw *hw)
nvm->ops.validate = e1000_validate_nvm_checksum_generic;
nvm->ops.write = e1000_write_nvm_spi;
+ /* override genric family function pointers for specific descendants */
+ switch (hw->mac.type) {
+ case e1000_i350:
+ nvm->ops.validate = e1000_validate_nvm_checksum_i350;
+ nvm->ops.update = e1000_update_nvm_checksum_i350;
+ break;
+ default:
+ break;
+ }
+
+
return (E1000_SUCCESS);
}
@@ -284,6 +305,11 @@ e1000_init_mac_params_82575(struct e1000_hw *hw)
mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
if (mac->type == e1000_82580)
mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
+ if (mac->type == e1000_i350) {
+ mac->rar_entry_count = E1000_RAR_ENTRIES_I350;
+ /* Enable EEE default settings for i350 */
+ dev_spec->eee_disable = B_FALSE;
+ }
/* Set if part includes ASF firmware */
mac->asf_firmware_present = true;
/* Set if manageability features are enabled. */
@@ -319,10 +345,18 @@ e1000_init_mac_params_82575(struct e1000_hw *hw)
mac->ops.read_mac_addr = e1000_read_mac_addr_82575;
/* multicast address update */
mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
- /* writing VFTA */
- mac->ops.write_vfta = e1000_write_vfta_generic;
- /* clearing VFTA */
- mac->ops.clear_vfta = e1000_clear_vfta_generic;
+
+ if (hw->mac.type == e1000_i350) {
+ /* writing VFTA */
+ mac->ops.write_vfta = e1000_write_vfta_i350;
+ /* clearing VFTA */
+ mac->ops.clear_vfta = e1000_clear_vfta_i350;
+ } else {
+ /* writing VFTA */
+ mac->ops.write_vfta = e1000_write_vfta_generic;
+ /* clearing VFTA */
+ mac->ops.clear_vfta = e1000_clear_vfta_generic;
+ }
/* setting MTA */
mac->ops.mta_set = e1000_mta_set_generic;
/* ID LED init */
@@ -697,6 +731,22 @@ e1000_acquire_nvm_82575(struct e1000_hw *hw)
if (ret_val)
goto out;
+ /*
+ * Check if there is some access
+ * error this access may hook on
+ */
+ if (hw->mac.type == e1000_i350) {
+ u32 eecd = E1000_READ_REG(hw, E1000_EECD);
+ if (eecd & (E1000_EECD_BLOCKED | E1000_EECD_ABORT |
+ E1000_EECD_TIMEOUT)) {
+ /* Clear all access error flags */
+ E1000_WRITE_REG(hw, E1000_EECD, eecd |
+ E1000_EECD_ERROR_CLR);
+ DEBUGOUT("Nvm bit banging access error "
+ "detected and cleared.\n");
+ }
+ }
+
ret_val = e1000_acquire_nvm_generic(hw);
if (ret_val)
@@ -1866,3 +1916,229 @@ e1000_rxpbs_adjust_82580(u32 data)
return (ret_val);
}
+
+/*
+ * Due to a hw errata, if the host tries to configure the VFTA register
+ * while performing queries from the BMC or DMA, then the VFTA in some
+ * cases won't be written.
+ */
+
+/*
+ * e1000_clear_vfta_i350 - Clear VLAN filter table
+ * @hw: pointer to the HW structure
+ *
+ * Clears the register array which contains the VLAN filter table by
+ * setting all the values to 0.
+ */
+void
+e1000_clear_vfta_i350(struct e1000_hw *hw)
+{
+ u32 offset;
+ int i;
+
+ DEBUGFUNC("e1000_clear_vfta_350");
+
+ for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
+ for (i = 0; i < 10; i++)
+ E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0);
+
+ E1000_WRITE_FLUSH(hw);
+ }
+}
+
+/*
+ * e1000_write_vfta_i350 - Write value to VLAN filter table
+ * @hw: pointer to the HW structure
+ * @offset: register offset in VLAN filter table
+ * @value: register value written to VLAN filter table
+ *
+ * Writes value at the given offset in the register array which stores
+ * the VLAN filter table.
+ */
+void
+e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
+{
+ int i;
+
+ DEBUGFUNC("e1000_write_vfta_350");
+
+ for (i = 0; i < 10; i++)
+ E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
+
+ E1000_WRITE_FLUSH(hw);
+}
+
+/*
+ * e1000_validate_nvm_checksum_with_offset - Validate EEPROM
+ * checksum
+ * @hw: pointer to the HW structure
+ * @offset: offset in words of the checksum protected region
+ *
+ * Calculates the EEPROM checksum by reading/adding each word of the EEPROM
+ * and then verifies that the sum of the EEPROM is equal to 0xBABA.
+ */
+s32
+e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 checksum = 0;
+ u16 i, nvm_data;
+
+ DEBUGFUNC("e1000_validate_nvm_checksum_with_offset");
+
+ for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) {
+ ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error\n");
+ goto out;
+ }
+ checksum += nvm_data;
+ }
+
+ if (checksum != (u16) NVM_SUM) {
+ DEBUGOUT("NVM Checksum Invalid\n");
+ ret_val = -E1000_ERR_NVM;
+ goto out;
+ }
+
+out:
+ return (ret_val);
+}
+
+/*
+ * e1000_update_nvm_checksum_with_offset - Update EEPROM
+ * checksum
+ * @hw: pointer to the HW structure
+ * @offset: offset in words of the checksum protected region
+ *
+ * Updates the EEPROM checksum by reading/adding each word of the EEPROM
+ * up to the checksum. Then calculates the EEPROM checksum and writes the
+ * value to the EEPROM.
+ */
+s32
+e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+{
+ s32 ret_val;
+ u16 checksum = 0;
+ u16 i, nvm_data;
+
+ DEBUGFUNC("e1000_update_nvm_checksum_with_offset");
+
+ for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) {
+ ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error while updating checksum.\n");
+ goto out;
+ }
+ checksum += nvm_data;
+ }
+ checksum = (u16) NVM_SUM - checksum;
+ ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1,
+ &checksum);
+ if (ret_val)
+ DEBUGOUT("NVM Write Error while updating checksum.\n");
+
+out:
+ return (ret_val);
+}
+
+/*
+ * e1000_validate_nvm_checksum_i350 - Validate EEPROM checksum
+ * @hw: pointer to the HW structure
+ *
+ * Calculates the EEPROM section checksum by reading/adding each word of
+ * the EEPROM and then verifies that the sum of the EEPROM is
+ * equal to 0xBABA.
+ */
+static s32
+e1000_validate_nvm_checksum_i350(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 j;
+ u16 nvm_offset;
+
+ DEBUGFUNC("e1000_validate_nvm_checksum_i350");
+
+ for (j = 0; j < 4; j++) {
+ nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+ ret_val = e1000_validate_nvm_checksum_with_offset(hw,
+ nvm_offset);
+ if (ret_val != E1000_SUCCESS)
+ goto out;
+ }
+
+out:
+ return (ret_val);
+}
+
+/*
+ * e1000_update_nvm_checksum_i350 - Update EEPROM checksum
+ * @hw: pointer to the HW structure
+ *
+ * Updates the EEPROM section checksums for all 4 ports by reading/adding
+ * each word of the EEPROM up to the checksum. Then calculates the EEPROM
+ * checksum and writes the value to the EEPROM.
+ */
+static s32
+e1000_update_nvm_checksum_i350(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 j;
+ u16 nvm_offset;
+
+ DEBUGFUNC("e1000_update_nvm_checksum_i350");
+
+ for (j = 0; j < 4; j++) {
+ nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+ ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset);
+ if (ret_val != E1000_SUCCESS)
+ goto out;
+ }
+
+out:
+ return (ret_val);
+}
+
+
+
+/*
+ * e1000_set_eee_i350 - Enable/disable EEE support
+ * @hw: pointer to the HW structure
+ *
+ * Enable/disable EEE based on setting in dev_spec structure.
+ *
+ */
+s32
+e1000_set_eee_i350(struct e1000_hw *hw)
+{
+
+ s32 ret_val = E1000_SUCCESS;
+ u32 ipcnfg, eeer;
+
+ DEBUGFUNC("e1000_set_eee_i350");
+
+ if ((hw->mac.type < e1000_i350) ||
+ (hw->phy.media_type != e1000_media_type_copper))
+ goto out;
+ ipcnfg = E1000_READ_REG(hw, E1000_IPCNFG);
+ eeer = E1000_READ_REG(hw, E1000_EEER);
+
+ /* enable or disable per user setting */
+ if (!(hw->dev_spec._82575.eee_disable)) {
+ ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN);
+ eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
+ E1000_EEER_LPI_FC);
+
+ } else {
+ ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN);
+ eeer &= ~(E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
+ E1000_EEER_LPI_FC);
+ }
+ E1000_WRITE_REG(hw, E1000_IPCNFG, ipcnfg);
+ E1000_WRITE_REG(hw, E1000_EEER, eeer);
+ E1000_READ_REG(hw, E1000_IPCNFG);
+ E1000_READ_REG(hw, E1000_EEER);
+out:
+
+ return (ret_val);
+}
diff --git a/usr/src/uts/common/io/igb/igb_82575.h b/usr/src/uts/common/io/igb/igb_82575.h
index 8f0add0b4b..2d9c657447 100644
--- a/usr/src/uts/common/io/igb/igb_82575.h
+++ b/usr/src/uts/common/io/igb/igb_82575.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright(c) 2007-2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007-2012 Intel Corporation. All rights reserved.
*/
/*
@@ -54,6 +54,7 @@ extern "C" {
#define E1000_RAR_ENTRIES_82575 16
#define E1000_RAR_ENTRIES_82576 24
#define E1000_RAR_ENTRIES_82580 24
+#define E1000_RAR_ENTRIES_I350 32
#define E1000_SW_SYNCH_MB 0x00000100
#define E1000_STAT_DEV_RST_SET 0x00100000
#define E1000_CTRL_DEV_RST 0x20000000
@@ -466,6 +467,7 @@ struct e1000_adv_tx_context_desc {
void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable);
void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable);
u16 e1000_rxpbs_adjust_82580(u32 data);
+s32 e1000_set_eee_i350(struct e1000_hw *hw);
#ifdef __cplusplus
}
diff --git a/usr/src/uts/common/io/igb/igb_api.c b/usr/src/uts/common/io/igb/igb_api.c
index 2da7c1926a..c966508281 100644
--- a/usr/src/uts/common/io/igb/igb_api.c
+++ b/usr/src/uts/common/io/igb/igb_api.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright(c) 2007-2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007-2012 Intel Corporation. All rights reserved.
*/
/*
@@ -151,6 +151,9 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82580_COPPER_DUAL:
mac->type = e1000_82580;
break;
+ case E1000_DEV_ID_I350_COPPER:
+ mac->type = e1000_i350;
+ break;
default:
/* Should never have loaded on this device */
ret_val = -E1000_ERR_MAC_INIT;
@@ -207,6 +210,7 @@ e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
case e1000_82575:
case e1000_82576:
case e1000_82580:
+ case e1000_i350:
e1000_init_function_pointers_82575(hw);
break;
default:
diff --git a/usr/src/uts/common/io/igb/igb_defines.h b/usr/src/uts/common/io/igb/igb_defines.h
index 8545a82b9c..a152f3fb1a 100644
--- a/usr/src/uts/common/io/igb/igb_defines.h
+++ b/usr/src/uts/common/io/igb/igb_defines.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright(c) 2007-2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007-2012 Intel Corporation. All rights reserved.
*/
/*
@@ -1007,6 +1007,14 @@ extern "C" {
#define E1000_IMIR_PRIORITY_SHIFT 29 /* IMIR Priority Shift */
#define E1000_IMIREXT_CLEAR_MASK 0x7FFFF /* IMIREXT Reg Clear Mask */
+/* I350 EEE defines */
+#define E1000_IPCNFG_EEE_1G_AN 0x00000008 /* IPCNFG EEE Ena 1G AN */
+#define E1000_IPCNFG_EEE_100M_AN 0x00000004 /* IPCNFG EEE Ena 100M AN */
+#define E1000_EEER_TX_LPI_EN 0x00010000 /* EEER Tx LPI Enable */
+#define E1000_EEER_RX_LPI_EN 0x00020000 /* EEER Rx LPI Enable */
+#define E1000_EEER_LPI_FC 0x00040000 /* EEER Ena on Flow Cntrl */
+
+
/* PCI Express Control */
#define E1000_GCR_RXD_NO_SNOOP 0x00000001
#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002
@@ -1148,6 +1156,11 @@ extern "C" {
#define E1000_EECD_GNT 0x00000080 /* NVM Access Grant */
#define E1000_EECD_PRES 0x00000100 /* NVM Present */
#define E1000_EECD_SIZE 0x00000200 /* NVM Size (0=64 word 1=256 word) */
+#define E1000_EECD_BLOCKED 0x00008000 /* Bit banging access blocked flag */
+#define E1000_EECD_ABORT 0x00010000 /* NVM operation aborted flag */
+#define E1000_EECD_TIMEOUT 0x00020000 /* NVM read operation timeout flag */
+#define E1000_EECD_ERROR_CLR 0x00040000 /* NVM error status clear bit */
+
/* NVM Addressing bits based on type 0=small, 1=large */
#define E1000_EECD_ADDR_BITS 0x00000400
#define E1000_EECD_TYPE 0x00002000 /* NVM Type (1-SPI, 0-Microwire) */
@@ -1307,6 +1320,7 @@ extern "C" {
#define IFE_PLUS_E_PHY_ID 0x02A80320
#define IFE_C_E_PHY_ID 0x02A80310
#define I82580_I_PHY_ID 0x015403A0
+#define I350_I_PHY_ID 0x015403B0
#define IGP04E1000_E_PHY_ID 0x02A80391
#define M88_VENDOR 0x0141
diff --git a/usr/src/uts/common/io/igb/igb_hw.h b/usr/src/uts/common/io/igb/igb_hw.h
index fbeef29b94..68082f977d 100644
--- a/usr/src/uts/common/io/igb/igb_hw.h
+++ b/usr/src/uts/common/io/igb/igb_hw.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright(c) 2007-2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007-2012 Intel Corporation. All rights reserved.
*/
/*
@@ -57,6 +57,7 @@ struct e1000_hw;
#define E1000_DEV_ID_82580_SERDES 0x1510
#define E1000_DEV_ID_82580_SGMII 0x1511
#define E1000_DEV_ID_82580_COPPER_DUAL 0x1516
+#define E1000_DEV_ID_I350_COPPER 0x1521
#define E1000_REVISION_0 0
#define E1000_REVISION_1 1
@@ -79,6 +80,7 @@ enum e1000_mac_type {
e1000_82575,
e1000_82576,
e1000_82580,
+ e1000_i350,
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
};
@@ -640,6 +642,7 @@ struct e1000_fc_info {
struct e1000_dev_spec_82575 {
bool sgmii_active;
bool global_device_reset;
+ int eee_disable;
};
struct e1000_dev_spec_vf {
diff --git a/usr/src/uts/common/io/igb/igb_main.c b/usr/src/uts/common/io/igb/igb_main.c
index 2d5d813198..200f0bd1a1 100644
--- a/usr/src/uts/common/io/igb/igb_main.c
+++ b/usr/src/uts/common/io/igb/igb_main.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright(c) 2007-2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007-2012 Intel Corporation. All rights reserved.
*/
/*
@@ -30,7 +30,7 @@
#include "igb_sw.h"
static char ident[] = "Intel 1Gb Ethernet";
-static char igb_version[] = "igb 1.1.17";
+static char igb_version[] = "igb 1.1.18";
/*
* Local function protoypes
@@ -285,6 +285,30 @@ static adapter_info_t igb_82580_cap = {
0xffe00000 /* mask for RXDCTL register */
};
+static adapter_info_t igb_i350_cap = {
+ /* limits */
+ 8, /* maximum number of rx queues */
+ 1, /* minimum number of rx queues */
+ 4, /* default number of rx queues */
+ 8, /* maximum number of tx queues */
+ 1, /* minimum number of tx queues */
+ 4, /* default number of tx queues */
+ 65535, /* maximum interrupt throttle rate */
+ 0, /* minimum interrupt throttle rate */
+ 200, /* default interrupt throttle rate */
+
+ /* function pointers */
+ igb_enable_adapter_interrupts_82580,
+ igb_setup_msix_82580,
+
+ /* capabilities */
+ (IGB_FLAG_HAS_DCA | /* capability flags */
+ IGB_FLAG_VMDQ_POOL |
+ IGB_FLAG_NEED_CTX_IDX),
+
+ 0xffe00000 /* mask for RXDCTL register */
+};
+
/*
* Module Initialization Functions
*/
@@ -517,6 +541,13 @@ igb_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
igb_log(igb, "%s", igb_version);
atomic_or_32(&igb->igb_state, IGB_INITIALIZED);
+ /*
+ * Newer models have Energy Efficient Ethernet, let's disable this by
+ * default.
+ */
+ if (igb->hw.mac.type == e1000_i350)
+ e1000_set_eee_i350(&igb->hw);
+
return (DDI_SUCCESS);
attach_fail:
@@ -836,6 +867,9 @@ igb_identify_hardware(igb_t *igb)
case e1000_82580:
igb->capab = &igb_82580_cap;
break;
+ case e1000_i350:
+ igb->capab = &igb_i350_cap;
+ break;
default:
return (IGB_FAILURE);
}
@@ -1699,6 +1733,9 @@ igb_start(igb_t *igb, boolean_t alloc_buffer)
if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK)
goto start_failure;
+ if (igb->hw.mac.type == e1000_i350)
+ e1000_set_eee_i350(&igb->hw);
+
for (i = igb->num_tx_rings - 1; i >= 0; i--)
mutex_exit(&igb->tx_rings[i].tx_lock);
for (i = igb->num_rx_rings - 1; i >= 0; i--)
diff --git a/usr/src/uts/common/io/igb/igb_regs.h b/usr/src/uts/common/io/igb/igb_regs.h
index ac7c5847f5..0d0f2c4228 100644
--- a/usr/src/uts/common/io/igb/igb_regs.h
+++ b/usr/src/uts/common/io/igb/igb_regs.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright(c) 2007-2010 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007-2012 Intel Corporation. All rights reserved.
*/
/*
@@ -570,6 +570,14 @@ extern "C" {
/* PCIe Parity Status Register */
#define E1000_PCIEERRSTS 0x05BA8
+/* Energy Efficient Ethernet "EEE" registers */
+#define E1000_IPCNFG 0x0E38 /* Internal PHY Configuration */
+#define E1000_LTRC 0x01A0 /* Latency Tolerance Reporting Control */
+#define E1000_EEER 0x0E30 /* Energy Efficient Ethernet "EEE" */
+#define E1000_EEE_SU 0x0E34 /* EEE Setup */
+#define E1000_TLPIC 0x4148 /* EEE Tx LPI Count - TLPIC */
+#define E1000_RLPIC 0x414C /* EEE Rx LPI Count - RLPIC */
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/common/io/mac/mac_sched.c b/usr/src/uts/common/io/mac/mac_sched.c
index 76188b4223..06a5ac8cbf 100644
--- a/usr/src/uts/common/io/mac/mac_sched.c
+++ b/usr/src/uts/common/io/mac/mac_sched.c
@@ -429,16 +429,17 @@ int mac_srs_worker_wakeup_ticks = 0;
* said, the constant is left as a static variable to allow it to be
* dynamically tuned in the field if and as needed.
*/
-static uintptr_t mac_rx_srs_stack_needed = 8192;
-static int mac_rx_srs_stack_toodeep;
+static uintptr_t mac_rx_srs_stack_needed = 10240;
+static uint_t mac_rx_srs_stack_toodeep;
#ifndef STACK_GROWTH_DOWN
#error Downward stack growth assumed.
#endif
-#define MAC_RX_SRS_TOODEEP() (STACK_BIAS + (uintptr_t)getfp() - \
- (uintptr_t)curthread->t_stkbase < mac_rx_srs_stack_needed && \
- ++mac_rx_srs_stack_toodeep)
+#define MAC_RX_SRS_TOODEEP() (STACK_BIAS + (uintptr_t)getfp() - \
+ (uintptr_t)curthread->t_stkbase < mac_rx_srs_stack_needed && \
+ ++mac_rx_srs_stack_toodeep)
+
/*
* Drop the rx packet and advance to the next one in the chain.
@@ -2531,9 +2532,9 @@ mac_rx_srs_process(void *arg, mac_resource_handle_t srs, mblk_t *mp_chain,
if (!(mac_srs->srs_state & SRS_PROC)) {
/*
- * If we are coming via loopback or if we are not optimizing
- * for latency or if our stack is running deep, we should
- * signal the worker thread.
+ * If we are coming via loopback, if we are not optimizing for
+ * latency, or if our stack is running deep, we should signal
+ * the worker thread.
*/
if (loopback || !(mac_srs->srs_state & SRS_LATENCY_OPT) ||
MAC_RX_SRS_TOODEEP()) {
diff --git a/usr/src/uts/common/io/sata/impl/sata.c b/usr/src/uts/common/io/sata/impl/sata.c
index d6229aa9c5..90ff93a284 100644
--- a/usr/src/uts/common/io/sata/impl/sata.c
+++ b/usr/src/uts/common/io/sata/impl/sata.c
@@ -18451,7 +18451,7 @@ sata_process_port_failed_event(sata_hba_inst_t *sata_hba_inst,
/*
* Device Reset Event processing.
- * The seqeunce is managed by 3 stage flags:
+ * The sequence is managed by 3 stage flags:
* - reset event reported,
* - reset event being processed,
* - request to clear device reset state.
diff --git a/usr/src/uts/common/os/timer.c b/usr/src/uts/common/os/timer.c
index 57c1ed97bd..57e369adca 100644
--- a/usr/src/uts/common/os/timer.c
+++ b/usr/src/uts/common/os/timer.c
@@ -24,7 +24,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ */
#include <sys/timer.h>
#include <sys/systm.h>
@@ -772,25 +774,6 @@ timer_settime(timer_t tid, int flags, itimerspec_t *val, itimerspec_t *oval)
if ((it = timer_grab(p, tid)) == NULL)
return (set_errno(EINVAL));
- /*
- * From the man page:
- * Time values that are between two consecutive non-negative
- * integer multiples of the resolution of the specified timer
- * shall be rounded up to the larger multiple of the resolution.
- * We assume that the resolution of any clock is less than one second.
- */
- if (it->it_backend->clk_clock_getres(&res) == 0 && res.tv_nsec > 1) {
- long rem;
-
- if ((rem = when.it_interval.tv_nsec % res.tv_nsec) != 0) {
- when.it_interval.tv_nsec += res.tv_nsec - rem;
- timespecfix(&when.it_interval);
- }
- if ((rem = when.it_value.tv_nsec % res.tv_nsec) != 0) {
- when.it_value.tv_nsec += res.tv_nsec - rem;
- timespecfix(&when.it_value);
- }
- }
error = it->it_backend->clk_timer_settime(it, flags, &when);
timer_release(p, it);
diff --git a/usr/src/uts/common/os/zone.c b/usr/src/uts/common/os/zone.c
index a9bd61f05c..3ea0d0fe95 100644
--- a/usr/src/uts/common/os/zone.c
+++ b/usr/src/uts/common/os/zone.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent Inc. All rights reserved.
+ * Copyright (c) 2011, 2012, Joyent Inc. All rights reserved.
*/
/*
@@ -373,6 +373,8 @@ rctl_hndl_t rc_zone_max_swap;
rctl_hndl_t rc_zone_phys_mem;
rctl_hndl_t rc_zone_max_lofi;
rctl_hndl_t rc_zone_cpu_cap;
+rctl_hndl_t rc_zone_cpu_baseline;
+rctl_hndl_t rc_zone_cpu_burst_time;
rctl_hndl_t rc_zone_zfs_io_pri;
rctl_hndl_t rc_zone_nlwps;
rctl_hndl_t rc_zone_nprocs;
@@ -1382,6 +1384,76 @@ static rctl_ops_t zone_cpu_cap_ops = {
rcop_no_test
};
+/*ARGSUSED*/
+static rctl_qty_t
+zone_cpu_base_get(rctl_t *rctl, struct proc *p)
+{
+ ASSERT(MUTEX_HELD(&p->p_lock));
+ return (cpucaps_zone_get_base(p->p_zone));
+}
+
+/*
+ * The zone cpu base is used to set the baseline CPU for the zone
+ * so we can track when the zone is bursting.
+ */
+/*ARGSUSED*/
+static int
+zone_cpu_base_set(rctl_t *rctl, struct proc *p, rctl_entity_p_t *e,
+ rctl_qty_t nv)
+{
+ zone_t *zone = e->rcep_p.zone;
+
+ ASSERT(MUTEX_HELD(&p->p_lock));
+ ASSERT(e->rcep_t == RCENTITY_ZONE);
+
+ if (zone == NULL)
+ return (0);
+
+ return (cpucaps_zone_set_base(zone, nv));
+}
+
+static rctl_ops_t zone_cpu_base_ops = {
+ rcop_no_action,
+ zone_cpu_base_get,
+ zone_cpu_base_set,
+ rcop_no_test
+};
+
+/*ARGSUSED*/
+static rctl_qty_t
+zone_cpu_burst_time_get(rctl_t *rctl, struct proc *p)
+{
+ ASSERT(MUTEX_HELD(&p->p_lock));
+ return (cpucaps_zone_get_burst_time(p->p_zone));
+}
+
+/*
+ * The zone cpu burst time is used to set the amount of time CPU(s) can be
+ * bursting for the zone.
+ */
+/*ARGSUSED*/
+static int
+zone_cpu_burst_time_set(rctl_t *rctl, struct proc *p, rctl_entity_p_t *e,
+ rctl_qty_t nv)
+{
+ zone_t *zone = e->rcep_p.zone;
+
+ ASSERT(MUTEX_HELD(&p->p_lock));
+ ASSERT(e->rcep_t == RCENTITY_ZONE);
+
+ if (zone == NULL)
+ return (0);
+
+ return (cpucaps_zone_set_burst_time(zone, nv));
+}
+
+static rctl_ops_t zone_cpu_burst_time_ops = {
+ rcop_no_action,
+ zone_cpu_burst_time_get,
+ zone_cpu_burst_time_set,
+ rcop_no_test
+};
+
/*
* zone.zfs-io-pri resource control support (IO priority).
*/
@@ -2428,6 +2500,16 @@ zone_init(void)
RCTL_GLOBAL_INFINITE,
MAXCAP, MAXCAP, &zone_cpu_cap_ops);
+ rc_zone_cpu_baseline = rctl_register("zone.cpu-baseline",
+ RCENTITY_ZONE, RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_DENY_NEVER |
+ RCTL_GLOBAL_NOBASIC | RCTL_GLOBAL_COUNT | RCTL_GLOBAL_SYSLOG_NEVER,
+ MAXCAP, MAXCAP, &zone_cpu_base_ops);
+
+ rc_zone_cpu_burst_time = rctl_register("zone.cpu-burst-time",
+ RCENTITY_ZONE, RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_DENY_NEVER |
+ RCTL_GLOBAL_NOBASIC | RCTL_GLOBAL_COUNT | RCTL_GLOBAL_SYSLOG_NEVER,
+ INT_MAX, INT_MAX, &zone_cpu_burst_time_ops);
+
rc_zone_zfs_io_pri = rctl_register("zone.zfs-io-priority",
RCENTITY_ZONE, RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_DENY_NEVER |
RCTL_GLOBAL_NOBASIC | RCTL_GLOBAL_COUNT | RCTL_GLOBAL_SYSLOG_NEVER,
diff --git a/usr/src/uts/common/sys/cpucaps.h b/usr/src/uts/common/sys/cpucaps.h
index 6063ff4380..6bc042108c 100644
--- a/usr/src/uts/common/sys/cpucaps.h
+++ b/usr/src/uts/common/sys/cpucaps.h
@@ -22,6 +22,7 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2011, 2012, Joyent, Inc. All rights reserved.
*/
#ifndef _SYS_CPUCAPS_H
@@ -84,12 +85,16 @@ extern void cpucaps_zone_remove(zone_t *);
*/
extern int cpucaps_project_set(kproject_t *, rctl_qty_t);
extern int cpucaps_zone_set(zone_t *, rctl_qty_t);
+extern int cpucaps_zone_set_base(zone_t *, rctl_qty_t);
+extern int cpucaps_zone_set_burst_time(zone_t *, rctl_qty_t);
/*
* Get current CPU usage for a project/zone.
*/
extern rctl_qty_t cpucaps_project_get(kproject_t *);
extern rctl_qty_t cpucaps_zone_get(zone_t *);
+extern rctl_qty_t cpucaps_zone_get_base(zone_t *);
+extern rctl_qty_t cpucaps_zone_get_burst_time(zone_t *);
/*
* Scheduling class hooks into CPU caps framework.
diff --git a/usr/src/uts/common/sys/cpucaps_impl.h b/usr/src/uts/common/sys/cpucaps_impl.h
index 95afd21827..2cd4ed644d 100644
--- a/usr/src/uts/common/sys/cpucaps_impl.h
+++ b/usr/src/uts/common/sys/cpucaps_impl.h
@@ -22,6 +22,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2011, 2012, Joyent, Inc. All rights reserved.
*/
#ifndef _SYS_CPUCAPS_IMPL_H
@@ -66,8 +67,12 @@ typedef struct cpucap {
waitq_t cap_waitq; /* waitq for capped threads */
kstat_t *cap_kstat; /* cpucaps specific kstat */
int64_t cap_gen; /* zone cap specific */
+ hrtime_t cap_chk_value; /* effective CPU usage cap */
hrtime_t cap_value; /* scaled CPU usage cap */
hrtime_t cap_usage; /* current CPU usage */
+ hrtime_t cap_base; /* base CPU for burst */
+ u_longlong_t cap_burst_limit; /* max secs (in tics) for a burst */
+ u_longlong_t cap_bursting; /* # of ticks currently bursting */
disp_lock_t cap_usagelock; /* protects cap_usage above */
/*
* Per cap statistics.
@@ -75,6 +80,7 @@ typedef struct cpucap {
hrtime_t cap_maxusage; /* maximum cap usage */
u_longlong_t cap_below; /* # of ticks spend below the cap */
u_longlong_t cap_above; /* # of ticks spend above the cap */
+ u_longlong_t cap_above_base; /* # of ticks spent above the base */
} cpucap_t;
/*
diff --git a/usr/src/uts/common/sys/vm_usage.h b/usr/src/uts/common/sys/vm_usage.h
index 1aa4a8ee6d..97e3430ae2 100644
--- a/usr/src/uts/common/sys/vm_usage.h
+++ b/usr/src/uts/common/sys/vm_usage.h
@@ -21,6 +21,7 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2012 Joyent, Inc. All rights reserved.
*/
#ifndef _SYS_VM_USAGE_H
@@ -79,8 +80,9 @@ extern "C" {
/* zoneid */
#define VMUSAGE_COL_EUSERS 0x2000 /* same as VMUSAGE_COL_RUSERS, but by */
/* euser */
+#define VMUSAGE_A_ZONE 0x4000 /* rss/swap for a specified zone */
-#define VMUSAGE_MASK 0x3fff /* all valid flags for getvmusage() */
+#define VMUSAGE_MASK 0x7fff /* all valid flags for getvmusage() */
typedef struct vmusage {
id_t vmu_zoneid; /* zoneid, or ALL_ZONES for */
diff --git a/usr/src/uts/common/vm/vm_usage.c b/usr/src/uts/common/vm/vm_usage.c
index e1578538a3..18e3c4c806 100644
--- a/usr/src/uts/common/vm/vm_usage.c
+++ b/usr/src/uts/common/vm/vm_usage.c
@@ -22,7 +22,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2011 Joyent, Inc. All rights reserved.
+ * Copyright 2011, 2012, Joyent, Inc. All rights reserved.
*/
/*
@@ -519,7 +519,8 @@ vmu_alloc_zone(id_t id)
zone->vmz_id = id;
- if ((vmu_data.vmu_calc_flags & (VMUSAGE_ZONE | VMUSAGE_ALL_ZONES)) != 0)
+ if ((vmu_data.vmu_calc_flags &
+ (VMUSAGE_ZONE | VMUSAGE_ALL_ZONES | VMUSAGE_A_ZONE)) != 0)
zone->vmz_zone = vmu_alloc_entity(id, VMUSAGE_ZONE, id);
if ((vmu_data.vmu_calc_flags & (VMUSAGE_PROJECTS |
@@ -1462,8 +1463,9 @@ vmu_calculate_proc(proc_t *p)
entities = tmp;
}
if (vmu_data.vmu_calc_flags &
- (VMUSAGE_ZONE | VMUSAGE_ALL_ZONES | VMUSAGE_PROJECTS |
- VMUSAGE_ALL_PROJECTS | VMUSAGE_TASKS | VMUSAGE_ALL_TASKS |
+ (VMUSAGE_ZONE | VMUSAGE_ALL_ZONES | VMUSAGE_A_ZONE |
+ VMUSAGE_PROJECTS | VMUSAGE_ALL_PROJECTS |
+ VMUSAGE_TASKS | VMUSAGE_ALL_TASKS |
VMUSAGE_RUSERS | VMUSAGE_ALL_RUSERS | VMUSAGE_EUSERS |
VMUSAGE_ALL_EUSERS)) {
ret = i_mod_hash_find_nosync(vmu_data.vmu_zones_hash,
@@ -1767,7 +1769,7 @@ vmu_update_zone_rctls(vmu_cache_t *cache)
*/
static int
vmu_copyout_results(vmu_cache_t *cache, vmusage_t *buf, size_t *nres,
- uint_t flags, int cpflg)
+ uint_t flags, id_t req_zone_id, int cpflg)
{
vmusage_t *result, *out_result;
vmusage_t dummy;
@@ -1786,7 +1788,7 @@ vmu_copyout_results(vmu_cache_t *cache, vmusage_t *buf, size_t *nres,
/* figure out what results the caller is interested in. */
if ((flags & VMUSAGE_SYSTEM) && curproc->p_zone == global_zone)
types |= VMUSAGE_SYSTEM;
- if (flags & (VMUSAGE_ZONE | VMUSAGE_ALL_ZONES))
+ if (flags & (VMUSAGE_ZONE | VMUSAGE_ALL_ZONES | VMUSAGE_A_ZONE))
types |= VMUSAGE_ZONE;
if (flags & (VMUSAGE_PROJECTS | VMUSAGE_ALL_PROJECTS |
VMUSAGE_COL_PROJECTS))
@@ -1849,26 +1851,33 @@ vmu_copyout_results(vmu_cache_t *cache, vmusage_t *buf, size_t *nres,
continue;
}
- /* Skip "other zone" results if not requested */
- if (result->vmu_zoneid != curproc->p_zone->zone_id) {
- if (result->vmu_type == VMUSAGE_ZONE &&
- (flags & VMUSAGE_ALL_ZONES) == 0)
- continue;
- if (result->vmu_type == VMUSAGE_PROJECTS &&
- (flags & (VMUSAGE_ALL_PROJECTS |
- VMUSAGE_COL_PROJECTS)) == 0)
- continue;
- if (result->vmu_type == VMUSAGE_TASKS &&
- (flags & VMUSAGE_ALL_TASKS) == 0)
- continue;
- if (result->vmu_type == VMUSAGE_RUSERS &&
- (flags & (VMUSAGE_ALL_RUSERS |
- VMUSAGE_COL_RUSERS)) == 0)
- continue;
- if (result->vmu_type == VMUSAGE_EUSERS &&
- (flags & (VMUSAGE_ALL_EUSERS |
- VMUSAGE_COL_EUSERS)) == 0)
+ if (result->vmu_type == VMUSAGE_ZONE &&
+ flags & VMUSAGE_A_ZONE) {
+ /* Skip non-requested zone results */
+ if (result->vmu_zoneid != req_zone_id)
continue;
+ } else {
+ /* Skip "other zone" results if not requested */
+ if (result->vmu_zoneid != curproc->p_zone->zone_id) {
+ if (result->vmu_type == VMUSAGE_ZONE &&
+ (flags & VMUSAGE_ALL_ZONES) == 0)
+ continue;
+ if (result->vmu_type == VMUSAGE_PROJECTS &&
+ (flags & (VMUSAGE_ALL_PROJECTS |
+ VMUSAGE_COL_PROJECTS)) == 0)
+ continue;
+ if (result->vmu_type == VMUSAGE_TASKS &&
+ (flags & VMUSAGE_ALL_TASKS) == 0)
+ continue;
+ if (result->vmu_type == VMUSAGE_RUSERS &&
+ (flags & (VMUSAGE_ALL_RUSERS |
+ VMUSAGE_COL_RUSERS)) == 0)
+ continue;
+ if (result->vmu_type == VMUSAGE_EUSERS &&
+ (flags & (VMUSAGE_ALL_EUSERS |
+ VMUSAGE_COL_EUSERS)) == 0)
+ continue;
+ }
}
count++;
if (out_result != NULL) {
@@ -1924,10 +1933,12 @@ vm_getusage(uint_t flags, time_t age, vmusage_t *buf, size_t *nres, int cpflg)
int cacherecent = 0;
hrtime_t now;
uint_t flags_orig;
+ id_t req_zone_id;
/*
* Non-global zones cannot request system wide and/or collated
- * results, or the system result, so munge the flags accordingly.
+ * results, or the system result, or usage of another zone, so munge
+ * the flags accordingly.
*/
flags_orig = flags;
if (curproc->p_zone != global_zone) {
@@ -1947,6 +1958,10 @@ vm_getusage(uint_t flags, time_t age, vmusage_t *buf, size_t *nres, int cpflg)
flags &= ~VMUSAGE_SYSTEM;
flags |= VMUSAGE_ZONE;
}
+ if (flags & VMUSAGE_A_ZONE) {
+ flags &= ~VMUSAGE_A_ZONE;
+ flags |= VMUSAGE_ZONE;
+ }
}
/* Check for unknown flags */
@@ -1957,6 +1972,21 @@ vm_getusage(uint_t flags, time_t age, vmusage_t *buf, size_t *nres, int cpflg)
if ((flags & VMUSAGE_MASK) == 0)
return (set_errno(EINVAL));
+ /* If requesting results for a specific zone, get the zone ID */
+ if (flags & VMUSAGE_A_ZONE) {
+ size_t bufsize;
+ vmusage_t zreq;
+
+ if (ddi_copyin((caddr_t)nres, &bufsize, sizeof (size_t), cpflg))
+ return (set_errno(EFAULT));
+ /* Requested zone ID is passed in buf, so 0 len not allowed */
+ if (bufsize == 0)
+ return (set_errno(EINVAL));
+ if (ddi_copyin((caddr_t)buf, &zreq, sizeof (vmusage_t), cpflg))
+ return (set_errno(EFAULT));
+ req_zone_id = zreq.vmu_id;
+ }
+
mutex_enter(&vmu_data.vmu_lock);
now = gethrtime();
@@ -1976,7 +2006,7 @@ start:
mutex_exit(&vmu_data.vmu_lock);
ret = vmu_copyout_results(cache, buf, nres, flags_orig,
- cpflg);
+ req_zone_id, cpflg);
mutex_enter(&vmu_data.vmu_lock);
vmu_cache_rele(cache);
if (vmu_data.vmu_pending_waiters > 0)
@@ -2035,7 +2065,8 @@ start:
/* update zone's phys. mem. rctl usage */
vmu_update_zone_rctls(cache);
/* copy cache */
- ret = vmu_copyout_results(cache, buf, nres, flags_orig, cpflg);
+ ret = vmu_copyout_results(cache, buf, nres, flags_orig,
+ req_zone_id, cpflg);
mutex_enter(&vmu_data.vmu_lock);
vmu_cache_rele(cache);
mutex_exit(&vmu_data.vmu_lock);