Mercurial > illumos > git > illumos-core
changeset 14992:0bfb555837b4
Merge branch 'master' into core
Conflicts:
usr/src/man/man2/Makefile
usr/src/man/man2/chmod.2
usr/src/man/man2/link.2
usr/src/man/man2/mkdir.2
usr/src/man/man2/mknod.2
usr/src/man/man2/readlink.2
usr/src/man/man2/symlink.2
usr/src/man/man2/utimes.2
usr/src/man/man3c/Makefile
usr/src/man/man3c/mkfifo.3c
usr/src/man/man3c/pthread_mutex_consistent.3c
usr/src/man/man3c/pthread_mutexattr_getrobust.3c
usr/src/man/man3lib/libc.3lib
usr/src/man/man9f/Intro.9f
usr/src/pkg/manifests/system-kernel.man2.inc
line wrap: on
line diff
--- a/usr/src/cmd/Makefile Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/Makefile Sun Jan 04 07:19:22 2015 -0800 @@ -808,6 +808,7 @@ ksh: shcomp isaexec mdb: terminfo print: lp +fmt: mailx $(FIRST_SUBDIRS) $(BWOSDIRS) $(SUBDIRS) $(AUDITSUBDIRS): FRC @if [ -f $@/Makefile ]; then \
--- a/usr/src/cmd/dd/dd.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/dd/dd.c Sun Jan 04 07:19:22 2015 -0800 @@ -147,6 +147,7 @@ static off_t oseekn; /* number of output records to seek past */ static unsigned long long count; /* number of input records to copy */ /* (0 = all) */ +static boolean_t ecount; /* explicit count given */ static int trantype; /* BSD or SVr4 compatible EBCDIC */ static char *string; /* command arg pointer */ @@ -571,6 +572,7 @@ if (match("count=")) { count = number(BIG); + ecount = B_TRUE; continue; } if (match("files=")) @@ -1009,8 +1011,7 @@ nstats = 0; } - if ((count == 0) || (nifr+nipr < count)) - { + if ((count == 0 && ecount == B_FALSE) || (nifr+nipr < count)) { /* If proceed on error is enabled, zero the input buffer */ if (cflag&NERR)
--- a/usr/src/cmd/fmt/Makefile Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/fmt/Makefile Sun Jan 04 07:19:22 2015 -0800 @@ -33,6 +33,7 @@ include ../Makefile.cmd +LDLIBS += -lcmdutils CERRWARN += -_gcc=-Wno-switch CERRWARN += -_gcc=-Wno-parentheses
--- a/usr/src/cmd/fmt/fmt.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/fmt/fmt.c Sun Jan 04 07:19:22 2015 -0800 @@ -86,7 +86,7 @@ void (*(split))(wchar_t []); extern int scrwidth(wchar_t); -extern int ishead(char []); +extern boolean_t is_headline(const char *); static void fill_hdrbuf(wchar_t []); @@ -240,13 +240,13 @@ } /* * Need to convert string from wchar_t to char, - * since this is what ishead() expects. Since we + * since this is what is_headline() expects. Since we * only want to make sure cp points to a "From" line * of the email, we don't have to alloc * BUFSIZ * MB_LEN_MAX to cbuf. */ wcstombs(cbuf, cp, (BUFSIZ - 1)); - if (ishead(cbuf)) { + if (is_headline(cbuf) == B_TRUE) { hdr_state = in_hdr; fill_hdrbuf(canonb); } else {
--- a/usr/src/cmd/ipf/lib/common/load_hash.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/ipf/lib/common/load_hash.c Sun Jan 04 07:19:22 2015 -0800 @@ -7,15 +7,16 @@ * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <fcntl.h> #include <sys/ioctl.h> #include "ipf.h" #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" +#include "ipfzone.h" static int hashfd = -1; @@ -35,6 +36,10 @@ hashfd = open(IPLOOKUP_NAME, O_RDWR); if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) return -1; + if (setzone(hashfd) != 0) { + close(hashfd); + return -1; + } for (n = 0, a = list; a != NULL; a = a->ipe_next) n++;
--- a/usr/src/cmd/ipf/lib/common/load_hashnode.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/ipf/lib/common/load_hashnode.c Sun Jan 04 07:19:22 2015 -0800 @@ -7,15 +7,16 @@ * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <fcntl.h> #include <sys/ioctl.h> #include "ipf.h" #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" +#include "ipfzone.h" static int hashfd = -1; @@ -34,6 +35,10 @@ hashfd = open(IPLOOKUP_NAME, O_RDWR); if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) return -1; + if (setzone(hashfd) != 0) { + close(hashfd); + return -1; + } op.iplo_type = IPLT_HASH; op.iplo_unit = unit;
--- a/usr/src/cmd/ipf/lib/common/load_pool.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/ipf/lib/common/load_pool.c Sun Jan 04 07:19:22 2015 -0800 @@ -7,15 +7,16 @@ * * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <fcntl.h> #include <sys/ioctl.h> #include "ipf.h" #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" +#include "ipfzone.h" static int poolfd = -1; @@ -32,6 +33,10 @@ poolfd = open(IPLOOKUP_NAME, O_RDWR); if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0)) return -1; + if (setzone(poolfd) != 0) { + close(poolfd); + return -1; + } op.iplo_unit = plp->ipo_unit; op.iplo_type = IPLT_POOL;
--- a/usr/src/cmd/ipf/lib/common/load_poolnode.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/ipf/lib/common/load_poolnode.c Sun Jan 04 07:19:22 2015 -0800 @@ -4,6 +4,8 @@ * See the IPFILTER.LICENCE file for details on licencing. * * $Id: load_poolnode.c,v 1.3.2.1 2004/03/06 14:33:29 darrenr Exp $ + * + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #include <fcntl.h> @@ -11,6 +13,7 @@ #include "ipf.h" #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" +#include "ipfzone.h" static int poolfd = -1; @@ -29,6 +32,10 @@ poolfd = open(IPLOOKUP_NAME, O_RDWR); if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0)) return -1; + if (setzone(poolfd) != 0) { + close(poolfd); + return -1; + } op.iplo_unit = role; op.iplo_type = IPLT_POOL;
--- a/usr/src/cmd/ipf/tools/Makefile.tools Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/ipf/tools/Makefile.tools Sun Jan 04 07:19:22 2015 -0800 @@ -24,17 +24,19 @@ # # Copyright 2013 Nexenta Systems, Inc. All rights reserved. # +# Copyright (c) 2012, Joyent Inc. All rights reserved. +# PROG= ipf ipfs ipmon ipnat ippool ipfstat IPFPROG= ipftest -IPF_OBJS= ipf.o ipfcomp.o ipf_y.o ipf_l.o -IPFS_OBJS= ipfs.o -IPFSTAT_OBJS= ipfstat.o -IPMON_OBJS= ipmon.o ipmon_y.o ipmon_l.o -IPNAT_OBJS= ipnat.o ipnat_y.o ipnat_l.o -IPPOOL_OBJS= ippool.o ippool_y.o ippool_l.o -IPFTEST_OBJS= ipftest.o \ +IPF_OBJS= ipf.o ipfcomp.o ipfzone.o ipf_y.o ipf_l.o +IPFS_OBJS= ipfs.o ipfzone.o +IPFSTAT_OBJS= ipfstat.o ipfzone.o +IPMON_OBJS= ipmon.o ipfzone.o ipmon_y.o ipmon_l.o +IPNAT_OBJS= ipnat.o ipfzone.o ipnat_y.o ipnat_l.o +IPPOOL_OBJS= ippool.o ipfzone.o ippool_y.o ippool_l.o +IPFTEST_OBJS= ipftest.o ipfzone.o \ ip_fil.o ip_state.o ip_compat.o \ ip_frag.o ip_nat.o ip_nat6.o fil.o \ ip_htable.o ip_lookup.o \
--- a/usr/src/cmd/ipf/tools/ipf.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/ipf/tools/ipf.c Sun Jan 04 07:19:22 2015 -0800 @@ -5,6 +5,8 @@ * * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #ifdef __FreeBSD__ @@ -20,6 +22,7 @@ #include <fcntl.h> #include <sys/ioctl.h> #include "netinet/ipl.h" +#include "ipfzone.h" #if !defined(lint) static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed"; @@ -62,9 +65,9 @@ static void usage() { - fprintf(stderr, "usage: ipf [-6AdDEInoPrRsvVyzZ] %s %s %s\n", + fprintf(stderr, "usage: ipf [-6AdDEGInoPrRsvVyzZ] %s %s %s", "[-l block|pass|nomatch|state|nat]", "[-cc] [-F i|o|a|s|S|u]", - "[-f filename] [-T <tuneopts>]"); + "[-f filename] [-T <tuneopts>] [zonename]\n"); exit(1); } @@ -74,11 +77,21 @@ char *argv[]; { int c; + const char *optstr = "6Ac:dDEf:F:GIl:noPrRsT:vVyzZ"; if (argc < 2) usage(); - while ((c = getopt(argc, argv, "6Ac:dDEf:F:Il:noPrRsT:vVyzZ")) != -1) { + /* + * We need to set the zone name before calling the functions + * in the switch statement below. Note that ipf.c differs from the other + * tools in the ipfilter suite: the zone name is specified as the + * last argument, while the other tools use the -z option. ipf + * already has a -z option, so the last argument is used instead. + */ + getzonearg(argc, argv, optstr); + + while ((c = getopt(argc, argv, optstr)) != -1) { switch (c) { case '?' : @@ -111,6 +124,9 @@ case 'F' : flushfilter(optarg); break; + case 'G' : + /* Already handled by getzonearg() above */ + break; case 'I' : opts ^= OPT_INACTIVE; break; @@ -187,6 +203,12 @@ if ((fd = open(ipfdev, O_RDWR)) == -1) if ((fd = open(ipfdev, O_RDONLY)) == -1) perror("open device"); + + if (setzone(fd) != 0) { + close(fd); + return -2; + } + return fd; } @@ -307,6 +329,11 @@ if (opts & OPT_VERBOSE) printf("set state log flag\n"); xfd = open(IPSTATE_NAME, O_RDWR); + if (xfd >= 0 && setzone(xfd) != 0) { + close(xfd); + xfd = -1; + } + if (xfd >= 0) { logopt = 0; if (ioctl(xfd, SIOCGETLG, &logopt)) @@ -324,6 +351,11 @@ if (opts & OPT_VERBOSE) printf("set nat log flag\n"); xfd = open(IPNAT_NAME, O_RDWR); + if (xfd >= 0 && setzone(xfd) != 0) { + close(xfd); + xfd = -1; + } + if (xfd >= 0) { logopt = 0; if (ioctl(xfd, SIOCGETLG, &logopt)) @@ -516,6 +548,11 @@ return 1; } + if (setzone(vfd) != 0) { + close(vfd); + return 1; + } + if (ioctl(vfd, SIOCGETFS, &ipfo)) { perror("ioctl(SIOCGETFS)"); close(vfd);
--- a/usr/src/cmd/ipf/tools/ipfs.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/ipf/tools/ipfs.c Sun Jan 04 07:19:22 2015 -0800 @@ -5,6 +5,8 @@ * * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #ifdef __FreeBSD__ @@ -44,6 +46,7 @@ #include <resolv.h> #include "ipf.h" #include "netinet/ipl.h" +#include "ipfzone.h" #if !defined(lint) static const char rcsid[] = "@(#)Id: ipfs.c,v 1.12 2003/12/01 01:56:53 darrenr Exp"; @@ -86,14 +89,17 @@ void usage() { - fprintf(stderr, "usage: %s [-nv] -l\n", progname); - fprintf(stderr, "usage: %s [-nv] -u\n", progname); - fprintf(stderr, "usage: %s [-nv] [-d <dir>] -R\n", progname); - fprintf(stderr, "usage: %s [-nv] [-d <dir>] -W\n", progname); - fprintf(stderr, "usage: %s [-nv] [-N|-S] [-f <file>] -r\n", progname); - fprintf(stderr, "usage: %s [-nv] [-N|-S] [-f <file>] -w\n", progname); - fprintf(stderr, "usage: %s [-nv] [-N|-S] -f <file> -i <if1>,<if2>\n", - progname); + const char *zoneopt = "[-G|-z zonename] "; + fprintf(stderr, "usage: %s %s[-nv] -l\n", progname, zoneopt); + fprintf(stderr, "usage: %s %s[-nv] -u\n", progname, zoneopt); + fprintf(stderr, "usage: %s %s[-nv] [-d <dir>] -R\n", progname, zoneopt); + fprintf(stderr, "usage: %s %s[-nv] [-d <dir>] -W\n", progname, zoneopt); + fprintf(stderr, "usage: %s %s[-nv] [-N|-S] [-f <file>] -r\n", progname, + zoneopt); + fprintf(stderr, "usage: %s %s[-nv] [-N|-S] [-f <file>] -w\n", progname, + zoneopt); + fprintf(stderr, "usage: %s %s[-nv] [-N|-S] -f <file> -i <if1>,<if2>\n", + progname, zoneopt); exit(1); } @@ -218,7 +224,7 @@ char *dirname = NULL, *filename = NULL, *ifs = NULL; progname = argv[0]; - while ((c = getopt(argc, argv, "d:f:lNnSRruvWw")) != -1) + while ((c = getopt(argc, argv, "d:f:G:lNnSRruvWwz:")) != -1) switch (c) { case 'd' : @@ -233,6 +239,9 @@ else usage(); break; + case 'G' : + setzonename_global(optarg); + break; case 'i' : ifs = optarg; set = 1; @@ -287,6 +296,9 @@ rw = 3; set = 1; break; + case 'z' : + setzonename(optarg); + break; case '?' : default : usage(); @@ -355,6 +367,12 @@ if ((fd = open(ipfdev, O_RDWR)) == -1) if ((fd = open(ipfdev, O_RDONLY)) == -1) perror("open device"); + + if (setzone(fd) != 0) { + close(fd); + fd = -1; + } + return fd; }
--- a/usr/src/cmd/ipf/tools/ipfstat.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/ipf/tools/ipfstat.c Sun Jan 04 07:19:22 2015 -0800 @@ -5,6 +5,8 @@ * * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #ifdef __FreeBSD__ @@ -71,6 +73,7 @@ #if defined(__NetBSD__) || (__OpenBSD__) # include <paths.h> #endif +#include "ipfzone.h" #if !defined(lint) static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed"; @@ -177,6 +180,7 @@ #else fprintf(stderr, " %s -t [-C] ", name); #endif + fprintf(stderr, "[-G|-z zonename] "); fprintf(stderr, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n"); exit(1); } @@ -207,9 +211,9 @@ u_32_t frf; #ifdef USE_INET6 - options = "6aACdfghIilnostvD:M:N:P:RS:T:"; + options = "6aACdfgG:hIilnostvD:M:N:P:RS:T:z:"; #else - options = "aACdfghIilnostvD:M:N:P:RS:T:"; + options = "aACdfgG:hIilnostvD:M:N:P:RS:T:z:"; #endif saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */ @@ -223,13 +227,16 @@ opterr = 0; /* - * Parse these two arguments now lest there be any buffer overflows + * Parse these four arguments now lest there be any buffer overflows * in the parsing of the rest. */ myoptind = optind; while ((c = getopt(argc, argv, options)) != -1) { switch (c) { + case 'G' : + setzonename_global(optarg); + break; case 'M' : memf = optarg; live_kernel = 0; @@ -238,6 +245,9 @@ kern = optarg; live_kernel = 0; break; + case 'z' : + setzonename(optarg); + break; } } optind = myoptind; @@ -247,11 +257,22 @@ perror("open(IPSTATE_NAME)"); exit(-1); } + + if (setzone(state_fd) != 0) { + close(state_fd); + exit(-1); + } + if ((ipf_fd = open(device, O_RDONLY)) == -1) { fprintf(stderr, "open(%s)", device); perror(""); exit(-1); } + + if (setzone(ipf_fd) != 0) { + close(ipf_fd); + exit(-1); + } } if (kern != NULL || memf != NULL) { @@ -298,6 +319,9 @@ case 'g' : opts |= OPT_GROUPS; break; + case 'G' : + /* Already handled by getzoneopt() above */ + break; case 'h' : opts |= OPT_HITS; break; @@ -360,6 +384,9 @@ opts |= OPT_VERBOSE; opts |= OPT_UNDEF; break; + case 'z' : + /* Already handled by getzoneopt() above */ + break; default : usage(argv[0]); break; @@ -482,6 +509,11 @@ exit(-1); } + if (setzone(ipf_fd) != 0) { + close(ipf_fd); + exit(-1); + } + bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; ipfo.ipfo_size = sizeof(fr_authstat_t);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/ipf/tools/ipfzone.c Sun Jan 04 07:19:22 2015 -0800 @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2014 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + * + * See the IPFILTER.LICENCE file for details on licensing. + */ + + +#include <errno.h> +#include <net/if.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <zone.h> + +#include "netinet/ip_fil.h" +#include "ipfzone.h" + +static ipfzoneobj_t ipzo; +static boolean_t do_setzone = 0; +static int num_setzones = 0; + +extern int errno; +extern int opterr; +extern int optind; +extern char *optarg; + +/* + * Get the zonename if it's the last argument and set the zonename + * in ipfzo to it. This is used by ipf(1m) only - all of the other tools + * specify the zone with the -z option, and therefore use getzoneopt() below. + */ +void +getzonearg(int argc, char *argv[], const char *optstr) +{ + int c; + + /* + * Don't warn about unknown options - let subsequent calls to + * getopt() handle this. + */ + opterr = 0; + + /* + * getopt is also used here to set optind so that we can + * determine if the last argument belongs to a flag or is + * actually a zonename. + */ + while ((c = getopt(argc, argv, optstr)) != -1) { + if (c == 'G') + ipzo.ipfz_gz = 1; + } + + if (optind < argc) + setzonename(argv[optind]); + + /* + * Reset optind and opterr so the next getopt call will go through all + * of argv again and warn about unknown options. + */ + optind = 1; + opterr = 1; +} + +/* + * Get a -z option from argv and set the zonename in ipfzo accordingly + */ +void +getzoneopt(int argc, char *argv[], const char *optstr) +{ + int c; + + /* + * Don't warn about unknown options - let subsequent calls to + * getopt() handle this. + */ + opterr = 0; + + while ((c = getopt(argc, argv, optstr)) != -1) { + if (c == 'G') + setzonename_global(optarg); + + if (c == 'z') + setzonename(optarg); + } + + /* + * Reset optind and opterr so the next getopt call will go through all + * of argv again and warn about unknown options. + */ + optind = 1; + opterr = 1; +} + +/* + * Set the zonename in ipfzo to the given string: this is the zone all further + * ioctls will act on. + */ +void +setzonename(const char *zonename) +{ + memcpy(ipzo.ipfz_zonename, zonename, sizeof (ipzo.ipfz_zonename)); + do_setzone = B_TRUE; + num_setzones++; +} + +/* + * Set the zonename in ipfo, and the gz flag. This indicates that we want all + * further ioctls to act on the GZ-controlled stack for that zone. + */ +void +setzonename_global(const char *zonename) +{ + setzonename(zonename); + ipzo.ipfz_gz = 1; +} + +/* + * Set the zone that all further ioctls will operate on. See the "GZ-controlled + * and per-zone stacks" note at the top of ip_fil_solaris.c for further + * explanation. + */ +int +setzone(int fd) +{ + if (!do_setzone) + return (0); + + if (num_setzones > 1) { + (void) fprintf(stderr, + "Only one of -G and -z may be set\n"); + return (-1); + } + + if (ipzo.ipfz_gz == 1 && + getzoneidbyname(ipzo.ipfz_zonename) == GLOBAL_ZONEID) { + (void) fprintf(stderr, + "-G cannot be used with the global zone\n"); + return (-1); + } + + if (ioctl(fd, SIOCIPFZONESET, &ipzo) == -1) { + switch (errno) { + case ENODEV: + (void) fprintf(stderr, + "Could not find running zone: %s\n", + ipzo.ipfz_zonename); + break; + case EACCES: + (void) fprintf(stderr, + "Permission denied setting zone: %s\n", + ipzo.ipfz_zonename); + break; + default: + perror("Error setting zone"); + } + return (-1); + } + + return (0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/ipf/tools/ipfzone.h Sun Jan 04 07:19:22 2015 -0800 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2013 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + * + * See the IPFILTER.LICENCE file for details on licensing. + */ + +#ifndef __IPFZONE_H__ +#define __IPFZONE_H__ + +void getzonearg(int, char *[], const char *); +void getzoneopt(int, char *[], const char *); +int setzone(int); +void setzonename(const char *); +void setzonename_global(const char *); + +#endif /* __IPFZONE_H__ */
--- a/usr/src/cmd/ipf/tools/ipmon.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/ipf/tools/ipmon.c Sun Jan 04 07:19:22 2015 -0800 @@ -5,6 +5,8 @@ * * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ @@ -78,6 +80,7 @@ #include "netinet/ip_state.h" #include "netinet/ip_proxy.h" #include "ipmon.h" +#include "ipfzone.h" #if !defined(lint) static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed"; @@ -1340,10 +1343,10 @@ static void usage(prog) char *prog; { - fprintf(stderr, "%s: [-abDFhnpstvxX] %s %s %s %s %s %s\n", - prog, "[-N device]", "[ [-o [NSI]] [-O [NSI]]", - "[-P pidfile]", "[-S device]", "[-f device]", - "filename"); + fprintf(stderr, "%s: [-abDFhnpstvxX] %s %s %s %s %s %s %s\n", + prog, "[-G|-z zonename]", "[-N device]", + "[ [-o [NSI]] [-O [NSI]]", "[-P pidfile]", "[-S device]", + "[-f device]", "filename"); exit(1); } @@ -1380,6 +1383,11 @@ exit(1); } + if (setzone(fd) != 0) { + close(fd); + exit(1); + } + if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { printf("%d bytes flushed from log buffer\n", flushed); @@ -1444,6 +1452,7 @@ char buf[DEFAULT_IPFLOGSIZE], *iplfile[3], *s; extern int optind; extern char *optarg; + const char *optstr = "?abB:C:Df:G:FhnN:o:O:pP:sS:tvxXz:"; fd[0] = fd[1] = fd[2] = -1; fdt[0] = fdt[1] = fdt[2] = -1; @@ -1451,7 +1460,13 @@ iplfile[1] = IPNAT_NAME; iplfile[2] = IPSTATE_NAME; - while ((c = getopt(argc, argv, "?abB:C:Df:FhnN:o:O:pP:sS:tvxX")) != -1) + /* + * We need to set the zone name before calling openlog in + * the switch statement below + */ + getzoneopt(argc, argv, optstr); + + while ((c = getopt(argc, argv, optstr)) != -1) switch (c) { case 'a' : @@ -1483,6 +1498,9 @@ flushlogs(iplfile[1], log); flushlogs(iplfile[2], log); break; + case 'G' : + /* Already handled by getzoneopt() above */ + break; case 'n' : opts |= OPT_RESOLVE; break; @@ -1535,6 +1553,9 @@ case 'X' : opts |= OPT_HEXHDR; break; + case 'z' : + /* Already handled by getzoneopt() above */ + break; default : case 'h' : case '?' : @@ -1571,6 +1592,12 @@ exit(1); /* NOTREACHED */ } + + if (setzone(fd[i]) != 0) { + close(fd[i]); + exit(1); + } + if (!(regular[i] = !S_ISCHR(sb.st_mode))) devices++; }
--- a/usr/src/cmd/ipf/tools/ipnat.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/ipf/tools/ipnat.c Sun Jan 04 07:19:22 2015 -0800 @@ -7,6 +7,8 @@ * * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #include <stdio.h> @@ -55,6 +57,7 @@ #include "ipf.h" #include "netinet/ipl.h" #include "kmem.h" +#include "ipfzone.h" #ifdef __hpux # define nlist nlist64 @@ -95,7 +98,8 @@ void usage(name) char *name; { - fprintf(stderr, "Usage: %s [-CdFhlnrRsv] [-f filename]\n", name); + fprintf(stderr, "Usage: %s [-CdFhlnrRsv] [-f filename]", name); + fprintf(stderr, " [-G|-z zonename]\n"); exit(1); } @@ -117,7 +121,7 @@ kernel = NULL; mode = O_RDWR; - while ((c = getopt(argc, argv, "CdFf:hlM:N:nrRsv")) != -1) + while ((c = getopt(argc, argv, "CdFf:G:hlM:N:nrRsvz:")) != -1) switch (c) { case 'C' : @@ -132,6 +136,9 @@ case 'F' : opts |= OPT_FLUSH; break; + case 'G' : + setzonename_global(optarg); + break; case 'h' : opts |=OPT_HITS; break; @@ -162,6 +169,9 @@ case 'v' : opts |= OPT_VERBOSE; break; + case 'z' : + setzonename(optarg); + break; default : usage(argv[0]); } @@ -195,6 +205,11 @@ exit(1); } + if (setzone(fd) != 0) { + close(fd); + exit(1); + } + bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_size = sizeof(*nsp);
--- a/usr/src/cmd/ipf/tools/ippool.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/ipf/tools/ippool.c Sun Jan 04 07:19:22 2015 -0800 @@ -5,10 +5,10 @@ * * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <sys/time.h> #include <sys/param.h> @@ -41,6 +41,7 @@ #include "netinet/ip_pool.h" #include "netinet/ip_htable.h" #include "kmem.h" +#include "ipfzone.h" extern int ippool_yyparse __P((void)); extern int ippool_yydebug; @@ -71,15 +72,21 @@ void usage(prog) char *prog; { + const char *zoneopt = "[-G|-z zonename] "; fprintf(stderr, "Usage:\t%s\n", prog); - fprintf(stderr, "\t\t\t-a [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n"); - fprintf(stderr, "\t\t\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n"); - fprintf(stderr, "\t\t\t-f <file> [-dnuv]\n"); - fprintf(stderr, "\t\t\t-F [-dv] [-o <role>] [-t <type>]\n"); - fprintf(stderr, "\t\t\t-l [-dv] [-m <name>] [-t <type>]\n"); - fprintf(stderr, "\t\t\t-r [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n"); - fprintf(stderr, "\t\t\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n"); - fprintf(stderr, "\t\t\t-s [-dtv] [-M <core>] [-N <namelist>]\n"); + fprintf(stderr, "\t\t\t-a [-dnv] %s[-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n", + zoneopt); + fprintf(stderr, "\t\t\t-A [-dnv] %s[-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n", + zoneopt); + fprintf(stderr, "\t\t\t-f <file> %s[-dnuv]\n", zoneopt); + fprintf(stderr, "\t\t\t-F [-dv] %s[-o <role>] [-t <type>]\n", zoneopt); + fprintf(stderr, "\t\t\t-l [-dv] %s[-m <name>] [-t <type>]\n", zoneopt); + fprintf(stderr, "\t\t\t-r [-dnv] %s[-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n", + zoneopt); + fprintf(stderr, "\t\t\t-R [-dnv] %s[-m <name>] [-o <role>] [-t <type>]\n", + zoneopt); + fprintf(stderr, "\t\t\t-s [-dtv] %s[-M <core>] [-N <namelist>]\n", + zoneopt); exit(1); } @@ -140,13 +147,16 @@ role = IPL_LOGIPF; bzero((char *)&node, sizeof(node)); - while ((c = getopt(argc, argv, "di:m:no:Rv")) != -1) + while ((c = getopt(argc, argv, "di:G:m:no:Rvz:")) != -1) switch (c) { case 'd' : opts |= OPT_DEBUG; ippool_yydebug++; break; + case 'G' : + setzonename_global(optarg); + break; case 'i' : s = strchr(optarg, '/'); if (s == NULL) @@ -182,6 +192,9 @@ case 'v' : opts |= OPT_VERBOSE; break; + case 'z' : + setzonename(optarg); + break; } if (opts & OPT_DEBUG) @@ -219,13 +232,16 @@ bzero((char *)&iph, sizeof(iph)); bzero((char *)&pool, sizeof(pool)); - while ((c = getopt(argc, argv, "dm:no:RS:t:v")) != -1) + while ((c = getopt(argc, argv, "dG:m:no:RS:t:vz:")) != -1) switch (c) { case 'd' : opts |= OPT_DEBUG; ippool_yydebug++; break; + case 'G' : + setzonename_global(optarg); + break; case 'm' : poolname = optarg; break; @@ -255,6 +271,9 @@ case 'v' : opts |= OPT_VERBOSE; break; + case 'z' : + setzonename(optarg); + break; } if (opts & OPT_DEBUG) @@ -308,13 +327,16 @@ infile = optarg; - while ((c = getopt(argc, argv, "dnRuv")) != -1) + while ((c = getopt(argc, argv, "dG:nRuvz:")) != -1) switch (c) { case 'd' : opts |= OPT_DEBUG; ippool_yydebug++; break; + case 'G' : + setzonename_global(optarg); + break; case 'n' : opts |= OPT_DONOTHING; break; @@ -327,6 +349,9 @@ case 'v' : opts |= OPT_VERBOSE; break; + case 'z' : + setzonename(optarg); + break; } if (opts & OPT_DEBUG) @@ -338,6 +363,11 @@ perror("open(IPLOOKUP_NAME)"); exit(1); } + + if (setzone(fd) != 0) { + close(fd); + exit(1); + } } if (ippool_parsefile(fd, infile, ioctl) != 0) @@ -365,12 +395,15 @@ poolname = NULL; role = IPL_LOGALL; - while ((c = getopt(argc, argv, "dm:M:N:o:Rt:v")) != -1) + while ((c = getopt(argc, argv, "dG:m:M:N:o:Rt:vz:")) != -1) switch (c) { case 'd' : opts |= OPT_DEBUG; break; + case 'G' : + setzonename_global(optarg); + break; case 'm' : poolname = optarg; break; @@ -402,6 +435,9 @@ case 'v' : opts |= OPT_VERBOSE; break; + case 'z' : + setzonename(optarg); + break; } if (opts & OPT_DEBUG) @@ -413,6 +449,11 @@ perror("open(IPLOOKUP_NAME)"); exit(1); } + + if (setzone(fd) != 0) { + close(fd); + exit(1); + } } bzero((char *)&op, sizeof(op)); @@ -615,12 +656,15 @@ bzero((char *)&op, sizeof(op)); - while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1) + while ((c = getopt(argc, argv, "dG:M:N:o:t:vz:")) != -1) switch (c) { case 'd' : opts |= OPT_DEBUG; break; + case 'G' : + setzonename_global(optarg); + break; case 'M' : live_kernel = 0; core = optarg; @@ -647,6 +691,9 @@ case 'v' : opts |= OPT_VERBOSE; break; + case 'z' : + setzonename(optarg); + break; } if (opts & OPT_DEBUG) @@ -658,6 +705,11 @@ perror("open(IPLOOKUP_NAME)"); exit(1); } + + if (setzone(fd) != 0) { + close(fd); + exit(1); + } } if (type == IPLT_ALL || type == IPLT_POOL) { @@ -705,7 +757,7 @@ type = IPLT_ALL; role = IPL_LOGALL; - while ((c = getopt(argc, argv, "do:t:v")) != -1) + while ((c = getopt(argc, argv, "do:t:vz:")) != -1) switch (c) { case 'd' : @@ -728,6 +780,9 @@ case 'v' : opts |= OPT_VERBOSE; break; + case 'z' : + setzonename(optarg); + break; } if (opts & OPT_DEBUG) @@ -739,6 +794,11 @@ perror("open(IPLOOKUP_NAME)"); exit(1); } + + if (setzone(fd) != 0) { + close(fd); + exit(1); + } } bzero((char *)&flush, sizeof(flush));
--- a/usr/src/cmd/mailx/Makefile Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/mailx/Makefile Sun Jan 04 07:19:22 2015 -0800 @@ -22,6 +22,8 @@ # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2014 Joyent, Inc. +# # cmd/mailx/Makefile PROG= mailx @@ -62,7 +64,7 @@ CERRWARN += -_gcc=-Wno-unused-variable CERRWARN += -_gcc=-Wno-clobbered LINTFLAGS= -hb -LDLIBS += -lmail +LDLIBS += -lmail -lcmdutils LDFLAGS += $(MAPFILE.NGB:%=-M%) CLOBBERFILES += $(MAILXHELP)
--- a/usr/src/cmd/mailx/cmd1.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/mailx/cmd1.c Sun Jan 04 07:19:22 2015 -0800 @@ -19,6 +19,11 @@ * * CDDL HEADER END */ + +/* + * Copyright 2014 Joyent, Inc. + */ + /* * Copyright 2001 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -37,8 +42,7 @@ * contributors. */ -#pragma ident "%Z%%M% %I% %E% SMI" - +#include <err.h> #include "rcv.h" #include <locale.h> @@ -213,10 +217,14 @@ char *fromline; char pbuf[LINESIZE]; char name[LINESIZE]; - struct headline hl; + headline_t *hl; register char *cp; int showto; + if (headline_alloc(&hl) != 0) { + err(1, "could not allocate memory"); + } + mp = &message[mesg-1]; ibuf = setinput(mp); readline(ibuf, headline); @@ -248,9 +256,14 @@ dispc = 'H'; if (mp->m_flag & MBOX) dispc = 'M'; - parse(headline, &hl, pbuf); - if (hl.l_date == NOSTR) - hl.l_date = "<Unknown date>"; + if (parse_headline(headline, hl) == -1) { + headline_reset(hl); + } + if (custr_len(hl->hl_date) == 0) { + if (custr_append(hl->hl_date, "<Unknown date>") != 0) { + err(1, "could not print header"); + } + } /* * Netnews interface? @@ -299,11 +312,14 @@ } if (mp->m_text) { printf("%16.16s %4ld/%-5ld %-.25s\n", - hl.l_date, mp->m_lines, mp->m_size, subjline); + custr_cstr(hl->hl_date), mp->m_lines, mp->m_size, + subjline); } else { - printf("%16.16s binary/%-5ld %-.25s\n", hl.l_date, mp->m_size, - subjline); + printf("%16.16s binary/%-5ld %-.25s\n", custr_cstr(hl->hl_date), + mp->m_size, subjline); } + + headline_free(hl); } /*
--- a/usr/src/cmd/mailx/fio.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/mailx/fio.c Sun Jan 04 07:19:22 2015 -0800 @@ -21,6 +21,10 @@ */ /* + * Copyright 2014 Joyent, Inc. + */ + +/* * Copyright 1999 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -28,8 +32,6 @@ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "rcv.h" #include <locale.h> #include <wordexp.h> @@ -174,7 +176,7 @@ } /* Look for a From line that starts a new message */ - if (blankline && linebuf[0] == 'F' && ishead(linebuf)) { + if (blankline && linebuf[0] == 'F' && is_headline(linebuf)) { if (msgCount > 0 && !newmail) { message[msgCount-1].m_size = s; message[msgCount-1].m_lines = l; @@ -755,7 +757,7 @@ if (debug) fprintf(stderr, "%s\n", name); return (name); } - if (wordexp(name, &wrdexp_buf, 0) != 0) { + if (wordexp(name, &wrdexp_buf, WRDE_NOCMD) != 0) { fprintf(stderr, gettext("Syntax error in \"%s\"\n"), name); fflush(stderr); return (NOSTR);
--- a/usr/src/cmd/mailx/hdr/def.h Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/mailx/hdr/def.h Sun Jan 04 07:19:22 2015 -0800 @@ -20,6 +20,10 @@ */ /* + * Copyright 2014 Joyent, Inc. + */ + +/* * Copyright (c) 1985, 2010, Oracle and/or its affiliates. All rights reserved. */ @@ -60,6 +64,7 @@ #include <stdlib.h> #include <ulimit.h> #include <wait.h> +#include <libcmdutils.h> #endif #ifdef VMUNIX #include <sys/wait.h> @@ -204,11 +209,11 @@ * line */ -struct headline { - char *l_from; /* The name of the sender */ - char *l_tty; /* His tty string (if any) */ - char *l_date; /* The entire date string */ -}; +typedef struct headline { + custr_t *hl_from; /* The name of the sender */ + custr_t *hl_tty; /* His tty string (if any) */ + custr_t *hl_date; /* The entire date string */ +} headline_t; #define GTO 1 /* Grab To: line */ #define GSUBJECT 2 /* Likewise, Subject: line */ @@ -486,6 +491,9 @@ extern char *hcontents(char hfield[]); extern int headerp(register char *line); extern int headers(int *msgvec); +extern int headline_alloc(headline_t **); +extern void headline_free(headline_t *); +extern void headline_reset(headline_t *); extern int help(void); extern char *helppath(char *file); extern char *hfield(char field[], struct message *mp, @@ -497,7 +505,7 @@ extern int inc(void); extern void inithost(void); extern int isdir(char name[]); -extern int ishead(char linebuf[]); +extern boolean_t is_headline(const char *); extern int ishfield(char linebuf[], char field[]); extern int ishost(char *sys, char *rest); extern int isign(char *field, int saving); @@ -533,7 +541,7 @@ extern int outof(struct name *names, FILE *fo); extern struct name *outpre(struct name *to); extern void panic(char *str); -extern void parse(char line[], struct headline *hl, char pbuf[]); +extern int parse_headline(const char *, headline_t *); extern int pcmdlist(void); extern int pdot(void); extern int preserve(int *msgvec);
--- a/usr/src/cmd/mailx/head.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/mailx/head.c Sun Jan 04 07:19:22 2015 -0800 @@ -19,6 +19,11 @@ * * CDDL HEADER END */ + +/* + * Copyright 2014 Joyent, Inc. + */ + /* * Copyright 1995 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -38,7 +43,7 @@ * contributors. */ -#pragma ident "%Z%%M% %I% %E% SMI" +#include <err.h> #include "rcv.h" @@ -49,115 +54,188 @@ * Routines for processing and detecting headlines. */ -static char *copyin(char src[], char **space); -static char *nextword(char wp[], char wbuf[]); +static int nextword(const char *, custr_t *, const char **); /* * See if the passed line buffer is a mail header. * Return true if yes. */ - -int -ishead(char linebuf[]) +boolean_t +is_headline(const char *linebuf) { - register char *cp; - struct headline hl; - char parbuf[BUFSIZ]; + headline_t *hl; + boolean_t ret; - cp = linebuf; - if (strncmp("From ", cp, 5) != 0) - return(0); - parse(cp, &hl, parbuf); - if (hl.l_from == NOSTR) { - return(0); + if (strncmp("From ", linebuf, 5) != 0) { + return (B_FALSE); } - return(1); + + if (headline_alloc(&hl) != 0 || parse_headline(linebuf, hl) != 0) { + err(1, "could not parse headline"); + } + + ret = custr_len(hl->hl_from) > 0 ? B_TRUE : B_FALSE; + + headline_free(hl); + return (ret); } /* - * Split a headline into its useful components. - * Copy the line into dynamic string space, then set - * pointers into the copied line in the passed headline - * structure. Actually, it scans. + * Manage headline_t objects: */ -void -parse(char line[], struct headline *hl, char pbuf[]) +void +headline_free(headline_t *hl) { - register char *cp, *dp; - char *sp; - char word[LINESIZE]; + custr_free(hl->hl_from); + custr_free(hl->hl_tty); + custr_free(hl->hl_date); + free(hl); +} + +int +headline_alloc(headline_t **hl) +{ + int en; + headline_t *t; - hl->l_from = NOSTR; - hl->l_date = NOSTR; - cp = line; - sp = pbuf; + if ((t = calloc(1, sizeof (*t))) == NULL) { + return (-1); + } + + if (custr_alloc(&t->hl_from) != 0 || custr_alloc(&t->hl_tty) != 0 || + custr_alloc(&t->hl_date) != 0) { + en = errno; - /* - * Skip the first "word" of the line, which should be "From" - * anyway. - */ + headline_free(t); - cp = nextword(cp, word); - dp = nextword(cp, word); - if (!equal(word, "")) - hl->l_from = copyin(word, &sp); - if (dp != NOSTR) - hl->l_date = copyin(dp, &sp); + errno = en; + return (-1); + } + + *hl = t; + return (0); } /* - * Copy the string on the left into the string on the right - * and bump the right (reference) string pointer by the length. - * Thus, dynamically allocate space in the right string, copying - * the left string into it. + * Clear all of the strings in a headline_t: */ +void +headline_reset(headline_t *hl) +{ + custr_reset(hl->hl_from); + custr_reset(hl->hl_tty); + custr_reset(hl->hl_date); +} -static char * -copyin(char src[], char **space) +int +parse_headline(const char *line, headline_t *hl) { - register char *cp, *top; - register int s; + const char *c = line; + + headline_reset(hl); + + /* + * Load the first word from the line and ensure that it is "From". + */ + if (nextword(c, hl->hl_from, &c) != 0) { + return (-1); + } + if (strcmp(custr_cstr(hl->hl_from), "From") != 0) { + errno = EINVAL; + return (-1); + } + custr_reset(hl->hl_from); - s = strlen(src); - cp = *space; - top = cp; - strcpy(cp, src); - cp += s + 1; - *space = cp; - return(top); + /* + * The next word will be the From address. + */ + if (nextword(c, hl->hl_from, &c) != 0) { + return (-1); + } + + /* + * If there is a next word, the rest of the string is the Date. + */ + if (c != NULL) { + if (custr_append(hl->hl_date, c) != 0) { + return (-1); + } + } + + errno = 0; + return (0); } /* - * Collect a liberal (space, tab delimited) word into the word buffer - * passed. Also, return a pointer to the next word following that, - * or NOSTR if none follow. + * Collect a space- or tab-delimited word into the word buffer, if one is + * passed. The double quote character (") can be used to include whitespace + * within a word. Set "nextword" to the location of the first character of the + * _next_ word, or NULL if there were no more words. Returns 0 on success or + * -1 otherwise. */ +static int +nextword(const char *input, custr_t *word, const char **nextword) +{ + boolean_t in_quotes = B_FALSE; + const char *c = input != NULL ? input : ""; + + /* + * Collect the first word into the word buffer, if one is provided. + */ + for (;;) { + if (*c == '\0') { + /* + * We have reached the end of the string. + */ + *nextword = NULL; + return (0); + } -static char * -nextword(char wp[], char wbuf[]) -{ - register char *cp, *cp2; + if (*c == '"') { + /* + * Either beginning or ending a quoted string. + */ + in_quotes = in_quotes ? B_FALSE : B_TRUE; + } - if ((cp = wp) == NOSTR) { - copy("", wbuf); - return(NOSTR); + if (!in_quotes && (*c == ' ' || *c == '\t')) { + /* + * We have reached a whitespace region. + */ + break; + } + + /* + * Copy this character into the word buffer. + */ + if (word != NULL) { + if (custr_appendc(word, *c) != 0) { + return (-1); + } + } + c++; } - cp2 = wbuf; - while (!any(*cp, " \t") && *cp != '\0') - if (*cp == '"') { - *cp2++ = *cp++; - while (*cp != '\0' && *cp != '"') - *cp2++ = *cp++; - if (*cp == '"') - *cp2++ = *cp++; - } else - *cp2++ = *cp++; - *cp2 = '\0'; - while (any(*cp, " \t")) - cp++; - if (*cp == '\0') - return(NOSTR); - return(cp); + + /* + * Find the beginning of the next word, if there is one. + */ + for (;;) { + if (*c == '\0') { + /* + * We have reached the end of the string. + */ + *nextword = NULL; + return (0); + + } else if (*c != ' ' && *c != '\t') { + /* + * We have located the next word. + */ + *nextword = c; + return (0); + } + c++; + } } /*
--- a/usr/src/cmd/mailx/main.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/mailx/main.c Sun Jan 04 07:19:22 2015 -0800 @@ -37,8 +37,6 @@ * contributors. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "rcv.h" #ifndef preSVr4 #include <locale.h> @@ -104,7 +102,6 @@ progname = argv[0]; if (progname[strlen(progname) - 1] != 'x') { assign("bsdcompat", ""); - assign("escapeok", ""); /* XXX */ } myegid = getegid(); myrgid = getgid();
--- a/usr/src/cmd/mailx/misc/mailx.rc Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/mailx/misc/mailx.rc Sun Jan 04 07:19:22 2015 -0800 @@ -21,8 +21,6 @@ # Copyright 2000 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# # The following 3 settings produce the familiar Solaris behavior. set appenddeadletter unset pipeignore @@ -44,8 +42,6 @@ set LISTER="ls -LF" # default is to allow editing of message windows set editmessagewindow - # have to allow ~ escapes even though not using tty - set escapeok endif # most mail headers are uninteresting to most people. here we ignore all
--- a/usr/src/cmd/mailx/names.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/mailx/names.c Sun Jan 04 07:19:22 2015 -0800 @@ -191,7 +191,7 @@ /* * For each recipient in the passed name list with a / * in the name, append the message to the end of the named file - * and remove him from the recipient list. + * and remove them from the recipient list. * * Recipients whose name begins with | are piped through the given * program and removed. @@ -212,6 +212,9 @@ char line[BUFSIZ]; #endif + if (value("expandaddr") == NOSTR) + return (nout); + for (np = names; np != NIL; np = np->n_flink) { if (!isfileaddr(np->n_name) && np->n_name[0] != '|') continue; @@ -599,14 +602,15 @@ panic("No names to unpack"); /* - * Compute the number of extra arguments we will need. - * We need at least 2 extra -- one for "mail" and one for - * the terminating 0 pointer. - * Additional spots may be needed to pass along -r and -f to - * the host mailer. + * Compute the number of extra arguments we will need. We need at least + * 3 extra -- one for "mail", one for a terminating -- to stop sendmail + * option processing, and one for the terminating 0 pointer. + * + * Additional spots may be needed to pass along -r and -f to the host + * mailer. */ - extra = 2; + extra = 3; if (rflag != NOSTR) extra += 2; @@ -636,6 +640,7 @@ snprintf(hbuf, sizeof (hbuf), "%d", hflag); *ap++ = savestr(hbuf); } + *ap++ = "--"; while (n != NIL) { if (n->n_type & GDEL) { n = n->n_flink;
--- a/usr/src/cmd/mailx/receipt.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/mailx/receipt.c Sun Jan 04 07:19:22 2015 -0800 @@ -19,6 +19,11 @@ * * CDDL HEADER END */ + +/* + * Copyright 2014 Joyent, Inc. + */ + /* * Copyright 1998 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -38,7 +43,7 @@ * contributors. */ -#pragma ident "%Z%%M% %I% %E% SMI" +#include <err.h> #include "rcv.h" @@ -47,12 +52,12 @@ void receipt(struct message *mp) { - struct headline hl; char head[LINESIZE]; char buf[BUFSIZ]; FILE *pp, *fp; char *mail, *s; + if ((mail = value("sendmail")) == 0) #ifdef SENDMAIL mail = SENDMAIL; @@ -63,16 +68,27 @@ || icsubstr(hfield(">to", mp, addto), "/receipt")) { snprintf(buf, sizeof (buf), "%s %s", mail, skin(nameof(mp))); if (pp = npopen(buf, "w")) { + headline_t *hl; + + if (headline_alloc(&hl) != 0) { + err(1, "could not allocate memory"); + } + fp = setinput(mp); readline(fp, head); - parse(head, &hl, buf); - if (hl.l_date != NOSTR) - fprintf(pp, "Original-Date: %s\n", hl.l_date); + if (parse_headline(head, hl) != 0) { + headline_reset(hl); + } + if (custr_len(hl->hl_date) > 0) { + fprintf(pp, "Original-Date: %s\n", + custr_cstr(hl->hl_date)); + } if (s = hfield("message-id", mp, addone)) fprintf(pp, "Original-Message-ID: %s\n", s); s = hfield("subject", mp, addone); fprintf(pp, "Subject: RR: %s\n", s ? s : "(none)"); npclose(pp); + headline_free(hl); } } }
--- a/usr/src/cmd/mdb/common/modules/zfs/zfs.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/mdb/common/modules/zfs/zfs.c Sun Jan 04 07:19:22 2015 -0800 @@ -960,7 +960,16 @@ static const char *bytestats[] = { "p", "c", "c_min", "c_max", "size", "duplicate_buffers_size", "arc_meta_used", "arc_meta_limit", "arc_meta_max", - "arc_meta_min", "hdr_size", "data_size", "other_size", + "arc_meta_min", "hdr_size", "data_size", "metadata_size", + "other_size", "anon_size", "anon_evictable_data", + "anon_evictable_metadata", "mru_size", "mru_evictable_data", + "mru_evictable_metadata", "mru_ghost_size", + "mru_ghost_evictable_data", "mru_ghost_evictable_metadata", + "mfu_size", "mfu_evictable_data", "mfu_evictable_metadata", + "mfu_ghost_size", "mfu_ghost_evictable_data", + "mfu_ghost_evictable_metadata", "evict_l2_cached", + "evict_l2_eligible", "evict_l2_ineligible", "l2_read_bytes", + "l2_write_bytes", "l2_size", "l2_asize", "l2_hdr_size", NULL };
--- a/usr/src/cmd/ndmpadm/ndmpadm_main.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/ndmpadm/ndmpadm_main.c Sun Jan 04 07:19:22 2015 -0800 @@ -616,14 +616,14 @@ if (strncmp(auth_type, ndmp_auth_table[i].auth_type, strlen(ndmp_auth_table[i].auth_type)) == 0) { auth_type_flag = 1; - if ((ndmp_set_prop((char *)ndmp_auth_table[i].username, + if ((ndmp_set_prop(ndmp_auth_table[i].username, username)) == -1) { (void) fprintf(stdout, gettext("Could not set username - %s\n"), ndmp_strerror(ndmp_errno)); continue; } - if ((ndmp_set_prop((char *)ndmp_auth_table[i].password, + if ((ndmp_set_prop(ndmp_auth_table[i].password, enc_password)) == -1) { (void) fprintf(stdout, gettext("Could not set password - %s\n"), @@ -677,14 +677,14 @@ if (strncmp(auth_type, ndmp_auth_table[i].auth_type, strlen(ndmp_auth_table[i].auth_type)) == 0) { auth_type_flag = 1; - if ((ndmp_set_prop((char *)ndmp_auth_table[i].username, + if ((ndmp_set_prop(ndmp_auth_table[i].username, "")) == -1) { (void) fprintf(stdout, gettext("Could not clear username - %s\n"), ndmp_strerror(ndmp_errno)); continue; } - if ((ndmp_set_prop((char *)ndmp_auth_table[i].password, + if ((ndmp_set_prop(ndmp_auth_table[i].password, "")) == -1) { (void) fprintf(stdout, gettext("Could not clear password - %s\n"),
--- a/usr/src/cmd/sgs/libld/common/unwind.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/sgs/libld/common/unwind.c Sun Jan 04 07:19:22 2015 -0800 @@ -634,7 +634,7 @@ * field. */ (void) dwarf_ehe_extract( - &data[off + ndx], + &data[off], &ndx, ciePflag, ofl->ofl_dehdr->e_ident, B_FALSE, shdr->sh_addr, off + ndx, 0);
--- a/usr/src/cmd/utmpd/Makefile Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/utmpd/Makefile Sun Jan 04 07:19:22 2015 -0800 @@ -18,7 +18,7 @@ # # CDDL HEADER END # -# +# Copyright 2014 Shruti V Sampat <shrutisampat@gmail.com> # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -34,8 +34,6 @@ FILEMODE = 555 -CERRWARN += -_gcc=-Wno-extra - .KEEP_STATE: all: $(PROG)
--- a/usr/src/cmd/utmpd/utmpd.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/utmpd/utmpd.c Sun Jan 04 07:19:22 2015 -0800 @@ -19,6 +19,10 @@ * CDDL HEADER END */ /* + * Copyright 2014 Shruti V Sampat <shrutisampat@gmail.com> + */ + +/* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -177,8 +181,7 @@ */ int -main(argc, argv) - char **argv; +main(int argc, char *argv[]) { char *defp; struct rlimit rlim; @@ -189,7 +192,7 @@ if (getuid() != 0) { (void) fprintf(stderr, - "You must be root to run this program\n"); + "You must be root to run this program\n"); fatal("You must be root to run this program"); } @@ -199,9 +202,9 @@ Debug = 1; } else { (void) fprintf(stderr, - "%s: Wrong number of arguments\n", prog_name); + "%s: Wrong number of arguments\n", prog_name); (void) fprintf(stderr, - "Usage: %s [-debug]\n", prog_name); + "Usage: %s [-debug]\n", prog_name); exit(2); } } @@ -349,7 +352,7 @@ register struct pollfd *pfd; register int i; pid_t pid; - int ret_val; + int ret_val = 0; int timeout; static time_t last_timeout = 0; static int bad_error = 0; /* Count of POLL errors */
--- a/usr/src/cmd/ypcmd/ypinit.sh Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/ypcmd/ypinit.sh Sun Jan 04 07:19:22 2015 -0800 @@ -19,6 +19,7 @@ # # CDDL HEADER END # +# Copyright 2014 Nexenta Systems, Inc. All rights reserved. # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. @@ -29,8 +30,6 @@ # Portions of this source code were derived from Berkeley 4.3 BSD # under license from the Regents of the University of California. -#ident "%Z%%M% %I% %E% SMI" - # set -xv YPXFR=/usr/lib/netsvc/yp/ypxfr MAKEPATH=/usr/ccs/bin @@ -50,6 +49,7 @@ master="" got_host_list=F first_time=T +non_interactive=F exit_on_error=F errors_in_setup=F @@ -84,12 +84,13 @@ # To do cleanup trap '/usr/bin/rm -f $hf' 0 1 2 3 15 +# Check out total number of arguments case $# in 1) case $1 in -c) clientp=T;; -m) masterp=T;; *) echo 'usage:' - echo ' ypinit -c' + echo ' ypinit -c [server_name...]' echo ' ypinit -m' echo ' ypinit -s master_server' echo "" @@ -111,9 +112,13 @@ echo "server not found in $hosts_file or $hosts6_file" exit 1 fi;; - + + # the case with more than one argument with the '-c' option + # is a subject to enter non-interactive mode + -c) clientp=T; non_interactive=T; + ;; *) echo 'usage:' - echo ' ypinit -c' + echo ' ypinit -c [server_name...]' echo ' ypinit -m' echo ' ypinit -s master_server' echo "" @@ -125,10 +130,14 @@ master_server must be an existing reachable yp server." exit 1;; esac;; -3) case $1 in - -c) clientp=T;; +*) case $1 in + + # the case with more than one argument with the '-c' option + # is a subject to enter non-interactive mode + -c) clientp=T; non_interactive=T; + ;; *) echo 'usage:' - echo ' ypinit -c' + echo ' ypinit -c [server_name...]' echo ' ypinit -m' echo ' ypinit -s master_server' echo "" @@ -140,19 +149,6 @@ master_server must be an existing reachable yp server." exit 1;; esac;; - -*) echo 'usage:' - echo ' ypinit -c' - echo ' ypinit -m' - echo ' ypinit -s master_server' - echo "" - echo "\ -where -c is used to set up a yp client, -m is used to build a master " - echo "\ -yp server data base, and -s is used for a slave data base." - echo "\ -master_server must be an existing reachable yp server." - exit 1;; esac if [ $? -ne 0 ] @@ -222,97 +218,114 @@ if [ $slavep = F ] then - while [ $got_host_list = F ]; do - touch $hf # make sure file exists - echo "" - echo "\ + if [ $non_interactive = F ] + then + while [ $got_host_list = F ]; do + touch $hf # make sure file exists + echo "" + echo "\ In order for NIS to operate sucessfully, we have to construct a list of the " - echo "\ + echo "\ NIS servers. Please continue to add the names for YP servers in order of" - echo "\ + echo "\ preference, one per line. When you are done with the list, type a <control D>" - echo "\ + echo "\ or a return on a line by itself." - if [ $masterp = T ] - then - echo $host > $hf - echo "\tnext host to add: $host" - elif [ -f $binding_file ] - then - if [ $first_time = T ] + if [ $masterp = T ] + then + echo $host > $hf + echo "\tnext host to add: $host" + elif [ -f $binding_file ] then - for h in `cat $binding_file` - do - echo $h >> $hf - echo "\tnext host to add: $h" - done + if [ $first_time = T ] + then + for h in `cat $binding_file` + do + echo $h >> $hf + echo "\tnext host to add: $h" + done + fi fi - fi + + echo "\tnext host to add: \c" - echo "\tnext host to add: \c" + while read h ; test -n "$h" + do + # + # Host should be in the v4 or v6 hosts file or + # reasonably resemble an IP address. We'll do a + # sanity check that a v4 addr is one word consisting + # of only numbers and the "." character, + # which should guard against fully qualified + # hostnames and most malformed entries. IPv6 + # addresses can be numbers, hex letters, and have + # at least one ":" character and possibly one or + # more "." characters for embedded v4 addresses + # + if ( grep $h $hosts_file $hosts6_file > /dev/null ) || \ + ( test $clientp = T && `is_valid_ipaddr $h` ) + then + echo $h >> $hf + echo "\tnext host to add: \c" + else + echo "host $h not found in $hosts_file or" \ + "$hosts6_file.\nNot added to the list." + echo "" + echo "Do you wish to abort [y/n: y] \c" + read cont_ok + + case $cont_ok in + n*) echo "\tnext host to add: \c";; + N*) echo "\tnext host to add: \c";; + *) exit 1;; + esac + fi + done - while read h ; test -n "$h" - do - # - # Host should be in the v4 or v6 hosts file or - # reasonably resemble an IP address. We'll do a - # sanity check that a v4 addr is one word consisting - # of only numbers and the "." character, - # which should guard against fully qualified - # hostnames and most malformed entries. IPv6 - # addresses can be numbers, hex letters, and have - # at least one ":" character and possibly one or - # more "." characters for embedded v4 addresses - # - if ( grep $h $hosts_file $hosts6_file > /dev/null ) || \ - ( test $clientp = T && `is_valid_ipaddr $h` ) + echo "" + if [ -s $hf ] then - echo $h >> $hf - echo "\tnext host to add: \c" + echo "The current list of yp servers looks like this:" + echo "" + cat $hf + echo "" + echo "Is this correct? [y/n: y] \c" else - echo "host $h not found in $hosts_file or" \ + echo "You have not added any server information." + echo "" + echo "Do you still wish to exit? [y/n: y] \c" + fi + + read hlist_ok + + case $hlist_ok in + n*) got_host_list=F + first_time=F + rm $hf + echo "Let's try the whole thing again...";; + N*) got_host_list=F + first_time=F + rm $hf + echo "Let's try the whole thing again...";; + *) got_host_list=T;; + esac + done + else + shift + > $hf + while [[ $# > 0 ]]; do + if ( grep $1 $hosts_file $hosts6_file > /dev/null ) || \ + ( `is_valid_ipaddr $1` ) + then + echo $1 >> $hf + else + echo "host $1 not found in $hosts_file or" \ "$hosts6_file.\nNot added to the list." echo "" - echo "Do you wish to abort [y/n: y] \c" - read cont_ok - - case $cont_ok in - n*) echo "\tnext host to add: \c";; - N*) echo "\tnext host to add: \c";; - *) exit 1;; - esac fi - + shift done - - echo "" - if [ -s $hf ] - then - echo "The current list of yp servers looks like this:" - echo "" - cat $hf - echo "" - echo "Is this correct? [y/n: y] \c" - else - echo "You have not added any server information." - echo "" - echo "Do you still wish to exit? [y/n: y] \c" - fi - - read hlist_ok - - case $hlist_ok in - n*) got_host_list=F - first_time=F - rm $hf - echo "Let's try the whole thing again...";; - N*) got_host_list=F - first_time=F - rm $hf - echo "Let's try the whole thing again...";; - *) got_host_list=T;; - esac - done + fi if [ -s $hf ] then
--- a/usr/src/cmd/zoneadm/zoneadm.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/zoneadm/zoneadm.c Sun Jan 04 07:19:22 2015 -0800 @@ -1023,6 +1023,18 @@ (void) fprintf(stderr, gettext("%s is not owned by root.\n"), rpath); err = B_TRUE; + + /* Try to change owner */ + if (cmd_num != CMD_VERIFY) { + (void) fprintf(stderr, gettext("%s: changing owner " + "to root.\n"), rpath); + if (chown(rpath, 0, -1) != 0) { + zperror(rpath, B_FALSE); + return (Z_ERR); + } else { + err = B_FALSE; + } + } } err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rpath); err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rpath); @@ -1034,6 +1046,17 @@ err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rpath); err |= bad_mode_bit(stbuf.st_mode, S_IXOTH, B_FALSE, rpath); + /* If the group perms are wrong, fix them */ + if (err && (cmd_num != CMD_VERIFY)) { + (void) fprintf(stderr, gettext("%s: changing permissions " + "to 0700.\n"), rpath); + if (chmod(rpath, S_IRWXU) != 0) { + zperror(path, B_FALSE); + } else { + err = B_FALSE; + } + } + (void) snprintf(ppath, sizeof (ppath), "%s/..", path); if ((res = resolvepath(ppath, rppath, sizeof (rppath))) == -1) { zperror(ppath, B_FALSE);
--- a/usr/src/cmd/ztest/ztest.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/cmd/ztest/ztest.c Sun Jan 04 07:19:22 2015 -0800 @@ -3905,7 +3905,7 @@ * assign an arcbuf to a dbuf. */ for (j = 0; j < s; j++) { - if (i != 5) { + if (i != 5 || chunksize < (SPA_MINBLOCKSIZE * 2)) { bigbuf_arcbufs[j] = dmu_request_arcbuf(bonus_db, chunksize); } else { @@ -3929,7 +3929,8 @@ umem_free(packbuf, packsize); umem_free(bigbuf, bigsize); for (j = 0; j < s; j++) { - if (i != 5) { + if (i != 5 || + chunksize < (SPA_MINBLOCKSIZE * 2)) { dmu_return_arcbuf(bigbuf_arcbufs[j]); } else { dmu_return_arcbuf( @@ -3973,7 +3974,7 @@ } for (off = bigoff, j = 0; j < s; j++, off += chunksize) { dmu_buf_t *dbt; - if (i != 5) { + if (i != 5 || chunksize < (SPA_MINBLOCKSIZE * 2)) { bcopy((caddr_t)bigbuf + (off - bigoff), bigbuf_arcbufs[j]->b_data, chunksize); } else { @@ -3990,7 +3991,7 @@ VERIFY(dmu_buf_hold(os, bigobj, off, FTAG, &dbt, DMU_READ_NO_PREFETCH) == 0); } - if (i != 5) { + if (i != 5 || chunksize < (SPA_MINBLOCKSIZE * 2)) { dmu_assign_arcbuf(bonus_db, off, bigbuf_arcbufs[j], tx); } else {
--- a/usr/src/head/netdb.h Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/head/netdb.h Sun Jan 04 07:19:22 2015 -0800 @@ -131,7 +131,10 @@ struct addrinfo *ai_next; /* next structure in linked list */ }; - +/* + * The flag 0x8000 is currently reserved for private use between libnsl and + * libsocket. See lib/libsocket/inet/getaddrinfo.c for more information. + */ /* addrinfo flags */ #define AI_PASSIVE 0x0008 /* intended for bind() + listen() */ #define AI_CANONNAME 0x0010 /* return canonical version of host */
--- a/usr/src/lib/libcmdutils/Makefile.com Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/lib/libcmdutils/Makefile.com Sun Jan 04 07:19:22 2015 -0800 @@ -25,7 +25,8 @@ LIBRARY= libcmdutils.a VERS= .1 -CMD_OBJS= avltree.o sysattrs.o writefile.o process_xattrs.o uid.o gid.o +CMD_OBJS= avltree.o sysattrs.o writefile.o process_xattrs.o uid.o gid.o \ + custr.o COM_OBJS= list.o OBJECTS= $(CMD_OBJS) $(COM_OBJS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libcmdutils/common/custr.c Sun Jan 04 07:19:22 2015 -0800 @@ -0,0 +1,135 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * String utility functions with dynamic memory management. + */ + +/* + * Copyright 2014, Joyent, Inc. + */ + +#include <stdlib.h> +#include <err.h> +#include <string.h> + +#include "libcmdutils.h" + +struct custr { + size_t cus_strlen; + size_t cus_datalen; + char *cus_data; +}; + +#define STRING_CHUNK_SIZE 64 + +void +custr_reset(custr_t *cus) +{ + if (cus->cus_data == NULL) + return; + + cus->cus_strlen = 0; + cus->cus_data[0] = '\0'; +} + +size_t +custr_len(custr_t *cus) +{ + return (cus->cus_strlen); +} + +const char * +custr_cstr(custr_t *cus) +{ + return (cus->cus_data); +} + +int +custr_appendc(custr_t *cus, char newc) +{ + char news[2]; + + news[0] = newc; + news[1] = '\0'; + + return (custr_append(cus, news)); +} + +int +custr_append(custr_t *cus, const char *news) +{ + size_t len = strlen(news); + size_t chunksz = STRING_CHUNK_SIZE; + + while (chunksz < len) { + chunksz *= 2; + } + + if (len + cus->cus_strlen + 1 >= cus->cus_datalen) { + char *new_data; + size_t new_datalen = cus->cus_datalen + chunksz; + + /* + * Allocate replacement memory: + */ + if ((new_data = malloc(new_datalen)) == NULL) { + return (-1); + } + + /* + * Copy existing data into replacement memory and free + * the old memory. + */ + if (cus->cus_data != NULL) { + (void) memcpy(new_data, cus->cus_data, + cus->cus_strlen + 1); + free(cus->cus_data); + } + + /* + * Swap in the replacement buffer: + */ + cus->cus_data = new_data; + cus->cus_datalen = new_datalen; + } + /* + * Append new string to existing string: + */ + (void) memcpy(cus->cus_data + cus->cus_strlen, news, len + 1); + cus->cus_strlen += len; + + return (0); +} + +int +custr_alloc(custr_t **cus) +{ + custr_t *t; + + if ((t = calloc(1, sizeof (*t))) == NULL) { + *cus = NULL; + return (-1); + } + + *cus = t; + return (0); +} + +void +custr_free(custr_t *cus) +{ + if (cus == NULL) + return; + + free(cus->cus_data); + free(cus); +}
--- a/usr/src/lib/libcmdutils/common/mapfile-vers Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/lib/libcmdutils/common/mapfile-vers Sun Jan 04 07:19:22 2015 -0800 @@ -42,6 +42,13 @@ SYMBOL_VERSION SUNWprivate_1.1 { global: add_tnode; + custr_alloc; + custr_append; + custr_appendc; + custr_cstr; + custr_free; + custr_len; + custr_reset; destroy_tree; findnextgid; findnextuid;
--- a/usr/src/lib/libcmdutils/libcmdutils.h Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/lib/libcmdutils/libcmdutils.h Sun Jan 04 07:19:22 2015 -0800 @@ -25,6 +25,9 @@ /* * Copyright (c) 2013 RackTop Systems. */ +/* + * Copyright 2014 Joyent, Inc. + */ /* * Declarations for the functions in libcmdutils. @@ -140,6 +143,46 @@ */ extern int findnextgid(gid_t, gid_t, gid_t *); + + + /* dynamic string utilities */ + +typedef struct custr custr_t; + +/* + * Allocate and free a "custr_t" dynamic string object. Returns 0 on success + * and -1 otherwise. + */ +extern int custr_alloc(custr_t **); +extern void custr_free(custr_t *); + +/* + * Append a single character, or a NUL-terminated string of characters, to a + * dynamic string. Returns 0 on success and -1 otherwise. The dynamic string + * will be unmodified if the function returns -1. + */ +extern int custr_appendc(custr_t *, char); +extern int custr_append(custr_t *, const char *); + +/* + * Determine the length in bytes, not including the NUL terminator, of the + * dynamic string. + */ +extern size_t custr_len(custr_t *); + +/* + * Clear the contents of a dynamic string. Does not free the underlying + * memory. + */ +extern void custr_reset(custr_t *); + +/* + * Retrieve a const pointer to a NUL-terminated string version of the contents + * of the dynamic string. Storage for this string should not be freed, and + * the pointer will be invalidated by any mutations to the dynamic string. + */ +extern const char *custr_cstr(custr_t *str); + #ifdef __cplusplus } #endif
--- a/usr/src/lib/libipadm/common/libipadm.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/lib/libipadm/common/libipadm.c Sun Jan 04 07:19:22 2015 -0800 @@ -18,8 +18,10 @@ * * CDDL HEADER END */ + /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ #include <stdio.h> @@ -806,14 +808,14 @@ status = ipadm_errno2status(err); goto done; } - nvlsize = rvalp->ir_nvlsize; - nvlbuf = (char *)rvalp + sizeof (ipmgmt_get_rval_t); /* - * nvlbuf contains a list of nvlists, each of which represents - * configuration information for the given interface(s) + * Daemon reply pointed to by rvalp contains ipmgmt_get_rval_t structure + * followed by a list of packed nvlists, each of which represents + * configuration information for the given interface(s). */ - err = nvlist_unpack(nvlbuf, nvlsize, allifs, NV_ENCODE_NATIVE); + err = nvlist_unpack((char *)rvalp + sizeof (ipmgmt_get_rval_t), + rvalp->ir_nvlsize, allifs, NV_ENCODE_NATIVE); if (err != 0) status = ipadm_errno2status(err); done:
--- a/usr/src/lib/libndmp/common/libndmp.h Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/lib/libndmp/common/libndmp.h Sun Jan 04 07:19:22 2015 -0800 @@ -37,6 +37,7 @@ */ /* Copyright (c) 2007, The Storage Networking Industry Association. */ /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */ +/* Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ #ifndef _LIBNDMP_H #define _LIBNDMP_H @@ -347,11 +348,11 @@ extern int ndmp_set_dbglevel(int); extern const char *ndmp_strerror(int); extern int ndmp_door_status(void); -extern int ndmp_get_prop(char *, char **); -extern int ndmp_set_prop(char *, char *); +extern int ndmp_get_prop(const char *, char **); +extern int ndmp_set_prop(const char *, const char *); extern int ndmp_service_refresh(void); -extern char *ndmp_base64_encode(char *); -extern char *ndmp_base64_decode(char *); +extern char *ndmp_base64_encode(const char *); +extern char *ndmp_base64_decode(const char *); extern ndmp_door_ctx_t *ndmp_door_decode_start(char *, int); extern int ndmp_door_decode_finish(ndmp_door_ctx_t *); extern ndmp_door_ctx_t *ndmp_door_encode_start(char *, int);
--- a/usr/src/lib/libndmp/common/libndmp_base64.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/lib/libndmp/common/libndmp_base64.c Sun Jan 04 07:19:22 2015 -0800 @@ -36,6 +36,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +/* Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ #include <stdio.h> #include <sys/types.h> @@ -47,9 +48,6 @@ #define NDMP_ENC_LEN 1024 #define NDMP_DEC_LEN 256 -char *ndmp_base64_encode(char *); -char *ndmp_base64_decode(char *); - static boolean_t ndmp_is_base64(unsigned char); static char *b64_data = @@ -61,9 +59,9 @@ return (isalnum(c) || (c == '+') || (c == '/')); } -/* caller should use the encloded string and then free the string. */ +/* caller should use the encoded string and then free the string. */ char * -ndmp_base64_encode(char *str_to_encode) +ndmp_base64_encode(const char *str_to_encode) { int ret_cnt = 0; int i = 0, j = 0; @@ -115,7 +113,7 @@ } char * -ndmp_base64_decode(char *encoded_str) +ndmp_base64_decode(const char *encoded_str) { int len = strlen(encoded_str); int i = 0, j = 0; @@ -136,8 +134,10 @@ en_ind++; if (i == 4) { for (i = 0; i < 4; i++) { - if ((p = strchr(b64_data, arr_4[i])) == NULL) + if ((p = strchr(b64_data, arr_4[i])) == NULL) { + free(ret); return (NULL); + } arr_4[i] = (int)(p - b64_data); } @@ -161,8 +161,10 @@ arr_4[j] = 0; for (j = 0; j < 4; j++) { - if ((p = strchr(b64_data, arr_4[j])) == NULL) + if ((p = strchr(b64_data, arr_4[j])) == NULL) { + free(ret); return (NULL); + } arr_4[j] = (int)(p - b64_data); }
--- a/usr/src/lib/libndmp/common/libndmp_prop.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/lib/libndmp/common/libndmp_prop.c Sun Jan 04 07:19:22 2015 -0800 @@ -75,15 +75,17 @@ } ndmp_scfhandle_t; static int ndmp_config_saveenv(ndmp_scfhandle_t *); -static ndmp_scfhandle_t *ndmp_smf_scf_init(char *); +static ndmp_scfhandle_t *ndmp_smf_scf_init(const char *); static void ndmp_smf_scf_fini(ndmp_scfhandle_t *); static int ndmp_smf_start_transaction(ndmp_scfhandle_t *); static int ndmp_smf_end_transaction(ndmp_scfhandle_t *); -static int ndmp_smf_set_property(ndmp_scfhandle_t *, char *, char *); -static int ndmp_smf_get_property(ndmp_scfhandle_t *, char *, char *, size_t); -static int ndmp_smf_create_service_pgroup(ndmp_scfhandle_t *, char *); -static int ndmp_smf_delete_property(ndmp_scfhandle_t *, char *); -static int ndmp_smf_get_pg_name(ndmp_scfhandle_t *, char *, char **); +static int ndmp_smf_set_property(ndmp_scfhandle_t *, const char *, + const char *); +static int ndmp_smf_get_property(ndmp_scfhandle_t *, const char *, char *, + size_t); +static int ndmp_smf_create_service_pgroup(ndmp_scfhandle_t *, const char *); +static int ndmp_smf_delete_property(ndmp_scfhandle_t *, const char *); +static int ndmp_smf_get_pg_name(ndmp_scfhandle_t *, const char *, char **); /* * This routine send a refresh signal to ndmpd service which cause ndmpd @@ -105,7 +107,7 @@ * defined otherwise it would be NULL. */ int -ndmp_get_prop(char *prop, char **value) +ndmp_get_prop(const char *prop, char **value) { ndmp_scfhandle_t *handle = NULL; char *lval = (char *)malloc(NDMP_PROP_LEN); @@ -141,7 +143,7 @@ } int -ndmp_set_prop(char *env, char *env_val) +ndmp_set_prop(const char *env, const char *env_val) { ndmp_scfhandle_t *handle = NULL; char *pgname; @@ -176,7 +178,7 @@ } static int -ndmp_smf_get_pg_name(ndmp_scfhandle_t *h, char *pname, char **pgname) +ndmp_smf_get_pg_name(ndmp_scfhandle_t *h, const char *pname, char **pgname) { scf_value_t *value; scf_property_t *prop; @@ -250,7 +252,7 @@ * ndmp_scfhandle_t pointer if success. */ static ndmp_scfhandle_t * -ndmp_smf_scf_init(char *svc_name) +ndmp_smf_scf_init(const char *svc_name) { ndmp_scfhandle_t *handle; @@ -301,7 +303,7 @@ * Create a new property group at service level. */ static int -ndmp_smf_create_service_pgroup(ndmp_scfhandle_t *handle, char *pgroup) +ndmp_smf_create_service_pgroup(ndmp_scfhandle_t *handle, const char *pgroup) { int err; @@ -397,7 +399,7 @@ * Deletes property in current pg */ static int -ndmp_smf_delete_property(ndmp_scfhandle_t *handle, char *propname) +ndmp_smf_delete_property(ndmp_scfhandle_t *handle, const char *propname) { scf_transaction_entry_t *entry = NULL; @@ -430,7 +432,7 @@ */ static int ndmp_smf_set_property(ndmp_scfhandle_t *handle, - char *propname, char *valstr) + const char *propname, const char *valstr) { int ret = 0; scf_value_t *value = NULL; @@ -516,7 +518,7 @@ * memory allocated. */ static int -ndmp_smf_get_property(ndmp_scfhandle_t *handle, char *propname, +ndmp_smf_get_property(ndmp_scfhandle_t *handle, const char *propname, char *valstr, size_t sz) { int ret = 0;
--- a/usr/src/lib/libnsl/nss/getipnodeby.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/lib/libnsl/nss/getipnodeby.c Sun Jan 04 07:19:22 2015 -0800 @@ -73,6 +73,8 @@ * IPNODE_LOOKUPIPNODES getipnodebyname() needs to lookup the name in ipnodes. * IPNODE_LOOKUPHOSTS getipnodebyname() needs to lookup the name in hosts. * IPNODE_ISLITERAL The name supplied is a literal address string. + * IPNODE_UNMAP The user doesn't want v4 mapped addresses if no IPv6 + * interfaces are plumbed on the system. */ #define IPNODE_WANTIPV6 0x00000001u #define IPNODE_WANTIPV4 0x00000002u @@ -80,9 +82,16 @@ #define IPNODE_LOOKUPIPNODES 0x00000008u #define IPNODE_LOOKUPHOSTS 0x00000010u #define IPNODE_LITERAL 0x00000020u +#define IPNODE_UNMAP 0x00000040u #define IPNODE_IPV4 (IPNODE_WANTIPV4 | IPNODE_IPV4IFNOIPV6) /* + * The private flag between libsocket and libnsl. See + * lib/libsocket/inet/getaddrinfo.c for more information. + */ +#define AI_ADDRINFO 0x8000 + +/* * The default set of bits corresponding to a getipnodebyname() flags * argument of AI_DEFAULT. */ @@ -162,6 +171,10 @@ } else if (flags & AI_ALL) { ipnode_bits &= ~IPNODE_IPV4IFNOIPV6; } + if ((flags & AI_ADDRCONFIG) && !ipv6configured && + (flags & AI_ADDRINFO)) { + ipnode_bits |= IPNODE_UNMAP; + } } else { ipnode_bits &= ~IPNODE_IPV4; } @@ -343,7 +356,18 @@ else if (!(ipnode_bits & IPNODE_WANTIPV6)) hp = __filter_addresses(AF_INET6, buf6->result); - if (hp == NULL) + /* + * We've been asked to unmap v4 addresses. This + * situation implies IPNODE_WANTIPV4 and + * !IPNODE_WANTIPV6. + */ + if (hp != NULL && (ipnode_bits & IPNODE_UNMAP)) { + /* + * Just set hp to a new value, cleanup: will + * free the old one + */ + hp = __mappedtov4(hp, error_num); + } else if (hp == NULL) *error_num = NO_ADDRESS; }
--- a/usr/src/lib/libsocket/inet/getaddrinfo.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/lib/libsocket/inet/getaddrinfo.c Sun Jan 04 07:19:22 2015 -0800 @@ -69,6 +69,17 @@ #define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST \ | AI_ADDRCONFIG | AI_NUMERICSERV | AI_V4MAPPED | AI_ALL) #define ANY 0 + +/* + * This is a private, undocumented, flag that getaddrinfo() uses for + * getipnodebyname(). In the case of AI_ADDRCONFIG && AI_V4MAPPED, if there are + * no IPv6 addresses, getaddrinfo() should return non-IPv4 mapped addresses. On + * the flip side, getipnodebyname() is defined by RFC 2553 to explicitly do so. + * Therefore this private flag indicates to getaddrinfo that we shouldn't do + * this. + */ +#define AI_ADDRINFO 0x8000 + /* function prototypes for used by getaddrinfo() routine */ static int get_addr(int family, const char *hostname, struct addrinfo *aip, struct addrinfo *cur, ushort_t port, int version); @@ -602,7 +613,7 @@ /* if hostname argument is literal, name service doesn't get called */ if (family == PF_UNSPEC) { hp = getipnodebyname(_hostname, AF_INET6, AI_ALL | - aip->ai_flags | AI_V4MAPPED, &errnum); + aip->ai_flags | AI_V4MAPPED | AI_ADDRINFO, &errnum); } else { hp = getipnodebyname(_hostname, family, aip->ai_flags, &errnum); }
--- a/usr/src/lib/libzfs/common/libzfs_iter.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/lib/libzfs/common/libzfs_iter.c Sun Jan 04 07:19:22 2015 -0800 @@ -22,7 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ #include <stdio.h> @@ -186,9 +186,6 @@ fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_CREATETXG)); fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_CREATION)); - /* Allocate an nvlist to hold the bookmarks. */ - bmarks = fnvlist_alloc(); - if ((err = lzc_get_bookmarks(zhp->zfs_name, props, &bmarks)) != 0) goto out;
--- a/usr/src/lib/nsswitch/dns/Makefile.com Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/lib/nsswitch/dns/Makefile.com Sun Jan 04 07:19:22 2015 -0800 @@ -22,8 +22,6 @@ # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# # lib/nsswitch/dns/Makefile.com LIBRARY = libnss_dns.a @@ -46,5 +44,5 @@ LINTFLAGS += -erroff=E_GLOBAL_COULD_BE_STATIC2 -LDLIBS += -lnsl +LDLIBS += -lnsl -lsocket DYNLIB1 = nss_dns.so$(VERS)
--- a/usr/src/lib/nsswitch/dns/common/dns_common.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/lib/nsswitch/dns/common/dns_common.c Sun Jan 04 07:19:22 2015 -0800 @@ -22,12 +22,19 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ /* * dns_common.c */ #include "dns_common.h" +#include <sys/types.h> +#include <sys/socket.h> +#include <ifaddrs.h> +#include <net/if.h> #pragma weak dn_expand #pragma weak res_ninit @@ -321,6 +328,51 @@ return (NSS_NOTFOUND); } +static int +_nss_has_interfaces(boolean_t *v4, boolean_t *v6) +{ + struct ifaddrs *ifp, *i; + struct in_addr in4; + struct in6_addr in6; + const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; + + *v4 = *v6 = B_FALSE; + + if (getifaddrs(&ifp) != 0) + return (-1); + + for (i = ifp; i != NULL; i = i->ifa_next) { + if (i->ifa_flags & IFF_LOOPBACK) + continue; + if ((i->ifa_flags & IFF_UP) == 0) + continue; + + if (i->ifa_addr->sa_family == AF_INET) { + if (*v4 != B_FALSE) + continue; + + if (((struct sockaddr_in *)i->ifa_addr)-> + sin_addr.s_addr == INADDR_ANY) + continue; + *v4 = B_TRUE; + } + + if (i->ifa_addr->sa_family == AF_INET6) { + if (*v6 != B_FALSE) + continue; + + if (memcmp(&in6addr_any, + &((struct sockaddr_in6 *)i->ifa_addr)->sin6_addr, + sizeof (struct in6_addr)) == 0) + continue; + *v6 = B_TRUE; + } + } + + freeifaddrs(ifp); + return (0); +} + /* * nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) * nss2 get hosts/ipnodes with ttl backend DNS search engine. @@ -331,13 +383,6 @@ * Additionally in the extended results a nssuint_t ttl is placed. * This ttl is the lessor of the ttl's extracted from the result. * - * ***Currently the first version of this API only performs simple - * single res_nsearch lookups for with T_A or T_AAAA results. - * Other searches are deferred to the generic API w/t ttls. - * - * This function is not a generic res_* operation. It only performs - * a single T_A or T_AAAA lookups*** - * * RETURNS: NSS_SUCCESS or NSS_ERROR * If an NSS_ERROR result is returned, nscd is expected * to resubmit the gethosts request using the old style @@ -384,11 +429,14 @@ int af; char *ap, *apc; int hlen = 0, alen, iplen, len, isans; + boolean_t has_v4 = B_FALSE, has_v6 = B_FALSE; + int flags, family, pass2 = 0; statp = &stat; (void) memset(statp, '\0', sizeof (struct __res_state)); - if (res_ninit(statp) == -1) + if (res_ninit(statp) == -1) { return (NSS_ERROR); + } ap = apc = (char *)aliases; alen = 0; @@ -404,33 +452,152 @@ return (NSS_ERROR); } + /* + * There may be flags set when we are handling ipnode. There are three + * different values for flags: + * + * o AI_V4MAPPED + * o AI_ALL + * o AI_ADDRCONFIG + * + * The first two only have a meaning when af_family is ipv6. The latter + * means something in both cases. These flags are documented in + * getipnodebyname(3SOCKET), though the combinations leave a little + * something to be desired. It would be great if we could actually use + * getipnodebyname directly here since it already knows how to handle + * this kind of logic; however, we're not quite so lucky. Ideally we + * would add such an interface to libresolv.so.2 to handle this kind of + * thing, but that's rather painful as well. We'll summarize what has to + * happen below: + * + * AI_ALL is only meaningful when AI_V4MAPPED is also specified. Both + * are ignored if the family is not AF_INET6 + * + * family == AF_INET, flags | AI_ADDRCONFIG + * - lookup A records iff we have v4 plumbed + * family == AF_INET, !(flags | AI_ADDRCONFIG) + * - lookup A records + * family == AF_INET6, flags == 0 || flags == AI_ALL + * - lookup AAAA records + * family == AF_INET6, flags | AI_V4MAPPED + * - lookup AAAA, if none, lookup A + * family == AF_INET6, flags | AI_ADDRCONFIG + * - lookup AAAA records if ipv6 + * family == AF_INET6, flags | AI_V4MAPPED && flags | AI_ALL + * - lookup AAAA records, lookup A records + * family == AF_INET6, flags | AI_V4MAPPED && flags | AI_ADDRCONFIG + * - lookup AAAA records if ipv6 + * - If no AAAA && ipv4 exists, lookup A + * family == AF_INET6, flags | AI_V4MAPPED && flags | AI_ADDRCONFIG && + * flags | AI_ALL + * - lookup AAAA records if ipv6 + * - loookup A records if ipv4 + */ if (ipnode) { /* initially only handle the simple cases */ - if (arg.key.ipnode.flags != 0) { - res_ndestroy(statp); - return (NSS_ERROR); + name = arg.key.ipnode.name; + flags = arg.key.ipnode.flags; + family = arg.key.ipnode.af_family; + if (flags != 0) { + /* + * Figure out our first pass. We'll determine if we need + * to do a second pass afterwards once we successfully + * finish our first pass. + */ + if ((flags & AI_ADDRCONFIG) != 0) { + if (_nss_has_interfaces(&has_v4, &has_v6) != + 0) { + res_ndestroy(statp); + return (NSS_ERROR); + } + /* Impossible situations... */ + if (family == AF_INET && has_v4 == B_FALSE) { + res_ndestroy(statp); + return (NSS_NOTFOUND); + } + if (family == AF_INET6 && has_v6 == B_FALSE && + !(flags & AI_V4MAPPED)) { + res_ndestroy(statp); + return (NSS_NOTFOUND); + } + if (family == AF_INET6 && has_v6) + qtype = T_AAAA; + if (family == AF_INET || (family == AF_INET6 && + has_v6 == B_FALSE && flags & AI_V4MAPPED)) + qtype = T_A; + } else { + has_v4 = has_v6 = B_TRUE; + if (family == AF_INET6) + qtype = T_AAAA; + else + qtype = T_A; + } + } else { + if (family == AF_INET6) + qtype = T_AAAA; + else + qtype = T_A; } - name = arg.key.ipnode.name; - if (arg.key.ipnode.af_family == AF_INET6) - qtype = T_AAAA; - else - qtype = T_A; } else { name = arg.key.name; qtype = T_A; } + +searchagain: ret = res_nsearch(statp, name, C_IN, qtype, resbuf.buf, NS_MAXMSG); if (ret == -1) { - if (statp->res_h_errno == HOST_NOT_FOUND) { + /* + * We want to continue on unless we got NO_RECOVERY. Otherwise, + * HOST_NOT_FOUND, TRY_AGAIN, and NO_DATA all suggest to me that + * we should keep going. + */ + if (statp->res_h_errno == NO_RECOVERY) { + /* else lookup error - handle in general code */ + res_ndestroy(statp); + return (NSS_ERROR); + } + + /* + * We found something on our first pass. Make sure that we do + * not clobber this information. This ultimately means that we + * were successful. + */ + if (pass2 == 2) + goto out; + + /* + * If we're on the second pass (eg. we need to check both for A + * and AAAA records), or we were only ever doing a search for + * one type of record and are not supposed to do a second pass, + * then we need to return that we couldn't find anything to the + * user. + */ + if (pass2 == 1 || flags == 0 || family == AF_INET || + (family == AF_INET6 && !(flags & AI_V4MAPPED))) { pbuf->p_herrno = HOST_NOT_FOUND; pbuf->p_status = NSS_NOTFOUND; pbuf->data_len = 0; res_ndestroy(statp); return (NSS_NOTFOUND); } - /* else lookup error - handle in general code */ - res_ndestroy(statp); - return (NSS_ERROR); + + /* + * If we were only requested to search for flags on an IPv6 + * interface or we have no IPv4 interface, we stick to only + * doing a single pass and bail now. + */ + if ((flags & AI_ADDRCONFIG) && !(flags & AI_ALL) && + has_v4 == B_FALSE) { + pbuf->p_herrno = HOST_NOT_FOUND; + pbuf->p_status = NSS_NOTFOUND; + pbuf->data_len = 0; + res_ndestroy(statp); + return (NSS_NOTFOUND); + } + qtype = T_A; + flags = 0; + pass2 = 1; + goto searchagain; } cp = resbuf.buf; @@ -579,6 +746,16 @@ *bptr++ = '\n'; blen++; } + + /* Depending on our flags we may need to go back another time. */ + if (qtype == T_AAAA && family == AF_INET6 && + ((flags & AI_V4MAPPED) != 0) && ((flags & AI_ALL) != 0) && + has_v4 == B_TRUE) { + qtype = T_A; + pass2 = 2; /* Indicate that we found data this pass */ + goto searchagain; + } + /* Presumably the buffer is now filled. */ len = ROUND_UP(blen, sizeof (nssuint_t)); /* still room? */ @@ -587,6 +764,7 @@ res_ndestroy(statp); return (NSS_ERROR); } +out: pbuf->ext_off = pbuf->data_off + len; pbuf->ext_len = sizeof (nssuint_t); pbuf->data_len = blen;
--- a/usr/src/lib/pylibbe/common/libbe_py.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/lib/pylibbe/common/libbe_py.c Sun Jan 04 07:19:22 2015 -0800 @@ -857,6 +857,11 @@ return (B_FALSE); } + if (PyDict_SetItemString(*listDict, BE_ATTR_GLOBAL_ACTIVE, + (be->be_global_active ? Py_True : Py_False)) != 0) { + return (B_FALSE); + } + if (be->be_space_used != 0) { if (PyDict_SetItemString(*listDict, BE_ATTR_SPACE, PyLong_FromUnsignedLongLong(be->be_space_used)) != 0) {
--- a/usr/src/man/man1/Makefile Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man1/Makefile Sun Jan 04 07:19:22 2015 -0800 @@ -180,6 +180,7 @@ krb5-config.1 \ ksh93.1 \ ktutil.1 \ + kvmstat.1 \ lari.1 \ last.1 \ lastcomm.1 \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/man/man1/kvmstat.1 Sun Jan 04 07:19:22 2015 -0800 @@ -0,0 +1,118 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright (c) 2014, Joyent, Inc. +.\" +.Dd Dec 20, 2014 +.Dt KVMSTAT 1 +.Os +.Sh NAME +.Nm kvmstat +.Nd report KVM statistics +.Sh SYNOPSIS +.Nm kvmstat +.Oo +.Ar interval +.Op Ar count +.Oc +.Sh DESCRIPTION +.Nm +reports the activity of running KVM virtual machines and their exit activity, +injected interrupts, emulations, and more, on a per virtual CPU basis. +.Lp +.Nm +should be used when trying to get a rough sense of guest activity from the +hypervisor's perspective, and allows one to understand from a low-level +perspective, what kind of activity is going on inside of the virtual machine. In +addition, +.Nm +is useful for diagnosing reports of pathological or faulty behavior inside of +guests. While there is no expected range of values for the fields displayed as +that varies with the use of virtual machines, if all of the virtual CPUs for a +given virtual machine are consistently zero, then that may indicate that a +problem has occurred, for example, a panic inside of the guest or a bug in the +hypervisor. +.Lp +If no operands are specified, then +.Nm +will display statistics every second until the program is terminated. +.Ss Output Fields +Every +.Ar interval +.Nm +will report data with the following fields: +.Bl -tag -width Ds +.It Nm pid +Identifier of the process controlling the virtual CPU. +.It Nm vcpu +Virtual CPU identifier relative to its virtual machine. +.It Nm exits +Count of all virtual machine exits for the virtual CPU over +.Ar interval . +.It Nm haltx +Count of virtual machine exits due to the guest executing the +.Sy HLT +instruction for the virtual CPU over +.Ar interval . +.It Nm irqx +Count of virtual machine exits due to a pending external interrupt arriving +on the physical CPU that the virtual CPU was actively running on over +.Ar interval . +.It Nm irqwx +Count of virtual machine exits due to an open interrupt window on the +virtual CPU over +.Ar interval . +.It Nm iox +Count of virtual machine exits due to the execution of an I/O instruction, +such as +.Sy inb , +on the virtual CPU over +.Ar interval . +.It Nm mmiox +Count of virtual machine exits due to performing memory mapped I/O on the +virtual CPU over +.Ar interval . +.It Nm irqs +Count of interrupts injected into the virtual CPU over +.Ar interval . +.It Nm emul +Count of instructions the hypervisor had to emulate on behalf of the guest +virtual CPU over +.Ar interval . +.It Nm eptv +Count of extended page table violations serviced on the virtual CPU over +.Ar interval . +.El +.Sh OPERANDS +The following operands are supported: +.Bl -hang -width Ds +.It Ar count +.Bd -filled -compact +Specifies the number of times that the statistics are repeated. If not +specified, +.Nm +will continue until it is terminated. +.Ed +.It Ar interval +.Bd -filled -compact +Specifies the number of seconds between reports of statistics. If not specified, +reports are generated every second. +.Ed +.El +.Sh STABILITY +The arguments are +.Sy committed , +while the output format is +.Sy Not an interface . +.Sh SEE ALSO +.Xr iostat 1M , +.Xr mpstat 1M , +.Xr attributes 5
--- a/usr/src/man/man1/mailx.1 Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man1/mailx.1 Sun Jan 04 07:19:22 2015 -0800 @@ -9,7 +9,7 @@ .\" 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] -.TH MAILX 1 "Sep 19, 2001" +.TH MAILX 1 "Dec 18, 2014" .SH NAME mailx \- interactive message processing system .SH SYNOPSIS @@ -36,7 +36,6 @@ .fi .SH DESCRIPTION -.sp .LP The mail utilities listed above provide a comfortable, flexible environment for sending and receiving mail messages electronically. @@ -64,7 +63,6 @@ \fBCommands\fR as in the primary \fBmailbox\fR. This gives rise within these pages to the notion of a current \fBmailbox\fR. .SH OPTIONS -.sp .LP On the command line options start with a dash (\(mi). Any other arguments are taken to be destinations (recipients). If no recipients are specified, @@ -294,7 +292,6 @@ .RE .SH OPERANDS -.sp .LP The following operands are supported: .sp @@ -308,7 +305,6 @@ .SH USAGE .SS "Starting Mail" -.sp .LP At startup time, \fBmailx\fR executes the system startup file \fB/etc/mail/mailx.rc\fR. If invoked as \fBmail\fR or \fBMail\fR, the system @@ -380,7 +376,6 @@ escape character followed by a single command letter and optional arguments. See \fBTilde Escapes\fR for a summary of these commands. .SS "Reading Mail" -.sp .LP Each message is assigned a sequential number, and there is at any time the notion of a current message, marked by a right angle bracket (>) in the header @@ -544,20 +539,23 @@ shell conventions (see \fBsh\fR(1)). Special characters are recognized by certain commands and are documented with the commands below. .SS "Sending Mail" -.sp .LP Recipients listed on the command line may be of three types: login names, shell commands, or alias groups. Login names may be any network address, including mixed network addressing. If mail is found to be undeliverable, an attempt is -made to return it to the sender's \fBmailbox\fR. If the recipient name begins -with a pipe symbol ( | ), the rest of the name is taken to be a shell command -to pipe the message through. This provides an automatic interface with any -program that reads the standard input, such as \fBlp\fR(1) for recording -outgoing mail on paper. Alias groups are set by the \fBa\fRlias command (see -\fBCommands\fR below) or in a system startup file (for example, -\fB$HOME/.mailrc\fR). Aliases are lists of recipients of any type. +made to return it to the sender's \fBmailbox\fR. If the \fBexpandaddr\fR option +is not set (the default), then the following rules do not apply and the name of +the recipient must be a local mailbox or network address. If the recipient name +begins with a pipe symbol ( | ), the rest of the name is taken to be a shell +command to pipe the message through. This provides an automatic interface with +any program that reads the standard input, such as \fBlp\fR(1) for recording +outgoing mail on paper. +.sp +.LP +Alias groups are set by the \fBa\fRlias command (see \fBCommands\fR below) or in +a system startup file (for example, \fB$HOME/.mailrc\fR). Aliases are lists of +recipients of any type. .SS "Forwarding Mail" -.sp .LP To forward a specific message, include it in a message to the desired recipients with the \fB~f\fR or \fB~m\fR tilde escapes. See \fBTilde\fR @@ -569,7 +567,6 @@ your mail to a new host by forwarding it to your new address if it is not yet listed in the \fBNIS\fR aliases domain. .SS "Commands" -.sp .LP Regular commands are of the form .sp @@ -768,6 +765,18 @@ .sp .ne 2 .na +\fB\fBexpandaddr\fR\fR +.ad +.sp .6 +.RS 4n +Causes recipient addresses to be expanded based on the discussion in the section +\fBSending Mail\fR. Note that enabling this option allows for addresses that can +cause arbitrary command execution by starting with the \fB|\fR character. +.RE + +.sp +.ne 2 +.na \fB\fBex\fRit\fR .ad .br @@ -1621,7 +1630,6 @@ .RE .SS "Tilde Escapes" -.sp .LP The following tilde escape commands can be used when composing mail to send. These may be entered only from \fIinput mode\fR, by beginning a line with the @@ -1905,7 +1913,6 @@ .RE .SS "Internal Variables" -.sp .LP The following variables are internal variables. They may be imported from the execution environment or set using the \fBse\fRt command at any time. The @@ -2539,12 +2546,10 @@ .RE .SS "Large File Behavior" -.sp .LP See \fBlargefile\fR(5) for the description of the behavior of \fBmailx\fR when encountering files greater than or equal to 2 Gbyte ( 2^31 bytes). .SH ENVIRONMENT VARIABLES -.sp .LP See \fBenviron\fR(5) for descriptions of the following environment variables that affect the execution of \fBmailx\fR: \fBHOME\fR, \fBLANG\fR, @@ -2661,7 +2666,6 @@ .RE .SH EXIT STATUS -.sp .LP When the \fB-e\fR option is specified, the following exit values are returned: .sp @@ -2706,7 +2710,6 @@ .RE .SH FILES -.sp .ne 2 .na \fB\fB$HOME/.mailrc\fR\fR @@ -2788,7 +2791,6 @@ .RE .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -2804,7 +2806,6 @@ .TE .SH SEE ALSO -.sp .LP \fBbiff\fR(1B), \fBecho\fR(1), \fBed\fR(1), \fBex\fR(1), \fBfmt\fR(1), \fBlp\fR(1), \fBls\fR(1), \fBmail\fR(1), \fBmail\fR(1B), \fBmailcompat\fR(1), @@ -2813,7 +2814,6 @@ \fBpasswd\fR(4), \fBattributes\fR(5), \fBenviron\fR(5), \fBlargefile\fR(5), \fBstandards\fR(5) .SH NOTES -.sp .LP Where \fIshell-command\fR is shown as valid, arguments are not always allowed. Experimentation is recommended.
--- a/usr/src/man/man1m/ipf.1m Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man1m/ipf.1m Sun Jan 04 07:19:22 2015 -0800 @@ -2,19 +2,19 @@ .\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed .\" location. .\" Portions Copyright (c) 2009, Sun Microsystems Inc. All Rights Reserved. -.TH IPF 1M "Feb 25, 2009" +.\" Portions Copyright (c) 2014, Joyent, Inc. All Rights Reserved. +.TH IPF 1M "Oct 7, 2014" .SH NAME ipf \- alter packet filtering lists for IP packet input and output .SH SYNOPSIS .LP .nf -\fBipf\fR [\fB-6AdDEInoPRrsvVyzZ\fR] [\fB-l\fR block | pass | nomatch] +\fBipf\fR [\fB-6AdDEGInoPRrsvVyzZ\fR] [\fB-l\fR block | pass | nomatch] [\fB-T\fR \fIoptionlist\fR] [\fB-F\fR i | o | a | s | S] \fB-f\fR \fIfilename\fR - [\fB-f\fR \fIfilename\fR...] + [\fB-f\fR \fIfilename\fR...] [\fIzonename\fR] .fi .SH DESCRIPTION -.sp .LP The \fBipf\fR utility is part of a suite of commands associated with the Solaris IP Filter feature. See \fBipfilter\fR(5). @@ -34,7 +34,6 @@ \fB/dev/ipl\fR, and \fB/dev/ipstate\fR. The default permissions of these files require \fBipf\fR to be run as root for all operations. .SS "Enabling Solaris IP Filter Feature" -.sp .LP Solaris IP Filter is installed with the Solaris operating system. However, packet filtering is not enabled by default. Use the following procedure to @@ -159,7 +158,6 @@ activated. .RE .SH OPTIONS -.sp .LP The following options are supported: .sp @@ -257,6 +255,17 @@ .sp .ne 2 .na +\fB\fB-G\fR\fR +.ad +.sp .6 +.RS 4n +Make changes to the Global Zone-controlled ipfilter for the zone given as an +argument. See the \fBZONES\fR section for more information. +.RE + +.sp +.ne 2 +.na \fB\fB-I\fR\fR .ad .sp .6 @@ -459,8 +468,25 @@ affect fragment or state statistics. .RE +.SH ZONES +.LP +Each non-global zone has two ipfilter instances: the in-zone ipfilter, which +can be controlled from both the zone itself and the global zone, and the +Global Zone-controlled (GZ-controlled) instance, which can only be controlled +from the Global Zone. The non-global zone is not able to observe or control +the GZ-controlled ipfilter. + +ipf optionally takes a zone name as an argument, which will change the +ipfilter settings for that zone, rather than the current one. The zonename +option is only available in the Global Zone. Using it in any other zone will +return an error. If the \fB-G\fR option is specified with this argument, the +Global Zone-controlled ipfilter is operated on. If \fB-G\fR is not specified, +the in-zone ipfilter is operated on. Note that ipf differs from the other +ipfilter tools in how the zone name is specified. It takes the zone name as the +last argument, while all of the other tools take the zone name as an argument +to the \fB-G\fR and \fB-z\fR options. + .SH FILES -.sp .ne 2 .na \fB\fB/dev/ipauth\fR\fR @@ -499,7 +525,6 @@ .RE .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -515,16 +540,14 @@ .TE .SH SEE ALSO -.sp .LP \fBipfstat\fR(1M), \fBipmon\fR(1M), \fBipnat\fR(1M), \fBippool\fR(1M), \fBsvcadm\fR(1M), \fBsvc.ipfd\fR(1M), \fBipf\fR(4), \fBipnat.conf\fR(4), -\fBippool\fR(4), \fBattributes\fR(5), \fBipfilter\fR(5) +\fBippool\fR(4), \fBattributes\fR(5), \fBipfilter\fR(5), \fBzones(5)\fR .sp .LP \fI\fR .SH DIAGNOSTICS -.sp .LP Needs to be run as root for the packet filtering lists to actually be affected inside the kernel.
--- a/usr/src/man/man1m/ipfs.1m Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man1m/ipfs.1m Sun Jan 04 07:19:22 2015 -0800 @@ -2,47 +2,47 @@ .\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed .\" location. .\" Portions Copyright (c) 2008, Sun Microsystems Inc. All Rights Reserved. -.TH IPFS 1M "Apr 3, 2008" +.\" Portions Copyright (c) 2013, Joyent, Inc. All Rights Reserved. +.TH IPFS 1M "Oct 30, 2013" .SH NAME ipfs \- saves and restores information for NAT and state tables .SH SYNOPSIS .LP .nf -\fBipfs\fR [\fB-nv\fR] \fB-l\fR +\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nv\fR] \fB-l\fR .fi .LP .nf -\fBipfs\fR [\fB-nv\fR] \fB-u\fR +\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nv\fR] \fB-u\fR .fi .LP .nf -\fBipfs\fR [\fB-nv\fR] [\fB-d\fR \fIdirname\fR] \fB-R\fR +\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nv\fR] [\fB-d\fR \fIdirname\fR] \fB-R\fR .fi .LP .nf -\fBipfs\fR [\fB-nv\fR] [\fB-d\fR \fIdirname\fR] \fB-W\fR +\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nv\fR] [\fB-d\fR \fIdirname\fR] \fB-W\fR .fi .LP .nf -\fBipfs\fR [\fB-nNSv\fR] [\fB-f\fR \fIfilename\fR] \fB-r\fR +\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nNSv\fR] [\fB-f\fR \fIfilename\fR] \fB-r\fR .fi .LP .nf -\fBipfs\fR [\fB-nNSv\fR] [\fB-f\fR \fIfilename\fR] \fB-w\fR +\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nNSv\fR] [\fB-f\fR \fIfilename\fR] \fB-w\fR .fi .LP .nf -\fBipfs\fR [\fB-nNSv\fR] \fB-f\fR \fIfilename\fR \fB-i\fR \fI<if1>\fR,\fI<if2>\fR +\fBipfs\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-nNSv\fR] \fB-f\fR \fIfilename\fR \fB-i\fR \fI<if1>\fR,\fI<if2>\fR .fi .SH DESCRIPTION -.sp .LP The \fBipfs\fR utility enables the saving of state information across reboots. Specifically, the utility allows state information created for NAT entries and @@ -50,7 +50,6 @@ to disk. Then, after a reboot, that information is restored. The result of this state-saving is that connections are not interrupted. .SH OPTIONS -.sp .LP The following options are supported: .sp @@ -164,6 +163,30 @@ beginning of this operation and unlocked once complete. .RE +.sp +.ne 2 +.na +\fB\fB-z\fR \fIzonename\fR\fR +.ad +.RS 6n +Operate on the in-zone state information for the specified zone. If neither +this option nor \fB-G\fR is specified, the current zone is used. This command +is only available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for +more information. +.RE + +.sp +.ne 2 +.na +\fB\fB-G\fR \fIzonename\fR\fR +.ad +.RS 6n +Operate on the global zone controlled state information for the specified +zone. If neither this option nor \fB-z\fR is specified, the current zone is +used. This command is only available in the Global Zone. See \fBZONES\fR in +\fBipf\fR(1m) for more information. +.RE + .SH FILES .RS +4 .TP @@ -196,7 +219,6 @@ \fB/dev/ipnat\fR .RE .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -212,11 +234,10 @@ .TE .SH SEE ALSO -.sp .LP -\fBipf\fR(1M), \fBipmon\fR(1M), \fBipnat\fR(1M), \fBattributes\fR(5) +\fBipf\fR(1M), \fBipmon\fR(1M), \fBipnat\fR(1M), \fBattributes\fR(5), +\fBzones(5)\fR .SH DIAGNOSTICS -.sp .LP Arguably, the \fB-W\fR and \fB-R\fR operations should set the locking and, rather than undo it, restore it to what it was previously.
--- a/usr/src/man/man1m/ipfstat.1m Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man1m/ipfstat.1m Sun Jan 04 07:19:22 2015 -0800 @@ -2,7 +2,8 @@ .\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed .\" location. .\" Portions Copyright (c) 2008, Sun Microsystems Inc. All Rights Reserved. -.TH IPFSTAT 1M "Apr 3, 2008" +.\" Portions Copyright (c) 2013, Joyent, Inc. All Rights Reserved. +.TH IPFSTAT 1M "Oct 30, 2013" .SH NAME ipfstat \- reports on packet filter statistics and filter list .SH SYNOPSIS @@ -14,11 +15,10 @@ .LP .nf \fBipfstat\fR [\fB-C\fR] [\fB-D\fR \fIaddrport\fR] [\fB-P\fR \fIprotocol\fR] [\fB-S\fR \fIaddrport\fR] - [\fB-T\fR \fIrefreshtime\fR] + [\fB-T\fR \fIrefreshtime\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] .fi .SH DESCRIPTION -.sp .LP The \fBipfstat\fR command is part of a suite of commands associated with the Solaris IP Filter feature. See \fBipfilter\fR(5). @@ -132,7 +132,6 @@ displayed (where \fIX\fR is the number of rows on the display). There is no way to see additional entries. .SH OPTIONS -.sp .LP The following options are supported: .sp @@ -351,6 +350,30 @@ Turn verbose mode on. Displays additional debugging information. .RE +.sp +.ne 2 +.na +\fB\fB-z\fR \fIzonename\fR\fR +.ad +.RS 18n +Report the in-zone statistics for the specified zone. If neither this option +nor \fB-G\fR is specified, the current zone is used. This command is only +available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for more +information. +.RE + +.sp +.ne 2 +.na +\fB\fB-G\fR \fIzonename\fR\fR +.ad +.RS 18n +Report the global zone controlled statistics for the specified zone. If +neither this option nor \fB-z\fR is specified, the current zone is used. This +command is only available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) +for more information. +.RE + .SH FILES .RS +4 .TP @@ -377,7 +400,6 @@ \fB/dev/ipstate\fR .RE .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -393,10 +415,9 @@ .TE .SH SEE ALSO -.sp .LP \fBipf\fR(1M), \fBkstat\fR(1M), \fBkstat\fR(3KSTAT), \fBattributes\fR(5), -\fBipfilter\fR(5) +\fBipfilter\fR(5), \fBzones(5)\fR .sp .LP \fI\fR
--- a/usr/src/man/man1m/ipmon.1m Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man1m/ipmon.1m Sun Jan 04 07:19:22 2015 -0800 @@ -2,18 +2,18 @@ .\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed .\" location. .\" Portions Copyright (c) 2008, Sun Microsystems Inc. All Rights Reserved. -.TH IPMON 1M "Apr 3, 2008" +.\" Portions Copyright (c) 2013, Joyent, Inc. All Rights Reserved. +.TH IPMON 1M "Oct 30, 2013" .SH NAME ipmon \- monitors /dev/ipl for logged packets .SH SYNOPSIS .LP .nf \fBipmon\fR [\fB-abDFhnpstvxX\fR] [\fB-N\fR \fIdevice\fR] [ [o] [NSI]] [\fB-O\fR [NSI]] - [\fB-P\fR \fIpidfile\fR] [\fB-S\fR \fIdevice\fR] [\fB-f\fR \fIdevice\fR] [\fIfilename\fR] + [\fB-P\fR \fIpidfile\fR] [\fB-S\fR \fIdevice\fR] [\fB-f\fR \fIdevice\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fIfilename\fR] .fi .SH DESCRIPTION -.sp .LP The \fBipmon\fR command is part of a suite of commands associated with the Solaris IP Filter feature. See \fBipfilter\fR(5). @@ -102,7 +102,6 @@ separated by a slash. For example, \fBicmp 3/3\fR for a port unreachable message. .SH OPTIONS -.sp .LP The following options are supported: .sp @@ -343,6 +342,32 @@ Show the log header record data in hex. .RE +.sp +.ne 2 +.na +\fB\fB-z\fR \fIzonename\fR\fR +.ad +.sp .6 +.RS 4n +Monitor packets the specified zone's in-zone filter. If neither this option +nor \fB-G\fR is specified, the current zone is used. This command is only +available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for more +information. +.RE + +.sp +.ne 2 +.na +\fB\fB-G\fR \fIzonename\fR\fR +.ad +.sp .6 +.RS 4n +Monitor packets for the specified zone's global zone controlled filter. If +neither this option nor \fB-z\fR is specified, the current zone is used. This +command is only available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) +for more information. +.RE + .SH FILES .RS +4 .TP @@ -363,7 +388,6 @@ \fB/dev/ipstate\fR .RE .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -379,15 +403,13 @@ .TE .SH SEE ALSO -.sp .LP \fBipf\fR(1M), \fBipfstat\fR(1M), \fBipnat\fR(1M), \fBattributes\fR(5), -\fBipfilter\fR(5) +\fBipfilter\fR(5), \fBzones(5)\fR .sp .LP \fI\fR .SH DIAGNOSTICS -.sp .LP \fBipmon\fR expects data that it reads to be consistent with how it should be saved and aborts if it fails an assertion which detects an anomaly in the
--- a/usr/src/man/man1m/ipnat.1m Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man1m/ipnat.1m Sun Jan 04 07:19:22 2015 -0800 @@ -2,17 +2,17 @@ .\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed .\" location. .\" Portions Copyright (c) 2008, Sun Microsystems Inc. All Rights Reserved. -.TH IPNAT 1M "Apr 3, 2008" +.\" Portions Copyright (c) 2013, Joyent, Inc. All Rights Reserved. +.TH IPNAT 1M "Oct 30, 2013" .SH NAME ipnat \- user interface to the NAT subsystem .SH SYNOPSIS .LP .nf -\fBipnat\fR [\fB-CdFhlnRrsv\fR] \fB-f\fR \fIfilename\fR +\fBipnat\fR [\fB-CdFhlnRrsv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] \fB-f\fR \fIfilename\fR .fi .SH DESCRIPTION -.sp .LP The \fBipnat\fR utility opens a specified file (treating \fB-\fR as stdin) and parses it for a set of rules that are to be added or removed from the IP NAT. @@ -32,7 +32,6 @@ permissions of \fB/dev/ipnat\fR require \fBipnat\fR to be run as root for all operations. .SH OPTIONS -.sp .LP The following options are supported: .sp @@ -140,8 +139,31 @@ active rules/table entries. .RE +.sp +.ne 2 +.na +\fB\fB-z\fR \fIzonename\fR\fR +.ad +.RS 15n +Operate on the in-zone IP NAT for the specified zone. If neither this option +nor \fB-G\fR is specified, the current zone is used. This command is only +available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for more +information. +.RE + +.sp +.ne 2 +.na +\fB\fB-G\fR \fIzonename\fR\fR +.ad +.RS 15n +Operate on the global zone controlled IP NAT for the specified zone. If +neither this option nor \fB-z\fR is specified, the current zone is used. This +command is only available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) +for more information. +.RE + .SH FILES -.sp .ne 2 .na \fB\fB/dev/ipnat\fR\fR @@ -182,7 +204,6 @@ .RE .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -198,6 +219,6 @@ .TE .SH SEE ALSO -.sp .LP -\fBipf\fR(1M), \fBipfstat\fR(1M), \fBipnat\fR(4), \fBattributes\fR(5) +\fBipf\fR(1M), \fBipfstat\fR(1M), \fBipnat\fR(4), \fBattributes\fR(5), +\fBzones(5)\fR
--- a/usr/src/man/man1m/ippool.1m Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man1m/ippool.1m Sun Jan 04 07:19:22 2015 -0800 @@ -2,60 +2,60 @@ .\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed .\" location. .\" Portions Copyright (c) 2008, Sun Microsystems Inc. All Rights Reserved. -.TH IPPOOL 1M "Apr 3, 2008" +.\" Portions Copyright (c) 2012, Joyent, Inc. All Rights Reserved. +.TH IPPOOL 1M "Nov 26, 2012" .SH NAME ippool \- user interface to the IP Filter pools .SH SYNOPSIS .LP .nf -\fBippool\fR \fB-a\fR [\fB-dnv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] \fB-i\fR \fIipaddr\fR +\fBippool\fR \fB-a\fR [\fB-dnv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] \fB-i\fR \fIipaddr\fR [/\fInetmask\fR] .fi .LP .nf -\fBippool\fR \fB-A\fR [\fB-dnv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] [\fB-S\fR \fIseed\fR] +\fBippool\fR \fB-A\fR [\fB-dnv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] [\fB-S\fR \fIseed\fR] [\fB-t\fR \fItype\fR] .fi .LP .nf -\fBippool\fR \fB-f\fR \fIfile\fR [\fB-dnuv\fR] +\fBippool\fR \fB-f\fR \fIfile\fR [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-dnuv\fR] .fi .LP .nf -\fBippool\fR \fB-F\fR [\fB-dv\fR] [\fB-o\fR \fIrole\fR] [\fB-t\fR \fItype\fR] +\fBippool\fR \fB-F\fR [\fB-dv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-o\fR \fIrole\fR] [\fB-t\fR \fItype\fR] .fi .LP .nf -\fBippool\fR \fB-h\fR [\fB-dv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-t\fR \fItype\fR] +\fBippool\fR \fB-h\fR [\fB-dv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-t\fR \fItype\fR] .fi .LP .nf -\fBippool\fR \fB-l\fR [\fB-dv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-t\fR \fItype\fR] +\fBippool\fR \fB-l\fR [\fB-dv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-t\fR \fItype\fR] .fi .LP .nf -\fBippool\fR \fB-r\fR [\fB-dnv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] \fB-i\fR \fIipaddr\fR +\fBippool\fR \fB-r\fR [\fB-dnv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] \fB-i\fR \fIipaddr\fR [/\fInetmask\fR] .fi .LP .nf -\fBippool\fR \fB-R\fR [\fB-dnv\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] [\fB-t\fR \fItype\fR] +\fBippool\fR \fB-R\fR [\fB-dnv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-m\fR \fIpoolname\fR] [\fB-o\fR \fIrole\fR] [\fB-t\fR \fItype\fR] .fi .LP .nf -\fBippool\fR \fB-s\fR [\fB-dtv\fR] [\fB-M\fR \fIcore\fR] [\fB-N\fR \fInamelist\fR] +\fBippool\fR \fB-s\fR [\fB-dtv\fR] [\fB-G\fR | \fB-z\fR \fIzonename\fR] [\fB-M\fR \fIcore\fR] [\fB-N\fR \fInamelist\fR] .fi .SH DESCRIPTION -.sp .LP The \fBippool\fR utility is used to manage information stored in the IP pools subsystem of IP Filter software. Configuration file information can be parsed @@ -76,11 +76,9 @@ \fB/dev/ipl\fR, and \fB/dev/ipstate\fR. The default permissions of these files require \fBippool\fR to be run as root for all operations. .SH OPTIONS -.sp .LP \fBippool\fR supports the option categories described below. .SS "Global Options" -.sp .LP The following global options are supported: .sp @@ -111,8 +109,31 @@ Turn verbose mode on. .RE +.sp +.ne 2 +.na +\fB\fB-z\fR \fIzonename\fR\fR +.ad +.RS 6n +Manage the specified zone's in-zone IP pools. If neither this option nor +\fB-G\fR is specified, the current zone is used. This command is only +available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for more +information. +.RE + +.sp +.ne 2 +.na +\fB\fB-G\fR \fIzonename\fR\fR +.ad +.RS 6n +Manage the specified zone's global zone controlled IP pools. If neither this +option nor \fB-z\fR is specified, the current zone is used. This command is +only available in the Global Zone. See \fBZONES\fR in \fBipf\fR(1m) for more +information. +.RE + .SS "Instance-Specific Options" -.sp .LP The following instance-specific options are supported: .sp @@ -198,7 +219,6 @@ .RE .SS "Other Options" -.sp .LP The following, additional options are supported: .sp @@ -282,7 +302,6 @@ .RE .SH FILES -.sp .ne 2 .na \fB\fB/dev/ippool\fR\fR @@ -310,7 +329,6 @@ .RE .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -326,6 +344,6 @@ .TE .SH SEE ALSO -.sp .LP -\fBipf\fR(1M), \fBipfstat\fR(1M), \fBippool\fR(4), \fBattributes\fR(5) +\fBipf\fR(1M), \fBipfstat\fR(1M), \fBippool\fR(4), \fBattributes\fR(5), +\fBzones(5)\fR
--- a/usr/src/man/man1m/ypinit.1m Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man1m/ypinit.1m Sun Jan 04 07:19:22 2015 -0800 @@ -4,17 +4,19 @@ .\" 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] -.TH YPINIT 1M "Dec 20, 2007" +.\" Copyright 2014 Nexenta Systems, Inc. All rights reserved. +.TH YPINIT 1M "Dec 15, 2014" .SH NAME ypinit \- set up NIS client .SH SYNOPSIS .LP .nf -\fB/usr/sbin/ypinit\fR [\fB-c\fR] [\fB-m\fR] [\fB-s\fR \fImaster_server\fR] +\fB/usr/sbin/ypinit\fR \fB-m\fR +\fB/usr/sbin/ypinit\fR \fB-s\fR [\fImaster_server\fR] +\fB/usr/sbin/ypinit\fR \fB-c\fR [\fIserver_name...\fR] .fi .SH DESCRIPTION -.sp .LP \fBypinit\fR can be used to set up an \fBNIS\fR client system. You must be the superuser to run this command. This script need not be used at all if @@ -40,14 +42,15 @@ \fB/var/yp/binding/\fIdomain\fR/ypservers\fR. This file is used by \fBypbind\fR when run without the \fB-broadcast\fR option. .SH OPTIONS -.sp .ne 2 .na -\fB\fB-c\fR\fR +\fB\fB-c\fR\fR [\fIserver_name...\fR] .ad .sp .6 .RS 4n -Set up a \fBypclient\fR system. +Set up a \fBypclient\fR system. If \fIserver_name\fR is specified, it will +replace currently configured list of servers. \fIserver_name\fR could be +represented by IPv4/v6 address as well as by hostname. .RE .sp @@ -72,7 +75,6 @@ .RE .SH FILES -.sp .ne 2 .na \fB\fB/etc/hosts\fR\fR @@ -93,12 +95,10 @@ .RE .SH SEE ALSO -.sp .LP \fBsvcs\fR(1), \fBypwhich\fR(1), \fBsvcadm\fR(1M), \fBypbind\fR(1M), \fBsysinfo\fR(2), \fBhosts\fR(4), \fBattributes\fR(5), \fBsmf\fR(5) .SH NOTES -.sp .LP The \fBNIS client\fR service is managed by the service management facility, \fBsmf\fR(5), under the service identifier: @@ -116,7 +116,6 @@ requesting restart, can be performed using \fBsvcadm\fR(1M). The service's status can be queried using the \fBsvcs\fR(1) command. .SH BUGS -.sp .LP \fBypinit\fR sets up the list of \fBNIS\fR servers only for the current domain on the system when it is run, that is, the domain returned by the
--- a/usr/src/man/man1m/zoneadm.1m Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man1m/zoneadm.1m Sun Jan 04 07:19:22 2015 -0800 @@ -4,7 +4,7 @@ .\" 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] -.TH ZONEADM 1M "Oct 30, 2013" +.TH ZONEADM 1M "Dec 26, 2014" .SH NAME zoneadm \- administer zones .SH SYNOPSIS @@ -26,17 +26,14 @@ .fi .SH DESCRIPTION -.sp .LP The \fBzoneadm\fR utility is used to administer system zones. A zone is an application container that is maintained by the operating system runtime. .SH SECURITY -.sp .LP Once a process has been placed in a zone other than zone \fB0\fR, the process or any of its children cannot change zones. .SH OPTIONS -.sp .LP The following options are supported: .sp @@ -74,7 +71,6 @@ .RE .SH SUBCOMMANDS -.sp .LP Subcommands which can result in destructive actions or loss of work have a \fB-F\fR flag to force the action. If input is from a terminal device, the user @@ -279,8 +275,8 @@ .sp .6 .RS 4n Install the specified zone on the system. This subcommand automatically -attempts to verify first. It refuses to install if the verify step fails. See -the \fBverify\fR subcommand. +attempts to verify first, most verification errors are fatal. See the +\fBverify\fR subcommand. .sp .ne 2 .na @@ -599,7 +595,6 @@ .sp .SH EXIT STATUS -.sp .LP The following exit values are returned: .sp @@ -633,7 +628,6 @@ .RE .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -649,7 +643,6 @@ .TE .SH SEE ALSO -.sp .LP \fBread\fR(1), \fBsvcs\fR(1), \fBzlogin\fR(1), \fBzonename\fR(1), \fBinit\fR(1M), \fBkernel\fR(1M), \fBsvcadm\fR(1M), \fBsvc.startd\fR(1M), @@ -657,7 +650,6 @@ \fBattributes\fR(5), \fBbrands\fR(5), \fBnative\fR(5), \fBsmf\fR(5), \fBzones\fR(5) .SH NOTES -.sp .LP The \fBzones\fR(5) service is managed by the service management facility, \fBsmf\fR(5), under the service identifier:
--- a/usr/src/man/man2/Makefile Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man2/Makefile Sun Jan 04 07:19:22 2015 -0800 @@ -185,6 +185,7 @@ facl.2 \ fchdir.2 \ fchmod.2 \ + fchmodat.2 \ fchown.2 \ fchownat.2 \ fchroot.2 \ @@ -213,11 +214,12 @@ lchown.2 \ linkat.2 \ lstat.2 \ - mkdirat.2 \ - mknodat.2 \ + mkdirat.2 \ + mknodat.2 \ openat.2 \ pathconf.2 \ pipe2.2 \ + ppoll.2 \ pread.2 \ pset_assign.2 \ pset_destroy.2 \ @@ -225,8 +227,8 @@ putacct.2 \ putpmsg.2 \ pwrite.2 \ + readlinkat.2 \ readv.2 \ - readlinkat.2 \ renameat.2 \ sbrk.2 \ semtimedop.2 \ @@ -279,6 +281,7 @@ fchdir.2 := LINKSRC = chdir.2 fchmod.2 := LINKSRC = chmod.2 +fchmodat.2 := LINKSRC = chmod.2 fchown.2 := LINKSRC = chown.2 fchownat.2 := LINKSRC = chown.2 @@ -351,6 +354,8 @@ pipe2.2 := LINKSRC = pipe.2 +ppoll.2 := LINKSRC = poll.2 + pset_assign.2 := LINKSRC = pset_create.2 pset_destroy.2 := LINKSRC = pset_create.2
--- a/usr/src/man/man2/open.2 Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man2/open.2 Sun Jan 04 07:19:22 2015 -0800 @@ -10,7 +10,7 @@ .\" 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] -.TH OPEN 2 "Nov 16, 2013" +.TH OPEN 2 "Dec 23, 2014" .SH NAME open, openat \- open a file .SH SYNOPSIS @@ -30,7 +30,6 @@ .fi .SH DESCRIPTION -.sp .LP The \fBopen()\fR function establishes the connection between a file and a file descriptor. It creates an open file description that refers to a file and a @@ -168,6 +167,19 @@ .sp .ne 2 .na +.B O_EXEC +.na +.ad +.sp .6 +.RS 4n +If set, indicates that the file should be opened for execute permission. +This option is only valid for regular files, an error will be returned +if it is not. +.RE + +.sp +.ne 2 +.na \fB\fBO_LARGEFILE\fR\fR .ad .sp .6 @@ -296,6 +308,18 @@ .sp .ne 2 .na +.B O_SEARCH +.ad +.sp .6 +.RS 4n +If set, indicates that the directory should be opened for searching. +This option is only valid for a directory, an error will be returned if +it is not. +.RE + +.sp +.ne 2 +.na \fB\fBO_SYNC\fR\fR .ad .sp .6 @@ -420,14 +444,12 @@ The largest value that can be represented correctly in an object of type \fBoff_t\fR is established as the offset maximum in the open file description. .SH RETURN VALUES -.sp .LP Upon successful completion, the \fBopen()\fR function opens the file and return a non-negative integer representing the lowest numbered unused file descriptor. Otherwise, \fB\(mi1\fR is returned, \fBerrno\fR is set to indicate the error, and no files are created or modified. .SH ERRORS -.sp .LP The \fBopen()\fR and \fBopenat()\fR functions will fail if: .sp @@ -632,6 +654,16 @@ .sp .ne 2 .na +.B ENOEXEC +.ad +.RS 16n +The \fBO_EXEC\fR flag is set and \fIpath\fR does not point to a regular +file. +.RE + +.sp +.ne 2 +.na \fB\fBENOLINK\fR\fR .ad .RS 16n @@ -676,7 +708,8 @@ .RS 16n A component of the path prefix is not a directory or a relative path was supplied to \fBopenat()\fR, the \fBO_XATTR\fR flag was not supplied, and the -file descriptor does not refer to a directory. +file descriptor does not refer to a directory. The \fBO_SEARCH\fR flag +was passed and \fIpath\fR does not refer to a directory. .RE .sp @@ -877,13 +910,11 @@ .in -2 .SH USAGE -.sp .LP The \fBopen()\fR function has a transitional interface for 64-bit file offsets. See \fBlf64\fR(5). Note that using \fBopen64()\fR is equivalent to using \fBopen()\fR with \fBO_LARGEFILE\fR set in \fIoflag\fR. .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -903,7 +934,6 @@ .TE .SH SEE ALSO -.sp .LP \fBIntro\fR(2), \fBchmod\fR(2), \fBclose\fR(2), \fBcreat\fR(2), \fBdup\fR(2), \fBexec\fR(2), \fBfcntl\fR(2), \fBgetmsg\fR(2), \fBgetrlimit\fR(2), @@ -912,7 +942,6 @@ \fBunlockpt\fR(3C), \fBattributes\fR(5), \fBlf64\fR(5), \fBprivileges\fR(5), \fBstandards\fR(5), \fBconnld\fR(7M), \fBstreamio\fR(7I) .SH NOTES -.sp .LP Hierarchical Storage Management (HSM) file systems can sometimes cause long delays when opening a file, since HSM files must be recalled from secondary
--- a/usr/src/man/man2/poll.2 Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man2/poll.2 Sun Jan 04 07:19:22 2015 -0800 @@ -1,4 +1,5 @@ '\" te +.\" Copyright (c) 2014, Joyent, Inc. .\" Copyright 1989 AT&T Copyright (c) 2001, Sun Microsystems, Inc. All Rights Reserved Portions Copyright (c) 1992, X/Open Company Limited All Rights Reserved .\" Sun Microsystems, Inc. gratefully acknowledges The Open Group for permission to reproduce portions of its copyrighted documentation. Original documentation from The Open Group can be obtained online at .\" http://www.opengroup.org/bookstore/. @@ -16,18 +17,41 @@ #include <poll.h> \fBint\fR \fBpoll\fR(\fBstruct pollfd\fR \fIfds[]\fR, \fBnfds_t\fR \fInfds\fR, \fBint\fR \fItimeout\fR); + +\fBint\fR \fBppoll\fR(\fBstruct pollfd *restrict\fR \fIfds\fR, \fBnfds_t\fR \fInfds\fR, + \fBconst struct timespec *restrict\fR \fItsp\fR, \fBconst sigset_t *restrict\fR \fIsigmask\fR); .fi .SH DESCRIPTION +.LP +The \fBpoll()\fR and \fBppoll()\fR functions provides applications with a +mechanism for multiplexing input/output over a set of file descriptors. For +each member of the array pointed to by \fIfds\fR, \fBpoll()\fR and \fBppoll()\fR +examine the given file descriptor for the event(s) specified in \fIevents\fR. +The number of \fBpollfd\fR structures in the \fIfds\fR array is specified by +\fInfds\fR. The \fBpoll()\fR and \fBppoll()\fR functions identify those file +descriptors on which an application can read or write data, or on which certain +events have occurred. .sp .LP -The \fBpoll()\fR function provides applications with a mechanism for -multiplexing input/output over a set of file descriptors. For each member of -the array pointed to by \fIfds\fR, \fBpoll()\fR examines the given file -descriptor for the event(s) specified in \fIevents\fR. The number of -\fBpollfd\fR structures in the \fIfds\fR array is specified by \fInfds\fR. The -\fBpoll()\fR function identifies those file descriptors on which an application -can read or write data, or on which certain events have occurred. +The \fBppoll()\fR function behaves identically to \fBpoll()\fR, except as follows: +.RS +4 +.TP +.ie t \(bu +.el o +For the \fBppoll\fR function, the timeout period is given in seconds and +nanoseconds in an argument of type \fBstruct timespec\fR, where as \fBpoll()\fR +takes a timeout in milliseconds in the form of an integer argument. +.RE +.RS +4 +.TP +.ie t \(bu +.el o +The \fBppoll()\fR function takes an optional \fIsigmask\fR argument. When a +non-\fBNULL\fR pointer is passed, the calling threads signal mask is replaced by +the one specified in \fIsigset\fR before examining file descriptors, and +restored before returning. +.RE .sp .LP The \fIfds\fR argument specifies the file descriptors to be examined and the @@ -152,35 +176,36 @@ .sp .LP If the value \fBfd\fR is less than 0, \fBevents\fR is ignored and \fBrevents\fR -is set to 0 in that entry on return from \fBpoll()\fR. +is set to 0 in that entry on return from \fBpoll()\fR and \fBppoll()\fR. .sp .LP -The results of the \fBpoll()\fR query are stored in the \fBrevents\fR member in -the \fBpollfd\fR structure. Bits are set in the \fBrevents\fR bitmask to -indicate which of the requested events are true. If none are true, none of the -specified bits are set in \fBrevents\fR when the \fBpoll()\fR call returns. The -event flags \fBPOLLHUP\fR, \fBPOLLERR\fR, and \fBPOLLNVAL\fR are always set -in \fBrevents\fR if the conditions they indicate are true; this occurs even -though these flags were not present in \fBevents\fR. +The results of the \fBpoll()\fR or \fBppoll()\fR query are stored in the +\fBrevents\fR member in the \fBpollfd\fR structure. Bits are set in the +\fBrevents\fR bitmask to indicate which of the requested events are true. If +none are true, none of the specified bits are set in \fBrevents\fR when either +the \fBpoll()\fR or \fBppoll()\fR call returns. The event flags \fBPOLLHUP\fR, +\fBPOLLERR\fR, and \fBPOLLNVAL\fR are always set in \fBrevents\fR if the +conditions they indicate are true; this occurs even though these flags were not +present in \fBevents\fR. .sp .LP If none of the defined events have occurred on any selected file descriptor, -\fBpoll()\fR waits at least \fItimeout\fR milliseconds for an event to occur on -any of the selected file descriptors. On a computer where millisecond timing -accuracy is not available, \fItimeout\fR is rounded up to the nearest legal -value available on that system. If the value \fItimeout\fR is 0, \fBpoll()\fR -returns immediately. If the value of \fItimeout\fR is \(mi1, \fBpoll()\fR -blocks until a requested event occurs or until the call is interrupted. The -\fBpoll()\fR function is not affected by the \fBO_NDELAY\fR and -\fBO_NONBLOCK\fR flags. +\fBpoll()\fR and \fBppoll()\fR wait at least \fItimeout\fR milliseconds for an +event to occur on any of the selected file descriptors. On a computer where +millisecond timing accuracy is not available, \fItimeout\fR is rounded up to the +nearest legal value available on that system. If the value \fItimeout\fR is 0, +\fBpoll()\fR returns immediately. If the value of \fItimeout\fR is \(mi1, +\fBpoll()\fR blocks until a requested event occurs or until the call is +interrupted. If the value of \fBtsp\fR is \fBNULL\fR, then \fBppoll()\fR blocks +until a requested event occurs or until the call is interrupted. The +\fBpoll()\fR and \fBppoll()\fR functions are not affected by the \fBO_NDELAY\fR +and \fBO_NONBLOCK\fR flags. .sp .LP -The \fBpoll()\fR function supports regular files, terminal and pseudo-terminal -devices, streams-based files, FIFOs and pipes. The behavior of \fBpoll()\fR on -elements of \fIfds\fR that refer to other types of file is unspecified. -.sp -.LP -The \fBpoll()\fR function supports sockets. +The \fBpoll()\fR and \fBppoll()\fR functions support regular files, terminal and +pseudo-terminal devices, streams-based files, FIFOs, pipes, and sockets. The +behavior of \fBpoll()\fR and \fBppoll()\fR on elements of \fIfds\fR that refer +to other types of file is unspecified. .sp .LP A file descriptor for a socket that is listening for connections will indicate @@ -189,9 +214,9 @@ is ready for writing, once a connection has been established. .sp .LP -Regular files always \fBpoll()\fR \fBTRUE\fR for reading and writing. +Regular files always \fBpoll()\fR and \fBppoll()\fR \fBTRUE\fR for reading and +writing. .SH RETURN VALUES -.sp .LP Upon successful completion, a non-negative value is returned. A positive value indicates the total number of file descriptors that has been selected (that is, @@ -200,9 +225,8 @@ selected. Upon failure, \fB\(mi1\fR is returned and \fBerrno\fR is set to indicate the error. .SH ERRORS -.sp .LP -The \fBpoll()\fR function will fail if: +The \fBpoll()\fR and \fBppoll()\fR functions will fail if: .sp .ne 2 .na @@ -228,7 +252,7 @@ \fB\fBEINTR\fR\fR .ad .RS 10n -A signal was caught during the \fBpoll()\fR function. +A signal was caught during the \fBpoll()\fR or \fBppoll()\fR function. .RE .sp @@ -243,7 +267,6 @@ .RE .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -259,7 +282,6 @@ .TE .SH SEE ALSO -.sp .LP \fBIntro\fR(2), \fBgetmsg\fR(2), \fBgetrlimit\fR(2), \fBputmsg\fR(2), \fBread\fR(2), \fBwrite\fR(2), \fBselect\fR(3C), \fBattributes\fR(5), @@ -268,7 +290,6 @@ .LP \fISTREAMS Programming Guide\fR .SH NOTES -.sp .LP Non-STREAMS drivers use \fBchpoll\fR(9E) to implement \fBpoll()\fR on these devices.
--- a/usr/src/man/man3c/Makefile Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man3c/Makefile Sun Jan 04 07:19:22 2015 -0800 @@ -60,6 +60,7 @@ catopen.3c \ cfgetispeed.3c \ cfsetispeed.3c \ + clearenv.3c \ clock.3c \ clock_nanosleep.3c \ clock_settime.3c \ @@ -112,6 +113,7 @@ exit.3c \ fattach.3c \ fclose.3c \ + fcloseall.3c \ fdatasync.3c \ fdetach.3c \ fdopen.3c \ @@ -159,12 +161,14 @@ getlogin.3c \ getmntent.3c \ getnetgrent.3c \ + get_nprocs.3c \ getopt.3c \ getpagesize.3c \ getpagesizes.3c \ getpass.3c \ getpeerucred.3c \ getpriority.3c \ + getprogname.3c \ getpw.3c \ getpwnam.3c \ getrusage.3c \ @@ -406,6 +410,7 @@ sigwaitinfo.3c \ sleep.3c \ ssignal.3c \ + smt_pause.3c \ stack_getbounds.3c \ stack_inbounds.3c \ stack_setbounds.3c \ @@ -671,6 +676,7 @@ btowc_l.3c \ bzero.3c \ calloc.3c \ + canonicalize_file_name.3c \ catclose.3c \ cfgetospeed.3c \ cfsetospeed.3c \ @@ -734,6 +740,8 @@ fdopendir.3c \ fdwalk.3c \ feof.3c \ + ffsl.3c \ + ffsll.3c \ fgetgrent.3c \ fgetgrent_r.3c \ fgetpwent.3c \ @@ -746,6 +754,9 @@ file_to_decimal.3c \ fileno.3c \ finite.3c \ + fls.3c \ + flsl.3c \ + flsll.3c \ fpclass.3c \ fpgetmask.3c \ fpgetsticky.3c \ @@ -783,6 +794,7 @@ getlogin_r.3c \ getmntany.3c \ getnetgrent_r.3c \ + get_nprocs_conf.3c \ getpassphrase.3c \ getpwent.3c \ getpwent_r.3c \ @@ -914,11 +926,12 @@ memchr.3c \ memcmp.3c \ memcpy.3c \ + memmem.3c \ memmove.3c \ memset.3c \ minor.3c \ mkdtemp.3c \ - mkfifoat.3c \ + mkfifoat.3c \ mkostemp.3c \ mkostemps.3c \ mkstemps.3c \ @@ -1009,7 +1022,7 @@ pthread_mutexattr_setprioceiling.3c \ pthread_mutexattr_setprotocol.3c \ pthread_mutexattr_setpshared.3c \ - pthread_mutexattr_setrobust.3c \ + pthread_mutexattr_setrobust.3c \ pthread_mutexattr_settype.3c \ pthread_rwlock_destroy.3c \ pthread_rwlock_reltimedrdlock_np.3c \ @@ -1090,6 +1103,7 @@ setlogmask.3c \ setnetgrent.3c \ setpriority.3c \ + setprogname.3c \ setpwent.3c \ setspent.3c \ setstate.3c \ @@ -1124,15 +1138,21 @@ stderr.3c \ stdin.3c \ stdout.3c \ + stpcpy.3c \ + stpncpy.3c \ strcasecmp.3c \ strcasecmp_l.3c \ + strcasestr.3c \ + strcasestr_l.3c \ strcat.3c \ strchr.3c \ + strchrnul.3c \ strcmp.3c \ strcoll_l.3c \ strcpy.3c \ strcspn.3c \ strdup.3c \ + strdupa.3c \ strerror_r.3c \ strfmon_l.3c \ strftime_l.3c \ @@ -1144,7 +1164,10 @@ strncat.3c \ strncmp.3c \ strncpy.3c \ + strndup.3c \ + strndupa.3c \ strnlen.3c \ + strnstr.3c \ strpbrk.3c \ strptime_l.3c \ strrchr.3c \ @@ -1440,6 +1463,8 @@ btowc_l.3c := LINKSRC = btowc.3c +canonicalize_file_name.3c := LINKSRC = realpath.3c + catclose.3c := LINKSRC = catopen.3c cfgetospeed.3c := LINKSRC = cfgetispeed.3c @@ -1562,6 +1587,12 @@ feof.3c := LINKSRC = ferror.3c fileno.3c := LINKSRC = ferror.3c +ffsl.3c := LINKSRC = ffs.3c +ffsll.3c := LINKSRC = ffs.3c +fls.3c := LINKSRC = ffs.3c +flsl.3c := LINKSRC = ffs.3c +flsll.3c := LINKSRC = ffs.3c + fsetattr.3c := LINKSRC = fgetattr.3c getattrat.3c := LINKSRC = fgetattr.3c setattrat.3c := LINKSRC = fgetattr.3c @@ -1643,10 +1674,14 @@ innetgr.3c := LINKSRC = getnetgrent.3c setnetgrent.3c := LINKSRC = getnetgrent.3c +get_nprocs_conf.3c := LINKSRC = get_nprocs.3c + getpassphrase.3c := LINKSRC = getpass.3c setpriority.3c := LINKSRC = getpriority.3c +setprogname.3c := LINKSRC = getprogname.3c + endpwent.3c := LINKSRC = getpwnam.3c fgetpwent.3c := LINKSRC = getpwnam.3c fgetpwent_r.3c := LINKSRC = getpwnam.3c @@ -1809,6 +1844,7 @@ memchr.3c := LINKSRC = memory.3c memcmp.3c := LINKSRC = memory.3c memcpy.3c := LINKSRC = memory.3c +memmem.3c := LINKSRC = memory.3c memmove.3c := LINKSRC = memory.3c memset.3c := LINKSRC = memory.3c @@ -2113,14 +2149,20 @@ cftime.3c := LINKSRC = strftime.3c strftime_l.3c := LINKSRC = strftime.3c +stpcpy.3c := LINKSRC = string.3c +stpncpy.3c := LINKSRC = string.3c strcasecmp.3c := LINKSRC = string.3c strcasecmp_l.3c := LINKSRC = string.3c +strcasestr.3c := LINKSRC = string.3c +strcasestr_l.3c := LINKSRC = string.3c strcat.3c := LINKSRC = string.3c strchr.3c := LINKSRC = string.3c +strchrnul.3c := LINKSRC = string.3c strcmp.3c := LINKSRC = string.3c strcpy.3c := LINKSRC = string.3c strcspn.3c := LINKSRC = string.3c strdup.3c := LINKSRC = string.3c +strdupa.3c := LINKSRC = string.3c strlcat.3c := LINKSRC = string.3c strlcpy.3c := LINKSRC = string.3c strlen.3c := LINKSRC = string.3c @@ -2129,7 +2171,10 @@ strncat.3c := LINKSRC = string.3c strncmp.3c := LINKSRC = string.3c strncpy.3c := LINKSRC = string.3c +strndup.3c := LINKSRC = string.3c +strndupa.3c := LINKSRC = string.3c strnlen.3c := LINKSRC = string.3c +strnstr.3c := LINKSRC = string.3c strpbrk.3c := LINKSRC = string.3c strrchr.3c := LINKSRC = string.3c strsep.3c := LINKSRC = string.3c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/man/man3c/clearenv.3c Sun Jan 04 07:19:22 2015 -0800 @@ -0,0 +1,64 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright (c) 2014, Joyent, Inc. +.\" +.Dd "Dec 20, 2014" +.Dt CLEARENV 3C +.Os +.Sh NAME +.Nm clearenv +.Nd clear environment +.Sh SYNOPSIS +.In stdlib.h +.Ft int +.Fo clearenv +.Fa void +.Fc +.Sh DESCRIPTION +The +.Fn clearenv +function clears the contents of the environment. All environment variables in +the calling process are removed as though the function +.Xr unsetenv 3C +had been called on every environment variable. Until subsequent calls to +.Xr putenv 3C +or +.Xr setenv 3C +are made, calls to +.Xr getenv 3C +will always return +.Sy NULL . +.Sh RETURN VALUES +Upon successful completion, +.Fn clearenv +returns +.Sy 0 . +Otherwise, it returns a non-zero value and sets +.Sy errno +to indicate the error. At this time, no errors are defined for +.Fn clearenv , +it will always succeed. Portable applications should always check the return +value of +.Fn clearenv . +.Sh ERRORS +No errors are defined. +.Sh INTERFACE STABILITY +.Sy Committed . +.Sh MT-LEVEL +.Sy Mt-Safe . +.Sh SEE ALSO +.Xr getenv 3C , +.Xr unsetenv 3C , +.Xr setenv 3C , +.Xr attributes 5 , +.Xr environ 5 , +.Xr standards 5
--- a/usr/src/man/man3c/fclose.3c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man3c/fclose.3c Sun Jan 04 07:19:22 2015 -0800 @@ -19,7 +19,6 @@ .fi .SH DESCRIPTION -.sp .LP The \fBfclose()\fR function causes the stream pointed to by \fIstream\fR to be flushed and the associated file to be closed. Any unwritten buffered data for @@ -42,12 +41,10 @@ The \fBfclose()\fR function is performed automatically for all open files upon calling \fBexit\fR(2). .SH RETURN VALUES -.sp .LP Upon successful completion, \fBfclose()\fR returns \fB0\fR. Otherwise, it returns \fBEOF\fR and sets \fBerrno\fR to indicate the error. .SH ERRORS -.sp .LP The \fBfclose()\fR function will fail if: .sp @@ -135,7 +132,6 @@ .RE .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -153,7 +149,7 @@ .TE .SH SEE ALSO -.sp .LP \fBclose\fR(2), \fBexit\fR(2), \fBgetrlimit\fR(2), \fBulimit\fR(2), -\fBfopen\fR(3C), \fBstdio\fR(3C), \fBattributes\fR(5), \fBstandards\fR(5) +\fBfcloseall\fR(3C), \fBfopen\fR(3C), \fBstdio\fR(3C), +\fBattributes\fR(5), \fBstandards\fR(5)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/man/man3c/fcloseall.3c Sun Jan 04 07:19:22 2015 -0800 @@ -0,0 +1,53 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright (c) 2014, Joyent, Inc. +.\" +.Dd "Dec 20, 2014" +.Dt FCLOSEALL 3C +.Os +.Sh NAME +.Nm fcloseall +.Nd close all standard I/O streams +.Sh SYNOPSIS +.In stdio.h +.Ft int +.Fo fcloseall +.Fa void +.Fc +.Sh DESCRIPTION +The +.Fn fcloseall +function closes all open standard I/O streams. The equivalent of +.Xr fflush 3C +is called on each stream before closing, thus any buffered or pending +input is discarded while any buffered or pending output is written out +to the underlying file. This includes the standard streams, +.Vt stdin , +.Vt stdout , +and +.Vt stderr . +.Sh RETURN VALUES +Currently, the function +.Fn fcloseall +always returns +.Sy 0 . +Note, portable applications should always check the return value. +.Sh INTERFACE STABILITY +.Sy Committed . +.Sh MT-LEVEL +.Sy Mt-Safe . +.Sh SEE ALSO +.Xr close 3C , +.Xr fflush 3C , +.Xr attributes 5 , +.Xr environ 5 , +.Xr standards 5
--- a/usr/src/man/man3c/ffs.3c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man3c/ffs.3c Sun Jan 04 07:19:22 2015 -0800 @@ -1,4 +1,5 @@ '\" te +.\" Copyright (c) 2014, Joyent, Inc. .\" Copyright 1989 AT&T Copyright (c) 2002, Sun Microsystems, Inc. All Rights Reserved Portions Copyright (c) 1992, X/Open Company Limited All Rights Reserved .\" Sun Microsystems, Inc. gratefully acknowledges The Open Group for permission to reproduce portions of its copyrighted documentation. Original documentation from The Open Group can be obtained online at .\" http://www.opengroup.org/bookstore/. @@ -15,26 +16,41 @@ .nf #include <strings.h> -\fBint\fR \fBffs\fR(\fBconst int\fR \fIi\fR); +\fBint\fR \fBffs\fR(\fBint\fR \fIi\fR); + +\fBint\fR \fBffsl\fR(\flong\fR \fIi\fR); + +\fBint\fR \fBffsll\fR(\fBlong long\fR \fIi\fR); + +\fBint\fR \fBfls\fR(\fBint\fR \fIi\fR); + +\fBint\fR \fBflsl\fR(\fBlong\fR \fIi\fR); + +\fBint\fR \fBflsl\fR(\fBlong long\fR \fIi\fR); .fi .SH DESCRIPTION +.LP +The \fBffs()\fR, \fBffsl()\, and \fBffsll()\fR functions finds the first bit set +(beginning with the least significant bit) and return the index of that bit. +Bits are numbered starting at one (the least significant bit). .sp .LP -The \fBffs()\fR function finds the first bit set (beginning with the least -significant bit) and returns the index of that bit. Bits are numbered starting -at one (the least significant bit). +The \fBfls()\fR, \fBflsl()\fR, and \fBflsll()\fR functions find the last bit set +(beginning with the most significant bit) and return the index of that bit. +Bits are numbered starting at one (the least significant bit). .SH RETURN VALUES +.LP +The \fBffs()\fR, \fBffsl()\fR, and \fBffsll()\fR functions returns the index of +the first bit set. If \fIi\fR is 0, then they return 0. .sp .LP -The \fBffs()\fR function returns the index of the first bit set. If \fIi\fR is -0, then \fBffs()\fR returns 0. +The \fBfls()\fR, \fBflsl()\fR, and \fBflsll()\fR functions return the index of +the last bit set. If \fIi\fR is 0, then they return 0. .SH ERRORS -.sp .LP No errors are defined. .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -46,12 +62,11 @@ l | l . ATTRIBUTE TYPE ATTRIBUTE VALUE _ -Interface Stability Standard +Interface Stability Committed _ MT-Level MT-Safe .TE .SH SEE ALSO -.sp .LP \fBattributes\fR(5), \fBstandards\fR(5)
--- a/usr/src/man/man3c/fopen.3c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man3c/fopen.3c Sun Jan 04 07:19:22 2015 -0800 @@ -4,7 +4,7 @@ .\" Copyright (c) 2006, Sun Microsystems, Inc. All Rights Reserved. .\" Portions Copyright (c) 1992, X/Open Company Limited. All Rights Reserved. .\" Portions Copyright (c) 2013, OmniTI Computer Consulting, Inc. All Rights Reserved. -.\" Portions Copyright (c) 2013, Joyent, Inc. All Rights Reserved. +.\" Portions Copyright (c) 2014, Joyent, Inc. All Rights Reserved. .\" Sun Microsystems, Inc. gratefully acknowledges The Open Group for permission to reproduce portions of its copyrighted documentation. Original documentation from The Open Group can be obtained online at .\" http://www.opengroup.org/bookstore/. .\" The Institute of Electrical and Electronics Engineers and The Open Group, have given us permission to reprint portions of their documentation. In the following statement, the phrase "this text" refers to portions of the system documentation. Portions of this text are reprinted and reproduced in electronic form in the Sun OS Reference Manual, from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- Portable Operating System Interface (POSIX), The Open Group Base Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of Electrical and Electronics Engineers, Inc and The Open Group. In the event of any discrepancy between these versions and the original IEEE and The Open Group Standard, the original IEEE and The Open Group Standard is the referee document. The original Standard can be obtained online at http://www.opengroup.org/unix/online.html. @@ -402,6 +402,7 @@ respects this function is Standard. .SH SEE ALSO .LP -\fBenable_extended_FILE_stdio\fR(3C), \fBfclose\fR(3C), \fBfdopen\fR(3C), -\fBfflush\fR(3C), \fBfreopen\fR(3C), \fBfsetpos\fR(3C), \fBrewind\fR(3C), -\fBopen\fR(2), \fBattributes\fR(5), \fBlf64\fR(5), \fBstandards\fR(5) +\fBenable_extended_FILE_stdio\fR(3C), \fBfclose\fR(3C), +\fRfcloseall\fR(3C), \fBfdopen\fR(3C), \fBfflush\fR(3C), +\fBfreopen\fR(3C), \fBfsetpos\fR(3C), \fBrewind\fR(3C), \fBopen\fR(2), +\fBattributes\fR(5), \fBlf64\fR(5), \fBstandards\fR(5)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/man/man3c/get_nprocs.3c Sun Jan 04 07:19:22 2015 -0800 @@ -0,0 +1,59 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright (c) 2014 Joyent, Inc. +.\" +.Dd "Dec 21, 2014" +.Dt GET_NPROCS 3C +.Os +.Sh NAME +.Nm get_nprocs , +.Nm get_nprocs_conf +.Nd get number of processors +.Sh SYNOPSIS +.In unistd.h +.Ft int +.Fo get_nprocs +.Fa void +.Fc +.Ft int +.Fo get_nprocs_conf +.Fa void +.Fc +.Sh DESCRIPTION +The +.Fn get_nprocs +and +.Fn get_nprocs_conf +functions are provided for compatibility with other systems and are +equivalent to calling +.Fn sysconf _SC_NPROCESSORS_ONLN +and +.Fn sysconf _SC_NPROCESSORS_CONF +respectively. +.Sh RETURN VALUES +The +.Fn get_nprocs +function returns the number of processors that are currently online. The +.Fn get_nprocs_conf +function returns the number of processors that the operating system has +configured. +.Sh INTERFACE STABILITY +.Sy Committed . +.Sh MT-LEVEL +.Sy MT-Safe , +.Sy Async-Signal-Safe +.Sh SEE ALSO +.Xr psrinfo 1M , +.Xr processor_info 2 , +.Xr sysconf 3C , +.Xr attributes 5 , +.Xr standards 5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/man/man3c/getprogname.3c Sun Jan 04 07:19:22 2015 -0800 @@ -0,0 +1,77 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright (c) 2014, Joyent, Inc. +.\" +.Dd "Dec 22, 2014" +.Dt GETPROGNAME 3C +.Os +.Sh NAME +.Nm getprogname , +.Nm setprogname +.Nd get or set the program name +.Sh SYNOPSIS +.In stdlib.h +.Ft const char * +.Fo getprogname +.Fa void +.Fc +.Ft void +.Fo setprogname +.Fa "const char *progname" +.Fc +.Sh DESCRIPTION +The +.Fn getprogname +function is used to obtain the program name. The program name is set at +program start-up, before +.Fn main +is called. Note, other operating systems, do not guarantee that a +program name has been set at start up time and therefore may return a +null pointer if +.Fn setprogname +has not been called. +.Lp +The +.Fn setprogname +function is used to change the program name to another value. The +argument +.Fa progname +must contain a null terminatd character string, whose last component +which will become the new program name. +.Sh RETURN VALUES +The +.Fn getprogname +function always returns the current program name. The program name is +always set, it will not return a null pointer. +.Sh INTERFACE STABILITY +.Sy Committed +.Sh MT-LEVEL +.Fn getprogname +is +.Sy MT-Safe . +.Lp +.Fn setprogname +is +.Sy Unsafe . +.Sh SEE ALSO +.Xr err 3c , +.Xr attributes 5 +.Sh NOTES +The use of +.Fn setprogname +does not modify the program name as reported by utilities like +.Xr ps 1 +or +.Xr pargs 1 ; +however, it does ensure a consistent program name for the +.Xr err 3C +family of functions.
--- a/usr/src/man/man3c/mbsrtowcs.3c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man3c/mbsrtowcs.3c Sun Jan 04 07:19:22 2015 -0800 @@ -10,7 +10,7 @@ .\" 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] .TH MBSRTOWCS 3C "Jun 28, 2014" .SH NAME -mbsnrtwocs, mbsnrtowcs_l, mbsrtowcs, mbsrtowcs_l \- convert a character string +mbsnrtowcs, mbsnrtowcs_l, mbsrtowcs, mbsrtowcs_l \- convert a character string to a wide-character string (restartable) .SH SYNOPSIS .LP
--- a/usr/src/man/man3c/memory.3c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man3c/memory.3c Sun Jan 04 07:19:22 2015 -0800 @@ -1,4 +1,5 @@ '\" te +.\" Copyright (c) 2014, Joyent, Inc. .\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved. .\" Copyright 1989 AT&T .\" 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. @@ -6,7 +7,7 @@ .\" 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] .TH MEMORY 3C "Feb 4, 2009" .SH NAME -memory, memccpy, memchr, memcmp, memcpy, memmove, memset \- memory operations +memory, memccpy, memchr, memcmp, memcpy, memmem, memmove, memset \- memory operations .SH SYNOPSIS .LP .nf @@ -33,6 +34,11 @@ .LP .nf +\fBvoid *\fR\fBmemmem\fR(\fBconst void *\fR\fIl\fR, \fBsize_t\fR \fIl_len\fR, \fBconst void *\fR\fIs\fR, \fBsize_t\fR \fIs_len\fR); +.fi + +.LP +.nf \fBvoid *\fR\fBmemmove\fR(\fBvoid *\fR\fIs1\fR, \fBconst void *\fR\fIs2\fR, \fBsize_t\fR \fIn\fR); .fi @@ -57,7 +63,6 @@ .fi .SH DESCRIPTION -.sp .LP These functions operate as efficiently as possible on memory areas (arrays of bytes bounded by a count, not terminated by a null character). They do not @@ -90,6 +95,13 @@ overlap, the behavior is undefined. .sp .LP +The \fBmemmem()\fR function searches for the \fIs_len\fR long byte pattern +\fIs\fR in the memory region starting at \fBl\fR for \fl_len\fR bytes. If a +match is found, a pointer to the starting location in \fIl\fR is returned. If no +match is found, \fIl_len\fR is zero, \fIs_len\fR is zero, or \fIl_len\fR is less +than \fIs_len\fR, then a null pointer is return. +.sp +.LP The \fBmemmove()\fR function copies \fIn\fR bytes from memory area \fIs2\fR to memory area \fIs1\fR. Copying between objects that overlap will take place correctly. It returns \fIs1\fR. @@ -99,12 +111,10 @@ to the value of \fIc\fR (converted to an \fBunsigned char\fR). It returns \fIs\fR. .SH USAGE -.sp .LP Using \fBmemcpy()\fR might be faster than using \fBmemmove()\fR if the application knows that the objects being copied do not overlap. .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -124,11 +134,9 @@ .TE .SH SEE ALSO -.sp .LP \fBstring\fR(3C), \fBattributes\fR(5), \fBstandards\fR(5) .SH NOTES -.sp .LP Overlap between objects being copied can arise even when their (virtual) address ranges appear to be disjoint; for example, as a result of
--- a/usr/src/man/man3c/realpath.3c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man3c/realpath.3c Sun Jan 04 07:19:22 2015 -0800 @@ -1,4 +1,5 @@ '\" te +.\" Copyright (c) 2014, Joyent, Inc. .\" Copyright 1989 AT&T. Copyright (c) 2003, Sun Microsystems, Inc. All Rights Reserved. Portions Copyright (c) 1992, X/Open Company Limited. All Rights Reserved. .\" Sun Microsystems, Inc. gratefully acknowledges The Open Group for permission to reproduce portions of its copyrighted documentation. Original documentation from The Open Group can be obtained online at .\" http://www.opengroup.org/bookstore/. @@ -7,7 +8,7 @@ .\" 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] -.TH REALPATH 3C "Oct 9, 2003" +.TH REALPATH 3C "Dec 20, 2014" .SH NAME realpath \- resolve pathname .SH SYNOPSIS @@ -17,10 +18,11 @@ \fBchar *\fR\fBrealpath\fR(\fBconst char *restrict\fR \fIfile_name\fR, \fBchar *restrict\fR \fIresolved_name\fR); + +\fBchar *\fR\fBcanonicalize_file_name\fR(\fBconst char *\fR\fIpath\fR); .fi .SH DESCRIPTION -.sp .LP The \fBrealpath()\fR function derives, from the pathname pointed to by \fIfile_name\fR, an absolute pathname that names the same file, whose @@ -28,15 +30,18 @@ generated pathname is stored as a null-terminated string, up to a maximum of {\fBPATH_MAX\fR} bytes (defined in \fBlimits.h\fR(3HEAD)), in the buffer pointed to by \fIresolved_name\fR. +.sp +.LP +The \fBcanonicalize_file_name()\fR function is equivalent to calling +\fBrealpath\fR(\fIpath\fR, \fINULL\fR). This function is only provided for +compatibility. .SH RETURN VALUES -.sp .LP On successful completion, \fBrealpath()\fR returns a pointer to the resolved name. Otherwise, \fBrealpath()\fR returns a null pointer and sets \fBerrno\fR to indicate the error, and the contents of the buffer pointed to by \fIresolved_name\fR are left in an indeterminate state. .SH ERRORS -.sp .LP The \fBrealpath()\fR function will fail if: .sp @@ -137,7 +142,6 @@ .RE .SH USAGE -.sp .LP The \fBrealpath()\fR function operates on null-terminated strings. .sp @@ -149,7 +153,6 @@ The \fBrealpath()\fR function might fail to return to the current directory if an error occurs. .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -167,7 +170,6 @@ .TE .SH SEE ALSO -.sp .LP \fBgetcwd\fR(3C), \fBlimits.h\fR(3HEAD), \fBsysconf\fR(3C), \fBattributes\fR(5), \fBstandards\fR(5)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/man/man3c/smt_pause.3c Sun Jan 04 07:19:22 2015 -0800 @@ -0,0 +1,38 @@ +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" +.\" Copyright (c) 2014, Joyent, Inc. +.\" +.Dd "Dec 22, 2014" +.Dt SMT_PAUSE 3C +.Os +.Sh NAME +.Nm smt_pause +.Nd hardware-aware busy wait +.Sh SYNOPSIS +.In synch.h +.Ft void +.Fo smt_pause +.Fa void +.Fc +.Sh DESCRIPTION +The +.Fn smt_pause +function performs a busy-wait for an implementation defined period of +time. On hardware platforms that support it, it notifies the hardware +that this is occurring in an effort to minimize resource usage. This is +commonly used in the implementation of spin loops. +.Sh INTERFACE STABILITY +.Sy Committed +.Sh MT-LEVEL +.Sy MT-Safe +.Sh SEE ALSO +.Xr attributes 5
--- a/usr/src/man/man3c/string.3c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man3c/string.3c Sun Jan 04 07:19:22 2015 -0800 @@ -1,5 +1,6 @@ '\" te .\" Copyright 2014 Garrett D'Amore <garrett@damore.org> +.\" Copyright (c) 2014, Joyent, Inc. .\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved. .\" Copyright 1989 AT&T .\" Portions Copyright (c) 1994 Man-cgi 1.15, Panagiotis Christias (christia@softlab.ntua.gr) @@ -12,12 +13,13 @@ .\" 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] -.TH STRING 3C "Jun 21, 2013" +.TH STRING 3C "Dec 20, 2014" .SH NAME string, strcasecmp, strcasecmp_l, strncasecmp, strncasecmp_l, strcat, strncat, -strlcat, strchr, strrchr, -strcmp, strncmp, strcpy, strncpy, strlcpy, strcspn, strspn, strdup, strlen, -strnlen, strpbrk, strsep, strstr, strtok, strtok_r \- string operations +strlcat, strchr, strchrnul, strrchr, strcmp, strncmp, stpcpy, stpncpy, strcpy, +strncpy, strlcpy, strcspn, strspn, strdup, strndup, strdupa, strndupa, strlen, +strnlen, strpbrk, strsep, strstr, strnstr, strcasestr, strtok, strtok_r \- +string operations .SH SYNOPSIS .LP .nf @@ -69,6 +71,14 @@ .fi .LP .nf +\fBchar *\fR\fBstpcpy\fR(\fBchar *restrict\fR \fIs1\fR, \fBconst char *restrict\fR \fIs2\fR); +.fi +.LP +.nf +\fBchar *\fR\fBstpncpy\fR(\fBchar *restrict\fR \fIs1\fR, \fBconst char *restrict\fR \fIs2\fR, \fBsize_t\fR \fIn\fR); +.fi +.LP +.nf \fBchar *\fR\fBstrcpy\fR(\fBchar *restrict\fR \fIs1\fR, \fBconst char *restrict\fR \fIs2\fR); .fi .LP @@ -93,6 +103,18 @@ .fi .LP .nf +\fBchar *\fR\fBstrndup\fR(\fBconst char *\fR\fIs1\fR, \fBsize_t\fR \fIn\fR); +.fi +.LP +.nf +\fBchar *\fR\fBstrdupa\fR(\fBconst char *\fR\fIs1\fR); +.fi +.LP +.nf +\fBchar *\fR\fBstrndupa\fR(\fBconst char *\fR\fIs1\fR, \fBsize_t\fR \fIn\fR); +.fi +.LP +.nf \fBsize_t\fR \fBstrlen\fR(\fBconst char *\fR\fIs\fR); .fi .LP @@ -113,6 +135,18 @@ .fi .LP .nf +\fBchar *\fR\fBstrnstr\fR(\fBconst char *\fR\fIs1\fR, \fBconst char *\fR\fIs2\fR, \fBsize_t\fR \fIn\fR); +.fi +.LP +.nf +\fBchar *\fR\fBstrcasestr\fR(\fBconst char *\fR\fIs1\fR, \fBconst char *\fR\fIs2\fR); +.fi +.LP +.nf +\fBchar *\fR\fBstrcasestr_l\fR(\fBconst char *\fR\fIs1\fR, \fBconst char *\fR\fIs2\fR, \fBlocale_t\fR \fIloc\fR); +.fi +.LP +.nf \fBchar *\fR\fBstrtok\fR(\fBchar *restrict\fR \fIs1\fR, \fBconst char *restrict\fR \fIs2\fR); .fi .LP @@ -129,6 +163,10 @@ .fi .LP .nf +\fBconst char *\fR\fBstrchrnul\fR(\fBconst char *\fR\fIs\fR, \fBint\fR \fIc\fR); +.fi +.LP +.nf \fBconst char *\fR\fBstrpbrk\fR(\fBconst char *\fR\fIs1\fR, \fBconst char *\fR\fIs2\fR); .fi .LP @@ -160,13 +198,13 @@ .SH DESCRIPTION .LP The arguments \fIs\fR, \fIs1\fR, and \fIs2\fR point to strings (arrays of -characters terminated by a null character). The \fBstrcat()\fR, -\fBstrncat()\fR, \fBstrlcat()\fR, \fBstrcpy()\fR, \fBstrncpy()\fR, -\fBstrlcpy()\fR, \fBstrsep()\fR, \fBstrtok()\fR, and \fBstrtok_r()\fR functions -all alter their first argument. Additionally, the \fBstrcat()\fR and -\fBstrcpy()\fR functions do not check for overflow of the array. +characters terminated by a null character). The \fBstrcat()\fR, \fBstrncat()\fR, +\fBstrlcat()\fR, \fBstrcpy()\fR, \fBstpcpy()\fR, \fBstpncpy()\fR, +\fBstrncpy()\fR, \fBstrlcpy()\fR, \fBstrsep()\fR, \fBstrtok()\fR, and +\fBstrtok_r()\fR functions all alter their first argument. Additionally, the +\fBstrcat()\fR, \fBstpcpy()\fR, and \fBstrcpy()\fR functions do not check for +overflow of the array. .SS "\fBstrcasecmp()\fR, \fBstrncasecmp()\fR" -.sp .LP The \fBstrcasecmp()\fR and \fBstrncasecmp()\fR functions are case-insensitive versions of \fBstrcmp()\fR and \fBstrncmp()\fR respectively, described below. @@ -220,13 +258,16 @@ return \(mi1; .fi .in -2 -.SS "\fBstrchr()\fR, \fBstrrchr()\fR" +.SS "\fBstrchr()\fR, \fBstrrchr()\fR, \fBstrchrnul()\fR" .LP The \fBstrchr()\fR function returns a pointer to the first occurrence of \fIc\fR (converted to a \fBchar\fR) in string \fIs\fR, or a null pointer if \fIc\fR does not occur in the string. The \fBstrrchr()\fR function returns a pointer to the last occurrence of \fIc\fR. The null character terminating a -string is considered to be part of the string. +string is considered to be part of the string. The \fBstrchrnul()\fR function +behaves similarly to \fBstrchr()\fR, except when the character \fBc\fR is not +found, it returns a pointer to the null terminator of the string \fBs\fR and not +a null pointer. .SS "\fBstrcmp()\fR, \fBstrncmp()\fR" .LP The \fBstrcmp()\fR function compares two strings byte-by-byte, according to the @@ -260,23 +301,35 @@ return \(mi1; .fi .in -2 - +.SS "\fBstpcpy()\fR, \fBstpncpy()\fR" +.LP +The \fBstpcpy()\fR and \fBstpncpy()\fR functions behave identically to +\fBstrcpy()\fR and \fBstrncpy()\fR respectively; however, instead of returning a +pointer to the beginning of \fIs1\fR, they return a pointer to the terminating +null character. .SS "\fBstrcspn()\fR, \fBstrspn()\fR" .LP The \fBstrcspn()\fR function returns the length of the initial segment of string \fIs1\fR that consists entirely of characters not from string \fIs2\fR. The \fBstrspn()\fR function returns the length of the initial segment of string \fIs1\fR that consists entirely of characters from string \fIs2\fR. -.SS "\fBstrdup()\fR" +.SS "\fBstrdup()\fR, \fBstrndup()\fR, \fBstrdupa()\fR, \fBstrndupa()\fR" .LP The \fBstrdup()\fR function returns a pointer to a new string that is a duplicate of the string pointed to by \fIs1\fR. The returned pointer can be passed to \fBfree()\fR. The space for the new string is obtained using \fBmalloc\fR(3C). If the new string cannot be created, a null pointer is returned and \fBerrno\fR may be set to \fBENOMEM\fR to indicate that the -storage space available is insufficient. +storage space available is insufficient. The \fBstrndup()\fR function is +identical to \fBstrdup()\fR, execept it copies at most \fIn\fR bytes from +\fBs1\fR and ensures the copied string is awlays null terminated. +.LP +The functions \fBstrdupa()\fR and \fBstrndupa()\fR behave identically to +\fBstrdup()\fr and \fBstrndup()\fR respectively; however, instead of allocating +memory using \fBmalloc\fR(3C), they use \fBalloca\fR(3C). These functions are +provided for compatibility only, their use is strongly discouraged due to their +use of \fBalloca\fR(3C). .SS "\fBstrlen()\fR, \fBstrnlen()\fR" -.sp The \fBstrlen()\fR function returns the number of bytes in \fIs\fR, not including the terminating null character. .LP @@ -303,13 +356,22 @@ \fBstrsep()\fR to `\e0'. .LP If *\fIstringp\fR is initially \fINULL\fR, \fBstrsep()\fR returns \fINULL\fR. -.SS "\fBstrstr()\fR" +.SS "\fBstrstr()\fR, \fBstrnstr()\fR, \fBstrcasestr()\fR, \fBstrcasestr_l()\fR" .LP The \fBstrstr()\fR function locates the first occurrence of the string \fIs2\fR (excluding the terminating null character) in string \fIs1\fR and returns a pointer to the located string, or a null pointer if the string is not found. If \fIs2\fR points to a string with zero length (that is, the string \fB""\fR), -the function returns \fIs1\fR. +the function returns \fIs1\fR. The \fBstrnstr()\fR function performs the same +search as \fBstrstr()\fR, but only considers up to \fIn\fR bytes of \fIs1\fR. +Bytes following a null byte are not compared. +.sp +.LP +The \fBstrcasestr()\fR and \fBstrcasestr_l()\fR functions are similar to +\fBstrstr()\fR, but both functions ignore the case of both \fBs1\fR and +\fBs2\fR. Where as the \fBstrcasestr()\fR function operates in the current +locale, the \fBstrcasestr_l()\fR function operates in the locale specified by +\fIloc\fR. .SS "\fBstrtok()\fR" .LP A sequence of calls to \fBstrtok()\fR breaks the string pointed to by \fIs1\fR @@ -487,8 +549,8 @@ \fBstrlcat()\fR, \fBstrlcpy()\fR, and \fBstrsep()\fR functions are Committed. All the rest are Standard. .LP -The \fBstrtok()\fR and \fBstrdup()\fR functions are MT-Safe. The remaining -functions are Async-Signal-Safe. +The \fBstrtok()\fR, \fBstrdup()\fR, and \fBstrndup()\fR functions are MT-Safe. +The remaining functions are Async-Signal-Safe. .LP For all except \fBstrlcat()\fR, \fBstrlcpy()\fR, and \fBstrsep()\fR, see \fBstandards\fR(5).
--- a/usr/src/man/man3c/unsetenv.3c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man3c/unsetenv.3c Sun Jan 04 07:19:22 2015 -0800 @@ -8,7 +8,7 @@ .\" 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] -.TH UNSETENV 3C "Nov 1, 2003" +.TH UNSETENV 3C "Dec 20, 2014" .SH NAME unsetenv \- remove an environment variable .SH SYNOPSIS @@ -20,7 +20,6 @@ .fi .SH DESCRIPTION -.sp .LP The \fBunsetenv()\fR function removes an environment variable from the environment of the calling process. The \fIname\fR argument points to a string @@ -34,12 +33,10 @@ the behavior of \fBunsetenv()\fR is undefined. The \fBunsetenv()\fR function updates the list of pointers to which \fIenviron\fR points. .SH RETURN VALUES -.sp .LP Upon successful completion, 0 is returned. Otherwise, -1 is returned, \fBerrno\fR set to indicate the error, and the environment is left unchanged. .SH ERRORS -.sp .LP The \fBunsetenv()\fR function will fail if: .sp @@ -53,7 +50,6 @@ .RE .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -71,6 +67,6 @@ .TE .SH SEE ALSO -.sp .LP -\fBgetenv\fR(3C), \fBsetenv\fR(3C), \fBattributes\fR(5), \fBstandards\fR(5) +\fBclearenv\fR(3C), \fBgetenv\fR(3C), \fBsetenv\fR(3C), \fBattributes\fR(5), +\fBstandards\fR(5)
--- a/usr/src/man/man3lib/libc.3lib Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man3lib/libc.3lib Sun Jan 04 07:19:22 2015 -0800 @@ -156,13 +156,15 @@ \fBbsearch\fR \fBbtowc\fR \fBbtowc_l\fR \fBbzero\fR \fBcalloc\fR +\fBcanonicalize_file_name\fR \fBcatclose\fR \fBcatgets\fR \fBcatopen\fR \fBcfgetispeed\fR \fBcfgetospeed\fR \fBcfsetispeed\fR \fBcfsetospeed\fR \fBcftime\fR \fBchdir\fR \fBchmod\fR \fBchown\fR \fBchroot\fR -\fBclearerr\fR \fBclock\fR +\fBclearerr\fR \fBclearenv\fR +\fBclock\fR \fBclock_getres\fR \fBclock_gettime\fR \fBclock_nanosleep\fR \fBclock_settime\fR \fBclose\fR \fBclosedir\fR @@ -223,14 +225,16 @@ \fBfchmod\fR \fBfchmodat\fR \fBfchown\fR \fBfchownat\fR \fBfchroot\fR \fBfclose\fR -\fBfcntl\fR \fBfconvert\fR -\fBfcvt\fR \fBfdatasync\fR -\fBfdetach\fR +\fBfcloseall\fR \fBfcntl\fR +\fBfconvert\fR \fBfcvt\fR +\fBfdatasync\fR \fBfdetach\fR \fBfdopen\fR \fBfdopendir\fR \fBfdwalk\fR \fBfeof\fR \fBferror\fR \fBfflush\fR -\fBffs\fR \fBfgetattr\fR -\fBfgetc\fR +\fBffs\fR \fBffsl\fR +\fBffsll\fR \fBfls\fR +\fBflsl\fR \fBflsll\fR +\fBfgetattr\fR \fBfgetc\fR \fBfgetgrent\fR \fBfgetgrent_r\fR \fBfgetpos\fR \fBfgetpwent\fR \fBfgetpwent_r\fR \fBfgets\fR @@ -287,6 +291,7 @@ \fBgetloadavg\fR \fBgetlogin\fR \fBgetlogin_r\fR \fBgetmntany\fR \fBgetmntent\fR \fBgetmsg\fR +\fBget_nprocs\fR \fBget_nprocs_conf\fR \fBgetnetgrent\fR \fBgetnetgrent_r\fR \fBgetopt\fR \fBgetopt_clip\fR \fBgetopt_long\fR \fBgetopt_long_only\fR @@ -296,7 +301,8 @@ \fBgetpgid\fR \fBgetpgrp\fR \fBgetpid\fR \fBgetpmsg\fR \fBgetppid\fR \fBgetppriv\fR -\fBgetpriority\fR \fBgetprojid\fR +\fBgetpriority\fR \fbgetprogname\fR +\fBgetprojid\fR \fBgetpw\fR \fBgetpwent\fR \fBgetpwent_r\fR \fBgetpwnam\fR \fBgetpwnam_r\fR \fBgetpwuid\fR @@ -381,8 +387,7 @@ \fBldivide\fR \fBlexp10\fR \fBlfind\fR \fBlfmt\fR \fBlink\fR \fBlinkat\fR -\fBlio_listio\fR -\fBllabs\fR +\fBlio_listio\fR \fBllabs\fR \fBlldiv\fR \fBllog10\fR \fBllseek\fR \fBlltostr\fR \fBlocaleconv\fR \fBlocaltime\fR @@ -408,7 +413,8 @@ \fBmembar_producer\fR \fBmemccpy\fR \fBmemchr\fR \fBmemcmp\fR \fBmemcntl\fR \fBmemcpy\fR -\fBmeminfo\fR \fBmemmove\fR +\fBmeminfo\fR \fBmemmem\fR +\fBmemmove\fR \fBmemset\fR \fBmincore\fR \fBmkdir\fR \fBmkdirat\fR \fBmkfifo\fR \fBmkfifoat\fR @@ -577,8 +583,8 @@ \fBrctlblk_set_value\fR \fBrctlblk_size\fR \fBre_comp\fR \fBre_exec\fR \fBread\fR \fBreaddir\fR -\fBreaddir_r\fR -\fBreadlink\fR \fBreadlinkat\fR +\fBreaddir_r\fR \fBreadlink\fR +\fBreadlinkat\fR \fBreadv\fR \fBrealloc\fR \fBrealpath\fR \fBreboot\fR \fBregcmp\fR \fBregcomp\fR @@ -628,7 +634,8 @@ \fBsetlogmask\fR \fBsetnetgrent\fR \fBsetpflags\fR \fBsetpgid\fR \fBsetpgrp\fR \fBsetppriv\fR -\fBsetpriority\fR \fBsetpwent\fR +\fBsetpriority\fR \fBsetprogname\fR +\fBsetpwent\fR \fBsetrctl\fR \fBsetregid\fR \fBsetreuid\fR \fBsetrlimit\fR \fBsetsid\fR \fBsetspent\fR @@ -656,7 +663,8 @@ \fBsigstack\fR \fBsigsuspend\fR \fBsigtimedwait\fR \fBsigwait\fR \fBsigwaitinfo\fR \fBsingle_to_decimal\fR -\fBsleep\fR \fBsnprintf\fR +\fBsleep\fR \fBsmt_pause\fR +\fBsnprintf\fR \fBsprintf\fR \fBsrand\fR \fBsrand48\fR \fBsrandom\fR \fBsscanf\fR \fBssignal\fR @@ -675,10 +683,10 @@ \fBstrftime\fR \fBstrftime_l\fR \fBstring_to_decimal\fR \fBstrlcat\fR \fBstrlcpy\fR -\fBstrlen\fR -\fBstrncasecmp\fR \fBstrncasecmp_l\fR -\fBstrncat\fR \fBstrncmp\fR -\fBstrncpy\fR \fBstrpbrk\fR +\fBstrlen\fR \fBstrncasecmp\fR +\fBstrncasecmp_l\fR \fBstrncat\fR +\fBstrncmp\fR \fBstrncpy\fR +\fBstrnstr\fR \fBstrpbrk\fR \fBstrptime\fR \fBstrptime_l\fR \fBstrrchr\fR \fBstrsep\fR \fBstrsignal\fR \fBstrspn\fR @@ -691,8 +699,7 @@ \fBstrtows\fR \fBstrxfrm\fR \fBswab\fR \fBswapcontext\fR \fBswapctl\fR \fBswprintf\fR -\fBswscanf\fR -\fBsymlink\fR +\fBswscanf\fR \fBsymlink\fR \fBsymlinkat\fR \fBsync\fR \fBsync_instruction_memory\fR \fBsysconf\fR \fBsysfs\fR @@ -1014,13 +1021,13 @@ \fBgetpwent()\fR with completely different semantics. Standard-conforming applications may not define and use function names with leading underscores. .LP -Solaris system libraries are now built with direct binding. This means that a +illumos system libraries are now built with direct binding. This means that a system library that calls \fBgetpwent()\fR will bind directly to the instance of \fBgetpwent()\fR in \fBlibc\fR, even if the application to which it is linked defines a different \fBgetpwent()\fR for its own use. The application binds to its instance of \fBgetpwent()\fR and there is no resulting conflict. The direct binding mechanism is equally available to libraries not delivered -with Solaris. +with illumos. .LP As a result of this evolution, most of the leading-underscore synonym symbols have been removed from \fBlibc\fR. This means that applications that call
--- a/usr/src/man/man5/ipfilter.5 Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man5/ipfilter.5 Sun Jan 04 07:19:22 2015 -0800 @@ -2,11 +2,11 @@ .\" To view license terms, attribution, and copyright for IP Filter, the default path is /usr/lib/ipf/IPFILTER.LICENCE. If the Solaris operating environment has been installed anywhere other than the default, modify the given path to access the file at the installed .\" location. .\" Portions Copyright (c) 2009, Sun Microsystems Inc. All Rights Reserved. -.TH IPFILTER 5 "May 20, 2009" +.\" Portions Copyright (c) 2014, Joyent, Inc. All Rights Reserved. +.TH IPFILTER 5 "Oct 7, 2014" .SH NAME ipfilter \- IP packet filtering software .SH DESCRIPTION -.sp .LP IP Filter is software that provides packet filtering capabilities on a Solaris system. On a properly setup system, it can be used to build a firewall. @@ -16,7 +16,6 @@ packet filtering is not enabled by default. See \fBipf\fR(1M) for a procedure to enable and activate the IP Filter feature. .SH HOST-BASED FIREWALL -.sp .LP To simplify IP Filter configuration management, a firewall framework is created to allow users to configure IP Filter by expressing firewall policy at system @@ -34,14 +33,13 @@ advantage of the framework. See \fBipf\fR(1M) and \fBipf\fR(4). .RE .SS "Model" -.sp .LP This section describes the host-based firewall framework. See svc.ipfd(1M) for details on how to configure firewall policies. .sp .LP -A three-layer approach with different precedence levels helps the user achieve -the desired behaviors. +In a given zone, a three-layer approach with different precedence levels helps +the user achieve the desired behaviors. .sp .ne 2 .na @@ -127,7 +125,6 @@ .RE .SS "Layers in Detail" -.sp .LP The first system-wide layer, Global Default, defines a firewall policy that applies to \fBany\fR incoming traffic, for example, allowing or blocking all @@ -157,7 +154,6 @@ network services. The example is when it is desirable to block known malicious source(s) regardless of services' policies. .SS "User Interaction" -.sp .LP This framework leverages IP Filter functionality and is active only when \fBsvc:/network/ipfilter\fR is enabled and inactive when \fBnetwork/ipfilter\fR @@ -207,9 +203,94 @@ .el o changes to system-wide or per-service firewall policy results in an update to the system's firewall rules -.RE + +.SS "In-Zone and Global Zone Controlled firewalls" +.LP +Each non-global zone in the system can potentially have two firewalls +configured: the in-zone firewall and the Global Zone controlled (GZ-controlled) +firewall. The in-zone firewall can be controlled and observed inside the zone +using the framework detailed above, or from the Global Zone. The GZ-controlled +firewall can only be controlled and observed from the Global Zone. The +GZ-controlled firewall is always "outermost" with respect to the zone. +.sp +.LP +For inbound traffic (from an external source to the zone), the traffic flow looks +like the following diagram. Traffic blocked by the GZ-controlled firewall will +not be processed by the in-zone firewall. +.sp +.in +2 +.nf + External Source + | + | +GZ-controlled Firewall + | + | + In-Zone Firewall + | + | + Zone +.fi +.in -2 +.sp +.LP +For outbound traffic (from the zone to an external destination), the traffic +flow looks like the following diagram. Traffic blocked by the in-zone firewall +will not be processed by the GZ-controlled firewall. +.sp +.in +2 +.nf + Zone + | + | + In-Zone Firewall + | + | +GZ-controlled Firewall + | + | + External Destination +.fi +.in -2 +.sp +.LP +Either of the in-Zone or GZ-controlled firewalls can be enabled, or both at the +same time. +.sp +.LP +The Global Zone does not have a GZ-controlled firewall, only an +in-zone firewall. For inbound traffic (from an external source to the global +zone), the traffic flow therefore looks like the following diagram. +.sp +.in +2 +.nf + External Source + | + | + In-Zone Firewall + | + | + Zone +.fi +.in -2 +.sp +.LP +For outbound traffic (from the global zone to an external destination), the +traffic flow looks like the following diagram. +.sp +.in +2 +.nf + Zone + | + | + In-Zone Firewall + | + | + External Destination +.fi +.in -2 + .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for a description of the following attributes: .sp @@ -225,7 +306,6 @@ .TE .SH SEE ALSO -.sp .LP \fBsvcs\fR(1), \fBipf\fR(1M), \fBipnat\fR(1M), \fBsvcadm\fR(1M), \fBsvc.ipfd\fR(1M), \fBipf\fR(4), \fBipnat\fR(4), \fBattributes\fR(5), @@ -234,7 +314,6 @@ .LP \fISystem Administration Guide: IP Services\fR .SH NOTES -.sp .LP The \fBipfilter\fR service is managed by the service management facility, \fBsmf\fR(5), under the service identifier:
--- a/usr/src/man/man9f/Intro.9f Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man9f/Intro.9f Sun Jan 04 07:19:22 2015 -0800 @@ -61,25 +61,29 @@ the kernel. In a block device driver, the .Xr strategy 9E entry point may be -called by the page daemon to write pages to the device. The page daemon has no +called by the page daemon to write pages to the device. +The page daemon has no relation to the current user thread, so in this case .Xr strategy 9E has kernel context. .Lp .Em Interrupt context is kernel context, but also has an interrupt level -associated with it. Driver interrupt routines have interrupt context. +associated with it. +Driver interrupt routines have interrupt context. .Lp Note that a mutex acquired in user or kernel context that can also be acquired in interrupt context means that the user or kernel context thread holding that mutex is subject to all the restrictions imposed by interrupt context, for the -duration of the ownership of that mutex. Please see the +duration of the ownership of that mutex. +Please see the .Xr mutex 9F man page for a more complete discussion of proper mutex handling for drivers. .Lp .Em High-level interrupt context is a more restricted form of interrupt -context. If a driver interrupt priority returned from +context. +If a driver interrupt priority returned from .Xr ddi_intr_get_pri 9F is greater than the priority returned from .Xr ddi_intr_get_hilevel_pri 9F @@ -117,7 +121,7 @@ .It Sy Routine Sy Type .It Sy adjmsg DDI/DKI .It Sy allocb DDI/DKI -.It Sy allocb_tmpl Solaris DDI +.It Sy allocb_tmpl illumos DDI .It Sy backq DDI/DKI .It Sy bcanput DDI/DKI .It Sy bcanputnext DDI/DKI @@ -127,10 +131,10 @@ .It Sy clrbuf DDI/DKI .It Sy copyb DDI/DKI .It Sy copymsg DDI/DKI -.It Sy DB_BASE Solaris DDI -.It Sy DB_LIM Solaris DDI -.It Sy DB_REF Solaris DDI -.It Sy DB_TYPE Solaris DDI +.It Sy DB_BASE illumos DDI +.It Sy DB_LIM illumos DDI +.It Sy DB_REF illumos DDI +.It Sy DB_TYPE illumos DDI .It Sy datamsg DDI/DKI .It Sy dupb DDI/DKI .It Sy dupmsg DDI/DKI @@ -143,28 +147,28 @@ .It Sy freemsg DDI/DKI .It Sy freezestr DDI/DKI .It Sy getq DDI/DKI -.It Sy IOC_CONVERT_FROM Solaris DDI +.It Sy IOC_CONVERT_FROM illumos DDI .It Sy insq DDI/DKI .It Sy linkb DDI/DKI -.It Sy MBLKHEAD Solaris DDI -.It Sy MBLKIN Solaris DDI -.It Sy MBLKL Solaris DDI -.It Sy MBLKSIZE Solaris DDI -.It Sy MBLKTAIL Solaris DDI -.It Sy mcopyin Solaris DDI -.It Sy mcopymsg Solaris DDI -.It Sy mcopyout Solaris DDI -.It Sy merror Solaris DDI -.It Sy mexchange Solaris DDI -.It Sy mioc2ack Solaris DDI -.It Sy miocack Solaris DDI -.It Sy mexchange Solaris DDI -.It Sy miocpullup Solaris DDI -.It Sy mkiocb Solaris DDI +.It Sy MBLKHEAD illumos DDI +.It Sy MBLKIN illumos DDI +.It Sy MBLKL illumos DDI +.It Sy MBLKSIZE illumos DDI +.It Sy MBLKTAIL illumos DDI +.It Sy mcopyin illumos DDI +.It Sy mcopymsg illumos DDI +.It Sy mcopyout illumos DDI +.It Sy merror illumos DDI +.It Sy mexchange illumos DDI +.It Sy mioc2ack illumos DDI +.It Sy miocack illumos DDI +.It Sy mexchange illumos DDI +.It Sy miocpullup illumos DDI +.It Sy mkiocb illumos DDI .It Sy msgdsize DDI/DKI .It Sy msgpullup DDI/DKI -.It Sy msgsize Solaris DDI -.It Sy mt-streams Solaris DDI +.It Sy msgsize illumos DDI +.It Sy mt-streams illumos DDI .It Sy noenable DDI/DKI .It Sy OTHERQ DDI/DKI .It Sy pullupmsg DDI/DKI @@ -175,19 +179,19 @@ .It Sy putnext DDI/DKI .It Sy putnextctl DDI/DKI .It Sy putq DDI/DKI -.It Sy qassociate Solaris DDI -.It Sy qbufcall Solaris DDI +.It Sy qassociate illumos DDI +.It Sy qbufcall illumos DDI .It Sy qenable DDI/DKI .It Sy qprocson DDI/DKI .It Sy qprocsoff DDI/DKI .It Sy qreply DDI/DKI .It Sy qsize DDI/DKI -.It Sy qtimeout Solaris DDI -.It Sy qunbufcall Solaris DDI -.It Sy quntimeout Solaris DDI -.It Sy qwait Solaris DDI -.It Sy qwait_sig Solaris DDI -.It Sy qwriter Solaris DDI +.It Sy qtimeout illumos DDI +.It Sy qunbufcall illumos DDI +.It Sy quntimeout illumos DDI +.It Sy qwait illumos DDI +.It Sy qwait_sig illumos DDI +.It Sy qwriter illumos DDI .It Sy RD DDI/DKI .It Sy rmvb DDI/DKI .It Sy rmvq DDI/DKI @@ -206,8 +210,8 @@ .Bl -column usb_pipe_get_max_bulk_transfer_size .It Sy Routine Sy Type .It Sy ASSERT DDI/DKI -.It Sy anocancel Solaris DDI -.It Sy aphysio Solaris DDI +.It Sy anocancel illumos DDI +.It Sy aphysio illumos DDI .It Sy atomic_add DDI/DKI .It Sy atomic_and DDI/DKI .It Sy atomic_bits DDI/DKI @@ -219,14 +223,14 @@ .It Sy atomic_swap DDI/DKI .It Sy bcmp DDI/DKI .It Sy bcopy DDI/DKI -.It Sy bioclone Solaris DDI +.It Sy bioclone illumos DDI .It Sy biodone DDI/DKI -.It Sy biofini Solaris DDI -.It Sy bioinit Solaris DDI -.It Sy biomodified Solaris DDI -.It Sy biosize Solaris DDI -.It Sy bioerror Solaris DDI -.It Sy bioreset Solaris DDI +.It Sy biofini illumos DDI +.It Sy bioinit illumos DDI +.It Sy biomodified illumos DDI +.It Sy biosize illumos DDI +.It Sy bioerror illumos DDI +.It Sy bioreset illumos DDI .It Sy biowait DDI/DKI .It Sy bp_copyin DDI/DKI .It Sy bp_copyout DDI/DKI @@ -236,543 +240,545 @@ .It Sy btopr DDI/DKI .It Sy bzero DDI/DKI .It Sy cmn_err DDI/DKI -.It Sy condvar Solaris DDI +.It Sy condvar illumos DDI .It Sy copyin DDI/DKI .It Sy copyout DDI/DKI -.It Sy cv_broadcast Solaris DDI -.It Sy cv_destroy Solaris DDI -.It Sy cv_init Solaris DDI -.It Sy cv_signal Solaris DDI -.It Sy cv_timedwait Solaris DDI -.It Sy cv_wait Solaris DDI -.It Sy cv_wait_sig Solaris DDI -.It Sy ddi_add_event_handler Solaris DDI -.It Sy ddi_add_intr Solaris DDI -.It Sy ddi_add_softintr Solaris DDI -.It Sy ddi_binding_name Solaris DDI -.It Sy ddi_btop Solaris DDI -.It Sy ddi_btopr Solaris DDI -.It Sy ddi_can_receive_sig Solaris DDI -.It Sy ddi_check_acc_handle Solaris DDI -.It Sy ddi_copyin Solaris DDI -.It Sy ddi_copyout Solaris DDI -.It Sy ddi_create_minor_node Solaris DDI -.It Sy ddi_cred Solaris DDI -.It Sy ddi_dev_is_sid Solaris DDI -.It Sy ddi_dev_nintrs Solaris DDI -.It Sy ddi_dev_nregs Solaris DDI -.It Sy ddi_dev_regsize Solaris DDI -.It Sy ddi_device_copy Solaris DDI -.It Sy ddi_device_zero Solaris DDI -.It Sy ddi_devmap_segmap Solaris DDI -.It Sy ddi_dma_addr_bind_handle Solaris DDI -.It Sy ddi_dma_alloc_handle Solaris DDI -.It Sy ddi_dma_buf_bind_handle Solaris DDI -.It Sy ddi_dma_burstsizes Solaris DDI -.It Sy ddi_dma_free_handle Solaris DDI -.It Sy ddi_dma_getwin Solaris DDI -.It Sy ddi_dma_mem_alloc Solaris DDI -.It Sy ddi_dma_mem_free Solaris DDI -.It Sy ddi_dma_nextcookie Solaris DDI -.It Sy ddi_dma_numwin Solaris DDI -.It Sy ddi_dma_set_sbus64 Solaris DDI -.It Sy ddi_dma_sync Solaris DDI -.It Sy ddi_dma_unbind_handle Solaris DDI -.It Sy ddi_dmae Solaris x86 DDI -.It Sy ddi_dmae_1stparty Solaris x86 DDI -.It Sy ddi_dmae_alloc Solaris x86 DDI -.It Sy ddi_dmae_disable Solaris x86 DDI -.It Sy ddi_dmae_enable Solaris x86 DDI -.It Sy ddi_dmae_getattr Solaris x86 DDI -.It Sy ddi_dmae_getcnt Solaris x86 DDI -.It Sy ddi_dmae_getlim Solaris x86 DDI -.It Sy ddi_dmae_prog Solaris x86 DDI -.It Sy ddi_dmae_release Solaris x86 DDI -.It Sy ddi_dmae_stop Solaris x86 DDI -.It Sy ddi_driver_major Solaris DDI -.It Sy ddi_driver_name Solaris DDI -.It Sy ddi_enter_critical Solaris DDI -.It Sy ddi_exit_critical Solaris DDI -.It Sy ddi_ffs Solaris DDI -.It Sy ddi_fls Solaris DDI -.It Sy ddi_fm_acc_err_clear Solaris DDI -.It Sy ddi_fm_acc_err_get Solaris DDI -.It Sy ddi_fm_ereport_post Solaris DDI -.It Sy ddi_fm_handler_register Solaris DDI -.It Sy ddi_fm_init Solaris DDI -.It Sy ddi_fm_service_impact Solaris DDI -.It Sy ddi_get16 Solaris DDI -.It Sy ddi_get32 Solaris DDI -.It Sy ddi_get64 Solaris DDI -.It Sy ddi_get8 Solaris DDI -.It Sy ddi_get_cred Solaris DDI -.It Sy ddi_get_devstate Solaris DDI -.It Sy ddi_get_driver_private Solaris DDI -.It Sy ddi_get_eventcookie Solaris DDI -.It Sy ddi_get_iblock_cookie Solaris DDI -.It Sy ddi_get_iminor Solaris DDI -.It Sy ddi_get_instance Solaris DDI -.It Sy ddi_get_kt_did Solaris DDI -.It Sy ddi_get_lbolt Solaris DDI -.It Sy ddi_get_name Solaris DDI -.It Sy ddi_get_parent Solaris DDI -.It Sy ddi_get_pid Solaris DDI -.It Sy ddi_get_soft_iblock_cookie Solaris DDI -.It Sy ddi_get_soft_state Solaris DDI -.It Sy ddi_getb Solaris DDI -.It Sy ddi_getl Solaris DDI -.It Sy ddi_getll Solaris DDI -.It Sy ddi_getlongprop Solaris DDI -.It Sy ddi_getlongprop_buf Solaris DDI -.It Sy ddi_getprop Solaris DDI -.It Sy ddi_getproplen Solaris DDI -.It Sy ddi_getw Solaris DDI -.It Sy ddi_intr_add_handler Solaris DDI -.It Sy ddi_intr_add_softint Solaris DDI -.It Sy ddi_intr_alloc Solaris DDI -.It Sy ddi_intr_block_disable Solaris DDI -.It Sy ddi_intr_block_enable Solaris DDI -.It Sy ddi_intr_clr_mask Solaris DDI -.It Sy ddi_intr_dup_handler Solaris DDI -.It Sy ddi_intr_disable Solaris DDI -.It Sy ddi_intr_enable Solaris DDI -.It Sy ddi_intr_free Solaris DDI -.It Sy ddi_intr_get_cap Solaris DDI -.It Sy ddi_intr_get_hilevel_pri Solaris DDI -.It Sy ddi_intr_get_navail Solaris DDI -.It Sy ddi_intr_get_nintrs Solaris DDI -.It Sy ddi_intr_get_pending Solaris DDI -.It Sy ddi_intr_get_pri Solaris DDI -.It Sy ddi_intr_get_softint_pri Solaris DDI -.It Sy ddi_intr_get_supported_types Solaris DDI -.It Sy ddi_intr_remove_handler Solaris DDI -.It Sy ddi_intr_remove_softint Solaris DDI -.It Sy ddi_intr_set_cap Solaris DDI -.It Sy ddi_intr_set_mask Solaris DDI -.It Sy ddi_intr_set_pri Solaris DDI -.It Sy ddi_intr_set_softint_pri Solaris DDI -.It Sy ddi_intr_trigger_softint Solaris DDI -.It Sy ddi_io_get16 Solaris DDI -.It Sy ddi_io_get32 Solaris DDI -.It Sy ddi_io_get8 Solaris DDI -.It Sy ddi_io_getb Solaris DDI -.It Sy ddi_io_getl Solaris DDI -.It Sy ddi_io_getw Solaris DDI -.It Sy ddi_io_put16 Solaris DDI -.It Sy ddi_io_put32 Solaris DDI -.It Sy ddi_io_put8 Solaris DDI -.It Sy ddi_io_putb Solaris DDI -.It Sy ddi_io_putl Solaris DDI -.It Sy ddi_io_putw Solaris DDI -.It Sy ddi_io_rep_get16 Solaris DDI -.It Sy ddi_io_rep_get32 Solaris DDI -.It Sy ddi_io_rep_get8 Solaris DDI -.It Sy ddi_io_rep_getb Solaris DDI -.It Sy ddi_io_rep_getl Solaris DDI -.It Sy ddi_io_rep_getw Solaris DDI -.It Sy ddi_io_rep_put16 Solaris DDI -.It Sy ddi_io_rep_put32 Solaris DDI -.It Sy ddi_io_rep_put8 Solaris DDI -.It Sy ddi_io_rep_putb Solaris DDI -.It Sy ddi_io_rep_putl Solaris DDI -.It Sy ddi_io_rep_putw Solaris DDI -.It Sy ddi_iomin Solaris DDI -.It Sy ddi_log_sysevent Solaris DDI -.It Sy ddi_map_regs Solaris DDI -.It Sy ddi_mapdev Solaris DDI -.It Sy ddi_mapdev_intercept Solaris DDI -.It Sy ddi_mapdev_nointercept Solaris DDI -.It Sy ddi_mapdev_set_device_acc_attr Solaris DDI -.It Sy ddi_mem_get16 Solaris DDI -.It Sy ddi_mem_get32 Solaris DDI -.It Sy ddi_mem_get64 Solaris DDI -.It Sy ddi_mem_get8 Solaris DDI -.It Sy ddi_mem_getb Solaris DDI -.It Sy ddi_mem_getl Solaris DDI -.It Sy ddi_mem_getll Solaris DDI -.It Sy ddi_mem_getw Solaris DDI -.It Sy ddi_mem_put16 Solaris DDI -.It Sy ddi_mem_put32 Solaris DDI -.It Sy ddi_mem_put64 Solaris DDI -.It Sy ddi_mem_put8 Solaris DDI -.It Sy ddi_mem_putb Solaris DDI -.It Sy ddi_mem_putl Solaris DDI -.It Sy ddi_mem_putll Solaris DDI -.It Sy ddi_mem_putw Solaris DDI -.It Sy ddi_mem_rep_get16 Solaris DDI -.It Sy ddi_mem_rep_get32 Solaris DDI -.It Sy ddi_mem_rep_get64 Solaris DDI -.It Sy ddi_mem_rep_get8 Solaris DDI -.It Sy ddi_mem_rep_getb Solaris DDI -.It Sy ddi_mem_rep_getl Solaris DDI -.It Sy ddi_mem_rep_getll Solaris DDI -.It Sy ddi_mem_rep_getw Solaris DDI -.It Sy ddi_mem_rep_put16 Solaris DDI -.It Sy ddi_mem_rep_put32 Solaris DDI -.It Sy ddi_mem_rep_put64 Solaris DDI -.It Sy ddi_mem_rep_put8 Solaris DDI -.It Sy ddi_mem_rep_putb Solaris DDI -.It Sy ddi_mem_rep_putl Solaris DDI -.It Sy ddi_mem_rep_putll Solaris DDI -.It Sy ddi_mem_rep_putw Solaris DDI -.It Sy ddi_mmap_get_model Solaris DDI -.It Sy ddi_model_convert_from Solaris DDI -.It Sy ddi_modopen Solaris DDI -.It Sy ddi_no_info Solaris DDI -.It Sy ddi_node_name Solaris DDI -.It Sy ddi_peek16 Solaris DDI -.It Sy ddi_peek32 Solaris DDI -.It Sy ddi_peek64 Solaris DDI -.It Sy ddi_peek8 Solaris DDI -.It Sy ddi_peekc Solaris DDI -.It Sy ddi_peekd Solaris DDI -.It Sy ddi_peekl Solaris DDI -.It Sy ddi_peeks Solaris DDI -.It Sy ddi_periodic_add Solaris DDI -.It Sy ddi_periodic_delete Solaris DDI -.It Sy ddi_poke16 Solaris DDI -.It Sy ddi_poke32 Solaris DDI -.It Sy ddi_poke64 Solaris DDI -.It Sy ddi_poke8 Solaris DDI -.It Sy ddi_pokec Solaris DDI -.It Sy ddi_poked Solaris DDI -.It Sy ddi_pokel Solaris DDI -.It Sy ddi_pokes Solaris DDI -.It Sy ddi_prop_create Solaris DDI -.It Sy ddi_prop_exists Solaris DDI -.It Sy ddi_prop_free Solaris DDI -.It Sy ddi_prop_get_int Solaris DDI -.It Sy ddi_prop_lookup Solaris DDI -.It Sy ddi_prop_lookup_byte_array Solaris DDI -.It Sy ddi_prop_lookup_int_array Solaris DDI -.It Sy ddi_prop_lookup_string Solaris DDI -.It Sy ddi_prop_lookup_string_array Solaris DDI -.It Sy ddi_prop_modify Solaris DDI -.It Sy ddi_prop_op Solaris DDI -.It Sy ddi_prop_remove Solaris DDI -.It Sy ddi_prop_remove_all Solaris DDI -.It Sy ddi_prop_undefine Solaris DDI -.It Sy ddi_prop_update Solaris DDI -.It Sy ddi_prop_update_byte_array Solaris DDI -.It Sy ddi_prop_update_int Solaris DDI -.It Sy ddi_prop_update_int_array Solaris DDI -.It Sy ddi_prop_update_string Solaris DDI -.It Sy ddi_prop_update_string_array Solaris DDI -.It Sy ddi_ptob Solaris DDI -.It Sy ddi_put16 Solaris DDI -.It Sy ddi_put32 Solaris DDI -.It Sy ddi_put64 Solaris DDI -.It Sy ddi_put8 Solaris DDI -.It Sy ddi_putb Solaris DDI -.It Sy ddi_putl Solaris DDI -.It Sy ddi_putll Solaris DDI -.It Sy ddi_putw Solaris DDI -.It Sy ddi_regs_map_free Solaris DDI -.It Sy ddi_regs_map_setup Solaris DDI -.It Sy ddi_remove_event_handler Solaris DDI -.It Sy ddi_remove_intr Solaris DDI -.It Sy ddi_remove_minor_node Solaris DDI -.It Sy ddi_remove_softintr Solaris DDI -.It Sy ddi_removing_power Solaris DDI -.It Sy ddi_rep_get16 Solaris DDI -.It Sy ddi_rep_get32 Solaris DDI -.It Sy ddi_rep_get64 Solaris DDI -.It Sy ddi_rep_get8 Solaris DDI -.It Sy ddi_rep_getb Solaris DDI -.It Sy ddi_rep_getl Solaris DDI -.It Sy ddi_rep_getll Solaris DDI -.It Sy ddi_rep_getw Solaris DDI -.It Sy ddi_rep_put16 Solaris DDI -.It Sy ddi_rep_put32 Solaris DDI -.It Sy ddi_rep_put64 Solaris DDI -.It Sy ddi_rep_put8 Solaris DDI -.It Sy ddi_rep_putb Solaris DDI -.It Sy ddi_rep_putl Solaris DDI -.It Sy ddi_rep_putll Solaris DDI -.It Sy ddi_rep_putw Solaris DDI -.It Sy ddi_report_dev Solaris DDI -.It Sy ddi_root_node Solaris DDI -.It Sy ddi_segmap Solaris DDI -.It Sy ddi_segmap_setup Solaris DDI -.It Sy ddi_set_driver_private Solaris DDI -.It Sy ddi_slaveonly Solaris DDI -.It Sy ddi_soft_state Solaris DDI -.It Sy ddi_soft_state_fini Solaris DDI -.It Sy ddi_soft_state_free Solaris DDI -.It Sy ddi_soft_state_init Solaris DDI -.It Sy ddi_soft_state_zalloc Solaris DDI -.It Sy ddi_strlol Solaris DDI -.It Sy ddi_strloul Solaris DDI -.It Sy ddi_trigger_softintr Solaris DDI -.It Sy ddi_umem_alloc Solaris DDI -.It Sy ddi_umem_free Solaris DDI -.It Sy ddi_umem_iosetup Solaris DDI -.It Sy ddi_umem_lock Solaris DDI -.It Sy ddi_unmap_regs Solaris DDI +.It Sy cv_broadcast illumos DDI +.It Sy cv_destroy illumos DDI +.It Sy cv_init illumos DDI +.It Sy cv_signal illumos DDI +.It Sy cv_reltimedwait illumos DDI +.It Sy cv_reltimedwait_sig illumos DDI +.It Sy cv_timedwait illumos DDI +.It Sy cv_wait illumos DDI +.It Sy cv_wait_sig illumos DDI +.It Sy ddi_add_event_handler illumos DDI +.It Sy ddi_add_intr illumos DDI +.It Sy ddi_add_softintr illumos DDI +.It Sy ddi_binding_name illumos DDI +.It Sy ddi_btop illumos DDI +.It Sy ddi_btopr illumos DDI +.It Sy ddi_can_receive_sig illumos DDI +.It Sy ddi_check_acc_handle illumos DDI +.It Sy ddi_copyin illumos DDI +.It Sy ddi_copyout illumos DDI +.It Sy ddi_create_minor_node illumos DDI +.It Sy ddi_cred illumos DDI +.It Sy ddi_dev_is_sid illumos DDI +.It Sy ddi_dev_nintrs illumos DDI +.It Sy ddi_dev_nregs illumos DDI +.It Sy ddi_dev_regsize illumos DDI +.It Sy ddi_device_copy illumos DDI +.It Sy ddi_device_zero illumos DDI +.It Sy ddi_devmap_segmap illumos DDI +.It Sy ddi_dma_addr_bind_handle illumos DDI +.It Sy ddi_dma_alloc_handle illumos DDI +.It Sy ddi_dma_buf_bind_handle illumos DDI +.It Sy ddi_dma_burstsizes illumos DDI +.It Sy ddi_dma_free_handle illumos DDI +.It Sy ddi_dma_getwin illumos DDI +.It Sy ddi_dma_mem_alloc illumos DDI +.It Sy ddi_dma_mem_free illumos DDI +.It Sy ddi_dma_nextcookie illumos DDI +.It Sy ddi_dma_numwin illumos DDI +.It Sy ddi_dma_set_sbus64 illumos DDI +.It Sy ddi_dma_sync illumos DDI +.It Sy ddi_dma_unbind_handle illumos DDI +.It Sy ddi_dmae illumos x86 DDI +.It Sy ddi_dmae_1stparty illumos x86 DDI +.It Sy ddi_dmae_alloc illumos x86 DDI +.It Sy ddi_dmae_disable illumos x86 DDI +.It Sy ddi_dmae_enable illumos x86 DDI +.It Sy ddi_dmae_getattr illumos x86 DDI +.It Sy ddi_dmae_getcnt illumos x86 DDI +.It Sy ddi_dmae_getlim illumos x86 DDI +.It Sy ddi_dmae_prog illumos x86 DDI +.It Sy ddi_dmae_release illumos x86 DDI +.It Sy ddi_dmae_stop illumos x86 DDI +.It Sy ddi_driver_major illumos DDI +.It Sy ddi_driver_name illumos DDI +.It Sy ddi_enter_critical illumos DDI +.It Sy ddi_exit_critical illumos DDI +.It Sy ddi_ffs illumos DDI +.It Sy ddi_fls illumos DDI +.It Sy ddi_fm_acc_err_clear illumos DDI +.It Sy ddi_fm_acc_err_get illumos DDI +.It Sy ddi_fm_ereport_post illumos DDI +.It Sy ddi_fm_handler_register illumos DDI +.It Sy ddi_fm_init illumos DDI +.It Sy ddi_fm_service_impact illumos DDI +.It Sy ddi_get16 illumos DDI +.It Sy ddi_get32 illumos DDI +.It Sy ddi_get64 illumos DDI +.It Sy ddi_get8 illumos DDI +.It Sy ddi_get_cred illumos DDI +.It Sy ddi_get_devstate illumos DDI +.It Sy ddi_get_driver_private illumos DDI +.It Sy ddi_get_eventcookie illumos DDI +.It Sy ddi_get_iblock_cookie illumos DDI +.It Sy ddi_get_iminor illumos DDI +.It Sy ddi_get_instance illumos DDI +.It Sy ddi_get_kt_did illumos DDI +.It Sy ddi_get_lbolt illumos DDI +.It Sy ddi_get_name illumos DDI +.It Sy ddi_get_parent illumos DDI +.It Sy ddi_get_pid illumos DDI +.It Sy ddi_get_soft_iblock_cookie illumos DDI +.It Sy ddi_get_soft_state illumos DDI +.It Sy ddi_getb illumos DDI +.It Sy ddi_getl illumos DDI +.It Sy ddi_getll illumos DDI +.It Sy ddi_getlongprop illumos DDI +.It Sy ddi_getlongprop_buf illumos DDI +.It Sy ddi_getprop illumos DDI +.It Sy ddi_getproplen illumos DDI +.It Sy ddi_getw illumos DDI +.It Sy ddi_intr_add_handler illumos DDI +.It Sy ddi_intr_add_softint illumos DDI +.It Sy ddi_intr_alloc illumos DDI +.It Sy ddi_intr_block_disable illumos DDI +.It Sy ddi_intr_block_enable illumos DDI +.It Sy ddi_intr_clr_mask illumos DDI +.It Sy ddi_intr_dup_handler illumos DDI +.It Sy ddi_intr_disable illumos DDI +.It Sy ddi_intr_enable illumos DDI +.It Sy ddi_intr_free illumos DDI +.It Sy ddi_intr_get_cap illumos DDI +.It Sy ddi_intr_get_hilevel_pri illumos DDI +.It Sy ddi_intr_get_navail illumos DDI +.It Sy ddi_intr_get_nintrs illumos DDI +.It Sy ddi_intr_get_pending illumos DDI +.It Sy ddi_intr_get_pri illumos DDI +.It Sy ddi_intr_get_softint_pri illumos DDI +.It Sy ddi_intr_get_supported_types illumos DDI +.It Sy ddi_intr_remove_handler illumos DDI +.It Sy ddi_intr_remove_softint illumos DDI +.It Sy ddi_intr_set_cap illumos DDI +.It Sy ddi_intr_set_mask illumos DDI +.It Sy ddi_intr_set_pri illumos DDI +.It Sy ddi_intr_set_softint_pri illumos DDI +.It Sy ddi_intr_trigger_softint illumos DDI +.It Sy ddi_io_get16 illumos DDI +.It Sy ddi_io_get32 illumos DDI +.It Sy ddi_io_get8 illumos DDI +.It Sy ddi_io_getb illumos DDI +.It Sy ddi_io_getl illumos DDI +.It Sy ddi_io_getw illumos DDI +.It Sy ddi_io_put16 illumos DDI +.It Sy ddi_io_put32 illumos DDI +.It Sy ddi_io_put8 illumos DDI +.It Sy ddi_io_putb illumos DDI +.It Sy ddi_io_putl illumos DDI +.It Sy ddi_io_putw illumos DDI +.It Sy ddi_io_rep_get16 illumos DDI +.It Sy ddi_io_rep_get32 illumos DDI +.It Sy ddi_io_rep_get8 illumos DDI +.It Sy ddi_io_rep_getb illumos DDI +.It Sy ddi_io_rep_getl illumos DDI +.It Sy ddi_io_rep_getw illumos DDI +.It Sy ddi_io_rep_put16 illumos DDI +.It Sy ddi_io_rep_put32 illumos DDI +.It Sy ddi_io_rep_put8 illumos DDI +.It Sy ddi_io_rep_putb illumos DDI +.It Sy ddi_io_rep_putl illumos DDI +.It Sy ddi_io_rep_putw illumos DDI +.It Sy ddi_iomin illumos DDI +.It Sy ddi_log_sysevent illumos DDI +.It Sy ddi_map_regs illumos DDI +.It Sy ddi_mapdev illumos DDI +.It Sy ddi_mapdev_intercept illumos DDI +.It Sy ddi_mapdev_nointercept illumos DDI +.It Sy ddi_mapdev_set_device_acc_attr illumos DDI +.It Sy ddi_mem_get16 illumos DDI +.It Sy ddi_mem_get32 illumos DDI +.It Sy ddi_mem_get64 illumos DDI +.It Sy ddi_mem_get8 illumos DDI +.It Sy ddi_mem_getb illumos DDI +.It Sy ddi_mem_getl illumos DDI +.It Sy ddi_mem_getll illumos DDI +.It Sy ddi_mem_getw illumos DDI +.It Sy ddi_mem_put16 illumos DDI +.It Sy ddi_mem_put32 illumos DDI +.It Sy ddi_mem_put64 illumos DDI +.It Sy ddi_mem_put8 illumos DDI +.It Sy ddi_mem_putb illumos DDI +.It Sy ddi_mem_putl illumos DDI +.It Sy ddi_mem_putll illumos DDI +.It Sy ddi_mem_putw illumos DDI +.It Sy ddi_mem_rep_get16 illumos DDI +.It Sy ddi_mem_rep_get32 illumos DDI +.It Sy ddi_mem_rep_get64 illumos DDI +.It Sy ddi_mem_rep_get8 illumos DDI +.It Sy ddi_mem_rep_getb illumos DDI +.It Sy ddi_mem_rep_getl illumos DDI +.It Sy ddi_mem_rep_getll illumos DDI +.It Sy ddi_mem_rep_getw illumos DDI +.It Sy ddi_mem_rep_put16 illumos DDI +.It Sy ddi_mem_rep_put32 illumos DDI +.It Sy ddi_mem_rep_put64 illumos DDI +.It Sy ddi_mem_rep_put8 illumos DDI +.It Sy ddi_mem_rep_putb illumos DDI +.It Sy ddi_mem_rep_putl illumos DDI +.It Sy ddi_mem_rep_putll illumos DDI +.It Sy ddi_mem_rep_putw illumos DDI +.It Sy ddi_mmap_get_model illumos DDI +.It Sy ddi_model_convert_from illumos DDI +.It Sy ddi_modopen illumos DDI +.It Sy ddi_no_info illumos DDI +.It Sy ddi_node_name illumos DDI +.It Sy ddi_peek16 illumos DDI +.It Sy ddi_peek32 illumos DDI +.It Sy ddi_peek64 illumos DDI +.It Sy ddi_peek8 illumos DDI +.It Sy ddi_peekc illumos DDI +.It Sy ddi_peekd illumos DDI +.It Sy ddi_peekl illumos DDI +.It Sy ddi_peeks illumos DDI +.It Sy ddi_periodic_add illumos DDI +.It Sy ddi_periodic_delete illumos DDI +.It Sy ddi_poke16 illumos DDI +.It Sy ddi_poke32 illumos DDI +.It Sy ddi_poke64 illumos DDI +.It Sy ddi_poke8 illumos DDI +.It Sy ddi_pokec illumos DDI +.It Sy ddi_poked illumos DDI +.It Sy ddi_pokel illumos DDI +.It Sy ddi_pokes illumos DDI +.It Sy ddi_prop_create illumos DDI +.It Sy ddi_prop_exists illumos DDI +.It Sy ddi_prop_free illumos DDI +.It Sy ddi_prop_get_int illumos DDI +.It Sy ddi_prop_lookup illumos DDI +.It Sy ddi_prop_lookup_byte_array illumos DDI +.It Sy ddi_prop_lookup_int_array illumos DDI +.It Sy ddi_prop_lookup_string illumos DDI +.It Sy ddi_prop_lookup_string_array illumos DDI +.It Sy ddi_prop_modify illumos DDI +.It Sy ddi_prop_op illumos DDI +.It Sy ddi_prop_remove illumos DDI +.It Sy ddi_prop_remove_all illumos DDI +.It Sy ddi_prop_undefine illumos DDI +.It Sy ddi_prop_update illumos DDI +.It Sy ddi_prop_update_byte_array illumos DDI +.It Sy ddi_prop_update_int illumos DDI +.It Sy ddi_prop_update_int_array illumos DDI +.It Sy ddi_prop_update_string illumos DDI +.It Sy ddi_prop_update_string_array illumos DDI +.It Sy ddi_ptob illumos DDI +.It Sy ddi_put16 illumos DDI +.It Sy ddi_put32 illumos DDI +.It Sy ddi_put64 illumos DDI +.It Sy ddi_put8 illumos DDI +.It Sy ddi_putb illumos DDI +.It Sy ddi_putl illumos DDI +.It Sy ddi_putll illumos DDI +.It Sy ddi_putw illumos DDI +.It Sy ddi_regs_map_free illumos DDI +.It Sy ddi_regs_map_setup illumos DDI +.It Sy ddi_remove_event_handler illumos DDI +.It Sy ddi_remove_intr illumos DDI +.It Sy ddi_remove_minor_node illumos DDI +.It Sy ddi_remove_softintr illumos DDI +.It Sy ddi_removing_power illumos DDI +.It Sy ddi_rep_get16 illumos DDI +.It Sy ddi_rep_get32 illumos DDI +.It Sy ddi_rep_get64 illumos DDI +.It Sy ddi_rep_get8 illumos DDI +.It Sy ddi_rep_getb illumos DDI +.It Sy ddi_rep_getl illumos DDI +.It Sy ddi_rep_getll illumos DDI +.It Sy ddi_rep_getw illumos DDI +.It Sy ddi_rep_put16 illumos DDI +.It Sy ddi_rep_put32 illumos DDI +.It Sy ddi_rep_put64 illumos DDI +.It Sy ddi_rep_put8 illumos DDI +.It Sy ddi_rep_putb illumos DDI +.It Sy ddi_rep_putl illumos DDI +.It Sy ddi_rep_putll illumos DDI +.It Sy ddi_rep_putw illumos DDI +.It Sy ddi_report_dev illumos DDI +.It Sy ddi_root_node illumos DDI +.It Sy ddi_segmap illumos DDI +.It Sy ddi_segmap_setup illumos DDI +.It Sy ddi_set_driver_private illumos DDI +.It Sy ddi_slaveonly illumos DDI +.It Sy ddi_soft_state illumos DDI +.It Sy ddi_soft_state_fini illumos DDI +.It Sy ddi_soft_state_free illumos DDI +.It Sy ddi_soft_state_init illumos DDI +.It Sy ddi_soft_state_zalloc illumos DDI +.It Sy ddi_strlol illumos DDI +.It Sy ddi_strloul illumos DDI +.It Sy ddi_trigger_softintr illumos DDI +.It Sy ddi_umem_alloc illumos DDI +.It Sy ddi_umem_free illumos DDI +.It Sy ddi_umem_iosetup illumos DDI +.It Sy ddi_umem_lock illumos DDI +.It Sy ddi_unmap_regs illumos DDI .It Sy delay DDI/DKI -.It Sy devmap_default_access Solaris DDI -.It Sy devmap_devmem_setup Solaris DDI -.It Sy devmap_do_ctxmgt Solaris DDI -.It Sy devmap_load Solaris DDI -.It Sy devmap_set_ctx_timeout Solaris DDI -.It Sy devmap_setup Solaris DDI -.It Sy devmap_umem_setup Solaris DDI -.It Sy devmap_unload Solaris DDI -.It Sy disksort Solaris DDI -.It Sy dlbindack Solaris DDI +.It Sy devmap_default_access illumos DDI +.It Sy devmap_devmem_setup illumos DDI +.It Sy devmap_do_ctxmgt illumos DDI +.It Sy devmap_load illumos DDI +.It Sy devmap_set_ctx_timeout illumos DDI +.It Sy devmap_setup illumos DDI +.It Sy devmap_umem_setup illumos DDI +.It Sy devmap_unload illumos DDI +.It Sy disksort illumos DDI +.It Sy dlbindack illumos DDI .It Sy drv_getparm DDI/DKI .It Sy drv_hztousec DDI/DKI .It Sy drv_priv DDI/DKI .It Sy drv_usectohz DDI/DKI .It Sy drv_usecwait DDI/DKI -.It Sy free_pktiopb Solaris DDI +.It Sy free_pktiopb illumos DDI .It Sy freerbuf DDI/DKI -.It Sy get_pktiopb Solaris DDI +.It Sy get_pktiopb illumos DDI .It Sy geterror DDI/DKI .It Sy gethrtime DDI/DKI .It Sy getmajor DDI/DKI .It Sy getminor DDI/DKI .It Sy getrbuf DDI/DKI -.It Sy gld Solaris DDI +.It Sy gld illumos DDI .It Sy hat_getkpfnum DKI only -.It Sy id32_alloc Solaris DDI -.It Sy inb Solaris x86 DDI -.It Sy inl Solaris x86 DDI -.It Sy inw Solaris x86 DDI -.It Sy kiconv Solaris DDI -.It Sy kiconv_close Solaris DDI -.It Sy kiconv_open Solaris DDI -.It Sy kiconvstr Solaris DDI +.It Sy id32_alloc illumos DDI +.It Sy inb illumos x86 DDI +.It Sy inl illumos x86 DDI +.It Sy inw illumos x86 DDI +.It Sy kiconv illumos DDI +.It Sy kiconv_close illumos DDI +.It Sy kiconv_open illumos DDI +.It Sy kiconvstr illumos DDI .It Sy kmem_alloc DDI/DKI -.It Sy kmem_cache_create Solaris DDI +.It Sy kmem_cache_create illumos DDI .It Sy kmem_free DDI/DKI .It Sy kmem_zalloc DDI/DKI -.It Sy kstat_create Solaris DDI -.It Sy kstat_delete Solaris DDI -.It Sy kstat_install Solaris DDI -.It Sy kstat_named_init Solaris DDI -.It Sy kstat_queue Solaris DDI -.It Sy kstat_runq_back_to_waitq Solaris DDI -.It Sy kstat_runq_enter Solaris DDI -.It Sy kstat_runq_exit Solaris DDI -.It Sy kstat_waitq_enter Solaris DDI -.It Sy kstat_waitq_exit Solaris DDI -.It Sy kstat_waitq_to_runq Solaris DDI -.It Sy ldi_add_event_handler Solaris DDI -.It Sy ldi_aread Solaris DDI -.It Sy ldi_devmap Solaris DDI -.It Sy ldi_dump Solaris DDI -.It Sy ldi_ev_finalize Solaris DDI -.It Sy ldi_ev_get_cookie Solaris DDI -.It Sy ldi_ev_get_type Solaris DDI -.It Sy ldi_ev_notify Solaris DDI -.It Sy ldi_ev_register_callbacks Solaris DDI -.It Sy ldi_ev_remove_callbacks Solaris DDI -.It Sy ldi_get_dev Solaris DDI -.It Sy ldi_get_eventcookie Solaris DDI -.It Sy ldi_get_size Solaris DDI -.It Sy ldi_ident_from_dev Solaris DDI -.It Sy ldi_ioctl Solaris DDI -.It Sy ldi_open_by_dev Solaris DDI -.It Sy ldi_poll Solaris DDI -.It Sy ldi_prop_exists Solaris DDI -.It Sy ldi_prop_get_int Solaris DDI -.It Sy ldi_prop_get_lookup_int_array Solaris DDI -.It Sy ldi_putmsg Solaris DDI -.It Sy ldi_read Solaris DDI -.It Sy ldi_remove_event_handler Solaris DDI -.It Sy ldi_strategy Solaris DDI -.It Sy makecom_g0 Solaris DDI -.It Sy makecom_g0_s Solaris DDI -.It Sy makecom_g1 Solaris DDI -.It Sy makecom_g5 Solaris DDI +.It Sy kstat_create illumos DDI +.It Sy kstat_delete illumos DDI +.It Sy kstat_install illumos DDI +.It Sy kstat_named_init illumos DDI +.It Sy kstat_queue illumos DDI +.It Sy kstat_runq_back_to_waitq illumos DDI +.It Sy kstat_runq_enter illumos DDI +.It Sy kstat_runq_exit illumos DDI +.It Sy kstat_waitq_enter illumos DDI +.It Sy kstat_waitq_exit illumos DDI +.It Sy kstat_waitq_to_runq illumos DDI +.It Sy ldi_add_event_handler illumos DDI +.It Sy ldi_aread illumos DDI +.It Sy ldi_devmap illumos DDI +.It Sy ldi_dump illumos DDI +.It Sy ldi_ev_finalize illumos DDI +.It Sy ldi_ev_get_cookie illumos DDI +.It Sy ldi_ev_get_type illumos DDI +.It Sy ldi_ev_notify illumos DDI +.It Sy ldi_ev_register_callbacks illumos DDI +.It Sy ldi_ev_remove_callbacks illumos DDI +.It Sy ldi_get_dev illumos DDI +.It Sy ldi_get_eventcookie illumos DDI +.It Sy ldi_get_size illumos DDI +.It Sy ldi_ident_from_dev illumos DDI +.It Sy ldi_ioctl illumos DDI +.It Sy ldi_open_by_dev illumos DDI +.It Sy ldi_poll illumos DDI +.It Sy ldi_prop_exists illumos DDI +.It Sy ldi_prop_get_int illumos DDI +.It Sy ldi_prop_get_lookup_int_array illumos DDI +.It Sy ldi_putmsg illumos DDI +.It Sy ldi_read illumos DDI +.It Sy ldi_remove_event_handler illumos DDI +.It Sy ldi_strategy illumos DDI +.It Sy makecom_g0 illumos DDI +.It Sy makecom_g0_s illumos DDI +.It Sy makecom_g1 illumos DDI +.It Sy makecom_g5 illumos DDI .It Sy makedevice DDI/DKI .It Sy max DDI/DKI -.It Sy membar_ops Solaris DDI -.It Sy memchr Solaris DDI +.It Sy membar_ops illumos DDI +.It Sy memchr illumos DDI .It Sy min DDI/DKI -.It Sy minphys Solaris DDI -.It Sy mod_info Solaris DDI -.It Sy mod_install Solaris DDI -.It Sy mod_remove Solaris DDI -.It Sy mutex_destroy Solaris DDI -.It Sy mutex_enter Solaris DDI -.It Sy mutex_exit Solaris DDI -.It Sy mutex_init Solaris DDI -.It Sy mutex_owned Solaris DDI -.It Sy mutex_tryenter Solaris DDI -.It Sy nochpoll Solaris DDI +.It Sy minphys illumos DDI +.It Sy mod_info illumos DDI +.It Sy mod_install illumos DDI +.It Sy mod_remove illumos DDI +.It Sy mutex_destroy illumos DDI +.It Sy mutex_enter illumos DDI +.It Sy mutex_exit illumos DDI +.It Sy mutex_init illumos DDI +.It Sy mutex_owned illumos DDI +.It Sy mutex_tryenter illumos DDI +.It Sy nochpoll illumos DDI .It Sy nodev DDI/DKI .It Sy nulldev DDI/DKI -.It Sy numtos Solaris DDI -.It Sy nvlist_add_boolean Solaris DDI -.It Sy nvlist_alloc Solaris DDI -.It Sy nvlist_lookup_boolean Solaris DDI -.It Sy nvlist_lookup_nvpair Solaris DDI -.It Sy nvlist_next_nvpair Solaris DDI -.It Sy nvlist_remove Solaris DDI -.It Sy nvlist_value_byte Solaris DDI -.It Sy outb Solaris x86 DDI -.It Sy outl Solaris x86 DDI -.It Sy outw Solaris x86 DDI -.It Sy pci_config_get16 Solaris DDI -.It Sy pci_config_get32 Solaris DDI -.It Sy pci_config_get64 Solaris DDI -.It Sy pci_config_get8 Solaris DDI -.It Sy pci_config_getb Solaris DDI -.It Sy pci_config_getl Solaris DDI -.It Sy pci_config_getw Solaris DDI -.It Sy pci_config_put16 Solaris DDI -.It Sy pci_config_put32 Solaris DDI -.It Sy pci_config_put64 Solaris DDI -.It Sy pci_config_put8 Solaris DDI -.It Sy pci_config_putb Solaris DDI -.It Sy pci_config_putl Solaris DDI -.It Sy pci_config_putw Solaris DDI -.It Sy pci_config_setup Solaris DDI -.It Sy pci_config_teardown Solaris DDI -.It Sy pci_ereport_setup Solaris DDI -.It Sy pci_report_pmcap Solaris DDI -.It Sy pci_save_config_regs Solaris DDI -.It Sy physio Solaris DDI -.It Sy pm_busy_component Solaris DDI -.It Sy pm_power_has_changed Solaris DDI -.It Sy pm_raise_power Solaris DDI -.It Sy pm_trans_check Solaris DDI +.It Sy numtos illumos DDI +.It Sy nvlist_add_boolean illumos DDI +.It Sy nvlist_alloc illumos DDI +.It Sy nvlist_lookup_boolean illumos DDI +.It Sy nvlist_lookup_nvpair illumos DDI +.It Sy nvlist_next_nvpair illumos DDI +.It Sy nvlist_remove illumos DDI +.It Sy nvlist_value_byte illumos DDI +.It Sy outb illumos x86 DDI +.It Sy outl illumos x86 DDI +.It Sy outw illumos x86 DDI +.It Sy pci_config_get16 illumos DDI +.It Sy pci_config_get32 illumos DDI +.It Sy pci_config_get64 illumos DDI +.It Sy pci_config_get8 illumos DDI +.It Sy pci_config_getb illumos DDI +.It Sy pci_config_getl illumos DDI +.It Sy pci_config_getw illumos DDI +.It Sy pci_config_put16 illumos DDI +.It Sy pci_config_put32 illumos DDI +.It Sy pci_config_put64 illumos DDI +.It Sy pci_config_put8 illumos DDI +.It Sy pci_config_putb illumos DDI +.It Sy pci_config_putl illumos DDI +.It Sy pci_config_putw illumos DDI +.It Sy pci_config_setup illumos DDI +.It Sy pci_config_teardown illumos DDI +.It Sy pci_ereport_setup illumos DDI +.It Sy pci_report_pmcap illumos DDI +.It Sy pci_save_config_regs illumos DDI +.It Sy physio illumos DDI +.It Sy pm_busy_component illumos DDI +.It Sy pm_power_has_changed illumos DDI +.It Sy pm_raise_power illumos DDI +.It Sy pm_trans_check illumos DDI .It Sy pollwakeup DDI/DKI -.It Sy pci_config_teardown Solaris DDI -.It Sy pci_config_teardown Solaris DDI -.It Sy priv_getbyname Solaris DDI -.It Sy priv_policy Solaris DDI -.It Sy proc_signal Solaris DDI -.It Sy proc_unref Solaris DDI +.It Sy pci_config_teardown illumos DDI +.It Sy pci_config_teardown illumos DDI +.It Sy priv_getbyname illumos DDI +.It Sy priv_policy illumos DDI +.It Sy proc_signal illumos DDI +.It Sy proc_unref illumos DDI .It Sy ptob DDI/DKI -.It Sy repinsb Solaris x86 DDI -.It Sy repinsd Solaris x86 DDI -.It Sy repinsw Solaris x86 DDI -.It Sy repoutsb Solaris x86 DDI -.It Sy repoutsd Solaris x86 DDI -.It Sy repoutsw Solaris x86 DDI +.It Sy repinsb illumos x86 DDI +.It Sy repinsd illumos x86 DDI +.It Sy repinsw illumos x86 DDI +.It Sy repoutsb illumos x86 DDI +.It Sy repoutsd illumos x86 DDI +.It Sy repoutsw illumos x86 DDI .It Sy rmalloc DDI/DKI .It Sy rmalloc_wait DDI/DKI .It Sy rmallocmap DDI/DKI .It Sy rmallocmap_wait DDI/DKI .It Sy rmfree DDI/DKI .It Sy rmfreemap DDI/DKI -.It Sy rw_destroy Solaris DDI -.It Sy rw_downgrade Solaris DDI -.It Sy rw_enter Solaris DDI -.It Sy rw_exit Solaris DDI -.It Sy rw_init Solaris DDI -.It Sy rw_read_locked Solaris DDI -.It Sy rw_tryenter Solaris DDI -.It Sy rw_tryupgrade Solaris DDI -.It Sy scsi_abort Solaris DDI -.It Sy scsi_alloc_consistent_buf Solaris DDI -.It Sy scsi_cname Solaris DDI -.It Sy scsi_destroy_pkt Solaris DDI -.It Sy scsi_dmafree Solaris DDI -.It Sy scsi_dmaget Solaris DDI -.It Sy scsi_dname Solaris DDI -.It Sy scsi_errmsg Solaris DDI -.It Sy scsi_ext_sense_fields Solaris DDI -.It Sy scsi_find_sense_descr Solaris DDI -.It Sy scsi_free_consistent_buf Solaris DDI -.It Sy scsi_get_device_type_scsi_options Solaris DDI -.It Sy scsi_get_device_type_string Solaris DDI -.It Sy scsi_hba_attach_setup Solaris DDI -.It Sy scsi_hba_detach Solaris DDI -.It Sy scsi_hba_fini Solaris DDI -.It Sy scsi_hba_init Solaris DDI -.It Sy scsi_hba_lookup_capstr Solaris DDI -.It Sy scsi_hba_pkt_alloc Solaris DDI -.It Sy scsi_hba_pkt_free Solaris DDI -.It Sy scsi_hba_probe Solaris DDI -.It Sy scsi_hba_tran_alloc Solaris DDI -.It Sy scsi_hba_tran_free Solaris DDI -.It Sy scsi_ifgetcap Solaris DDI -.It Sy scsi_ifsetcap Solaris DDI -.It Sy scsi_init_pkt Solaris DDI -.It Sy scsi_log Solaris DDI -.It Sy scsi_mname Solaris DDI -.It Sy scsi_pktalloc Solaris DDI -.It Sy scsi_pktfree Solaris DDI -.It Sy scsi_poll Solaris DDI -.It Sy scsi_probe Solaris DDI -.It Sy scsi_resalloc Solaris DDI -.It Sy scsi_reset Solaris DDI -.It Sy scsi_reset_notify Solaris DDI -.It Sy scsi_resfree Solaris DDI -.It Sy scsi_rname Solaris DDI -.It Sy scsi_sense_key Solaris DDI -.It Sy scsi_setup_cdb Solaris DDI -.It Sy scsi_slave Solaris DDI -.It Sy scsi_sname Solaris DDI -.It Sy scsi_sync_pkt Solaris DDI -.It Sy scsi_transport Solaris DDI -.It Sy scsi_unprobe Solaris DDI -.It Sy scsi_unslave Solaris DDI -.It Sy scsi_validate_sense Solaris DDI -.It Sy scsi_vu_errmsg Solaris DDI -.It Sy sema_destroy Solaris DDI -.It Sy sema_init Solaris DDI -.It Sy sema_p Solaris DDI -.It Sy sema_p_sig Solaris DDI -.It Sy sema_tryp Solaris DDI -.It Sy sema_v Solaris DDI -.It Sy sprintf Solaris DDI -.It Sy stoi Solaris DDI -.It Sy strchr Solaris DDI -.It Sy strcmp Solaris DDI -.It Sy strcpy Solaris DDI -.It Sy strlen Solaris DDI -.It Sy strncmp Solaris DDI -.It Sy strncpy Solaris DDI -.It Sy STRUCT_DECL Solaris DDI +.It Sy rw_destroy illumos DDI +.It Sy rw_downgrade illumos DDI +.It Sy rw_enter illumos DDI +.It Sy rw_exit illumos DDI +.It Sy rw_init illumos DDI +.It Sy rw_read_locked illumos DDI +.It Sy rw_tryenter illumos DDI +.It Sy rw_tryupgrade illumos DDI +.It Sy scsi_abort illumos DDI +.It Sy scsi_alloc_consistent_buf illumos DDI +.It Sy scsi_cname illumos DDI +.It Sy scsi_destroy_pkt illumos DDI +.It Sy scsi_dmafree illumos DDI +.It Sy scsi_dmaget illumos DDI +.It Sy scsi_dname illumos DDI +.It Sy scsi_errmsg illumos DDI +.It Sy scsi_ext_sense_fields illumos DDI +.It Sy scsi_find_sense_descr illumos DDI +.It Sy scsi_free_consistent_buf illumos DDI +.It Sy scsi_get_device_type_scsi_options illumos DDI +.It Sy scsi_get_device_type_string illumos DDI +.It Sy scsi_hba_attach_setup illumos DDI +.It Sy scsi_hba_detach illumos DDI +.It Sy scsi_hba_fini illumos DDI +.It Sy scsi_hba_init illumos DDI +.It Sy scsi_hba_lookup_capstr illumos DDI +.It Sy scsi_hba_pkt_alloc illumos DDI +.It Sy scsi_hba_pkt_free illumos DDI +.It Sy scsi_hba_probe illumos DDI +.It Sy scsi_hba_tran_alloc illumos DDI +.It Sy scsi_hba_tran_free illumos DDI +.It Sy scsi_ifgetcap illumos DDI +.It Sy scsi_ifsetcap illumos DDI +.It Sy scsi_init_pkt illumos DDI +.It Sy scsi_log illumos DDI +.It Sy scsi_mname illumos DDI +.It Sy scsi_pktalloc illumos DDI +.It Sy scsi_pktfree illumos DDI +.It Sy scsi_poll illumos DDI +.It Sy scsi_probe illumos DDI +.It Sy scsi_resalloc illumos DDI +.It Sy scsi_reset illumos DDI +.It Sy scsi_reset_notify illumos DDI +.It Sy scsi_resfree illumos DDI +.It Sy scsi_rname illumos DDI +.It Sy scsi_sense_key illumos DDI +.It Sy scsi_setup_cdb illumos DDI +.It Sy scsi_slave illumos DDI +.It Sy scsi_sname illumos DDI +.It Sy scsi_sync_pkt illumos DDI +.It Sy scsi_transport illumos DDI +.It Sy scsi_unprobe illumos DDI +.It Sy scsi_unslave illumos DDI +.It Sy scsi_validate_sense illumos DDI +.It Sy scsi_vu_errmsg illumos DDI +.It Sy sema_destroy illumos DDI +.It Sy sema_init illumos DDI +.It Sy sema_p illumos DDI +.It Sy sema_p_sig illumos DDI +.It Sy sema_tryp illumos DDI +.It Sy sema_v illumos DDI +.It Sy sprintf illumos DDI +.It Sy stoi illumos DDI +.It Sy strchr illumos DDI +.It Sy strcmp illumos DDI +.It Sy strcpy illumos DDI +.It Sy strlen illumos DDI +.It Sy strncmp illumos DDI +.It Sy strncpy illumos DDI +.It Sy STRUCT_DECL illumos DDI .It Sy swab DDI/DKI -.It Sy taskq Solaris DDI +.It Sy taskq illumos DDI .It Sy timeout DDI/DKI -.It Sy u8_strcmp Solaris DDI -.It Sy u8_textprep_str Solaris DDI -.It Sy u8_validate Solaris DDI -.It Sy uconv_u16tou32 Solaris DDI +.It Sy u8_strcmp illumos DDI +.It Sy u8_textprep_str illumos DDI +.It Sy u8_validate illumos DDI +.It Sy uconv_u16tou32 illumos DDI .It Sy uiomove DDI/DKI .It Sy untimeout DDI/DKI .It Sy ureadc DDI/DKI -.It Sy usb_alloc_request Solaris DDI -.It Sy usb_client_attach Solaris DDI -.It Sy usb_clr_feature Solaris DDI -.It Sy usb_create_pm_components Solaris DDI -.It Sy usb_get_addr Solaris DDI -.It Sy usb_get_alt_if Solaris DDI -.It Sy usb_get_cfg Solaris DDI -.It Sy usb_get_current_frame_number Solaris DDI -.It Sy usb_get_dev_data Solaris DDI -.It Sy usb_get_max_pkts_per_ioc_request Solaris DDI -.It Sy usb_get_status Solaris DDI -.It Sy usb_get_string_desc Solaris DDI -.It Sy usb_handle_remote_wakeup Solaris DDI -.It Sy usb_lookup_ep_data Solaris DDI -.It Sy usb_parse_data Solaris DDI -.It Sy usb_pipe_bulk_xfer Solaris DDI -.It Sy usb_pipe_close Solaris DDI -.It Sy usb_pipe_ctrl_xfer Solaris DDI -.It Sy usb_pipe_drain_reqs Solaris DDI -.It Sy usb_pipe_get_max_bulk_transfer_size Solaris DDI -.It Sy usb_pipe_get_state Solaris DDI -.It Sy usb_pipe_intr_xfer Solaris DDI -.It Sy usb_pipe_isoc_xfer Solaris DDI -.It Sy usb_pipe_open Solaris DDI -.It Sy usb_pipe_reset Solaris DDI -.It Sy usb_pipe_set_private Solaris DDI -.It Sy usb_register_hotplug_cbs Solaris DDI -.It Sy usb_reset_device Solaris DDI +.It Sy usb_alloc_request illumos DDI +.It Sy usb_client_attach illumos DDI +.It Sy usb_clr_feature illumos DDI +.It Sy usb_create_pm_components illumos DDI +.It Sy usb_get_addr illumos DDI +.It Sy usb_get_alt_if illumos DDI +.It Sy usb_get_cfg illumos DDI +.It Sy usb_get_current_frame_number illumos DDI +.It Sy usb_get_dev_data illumos DDI +.It Sy usb_get_max_pkts_per_ioc_request illumos DDI +.It Sy usb_get_status illumos DDI +.It Sy usb_get_string_desc illumos DDI +.It Sy usb_handle_remote_wakeup illumos DDI +.It Sy usb_lookup_ep_data illumos DDI +.It Sy usb_parse_data illumos DDI +.It Sy usb_pipe_bulk_xfer illumos DDI +.It Sy usb_pipe_close illumos DDI +.It Sy usb_pipe_ctrl_xfer illumos DDI +.It Sy usb_pipe_drain_reqs illumos DDI +.It Sy usb_pipe_get_max_bulk_transfer_size illumos DDI +.It Sy usb_pipe_get_state illumos DDI +.It Sy usb_pipe_intr_xfer illumos DDI +.It Sy usb_pipe_isoc_xfer illumos DDI +.It Sy usb_pipe_open illumos DDI +.It Sy usb_pipe_reset illumos DDI +.It Sy usb_pipe_set_private illumos DDI +.It Sy usb_register_hotplug_cbs illumos DDI +.It Sy usb_reset_device illumos DDI .It Sy uwritec DDI/DKI -.It Sy va_arg Solaris DDI -.It Sy va_end Solaris DDI -.It Sy va_start Solaris DDI +.It Sy va_arg illumos DDI +.It Sy va_end illumos DDI +.It Sy va_start illumos DDI .It Sy vcmn_err DDI/DKI -.It Sy vsprintf Solaris DDI +.It Sy vsprintf illumos DDI .El .Sh SEE ALSO .Xr Intro 9E ,
--- a/usr/src/man/man9f/condvar.9f Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/man/man9f/condvar.9f Sun Jan 04 07:19:22 2015 -0800 @@ -1,5 +1,6 @@ '\" te .\" Copyright (c) 2003, Sun Microsystems, Inc. All Rights Reserved +.\" Copyright (c) 2014, Joyent, Inc. .\" 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] @@ -52,12 +53,22 @@ \fBclock_t\fR \fBcv_timedwait_sig\fR(\fBkcondvar_t *\fR\fIcvp\fR, \fBkmutex_t *\fR\fImp\fR, \fBclock_t\fR \fItimeout\fR); .fi +.LP +.nf +\fBclock_t\fR \fBcv_reltimedwait\fR(\fBkcondvar_t *\fR\fIcvp\fR, \fBkmutex_t *\fR\fImp\fR, \fBclock_t\fR \fIdelta\fR, + \fBtime_res_t\fR \fIres\fR); +.fi + +.LP +.nf +\fBclock_t\fR \fBcv_reltimedwait_sig\fR(\fBkcondvar_t *\fR\fIcvp\fR, \fBkmutex_t *\fR\fImp\fR, \fBclock_t\fR \fIdelta\fR, + \fBtime_res_t\fR \fIres\fR); +.fi + .SH INTERFACE LEVEL -.sp .LP Solaris DDI specific (Solaris DDI). .SH PARAMETERS -.sp .ne 2 .na \fB\fIcvp\fR\fR @@ -114,8 +125,56 @@ \fBcv_timedwait_sig()\fR should return. .RE +.sp +.ne 2 +.na +\fB\fIres\fR\fR +.ad +.RS 11n +A value which describes the requested accuracy of the timeout argument. +The system may anticipate or defer the timeout based on the requested +accuracy to prevent unnecessary wakeups. The following identifiers are +valid arguments for this type: +.LP +.RS 4n +.B TR_NANOSEC +.RS 16n +Nanosecond granularity +.RE +.RE +.RS 4n +.B TR_MICROSEC +.RS 16n +Microsecond granularity +.RE +.RE +.RS 4n +.B TR_MILLISEC +.RS 16n +Millisecond granularity +.RE +.RE +.RS 4n +.B TR_SEC +.RS 16n +Second granularity +.RE +.RE +.RS 4n +.B TR_CLOCK_TICK +.RS 16n +Granularity of a kernel clock tick, commonly 100 or 1000 Hz. +.RE +.RE +.LP +Note that the granularity of these functions is in clock ticks, +therefore the only values which will have an effect are: +.B TR_SEC +and +.B TR_CLOCK_TICK . +.RE + .SH DESCRIPTION -.sp .LP Condition variables are a standard form of thread synchronization. They are designed to be used with mutual exclusion locks (mutexes). The associated mutex @@ -168,16 +227,32 @@ For both \fBcv_timedwait()\fR and \fBcv_timedwait_sig()\fR, time is in absolute clock ticks since the last system reboot. The current time may be found by calling \fBddi_get_lbolt\fR(9F). +.sp +.LP +The functions +.B cv_reltimedwait() +and +.B cv_reltimedwait_sig() +behave similarly to +.B cv_timedwait() and +.B cv_timedwait_sig() +respectively, except instead of taking a time in absolute clock ticks, +they take a relative number of clock ticks to wait. In addition, both +functions take an additional argument +.I res, +which specifies the desired granularity that the system should default +to, generally the value +.B TR_CLOCK_TICK . .SH RETURN VALUES -.sp .ne 2 .na \fB\fB0\fR\fR .ad .RS 9n -For \fBcv_wait_sig()\fR and \fBcv_timedwait_sig()\fR indicates that the -condition was not necessarily signaled and the function returned because a -signal (as in \fBkill\fR(2)) was pending. +For \fBcv_wait_sig()\fR, \fBcv_timedwait_sig()\fR, and +\fBcv_reltimedwait_sig()\fR indicates that the condition was not necessarily +signaled and the function returned because a signal (as in \fBkill\fR(2)) was +pending. .RE .sp @@ -186,9 +261,9 @@ \fB\fB\(mi1\fR\fR .ad .RS 9n -For \fBcv_timedwait()\fR and \fBcv_timedwait_sig()\fR indicates that the -condition was not necessarily signaled and the function returned because the -timeout time was reached. +For \fBcv_timedwait()\fR, \fBcv_timedwait_sig()\fR, \fBcv_reltimedwait()\fR, and +\fBcv_reltimedwait_sig()\fR, indicates that the condition was not necessarily +signaled and the function returned because the timeout time was reached. .RE .sp @@ -197,23 +272,24 @@ \fB\fB>0\fR\fR .ad .RS 9n -For \fBcv_wait_sig()\fR, \fBcv_timedwait()\fR or \fBcv_timedwait_sig()\fR -indicates that the condition was met and the function returned due to a call to -\fBcv_signal()\fR or \fBcv_broadcast()\fR, or due to a premature wakeup (see -NOTES). +For \fBcv_wait_sig()\fR, \fBcv_timedwait()\fR, \fBcv_timedwait_sig()\fR, +\fBcv_reltimedwait()\fR, and \fBcv_reltimedwait_sig()\fR, indicates that the +condition was met and the function returned due to a call to \fBcv_signal()\fR +or \fBcv_broadcast()\fR, or due to a premature wakeup (see NOTES). .RE .SH CONTEXT -.sp .LP These functions can be called from user, kernel or interrupt context. In most -cases, however, \fBcv_wait()\fR, \fBcv_timedwait()\fR, \fBcv_wait_sig()\fR, and -\fBcv_timedwait_sig()\fR should not be called from interrupt context, and +cases, however, \fBcv_wait()\fR, \fBcv_timedwait()\fR, \fBcv_wait_sig()\fR, +\fBcv_timedwait_sig()\fR, \fBcv_reltimedwait()\fR, and +\fBcv_reltimedwait_sig()\fR, should not be called from interrupt context, and cannot be called from a high-level interrupt context. .sp .LP -If \fBcv_wait()\fR, \fBcv_timedwait()\fR, \fBcv_wait_sig()\fR, or -\fBcv_timedwait_sig()\fR are used from interrupt context, lower-priority +If \fBcv_wait()\fR, \fBcv_timedwait()\fR, \fBcv_wait_sig()\fR, +\fBcv_timedwait_sig()\fR, \fBcv_reltimedwait()\fR, or +\fBcv_reltimedwait_sig()\fR, are used from interrupt context, lower-priority interrupts will not be serviced during the wait. This means that if the thread that will eventually perform the wakeup becomes blocked on anything that requires the lower-priority interrupt, the system will hang. @@ -264,16 +340,16 @@ .in -2 .SH NOTES -.sp .LP It is possible for \fBcv_wait()\fR, \fBcv_wait_sig()\fR, \fBcv_timedwait()\fR, -and \fBcv_timedwait_sig()\fR to return prematurely, that is, not due to a call -to \fBcv_signal()\fR or \fBcv_broadcast()\fR. This occurs most commonly in the -case of \fBcv_wait_sig()\fR and \fBcv_timedwait_sig()\fR when the thread is -stopped and restarted by job control signals or by a debugger, but can happen -in other cases as well, even for \fBcv_wait()\fR. Code that calls these -functions must always recheck the reason for blocking and call again if the -reason for blocking is still true. +\fBcv_timedwait_sig()\fR, \fBcv_reltimedwait()\fR, and +\fBcv_reltimedwait_sig()\fR to return prematurely, that is, not due to a call to +\fBcv_signal()\fR or \fBcv_broadcast()\fR. This occurs most commonly in the case +of \fBcv_wait_sig()\fR and \fBcv_timedwait_sig()\fR when the thread is stopped +and restarted by job control signals or by a debugger, but can happen in other +cases as well, even for \fBcv_wait()\fR. Code that calls these functions must +always recheck the reason for blocking and call again if the reason for blocking +is still true. .sp .LP If your driver needs to wait on behalf of processes that have real-time @@ -284,13 +360,13 @@ .LP Not all threads can receive signals from user level processes. In cases where such reception is impossible (such as during execution of \fBclose\fR(9E) due -to \fBexit\fR(2)), \fBcv_wait_sig()\fR behaves as \fBcv_wait()\fR, and -\fBcv_timedwait_sig()\fR behaves as \fBcv_timedwait()\fR. To avoid unkillable +to \fBexit\fR(2)), \fBcv_wait_sig()\fR behaves as \fBcv_wait()\fR, +\fBcv_timedwait_sig()\fR behaves as \fBcv_timedwait()\fR, and +\fBcv_reltimedwait_sig()\fR behaves as \fBcv_reltimedwait()\fR. To avoid unkillable processes, users of these functions may need to protect against waiting indefinitely for events that might not occur. The \fBddi_can_receive_sig\fR(9F) function is provided to detect when signal reception is possible. .SH SEE ALSO -.sp .LP \fBkill\fR(2), \fBddi_can_receive_sig\fR(9F), \fBddi_get_lbolt\fR(9F), \fBmutex\fR(9F), \fBmutex_init\fR(9F)
--- a/usr/src/pkg/manifests/SUNWcs.man1.inc Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/pkg/manifests/SUNWcs.man1.inc Sun Jan 04 07:19:22 2015 -0800 @@ -108,6 +108,7 @@ file path=usr/share/man/man1/kill.1 file path=usr/share/man/man1/kmfcfg.1 file path=usr/share/man/man1/ksh93.1 +file path=usr/share/man/man1/kvmstat.1 file path=usr/share/man/man1/ld.so.1.1 file path=usr/share/man/man1/less.1 file path=usr/share/man/man1/lesskey.1
--- a/usr/src/pkg/manifests/system-kernel.man2.inc Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/pkg/manifests/system-kernel.man2.inc Sun Jan 04 07:19:22 2015 -0800 @@ -180,6 +180,7 @@ link path=usr/share/man/man2/facl.2 target=acl.2 link path=usr/share/man/man2/fchdir.2 target=chdir.2 link path=usr/share/man/man2/fchmod.2 target=chmod.2 +link path=usr/share/man/man2/fchmodat.2 target=chmod.2 link path=usr/share/man/man2/fchown.2 target=chown.2 link path=usr/share/man/man2/fchownat.2 target=chown.2 link path=usr/share/man/man2/fchroot.2 target=chroot.2 @@ -213,6 +214,7 @@ link path=usr/share/man/man2/openat.2 target=open.2 link path=usr/share/man/man2/pathconf.2 target=fpathconf.2 link path=usr/share/man/man2/pipe2.2 target=pipe.2 +link path=usr/share/man/man2/ppoll.2 target=poll.2 link path=usr/share/man/man2/pread.2 target=read.2 link path=usr/share/man/man2/pset_assign.2 target=pset_create.2 link path=usr/share/man/man2/pset_destroy.2 target=pset_create.2
--- a/usr/src/pkg/manifests/system-library.man3c.inc Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/pkg/manifests/system-library.man3c.inc Sun Jan 04 07:19:22 2015 -0800 @@ -56,6 +56,7 @@ file path=usr/share/man/man3c/catopen.3c file path=usr/share/man/man3c/cfgetispeed.3c file path=usr/share/man/man3c/cfsetispeed.3c +file path=usr/share/man/man3c/clearenv.3c file path=usr/share/man/man3c/clock.3c file path=usr/share/man/man3c/clock_nanosleep.3c file path=usr/share/man/man3c/clock_settime.3c @@ -108,6 +109,7 @@ file path=usr/share/man/man3c/exit.3c file path=usr/share/man/man3c/fattach.3c file path=usr/share/man/man3c/fclose.3c +file path=usr/share/man/man3c/fcloseall.3c file path=usr/share/man/man3c/fdatasync.3c file path=usr/share/man/man3c/fdetach.3c file path=usr/share/man/man3c/fdopen.3c @@ -155,12 +157,14 @@ file path=usr/share/man/man3c/getlogin.3c file path=usr/share/man/man3c/getmntent.3c file path=usr/share/man/man3c/getnetgrent.3c +file path=usr/share/man/man3c/get_nprocs.3c file path=usr/share/man/man3c/getopt.3c file path=usr/share/man/man3c/getpagesize.3c file path=usr/share/man/man3c/getpagesizes.3c file path=usr/share/man/man3c/getpass.3c file path=usr/share/man/man3c/getpeerucred.3c file path=usr/share/man/man3c/getpriority.3c +file path=usr/share/man/man3c/getprogname.3c file path=usr/share/man/man3c/getpw.3c file path=usr/share/man/man3c/getpwnam.3c file path=usr/share/man/man3c/getrusage.3c @@ -310,6 +314,7 @@ file path=usr/share/man/man3c/pthread_key_delete.3c file path=usr/share/man/man3c/pthread_kill.3c file path=usr/share/man/man3c/pthread_mutex_getprioceiling.3c +file path=usr/share/man/man3c/pthread_mutex_consistent.3c file path=usr/share/man/man3c/pthread_mutex_init.3c file path=usr/share/man/man3c/pthread_mutex_lock.3c file path=usr/share/man/man3c/pthread_mutex_consistent.3c @@ -401,6 +406,7 @@ file path=usr/share/man/man3c/sigstack.3c file path=usr/share/man/man3c/sigwaitinfo.3c file path=usr/share/man/man3c/sleep.3c +file path=usr/share/man/man3c/smt_pause.3c file path=usr/share/man/man3c/ssignal.3c file path=usr/share/man/man3c/stack_getbounds.3c file path=usr/share/man/man3c/stack_inbounds.3c @@ -666,6 +672,7 @@ link path=usr/share/man/man3c/btowc_l.3c target=btowc.3c link path=usr/share/man/man3c/bzero.3c target=bstring.3c link path=usr/share/man/man3c/calloc.3c target=malloc.3c +link path=usr/share/man/man3c/canonicalize_file_name.3c target=realpath.3c link path=usr/share/man/man3c/catclose.3c target=catopen.3c link path=usr/share/man/man3c/cfgetospeed.3c target=cfgetispeed.3c link path=usr/share/man/man3c/cfsetospeed.3c target=cfsetispeed.3c @@ -735,6 +742,8 @@ link path=usr/share/man/man3c/fdopendir.3c target=opendir.3c link path=usr/share/man/man3c/fdwalk.3c target=closefrom.3c link path=usr/share/man/man3c/feof.3c target=ferror.3c +link path=usr/share/man/man3c/ffsl.3c target=ffs.3c +link path=usr/share/man/man3c/ffsll.3c target=ffs.3c link path=usr/share/man/man3c/fgetgrent.3c target=getgrnam.3c link path=usr/share/man/man3c/fgetgrent_r.3c target=getgrnam.3c link path=usr/share/man/man3c/fgetpwent.3c target=getpwnam.3c @@ -747,6 +756,9 @@ link path=usr/share/man/man3c/file_to_decimal.3c target=string_to_decimal.3c link path=usr/share/man/man3c/fileno.3c target=ferror.3c link path=usr/share/man/man3c/finite.3c target=isnand.3c +link path=usr/share/man/man3c/fls.3c target=ffs.3c +link path=usr/share/man/man3c/flsl.3c target=ffs.3c +link path=usr/share/man/man3c/flsll.3c target=ffs.3c link path=usr/share/man/man3c/fpclass.3c target=isnand.3c link path=usr/share/man/man3c/fpgetmask.3c target=fpgetround.3c link path=usr/share/man/man3c/fpgetsticky.3c target=fpgetround.3c @@ -784,6 +796,7 @@ link path=usr/share/man/man3c/getlogin_r.3c target=getlogin.3c link path=usr/share/man/man3c/getmntany.3c target=getmntent.3c link path=usr/share/man/man3c/getnetgrent_r.3c target=getnetgrent.3c +link path=usr/share/man/man3c/get_nprocs_conf.3c target=get_nprocs.3c link path=usr/share/man/man3c/getpassphrase.3c target=getpass.3c link path=usr/share/man/man3c/getpwent.3c target=getpwnam.3c link path=usr/share/man/man3c/getpwent_r.3c target=getpwnam.3c @@ -915,9 +928,11 @@ link path=usr/share/man/man3c/memchr.3c target=memory.3c link path=usr/share/man/man3c/memcmp.3c target=memory.3c link path=usr/share/man/man3c/memcpy.3c target=memory.3c +link path=usr/share/man/man3c/memmem.3c target=memory.3c link path=usr/share/man/man3c/memmove.3c target=memory.3c link path=usr/share/man/man3c/memset.3c target=memory.3c link path=usr/share/man/man3c/minor.3c target=makedev.3c +link path=usr/share/man/man3c/mkfifoat.3c target=mkfifo.3c link path=usr/share/man/man3c/mkdtemp.3c target=mkstemp.3c link path=usr/share/man/man3c/mkfifoat.3c target=mkfifo.3c link path=usr/share/man/man3c/mkostemp.3c target=mkstemp.3c @@ -1159,6 +1174,7 @@ link path=usr/share/man/man3c/setlogmask.3c target=syslog.3c link path=usr/share/man/man3c/setnetgrent.3c target=getnetgrent.3c link path=usr/share/man/man3c/setpriority.3c target=getpriority.3c +link path=usr/share/man/man3c/setprogname.3c target=getprogname.3c link path=usr/share/man/man3c/setpwent.3c target=getpwnam.3c link path=usr/share/man/man3c/setspent.3c target=getspnam.3c link path=usr/share/man/man3c/setstate.3c target=random.3c @@ -1194,15 +1210,21 @@ link path=usr/share/man/man3c/stderr.3c target=stdio.3c link path=usr/share/man/man3c/stdin.3c target=stdio.3c link path=usr/share/man/man3c/stdout.3c target=stdio.3c +link path=usr/share/man/man3c/stpcpy.3c target=string.3c +link path=usr/share/man/man3c/stpncpy.3c target=string.3c link path=usr/share/man/man3c/strcasecmp.3c target=string.3c link path=usr/share/man/man3c/strcasecmp_l.3c target=string.3c +link path=usr/share/man/man3c/strcasestr.3c target=string.3c +link path=usr/share/man/man3c/strcasestr_l.3c target=string.3c link path=usr/share/man/man3c/strcat.3c target=string.3c link path=usr/share/man/man3c/strchr.3c target=string.3c +link path=usr/share/man/man3c/strchrnul.3c target=string.3c link path=usr/share/man/man3c/strcmp.3c target=string.3c link path=usr/share/man/man3c/strcoll_l.3c target=strcoll.3c link path=usr/share/man/man3c/strcpy.3c target=string.3c link path=usr/share/man/man3c/strcspn.3c target=string.3c link path=usr/share/man/man3c/strdup.3c target=string.3c +link path=usr/share/man/man3c/strdupa.3c target=string.3c link path=usr/share/man/man3c/strerror_r.3c target=strerror.3c link path=usr/share/man/man3c/strfmon_l.3c target=strfmon.3c link path=usr/share/man/man3c/strftime_l.3c target=strftime.3c @@ -1214,7 +1236,10 @@ link path=usr/share/man/man3c/strncat.3c target=string.3c link path=usr/share/man/man3c/strncmp.3c target=string.3c link path=usr/share/man/man3c/strncpy.3c target=string.3c +link path=usr/share/man/man3c/strndup.3c target=string.3c +link path=usr/share/man/man3c/strndupa.3c target=string.3c link path=usr/share/man/man3c/strnlen.3c target=string.3c +link path=usr/share/man/man3c/strnstr.3c target=string.3c link path=usr/share/man/man3c/strpbrk.3c target=string.3c link path=usr/share/man/man3c/strptime_l.3c target=strptime.3c link path=usr/share/man/man3c/strrchr.3c target=string.3c
--- a/usr/src/uts/common/fs/hsfs/hsfs_vnops.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/common/fs/hsfs/hsfs_vnops.c Sun Jan 04 07:19:22 2015 -0800 @@ -1585,8 +1585,7 @@ /* does not support write */ if (rw == S_WRITE) { - panic("write attempt on READ ONLY HSFS"); - /*NOTREACHED*/ + return (EROFS); } if (vp->v_flag & VNOMAP) { @@ -1798,6 +1797,9 @@ if (vp->v_flag & VNOMAP) return (ENOSYS); + if ((prot & PROT_WRITE) && (flags & MAP_SHARED)) + return (ENOSYS); + if (off > HS_MAXFILEOFF || off < 0 || (off + len) < 0 || (off + len) > HS_MAXFILEOFF) return (ENXIO);
--- a/usr/src/uts/common/fs/nfs/nfs_auth.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/common/fs/nfs/nfs_auth.c Sun Jan 04 07:19:22 2015 -0800 @@ -783,7 +783,7 @@ struct netbuf *claddr; struct auth_cache **head; struct auth_cache *p; - struct auth_cache *prev = NULL; + struct auth_cache *prev; int access; time_t refresh; @@ -818,7 +818,9 @@ rw_enter(&exi->exi_cache_lock, RW_READER); head = &exi->exi_cache[hash(&addr)]; - for (p = *head; p; p = p->auth_next) { +retry: + prev = NULL; + for (p = *head; p != NULL; p = p->auth_next) { if (EQADDR(&addr, &p->auth_addr) && flavor == p->auth_flavor && crgetuid(cr) == p->auth_clnt_uid && crgetgid(cr) == p->auth_clnt_gid) @@ -831,44 +833,65 @@ * In a case the client's supplemental groups changed we need * to discard the auth_cache entry and re-retrieve it. */ - mutex_enter(&p->auth_lock); if (p->auth_clnt_ngids != crgetngroups(cr) || bcmp(p->auth_clnt_gids, crgetgroups(cr), p->auth_clnt_ngids * sizeof (gid_t))) { - auth_state_t prev_state = p->auth_state; - - p->auth_state = NFS_AUTH_INVALID; - mutex_exit(&p->auth_lock); + struct auth_cache *next; - if (prev_state == NFS_AUTH_FRESH) { + /* + * To remove the auth_cache entry from exi we need to + * hold the exi_cache_lock for write. If we do not + * have it yet, we will try to upgrade, or re-lock as a + * last resort. In a case of re-lock we will retry the + * search for the auth_cache entry because it might + * changed in the meantime. + */ + ASSERT(RW_LOCK_HELD(&exi->exi_cache_lock)); + if (rw_read_locked(&exi->exi_cache_lock) != 0) { if (rw_tryupgrade(&exi->exi_cache_lock) == 0) { - struct auth_cache *tmp; - rw_exit(&exi->exi_cache_lock); rw_enter(&exi->exi_cache_lock, RW_WRITER); - prev = NULL; - for (tmp = *head; tmp != NULL; - tmp = tmp->auth_next) { - if (p == tmp) - break; - prev = p; - } + goto retry; } + } - if (prev == NULL) - exi->exi_cache[hash(&addr)] = - p->auth_next; - else - prev->auth_next = p->auth_next; + /* + * Now, remove the entry from exi and free it, or place + * it at the dead list. + */ + next = p->auth_next; + mutex_enter(&p->auth_lock); + if (p->auth_state != NFS_AUTH_FRESH) { + p->auth_state = NFS_AUTH_INVALID; + mutex_exit(&p->auth_lock); + mutex_enter(&refreshq_lock); + p->auth_next = refreshq_dead_entries; + refreshq_dead_entries = p; + mutex_exit(&refreshq_lock); + } else { + mutex_exit(&p->auth_lock); nfsauth_free_node(p); } + /* + * Finally, disconnect the entry from exi + */ + if (prev == NULL) + *head = next; + else + prev->auth_next = next; + goto retrieve; } - mutex_exit(&p->auth_lock); + + /* + * If we hold the lock for write, downgrade + */ + if (rw_read_locked(&exi->exi_cache_lock) == 0) + rw_downgrade(&exi->exi_cache_lock); nfsauth_cache_hit++; @@ -1084,6 +1107,27 @@ int authnone_entry = -1; /* + * By default root is mapped to anonymous user. + * This might get overriden later in nfsauth_cache_get(). + */ + if (crgetuid(cr) == 0) { + if (uid != NULL) + *uid = exi->exi_export.ex_anon; + if (gid != NULL) + *gid = exi->exi_export.ex_anon; + } else { + if (uid != NULL) + *uid = crgetuid(cr); + if (gid != NULL) + *gid = crgetgid(cr); + } + + if (ngids != NULL) + *ngids = 0; + if (gids != NULL) + *gids = NULL; + + /* * Get the nfs flavor number from xprt. */ flavor = (int)(uintptr_t)req->rq_xprt->xp_cookie; @@ -1119,27 +1163,6 @@ } /* - * By default root is mapped to anonymous user. - * This might get overriden later in nfsauth_cache_get(). - */ - if (crgetuid(cr) == 0) { - if (uid != NULL) - *uid = exi->exi_export.ex_anon; - if (gid != NULL) - *gid = exi->exi_export.ex_anon; - } else { - if (uid != NULL) - *uid = crgetuid(cr); - if (gid != NULL) - *gid = crgetgid(cr); - } - - if (ngids != NULL) - *ngids = 0; - if (gids != NULL) - *gids = NULL; - - /* * If the flavor is in the ex_secinfo list, but not an explicitly * shared flavor by the user, it is a result of the nfsv4 server * namespace setup. We will grant an RO permission similar for
--- a/usr/src/uts/common/fs/vfs.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/common/fs/vfs.c Sun Jan 04 07:19:22 2015 -0800 @@ -20,6 +20,7 @@ */ /* * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ @@ -1129,6 +1130,7 @@ struct pathname pn, rpn; vsk_anchor_t *vskap; char fstname[FSTYPSZ]; + zone_t *zone; /* * The v_flag value for the mount point vp is permanently set @@ -1590,9 +1592,24 @@ } /* - * Serialize with zone creations. + * Serialize with zone state transitions. + * See vfs_list_add; zone mounted into is: + * zone_find_by_path(refstr_value(vfsp->vfs_mntpt)) + * not the zone doing the mount (curproc->p_zone), but if we're already + * inside a NGZ, then we know what zone we are. */ - mount_in_progress(); + if (INGLOBALZONE(curproc)) { + zone = zone_find_by_path(mountpt); + ASSERT(zone != NULL); + } else { + zone = curproc->p_zone; + /* + * zone_find_by_path does a hold, so do one here too so that + * we can do a zone_rele after mount_completed. + */ + zone_hold(zone); + } + mount_in_progress(zone); /* * Instantiate (or reinstantiate) the file system. If appropriate, * splice it into the file system name space. @@ -1761,7 +1778,8 @@ vfs_unlock(vfsp); } - mount_completed(); + mount_completed(zone); + zone_rele(zone); if (splice) vn_vfsunlock(vp);
--- a/usr/src/uts/common/fs/zfs/arc.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/common/fs/zfs/arc.c Sun Jan 04 07:19:22 2015 -0800 @@ -111,7 +111,7 @@ * Note that the majority of the performance stats are manipulated * with atomic operations. * - * The L2ARC uses the l2arc_buflist_mtx global mutex for the following: + * The L2ARC uses the l2ad_mtx on each vdev for the following: * * - L2ARC buflist creation * - L2ARC buflist eviction @@ -149,13 +149,7 @@ static kcondvar_t arc_reclaim_thr_cv; /* used to signal reclaim thr */ static uint8_t arc_thread_exit; -#define ARC_REDUCE_DNLC_PERCENT 3 -uint_t arc_reduce_dnlc_percent = ARC_REDUCE_DNLC_PERCENT; - -typedef enum arc_reclaim_strategy { - ARC_RECLAIM_AGGR, /* Aggressive reclaim strategy */ - ARC_RECLAIM_CONS /* Conservative reclaim strategy */ -} arc_reclaim_strategy_t; +uint_t arc_reduce_dnlc_percent = 3; /* * The number of iterations through arc_evict_*() before we @@ -170,7 +164,19 @@ static int arc_p_min_shift = 4; /* log2(fraction of arc to reclaim) */ -static int arc_shrink_shift = 5; +static int arc_shrink_shift = 7; + +/* + * log2(fraction of ARC which must be free to allow growing). + * I.e. If there is less than arc_c >> arc_no_grow_shift free memory, + * when reading a new block into the ARC, we will evict an equal-sized block + * from the ARC. + * + * This must be less than arc_shrink_shift, so that when we shrink the ARC, + * we will still not allow it to grow. + */ +int arc_no_grow_shift = 5; + /* * minimum lifespan of a prefetch block in clock ticks @@ -293,9 +299,137 @@ kstat_named_t arcstat_c_min; kstat_named_t arcstat_c_max; kstat_named_t arcstat_size; + /* + * Number of bytes consumed by internal ARC structures necessary + * for tracking purposes; these structures are not actually + * backed by ARC buffers. This includes arc_buf_hdr_t structures + * (allocated via arc_buf_hdr_t_full and arc_buf_hdr_t_l2only + * caches), and arc_buf_t structures (allocated via arc_buf_t + * cache). + */ kstat_named_t arcstat_hdr_size; + /* + * Number of bytes consumed by ARC buffers of type equal to + * ARC_BUFC_DATA. This is generally consumed by buffers backing + * on disk user data (e.g. plain file contents). + */ kstat_named_t arcstat_data_size; + /* + * Number of bytes consumed by ARC buffers of type equal to + * ARC_BUFC_METADATA. This is generally consumed by buffers + * backing on disk data that is used for internal ZFS + * structures (e.g. ZAP, dnode, indirect blocks, etc). + */ + kstat_named_t arcstat_metadata_size; + /* + * Number of bytes consumed by various buffers and structures + * not actually backed with ARC buffers. This includes bonus + * buffers (allocated directly via zio_buf_* functions), + * dmu_buf_impl_t structures (allocated via dmu_buf_impl_t + * cache), and dnode_t structures (allocated via dnode_t cache). + */ kstat_named_t arcstat_other_size; + /* + * Total number of bytes consumed by ARC buffers residing in the + * arc_anon state. This includes *all* buffers in the arc_anon + * state; e.g. data, metadata, evictable, and unevictable buffers + * are all included in this value. + */ + kstat_named_t arcstat_anon_size; + /* + * Number of bytes consumed by ARC buffers that meet the + * following criteria: backing buffers of type ARC_BUFC_DATA, + * residing in the arc_anon state, and are eligible for eviction + * (e.g. have no outstanding holds on the buffer). + */ + kstat_named_t arcstat_anon_evictable_data; + /* + * Number of bytes consumed by ARC buffers that meet the + * following criteria: backing buffers of type ARC_BUFC_METADATA, + * residing in the arc_anon state, and are eligible for eviction + * (e.g. have no outstanding holds on the buffer). + */ + kstat_named_t arcstat_anon_evictable_metadata; + /* + * Total number of bytes consumed by ARC buffers residing in the + * arc_mru state. This includes *all* buffers in the arc_mru + * state; e.g. data, metadata, evictable, and unevictable buffers + * are all included in this value. + */ + kstat_named_t arcstat_mru_size; + /* + * Number of bytes consumed by ARC buffers that meet the + * following criteria: backing buffers of type ARC_BUFC_DATA, + * residing in the arc_mru state, and are eligible for eviction + * (e.g. have no outstanding holds on the buffer). + */ + kstat_named_t arcstat_mru_evictable_data; + /* + * Number of bytes consumed by ARC buffers that meet the + * following criteria: backing buffers of type ARC_BUFC_METADATA, + * residing in the arc_mru state, and are eligible for eviction + * (e.g. have no outstanding holds on the buffer). + */ + kstat_named_t arcstat_mru_evictable_metadata; + /* + * Total number of bytes that *would have been* consumed by ARC + * buffers in the arc_mru_ghost state. The key thing to note + * here, is the fact that this size doesn't actually indicate + * RAM consumption. The ghost lists only consist of headers and + * don't actually have ARC buffers linked off of these headers. + * Thus, *if* the headers had associated ARC buffers, these + * buffers *would have* consumed this number of bytes. + */ + kstat_named_t arcstat_mru_ghost_size; + /* + * Number of bytes that *would have been* consumed by ARC + * buffers that are eligible for eviction, of type + * ARC_BUFC_DATA, and linked off the arc_mru_ghost state. + */ + kstat_named_t arcstat_mru_ghost_evictable_data; + /* + * Number of bytes that *would have been* consumed by ARC + * buffers that are eligible for eviction, of type + * ARC_BUFC_METADATA, and linked off the arc_mru_ghost state. + */ + kstat_named_t arcstat_mru_ghost_evictable_metadata; + /* + * Total number of bytes consumed by ARC buffers residing in the + * arc_mfu state. This includes *all* buffers in the arc_mfu + * state; e.g. data, metadata, evictable, and unevictable buffers + * are all included in this value. + */ + kstat_named_t arcstat_mfu_size; + /* + * Number of bytes consumed by ARC buffers that are eligible for + * eviction, of type ARC_BUFC_DATA, and reside in the arc_mfu + * state. + */ + kstat_named_t arcstat_mfu_evictable_data; + /* + * Number of bytes consumed by ARC buffers that are eligible for + * eviction, of type ARC_BUFC_METADATA, and reside in the + * arc_mfu state. + */ + kstat_named_t arcstat_mfu_evictable_metadata; + /* + * Total number of bytes that *would have been* consumed by ARC + * buffers in the arc_mfu_ghost state. See the comment above + * arcstat_mru_ghost_size for more details. + */ + kstat_named_t arcstat_mfu_ghost_size; + /* + * Number of bytes that *would have been* consumed by ARC + * buffers that are eligible for eviction, of type + * ARC_BUFC_DATA, and linked off the arc_mfu_ghost state. + */ + kstat_named_t arcstat_mfu_ghost_evictable_data; + /* + * Number of bytes that *would have been* consumed by ARC + * buffers that are eligible for eviction, of type + * ARC_BUFC_METADATA, and linked off the arc_mru_ghost state. + */ + kstat_named_t arcstat_mfu_ghost_evictable_metadata; kstat_named_t arcstat_l2_hits; kstat_named_t arcstat_l2_misses; kstat_named_t arcstat_l2_feeds; @@ -308,6 +442,7 @@ kstat_named_t arcstat_l2_writes_hdr_miss; kstat_named_t arcstat_l2_evict_lock_retry; kstat_named_t arcstat_l2_evict_reading; + kstat_named_t arcstat_l2_evict_l1cached; kstat_named_t arcstat_l2_free_on_write; kstat_named_t arcstat_l2_abort_lowmem; kstat_named_t arcstat_l2_cksum_bad; @@ -362,7 +497,23 @@ { "size", KSTAT_DATA_UINT64 }, { "hdr_size", KSTAT_DATA_UINT64 }, { "data_size", KSTAT_DATA_UINT64 }, + { "metadata_size", KSTAT_DATA_UINT64 }, { "other_size", KSTAT_DATA_UINT64 }, + { "anon_size", KSTAT_DATA_UINT64 }, + { "anon_evictable_data", KSTAT_DATA_UINT64 }, + { "anon_evictable_metadata", KSTAT_DATA_UINT64 }, + { "mru_size", KSTAT_DATA_UINT64 }, + { "mru_evictable_data", KSTAT_DATA_UINT64 }, + { "mru_evictable_metadata", KSTAT_DATA_UINT64 }, + { "mru_ghost_size", KSTAT_DATA_UINT64 }, + { "mru_ghost_evictable_data", KSTAT_DATA_UINT64 }, + { "mru_ghost_evictable_metadata", KSTAT_DATA_UINT64 }, + { "mfu_size", KSTAT_DATA_UINT64 }, + { "mfu_evictable_data", KSTAT_DATA_UINT64 }, + { "mfu_evictable_metadata", KSTAT_DATA_UINT64 }, + { "mfu_ghost_size", KSTAT_DATA_UINT64 }, + { "mfu_ghost_evictable_data", KSTAT_DATA_UINT64 }, + { "mfu_ghost_evictable_metadata", KSTAT_DATA_UINT64 }, { "l2_hits", KSTAT_DATA_UINT64 }, { "l2_misses", KSTAT_DATA_UINT64 }, { "l2_feeds", KSTAT_DATA_UINT64 }, @@ -375,6 +526,7 @@ { "l2_writes_hdr_miss", KSTAT_DATA_UINT64 }, { "l2_evict_lock_retry", KSTAT_DATA_UINT64 }, { "l2_evict_reading", KSTAT_DATA_UINT64 }, + { "l2_evict_l1cached", KSTAT_DATA_UINT64 }, { "l2_free_on_write", KSTAT_DATA_UINT64 }, { "l2_abort_lowmem", KSTAT_DATA_UINT64 }, { "l2_cksum_bad", KSTAT_DATA_UINT64 }, @@ -466,8 +618,6 @@ static uint64_t arc_tempreserve; static uint64_t arc_loaned_bytes; -typedef struct l2arc_buf_hdr l2arc_buf_hdr_t; - typedef struct arc_callback arc_callback_t; struct arc_callback { @@ -488,29 +638,53 @@ arc_buf_t *awcb_buf; }; -struct arc_buf_hdr { - /* protected by hash lock */ - dva_t b_dva; - uint64_t b_birth; - uint64_t b_cksum0; - +/* + * ARC buffers are separated into multiple structs as a memory saving measure: + * - Common fields struct, always defined, and embedded within it: + * - L2-only fields, always allocated but undefined when not in L2ARC + * - L1-only fields, only allocated when in L1ARC + * + * Buffer in L1 Buffer only in L2 + * +------------------------+ +------------------------+ + * | arc_buf_hdr_t | | arc_buf_hdr_t | + * | | | | + * | | | | + * | | | | + * +------------------------+ +------------------------+ + * | l2arc_buf_hdr_t | | l2arc_buf_hdr_t | + * | (undefined if L1-only) | | | + * +------------------------+ +------------------------+ + * | l1arc_buf_hdr_t | + * | | + * | | + * | | + * | | + * +------------------------+ + * + * Because it's possible for the L2ARC to become extremely large, we can wind + * up eating a lot of memory in L2ARC buffer headers, so the size of a header + * is minimized by only allocating the fields necessary for an L1-cached buffer + * when a header is actually in the L1 cache. The sub-headers (l1arc_buf_hdr and + * l2arc_buf_hdr) are embedded rather than allocated separately to save a couple + * words in pointers. arc_hdr_realloc() is used to switch a header between + * these two allocation states. + */ +typedef struct l1arc_buf_hdr { kmutex_t b_freeze_lock; - zio_cksum_t *b_freeze_cksum; +#ifdef ZFS_DEBUG + /* + * used for debugging wtih kmem_flags - by allocating and freeing + * b_thawed when the buffer is thawed, we get a record of the stack + * trace that thawed it. + */ void *b_thawed; - - arc_buf_hdr_t *b_hash_next; +#endif + arc_buf_t *b_buf; - arc_flags_t b_flags; uint32_t b_datacnt; - - arc_callback_t *b_acb; + /* for waiting on writes to complete */ kcondvar_t b_cv; - /* immutable */ - arc_buf_contents_t b_type; - uint64_t b_size; - uint64_t b_spa; - /* protected by arc state mutex */ arc_state_t *b_state; list_node_t b_arc_node; @@ -521,8 +695,46 @@ /* self protecting */ refcount_t b_refcnt; - l2arc_buf_hdr_t *b_l2hdr; + arc_callback_t *b_acb; + /* temporary buffer holder for in-flight compressed data */ + void *b_tmp_cdata; +} l1arc_buf_hdr_t; + +typedef struct l2arc_dev l2arc_dev_t; + +typedef struct l2arc_buf_hdr { + /* protected by arc_buf_hdr mutex */ + l2arc_dev_t *b_dev; /* L2ARC device */ + uint64_t b_daddr; /* disk address, offset byte */ + /* real alloc'd buffer size depending on b_compress applied */ + int32_t b_asize; + list_node_t b_l2node; +} l2arc_buf_hdr_t; + +struct arc_buf_hdr { + /* protected by hash lock */ + dva_t b_dva; + uint64_t b_birth; + /* + * Even though this checksum is only set/verified when a buffer is in + * the L1 cache, it needs to be in the set of common fields because it + * must be preserved from the time before a buffer is written out to + * L2ARC until after it is read back in. + */ + zio_cksum_t *b_freeze_cksum; + + arc_buf_hdr_t *b_hash_next; + arc_flags_t b_flags; + + /* immutable */ + int32_t b_size; + uint64_t b_spa; + + /* L2ARC fields. Undefined when not in L2ARC. */ + l2arc_buf_hdr_t b_l2hdr; + /* L1ARC fields. Undefined when in l2arc_only state */ + l1arc_buf_hdr_t b_l1hdr; }; static arc_buf_t *arc_eviction_list; @@ -539,22 +751,38 @@ #define HDR_PREFETCH(hdr) ((hdr)->b_flags & ARC_FLAG_PREFETCH) #define HDR_FREED_IN_READ(hdr) ((hdr)->b_flags & ARC_FLAG_FREED_IN_READ) #define HDR_BUF_AVAILABLE(hdr) ((hdr)->b_flags & ARC_FLAG_BUF_AVAILABLE) -#define HDR_FREE_IN_PROGRESS(hdr) \ - ((hdr)->b_flags & ARC_FLAG_FREE_IN_PROGRESS) + #define HDR_L2CACHE(hdr) ((hdr)->b_flags & ARC_FLAG_L2CACHE) +#define HDR_L2COMPRESS(hdr) ((hdr)->b_flags & ARC_FLAG_L2COMPRESS) #define HDR_L2_READING(hdr) \ - ((hdr)->b_flags & ARC_FLAG_IO_IN_PROGRESS && \ - (hdr)->b_l2hdr != NULL) + (((hdr)->b_flags & ARC_FLAG_IO_IN_PROGRESS) && \ + ((hdr)->b_flags & ARC_FLAG_HAS_L2HDR)) #define HDR_L2_WRITING(hdr) ((hdr)->b_flags & ARC_FLAG_L2_WRITING) #define HDR_L2_EVICTED(hdr) ((hdr)->b_flags & ARC_FLAG_L2_EVICTED) #define HDR_L2_WRITE_HEAD(hdr) ((hdr)->b_flags & ARC_FLAG_L2_WRITE_HEAD) +#define HDR_ISTYPE_METADATA(hdr) \ + ((hdr)->b_flags & ARC_FLAG_BUFC_METADATA) +#define HDR_ISTYPE_DATA(hdr) (!HDR_ISTYPE_METADATA(hdr)) + +#define HDR_HAS_L1HDR(hdr) ((hdr)->b_flags & ARC_FLAG_HAS_L1HDR) +#define HDR_HAS_L2HDR(hdr) ((hdr)->b_flags & ARC_FLAG_HAS_L2HDR) + +/* For storing compression mode in b_flags */ +#define HDR_COMPRESS_OFFSET 24 +#define HDR_COMPRESS_NBITS 7 + +#define HDR_GET_COMPRESS(hdr) ((enum zio_compress)BF32_GET(hdr->b_flags, \ + HDR_COMPRESS_OFFSET, HDR_COMPRESS_NBITS)) +#define HDR_SET_COMPRESS(hdr, cmp) BF32_SET(hdr->b_flags, \ + HDR_COMPRESS_OFFSET, HDR_COMPRESS_NBITS, (cmp)) + /* * Other sizes */ -#define HDR_SIZE ((int64_t)sizeof (arc_buf_hdr_t)) -#define L2HDR_SIZE ((int64_t)sizeof (l2arc_buf_hdr_t)) +#define HDR_FULL_SIZE ((int64_t)sizeof (arc_buf_hdr_t)) +#define HDR_L2ONLY_SIZE ((int64_t)offsetof(arc_buf_hdr_t, b_l1hdr)) /* * Hash table routines @@ -618,7 +846,7 @@ /* * L2ARC Internals */ -typedef struct l2arc_dev { +struct l2arc_dev { vdev_t *l2ad_vdev; /* vdev */ spa_t *l2ad_spa; /* spa */ uint64_t l2ad_hand; /* next write location */ @@ -627,15 +855,15 @@ uint64_t l2ad_evict; /* last addr eviction reached */ boolean_t l2ad_first; /* first sweep through */ boolean_t l2ad_writing; /* currently writing */ - list_t *l2ad_buflist; /* buffer list */ + kmutex_t l2ad_mtx; /* lock for buffer list */ + list_t l2ad_buflist; /* buffer list */ list_node_t l2ad_node; /* device list node */ -} l2arc_dev_t; +}; static list_t L2ARC_dev_list; /* device list */ static list_t *l2arc_dev_list; /* device list pointer */ static kmutex_t l2arc_dev_mtx; /* device list mutex */ static l2arc_dev_t *l2arc_dev_last; /* last device used */ -static kmutex_t l2arc_buflist_mtx; /* mutex for all buflists */ static list_t L2ARC_free_on_write; /* free after write buf list */ static list_t *l2arc_free_on_write; /* free after write list ptr */ static kmutex_t l2arc_free_on_write_mtx; /* mutex for list */ @@ -655,18 +883,6 @@ arc_buf_hdr_t *l2wcb_head; /* head of write buflist */ } l2arc_write_callback_t; -struct l2arc_buf_hdr { - /* protected by arc_buf_hdr mutex */ - l2arc_dev_t *b_dev; /* L2ARC device */ - uint64_t b_daddr; /* disk address, offset byte */ - /* compression applied to buffer data */ - enum zio_compress b_compress; - /* real alloc'd buffer size depending on b_compress applied */ - int b_asize; - /* temporary buffer holder for in-flight compressed data */ - void *b_tmp_cdata; -}; - typedef struct l2arc_data_free { /* protected by l2arc_free_on_write_mtx */ void *l2df_data; @@ -685,12 +901,13 @@ static void arc_evict_ghost(arc_state_t *, uint64_t, int64_t); static void arc_buf_watch(arc_buf_t *); +static arc_buf_contents_t arc_buf_type(arc_buf_hdr_t *); +static uint32_t arc_bufc_to_flags(arc_buf_contents_t); + static boolean_t l2arc_write_eligible(uint64_t, arc_buf_hdr_t *); static void l2arc_read_done(zio_t *); -static void l2arc_hdr_stat_add(void); -static void l2arc_hdr_stat_remove(void); - -static boolean_t l2arc_compress_buf(l2arc_buf_hdr_t *); + +static boolean_t l2arc_compress_buf(arc_buf_hdr_t *); static void l2arc_decompress_zio(zio_t *, arc_buf_hdr_t *, enum zio_compress); static void l2arc_release_cdata_buf(arc_buf_hdr_t *); @@ -713,8 +930,7 @@ #define BUF_EMPTY(buf) \ ((buf)->b_dva.dva_word[0] == 0 && \ - (buf)->b_dva.dva_word[1] == 0 && \ - (buf)->b_cksum0 == 0) + (buf)->b_dva.dva_word[1] == 0) #define BUF_EQUAL(spa, dva, birth, buf) \ ((buf)->b_dva.dva_word[0] == (dva)->dva_word[0]) && \ @@ -727,7 +943,6 @@ hdr->b_dva.dva_word[0] = 0; hdr->b_dva.dva_word[1] = 0; hdr->b_birth = 0; - hdr->b_cksum0 = 0; } static arc_buf_hdr_t * @@ -757,6 +972,7 @@ * equal to elem in the hash table, then the already existing element * will be returned and the new element will not be inserted. * Otherwise returns NULL. + * If lockp == NULL, the caller is assumed to already hold the hash lock. */ static arc_buf_hdr_t * buf_hash_insert(arc_buf_hdr_t *hdr, kmutex_t **lockp) @@ -769,8 +985,14 @@ ASSERT(!DVA_IS_EMPTY(&hdr->b_dva)); ASSERT(hdr->b_birth != 0); ASSERT(!HDR_IN_HASH_TABLE(hdr)); - *lockp = hash_lock; - mutex_enter(hash_lock); + + if (lockp != NULL) { + *lockp = hash_lock; + mutex_enter(hash_lock); + } else { + ASSERT(MUTEX_HELD(hash_lock)); + } + for (fhdr = buf_hash_table.ht_table[idx], i = 0; fhdr != NULL; fhdr = fhdr->b_hash_next, i++) { if (BUF_EQUAL(hdr->b_spa, &hdr->b_dva, hdr->b_birth, fhdr)) @@ -825,7 +1047,8 @@ /* * Global data structures and functions for the buf kmem cache. */ -static kmem_cache_t *hdr_cache; +static kmem_cache_t *hdr_full_cache; +static kmem_cache_t *hdr_l2only_cache; static kmem_cache_t *buf_cache; static void @@ -837,7 +1060,8 @@ (buf_hash_table.ht_mask + 1) * sizeof (void *)); for (i = 0; i < BUF_LOCKS; i++) mutex_destroy(&buf_hash_table.ht_locks[i].ht_lock); - kmem_cache_destroy(hdr_cache); + kmem_cache_destroy(hdr_full_cache); + kmem_cache_destroy(hdr_l2only_cache); kmem_cache_destroy(buf_cache); } @@ -847,15 +1071,27 @@ */ /* ARGSUSED */ static int -hdr_cons(void *vbuf, void *unused, int kmflag) +hdr_full_cons(void *vbuf, void *unused, int kmflag) { arc_buf_hdr_t *hdr = vbuf; - bzero(hdr, sizeof (arc_buf_hdr_t)); - refcount_create(&hdr->b_refcnt); - cv_init(&hdr->b_cv, NULL, CV_DEFAULT, NULL); - mutex_init(&hdr->b_freeze_lock, NULL, MUTEX_DEFAULT, NULL); - arc_space_consume(sizeof (arc_buf_hdr_t), ARC_SPACE_HDRS); + bzero(hdr, HDR_FULL_SIZE); + cv_init(&hdr->b_l1hdr.b_cv, NULL, CV_DEFAULT, NULL); + refcount_create(&hdr->b_l1hdr.b_refcnt); + mutex_init(&hdr->b_l1hdr.b_freeze_lock, NULL, MUTEX_DEFAULT, NULL); + arc_space_consume(HDR_FULL_SIZE, ARC_SPACE_HDRS); + + return (0); +} + +/* ARGSUSED */ +static int +hdr_l2only_cons(void *vbuf, void *unused, int kmflag) +{ + arc_buf_hdr_t *hdr = vbuf; + + bzero(hdr, HDR_L2ONLY_SIZE); + arc_space_consume(HDR_L2ONLY_SIZE, ARC_SPACE_L2HDRS); return (0); } @@ -879,15 +1115,25 @@ */ /* ARGSUSED */ static void -hdr_dest(void *vbuf, void *unused) +hdr_full_dest(void *vbuf, void *unused) { arc_buf_hdr_t *hdr = vbuf; ASSERT(BUF_EMPTY(hdr)); - refcount_destroy(&hdr->b_refcnt); - cv_destroy(&hdr->b_cv); - mutex_destroy(&hdr->b_freeze_lock); - arc_space_return(sizeof (arc_buf_hdr_t), ARC_SPACE_HDRS); + cv_destroy(&hdr->b_l1hdr.b_cv); + refcount_destroy(&hdr->b_l1hdr.b_refcnt); + mutex_destroy(&hdr->b_l1hdr.b_freeze_lock); + arc_space_return(HDR_FULL_SIZE, ARC_SPACE_HDRS); +} + +/* ARGSUSED */ +static void +hdr_l2only_dest(void *vbuf, void *unused) +{ + arc_buf_hdr_t *hdr = vbuf; + + ASSERT(BUF_EMPTY(hdr)); + arc_space_return(HDR_L2ONLY_SIZE, ARC_SPACE_L2HDRS); } /* ARGSUSED */ @@ -941,8 +1187,11 @@ goto retry; } - hdr_cache = kmem_cache_create("arc_buf_hdr_t", sizeof (arc_buf_hdr_t), - 0, hdr_cons, hdr_dest, hdr_recl, NULL, NULL, 0); + hdr_full_cache = kmem_cache_create("arc_buf_hdr_t_full", HDR_FULL_SIZE, + 0, hdr_full_cons, hdr_full_dest, hdr_recl, NULL, NULL, 0); + hdr_l2only_cache = kmem_cache_create("arc_buf_hdr_t_l2only", + HDR_L2ONLY_SIZE, 0, hdr_l2only_cons, hdr_l2only_dest, hdr_recl, + NULL, NULL, 0); buf_cache = kmem_cache_create("arc_buf_t", sizeof (arc_buf_t), 0, buf_cons, buf_dest, NULL, NULL, NULL, 0); @@ -956,6 +1205,81 @@ } } +/* + * Transition between the two allocation states for the arc_buf_hdr struct. + * The arc_buf_hdr struct can be allocated with (hdr_full_cache) or without + * (hdr_l2only_cache) the fields necessary for the L1 cache - the smaller + * version is used when a cache buffer is only in the L2ARC in order to reduce + * memory usage. + */ +static arc_buf_hdr_t * +arc_hdr_realloc(arc_buf_hdr_t *hdr, kmem_cache_t *old, kmem_cache_t *new) +{ + ASSERT(HDR_HAS_L2HDR(hdr)); + + arc_buf_hdr_t *nhdr; + l2arc_dev_t *dev = hdr->b_l2hdr.b_dev; + + ASSERT((old == hdr_full_cache && new == hdr_l2only_cache) || + (old == hdr_l2only_cache && new == hdr_full_cache)); + + nhdr = kmem_cache_alloc(new, KM_PUSHPAGE); + + ASSERT(MUTEX_HELD(HDR_LOCK(hdr))); + buf_hash_remove(hdr); + + bcopy(hdr, nhdr, HDR_L2ONLY_SIZE); + if (new == hdr_full_cache) { + nhdr->b_flags |= ARC_FLAG_HAS_L1HDR; + /* + * arc_access and arc_change_state need to be aware that a + * header has just come out of L2ARC, so we set its state to + * l2c_only even though it's about to change. + */ + nhdr->b_l1hdr.b_state = arc_l2c_only; + } else { + ASSERT(hdr->b_l1hdr.b_buf == NULL); + ASSERT0(hdr->b_l1hdr.b_datacnt); + ASSERT(!list_link_active(&hdr->b_l1hdr.b_arc_node)); + /* + * We might be removing the L1hdr of a buffer which was just + * written out to L2ARC. If such a buffer is compressed then we + * need to free its b_tmp_cdata before destroying the header. + */ + if (hdr->b_l1hdr.b_tmp_cdata != NULL && + HDR_GET_COMPRESS(hdr) != ZIO_COMPRESS_OFF) + l2arc_release_cdata_buf(hdr); + nhdr->b_flags &= ~ARC_FLAG_HAS_L1HDR; + } + /* + * The header has been reallocated so we need to re-insert it into any + * lists it was on. + */ + (void) buf_hash_insert(nhdr, NULL); + + ASSERT(list_link_active(&hdr->b_l2hdr.b_l2node)); + + mutex_enter(&dev->l2ad_mtx); + + /* + * We must place the realloc'ed header back into the list at + * the same spot. Otherwise, if it's placed earlier in the list, + * l2arc_write_buffers() could find it during the function's + * write phase, and try to write it out to the l2arc. + */ + list_insert_after(&dev->l2ad_buflist, hdr, nhdr); + list_remove(&dev->l2ad_buflist, hdr); + + mutex_exit(&dev->l2ad_mtx); + + buf_discard_identity(hdr); + hdr->b_freeze_cksum = NULL; + kmem_cache_free(old, hdr); + + return (nhdr); +} + + #define ARC_MINTIME (hz>>4) /* 62 ms */ static void @@ -966,16 +1290,15 @@ if (!(zfs_flags & ZFS_DEBUG_MODIFY)) return; - mutex_enter(&buf->b_hdr->b_freeze_lock); - if (buf->b_hdr->b_freeze_cksum == NULL || - (buf->b_hdr->b_flags & ARC_FLAG_IO_ERROR)) { - mutex_exit(&buf->b_hdr->b_freeze_lock); + mutex_enter(&buf->b_hdr->b_l1hdr.b_freeze_lock); + if (buf->b_hdr->b_freeze_cksum == NULL || HDR_IO_ERROR(buf->b_hdr)) { + mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock); return; } fletcher_2_native(buf->b_data, buf->b_hdr->b_size, &zc); if (!ZIO_CHECKSUM_EQUAL(*buf->b_hdr->b_freeze_cksum, zc)) panic("buffer modified while frozen!"); - mutex_exit(&buf->b_hdr->b_freeze_lock); + mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock); } static int @@ -984,10 +1307,10 @@ zio_cksum_t zc; int equal; - mutex_enter(&buf->b_hdr->b_freeze_lock); + mutex_enter(&buf->b_hdr->b_l1hdr.b_freeze_lock); fletcher_2_native(buf->b_data, buf->b_hdr->b_size, &zc); equal = ZIO_CHECKSUM_EQUAL(*buf->b_hdr->b_freeze_cksum, zc); - mutex_exit(&buf->b_hdr->b_freeze_lock); + mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock); return (equal); } @@ -998,15 +1321,15 @@ if (!force && !(zfs_flags & ZFS_DEBUG_MODIFY)) return; - mutex_enter(&buf->b_hdr->b_freeze_lock); + mutex_enter(&buf->b_hdr->b_l1hdr.b_freeze_lock); if (buf->b_hdr->b_freeze_cksum != NULL) { - mutex_exit(&buf->b_hdr->b_freeze_lock); + mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock); return; } buf->b_hdr->b_freeze_cksum = kmem_alloc(sizeof (zio_cksum_t), KM_SLEEP); fletcher_2_native(buf->b_data, buf->b_hdr->b_size, buf->b_hdr->b_freeze_cksum); - mutex_exit(&buf->b_hdr->b_freeze_lock); + mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock); arc_buf_watch(buf); } @@ -1053,30 +1376,58 @@ #endif } +static arc_buf_contents_t +arc_buf_type(arc_buf_hdr_t *hdr) +{ + if (HDR_ISTYPE_METADATA(hdr)) { + return (ARC_BUFC_METADATA); + } else { + return (ARC_BUFC_DATA); + } +} + +static uint32_t +arc_bufc_to_flags(arc_buf_contents_t type) +{ + switch (type) { + case ARC_BUFC_DATA: + /* metadata field is 0 if buffer contains normal data */ + return (0); + case ARC_BUFC_METADATA: + return (ARC_FLAG_BUFC_METADATA); + default: + break; + } + panic("undefined ARC buffer type!"); + return ((uint32_t)-1); +} + void arc_buf_thaw(arc_buf_t *buf) { if (zfs_flags & ZFS_DEBUG_MODIFY) { - if (buf->b_hdr->b_state != arc_anon) + if (buf->b_hdr->b_l1hdr.b_state != arc_anon) panic("modifying non-anon buffer!"); - if (buf->b_hdr->b_flags & ARC_FLAG_IO_IN_PROGRESS) + if (HDR_IO_IN_PROGRESS(buf->b_hdr)) panic("modifying buffer while i/o in progress!"); arc_cksum_verify(buf); } - mutex_enter(&buf->b_hdr->b_freeze_lock); + mutex_enter(&buf->b_hdr->b_l1hdr.b_freeze_lock); if (buf->b_hdr->b_freeze_cksum != NULL) { kmem_free(buf->b_hdr->b_freeze_cksum, sizeof (zio_cksum_t)); buf->b_hdr->b_freeze_cksum = NULL; } +#ifdef ZFS_DEBUG if (zfs_flags & ZFS_DEBUG_MODIFY) { - if (buf->b_hdr->b_thawed) - kmem_free(buf->b_hdr->b_thawed, 1); - buf->b_hdr->b_thawed = kmem_alloc(1, KM_SLEEP); + if (buf->b_hdr->b_l1hdr.b_thawed != NULL) + kmem_free(buf->b_hdr->b_l1hdr.b_thawed, 1); + buf->b_hdr->b_l1hdr.b_thawed = kmem_alloc(1, KM_SLEEP); } - - mutex_exit(&buf->b_hdr->b_freeze_lock); +#endif + + mutex_exit(&buf->b_hdr->b_l1hdr.b_freeze_lock); arc_buf_unwatch(buf); } @@ -1093,7 +1444,7 @@ mutex_enter(hash_lock); ASSERT(buf->b_hdr->b_freeze_cksum != NULL || - buf->b_hdr->b_state == arc_anon); + buf->b_hdr->b_l1hdr.b_state == arc_anon); arc_cksum_compute(buf, B_FALSE); mutex_exit(hash_lock); @@ -1102,30 +1453,34 @@ static void add_reference(arc_buf_hdr_t *hdr, kmutex_t *hash_lock, void *tag) { + ASSERT(HDR_HAS_L1HDR(hdr)); ASSERT(MUTEX_HELD(hash_lock)); - - if ((refcount_add(&hdr->b_refcnt, tag) == 1) && - (hdr->b_state != arc_anon)) { - uint64_t delta = hdr->b_size * hdr->b_datacnt; - list_t *list = &hdr->b_state->arcs_list[hdr->b_type]; - uint64_t *size = &hdr->b_state->arcs_lsize[hdr->b_type]; - - ASSERT(!MUTEX_HELD(&hdr->b_state->arcs_mtx)); - mutex_enter(&hdr->b_state->arcs_mtx); - ASSERT(list_link_active(&hdr->b_arc_node)); - list_remove(list, hdr); - if (GHOST_STATE(hdr->b_state)) { - ASSERT0(hdr->b_datacnt); - ASSERT3P(hdr->b_buf, ==, NULL); - delta = hdr->b_size; + arc_state_t *state = hdr->b_l1hdr.b_state; + + if ((refcount_add(&hdr->b_l1hdr.b_refcnt, tag) == 1) && + (state != arc_anon)) { + /* We don't use the L2-only state list. */ + if (state != arc_l2c_only) { + uint64_t delta = hdr->b_size * hdr->b_l1hdr.b_datacnt; + list_t *list = &state->arcs_list[arc_buf_type(hdr)]; + uint64_t *size = &state->arcs_lsize[arc_buf_type(hdr)]; + + ASSERT(!MUTEX_HELD(&state->arcs_mtx)); + mutex_enter(&state->arcs_mtx); + ASSERT(list_link_active(&hdr->b_l1hdr.b_arc_node)); + list_remove(list, hdr); + if (GHOST_STATE(state)) { + ASSERT0(hdr->b_l1hdr.b_datacnt); + ASSERT3P(hdr->b_l1hdr.b_buf, ==, NULL); + delta = hdr->b_size; + } + ASSERT(delta > 0); + ASSERT3U(*size, >=, delta); + atomic_add_64(size, -delta); + mutex_exit(&state->arcs_mtx); } - ASSERT(delta > 0); - ASSERT3U(*size, >=, delta); - atomic_add_64(size, -delta); - mutex_exit(&hdr->b_state->arcs_mtx); /* remove the prefetch flag if we get a reference */ - if (hdr->b_flags & ARC_FLAG_PREFETCH) - hdr->b_flags &= ~ARC_FLAG_PREFETCH; + hdr->b_flags &= ~ARC_FLAG_PREFETCH; } } @@ -1133,21 +1488,27 @@ remove_reference(arc_buf_hdr_t *hdr, kmutex_t *hash_lock, void *tag) { int cnt; - arc_state_t *state = hdr->b_state; - + arc_state_t *state = hdr->b_l1hdr.b_state; + + ASSERT(HDR_HAS_L1HDR(hdr)); ASSERT(state == arc_anon || MUTEX_HELD(hash_lock)); ASSERT(!GHOST_STATE(state)); - if (((cnt = refcount_remove(&hdr->b_refcnt, tag)) == 0) && + /* + * arc_l2c_only counts as a ghost state so we don't need to explicitly + * check to prevent usage of the arc_l2c_only list. + */ + if (((cnt = refcount_remove(&hdr->b_l1hdr.b_refcnt, tag)) == 0) && (state != arc_anon)) { - uint64_t *size = &state->arcs_lsize[hdr->b_type]; + uint64_t *size = &state->arcs_lsize[arc_buf_type(hdr)]; ASSERT(!MUTEX_HELD(&state->arcs_mtx)); mutex_enter(&state->arcs_mtx); - ASSERT(!list_link_active(&hdr->b_arc_node)); - list_insert_head(&state->arcs_list[hdr->b_type], hdr); - ASSERT(hdr->b_datacnt > 0); - atomic_add_64(size, hdr->b_size * hdr->b_datacnt); + ASSERT(!list_link_active(&hdr->b_l1hdr.b_arc_node)); + list_insert_head(&state->arcs_list[arc_buf_type(hdr)], hdr); + ASSERT(hdr->b_l1hdr.b_datacnt > 0); + atomic_add_64(size, hdr->b_size * + hdr->b_l1hdr.b_datacnt); mutex_exit(&state->arcs_mtx); } return (cnt); @@ -1161,40 +1522,60 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr, kmutex_t *hash_lock) { - arc_state_t *old_state = hdr->b_state; - int64_t refcnt = refcount_count(&hdr->b_refcnt); + arc_state_t *old_state; + int64_t refcnt; + uint32_t datacnt; uint64_t from_delta, to_delta; + arc_buf_contents_t buftype = arc_buf_type(hdr); + + /* + * We almost always have an L1 hdr here, since we call arc_hdr_realloc() + * in arc_read() when bringing a buffer out of the L2ARC. However, the + * L1 hdr doesn't always exist when we change state to arc_anon before + * destroying a header, in which case reallocating to add the L1 hdr is + * pointless. + */ + if (HDR_HAS_L1HDR(hdr)) { + old_state = hdr->b_l1hdr.b_state; + refcnt = refcount_count(&hdr->b_l1hdr.b_refcnt); + datacnt = hdr->b_l1hdr.b_datacnt; + } else { + old_state = arc_l2c_only; + refcnt = 0; + datacnt = 0; + } ASSERT(MUTEX_HELD(hash_lock)); ASSERT3P(new_state, !=, old_state); - ASSERT(refcnt == 0 || hdr->b_datacnt > 0); - ASSERT(hdr->b_datacnt == 0 || !GHOST_STATE(new_state)); - ASSERT(hdr->b_datacnt <= 1 || old_state != arc_anon); - - from_delta = to_delta = hdr->b_datacnt * hdr->b_size; + ASSERT(refcnt == 0 || datacnt > 0); + ASSERT(!GHOST_STATE(new_state) || datacnt == 0); + ASSERT(old_state != arc_anon || datacnt <= 1); + + from_delta = to_delta = datacnt * hdr->b_size; /* * If this buffer is evictable, transfer it from the * old state list to the new state list. */ if (refcnt == 0) { - if (old_state != arc_anon) { + if (old_state != arc_anon && old_state != arc_l2c_only) { int use_mutex = !MUTEX_HELD(&old_state->arcs_mtx); - uint64_t *size = &old_state->arcs_lsize[hdr->b_type]; + uint64_t *size = &old_state->arcs_lsize[buftype]; if (use_mutex) mutex_enter(&old_state->arcs_mtx); - ASSERT(list_link_active(&hdr->b_arc_node)); - list_remove(&old_state->arcs_list[hdr->b_type], hdr); + ASSERT(HDR_HAS_L1HDR(hdr)); + ASSERT(list_link_active(&hdr->b_l1hdr.b_arc_node)); + list_remove(&old_state->arcs_list[buftype], hdr); /* * If prefetching out of the ghost cache, * we will have a non-zero datacnt. */ - if (GHOST_STATE(old_state) && hdr->b_datacnt == 0) { + if (GHOST_STATE(old_state) && datacnt == 0) { /* ghost elements have a ghost size */ - ASSERT(hdr->b_buf == NULL); + ASSERT(hdr->b_l1hdr.b_buf == NULL); from_delta = hdr->b_size; } ASSERT3U(*size, >=, from_delta); @@ -1203,20 +1584,26 @@ if (use_mutex) mutex_exit(&old_state->arcs_mtx); } - if (new_state != arc_anon) { + if (new_state != arc_anon && new_state != arc_l2c_only) { int use_mutex = !MUTEX_HELD(&new_state->arcs_mtx); - uint64_t *size = &new_state->arcs_lsize[hdr->b_type]; - + uint64_t *size = &new_state->arcs_lsize[buftype]; + + /* + * An L1 header always exists here, since if we're + * moving to some L1-cached state (i.e. not l2c_only or + * anonymous), we realloc the header to add an L1hdr + * beforehand. + */ + ASSERT(HDR_HAS_L1HDR(hdr)); if (use_mutex) mutex_enter(&new_state->arcs_mtx); - list_insert_head(&new_state->arcs_list[hdr->b_type], - hdr); + list_insert_head(&new_state->arcs_list[buftype], hdr); /* ghost elements have a ghost size */ if (GHOST_STATE(new_state)) { - ASSERT(hdr->b_datacnt == 0); - ASSERT(hdr->b_buf == NULL); + ASSERT0(datacnt); + ASSERT(hdr->b_l1hdr.b_buf == NULL); to_delta = hdr->b_size; } atomic_add_64(size, to_delta); @@ -1230,20 +1617,22 @@ if (new_state == arc_anon && HDR_IN_HASH_TABLE(hdr)) buf_hash_remove(hdr); - /* adjust state sizes */ - if (to_delta) + /* adjust state sizes (ignore arc_l2c_only) */ + if (to_delta && new_state != arc_l2c_only) atomic_add_64(&new_state->arcs_size, to_delta); - if (from_delta) { + if (from_delta && old_state != arc_l2c_only) { ASSERT3U(old_state->arcs_size, >=, from_delta); atomic_add_64(&old_state->arcs_size, -from_delta); } - hdr->b_state = new_state; - - /* adjust l2arc hdr stats */ - if (new_state == arc_l2c_only) - l2arc_hdr_stat_add(); - else if (old_state == arc_l2c_only) - l2arc_hdr_stat_remove(); + if (HDR_HAS_L1HDR(hdr)) + hdr->b_l1hdr.b_state = new_state; + + /* + * L2 headers should never be on the L2 state list since they don't + * have L1 headers allocated. + */ + ASSERT(list_is_empty(&arc_l2c_only->arcs_list[ARC_BUFC_DATA]) && + list_is_empty(&arc_l2c_only->arcs_list[ARC_BUFC_METADATA])); } void @@ -1255,6 +1644,9 @@ case ARC_SPACE_DATA: ARCSTAT_INCR(arcstat_data_size, space); break; + case ARC_SPACE_META: + ARCSTAT_INCR(arcstat_metadata_size, space); + break; case ARC_SPACE_OTHER: ARCSTAT_INCR(arcstat_other_size, space); break; @@ -1266,7 +1658,9 @@ break; } - ARCSTAT_INCR(arcstat_meta_used, space); + if (type != ARC_SPACE_DATA) + ARCSTAT_INCR(arcstat_meta_used, space); + atomic_add_64(&arc_size, space); } @@ -1279,6 +1673,9 @@ case ARC_SPACE_DATA: ARCSTAT_INCR(arcstat_data_size, -space); break; + case ARC_SPACE_META: + ARCSTAT_INCR(arcstat_metadata_size, -space); + break; case ARC_SPACE_OTHER: ARCSTAT_INCR(arcstat_other_size, -space); break; @@ -1290,40 +1687,48 @@ break; } - ASSERT(arc_meta_used >= space); - if (arc_meta_max < arc_meta_used) - arc_meta_max = arc_meta_used; - ARCSTAT_INCR(arcstat_meta_used, -space); + if (type != ARC_SPACE_DATA) { + ASSERT(arc_meta_used >= space); + if (arc_meta_max < arc_meta_used) + arc_meta_max = arc_meta_used; + ARCSTAT_INCR(arcstat_meta_used, -space); + } + ASSERT(arc_size >= space); atomic_add_64(&arc_size, -space); } arc_buf_t * -arc_buf_alloc(spa_t *spa, int size, void *tag, arc_buf_contents_t type) +arc_buf_alloc(spa_t *spa, int32_t size, void *tag, arc_buf_contents_t type) { arc_buf_hdr_t *hdr; arc_buf_t *buf; ASSERT3U(size, >, 0); - hdr = kmem_cache_alloc(hdr_cache, KM_PUSHPAGE); + hdr = kmem_cache_alloc(hdr_full_cache, KM_PUSHPAGE); ASSERT(BUF_EMPTY(hdr)); + ASSERT3P(hdr->b_freeze_cksum, ==, NULL); hdr->b_size = size; - hdr->b_type = type; hdr->b_spa = spa_load_guid(spa); - hdr->b_state = arc_anon; - hdr->b_arc_access = 0; + buf = kmem_cache_alloc(buf_cache, KM_PUSHPAGE); buf->b_hdr = hdr; buf->b_data = NULL; buf->b_efunc = NULL; buf->b_private = NULL; buf->b_next = NULL; - hdr->b_buf = buf; + + hdr->b_flags = arc_bufc_to_flags(type); + hdr->b_flags |= ARC_FLAG_HAS_L1HDR; + + hdr->b_l1hdr.b_buf = buf; + hdr->b_l1hdr.b_state = arc_anon; + hdr->b_l1hdr.b_arc_access = 0; + hdr->b_l1hdr.b_datacnt = 1; + arc_get_data_buf(buf); - hdr->b_datacnt = 1; - hdr->b_flags = 0; - ASSERT(refcount_is_zero(&hdr->b_refcnt)); - (void) refcount_add(&hdr->b_refcnt, tag); + ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt)); + (void) refcount_add(&hdr->b_l1hdr.b_refcnt, tag); return (buf); } @@ -1356,8 +1761,9 @@ arc_buf_hdr_t *hdr = buf->b_hdr; ASSERT(buf->b_data != NULL); - (void) refcount_add(&hdr->b_refcnt, tag); - (void) refcount_remove(&hdr->b_refcnt, arc_onloan_tag); + ASSERT(HDR_HAS_L1HDR(hdr)); + (void) refcount_add(&hdr->b_l1hdr.b_refcnt, tag); + (void) refcount_remove(&hdr->b_l1hdr.b_refcnt, arc_onloan_tag); atomic_add_64(&arc_loaned_bytes, -hdr->b_size); } @@ -1366,12 +1772,12 @@ void arc_loan_inuse_buf(arc_buf_t *buf, void *tag) { - arc_buf_hdr_t *hdr; + arc_buf_hdr_t *hdr = buf->b_hdr; ASSERT(buf->b_data != NULL); - hdr = buf->b_hdr; - (void) refcount_add(&hdr->b_refcnt, arc_onloan_tag); - (void) refcount_remove(&hdr->b_refcnt, tag); + ASSERT(HDR_HAS_L1HDR(hdr)); + (void) refcount_add(&hdr->b_l1hdr.b_refcnt, arc_onloan_tag); + (void) refcount_remove(&hdr->b_l1hdr.b_refcnt, tag); buf->b_efunc = NULL; buf->b_private = NULL; @@ -1385,15 +1791,16 @@ arc_buf_hdr_t *hdr = from->b_hdr; uint64_t size = hdr->b_size; - ASSERT(hdr->b_state != arc_anon); + ASSERT(HDR_HAS_L1HDR(hdr)); + ASSERT(hdr->b_l1hdr.b_state != arc_anon); buf = kmem_cache_alloc(buf_cache, KM_PUSHPAGE); buf->b_hdr = hdr; buf->b_data = NULL; buf->b_efunc = NULL; buf->b_private = NULL; - buf->b_next = hdr->b_buf; - hdr->b_buf = buf; + buf->b_next = hdr->b_l1hdr.b_buf; + hdr->b_l1hdr.b_buf = buf; arc_get_data_buf(buf); bcopy(from->b_data, buf->b_data, size); @@ -1403,11 +1810,11 @@ * then track the size and number of duplicates. These stats will be * updated as duplicate buffers are created and destroyed. */ - if (hdr->b_type == ARC_BUFC_DATA) { + if (HDR_ISTYPE_DATA(hdr)) { ARCSTAT_BUMP(arcstat_duplicate_buffers); ARCSTAT_INCR(arcstat_duplicate_buffers_size, size); } - hdr->b_datacnt += 1; + hdr->b_l1hdr.b_datacnt += 1; return (buf); } @@ -1430,17 +1837,20 @@ hash_lock = HDR_LOCK(buf->b_hdr); mutex_enter(hash_lock); hdr = buf->b_hdr; + ASSERT(HDR_HAS_L1HDR(hdr)); ASSERT3P(hash_lock, ==, HDR_LOCK(hdr)); mutex_exit(&buf->b_evict_lock); - ASSERT(hdr->b_state == arc_mru || hdr->b_state == arc_mfu); + ASSERT(hdr->b_l1hdr.b_state == arc_mru || + hdr->b_l1hdr.b_state == arc_mfu); + add_reference(hdr, hash_lock, tag); DTRACE_PROBE1(arc__hit, arc_buf_hdr_t *, hdr); arc_access(hdr, hash_lock); mutex_exit(hash_lock); ARCSTAT_BUMP(arcstat_hits); - ARCSTAT_CONDSTAT(!(hdr->b_flags & ARC_FLAG_PREFETCH), - demand, prefetch, hdr->b_type != ARC_BUFC_METADATA, + ARCSTAT_CONDSTAT(!HDR_PREFETCH(hdr), + demand, prefetch, !HDR_ISTYPE_METADATA(hdr), data, metadata, hits); } @@ -1478,10 +1888,10 @@ arc_buf_t **bufp; /* free up data associated with the buf */ - if (buf->b_data) { - arc_state_t *state = buf->b_hdr->b_state; + if (buf->b_data != NULL) { + arc_state_t *state = buf->b_hdr->b_l1hdr.b_state; uint64_t size = buf->b_hdr->b_size; - arc_buf_contents_t type = buf->b_hdr->b_type; + arc_buf_contents_t type = arc_buf_type(buf->b_hdr); arc_cksum_verify(buf); arc_buf_unwatch(buf); @@ -1489,19 +1899,19 @@ if (!recycle) { if (type == ARC_BUFC_METADATA) { arc_buf_data_free(buf, zio_buf_free); - arc_space_return(size, ARC_SPACE_DATA); + arc_space_return(size, ARC_SPACE_META); } else { ASSERT(type == ARC_BUFC_DATA); arc_buf_data_free(buf, zio_data_buf_free); - ARCSTAT_INCR(arcstat_data_size, -size); - atomic_add_64(&arc_size, -size); + arc_space_return(size, ARC_SPACE_DATA); } } - if (list_link_active(&buf->b_hdr->b_arc_node)) { + if (list_link_active(&buf->b_hdr->b_l1hdr.b_arc_node)) { uint64_t *cnt = &state->arcs_lsize[type]; - ASSERT(refcount_is_zero(&buf->b_hdr->b_refcnt)); - ASSERT(state != arc_anon); + ASSERT(refcount_is_zero( + &buf->b_hdr->b_l1hdr.b_refcnt)); + ASSERT(state != arc_anon && state != arc_l2c_only); ASSERT3U(*cnt, >=, size); atomic_add_64(cnt, -size); @@ -1514,13 +1924,13 @@ * If we're destroying a duplicate buffer make sure * that the appropriate statistics are updated. */ - if (buf->b_hdr->b_datacnt > 1 && - buf->b_hdr->b_type == ARC_BUFC_DATA) { + if (buf->b_hdr->b_l1hdr.b_datacnt > 1 && + HDR_ISTYPE_DATA(buf->b_hdr)) { ARCSTAT_BUMPDOWN(arcstat_duplicate_buffers); ARCSTAT_INCR(arcstat_duplicate_buffers_size, -size); } - ASSERT(buf->b_hdr->b_datacnt > 0); - buf->b_hdr->b_datacnt -= 1; + ASSERT(buf->b_hdr->b_l1hdr.b_datacnt > 0); + buf->b_hdr->b_l1hdr.b_datacnt -= 1; } /* only remove the buf if requested */ @@ -1528,7 +1938,8 @@ return; /* remove the buf from the hdr list */ - for (bufp = &buf->b_hdr->b_buf; *bufp != buf; bufp = &(*bufp)->b_next) + for (bufp = &buf->b_hdr->b_l1hdr.b_buf; *bufp != buf; + bufp = &(*bufp)->b_next) continue; *bufp = buf->b_next; buf->b_next = NULL; @@ -1543,86 +1954,87 @@ static void arc_hdr_destroy(arc_buf_hdr_t *hdr) { - ASSERT(refcount_is_zero(&hdr->b_refcnt)); - ASSERT3P(hdr->b_state, ==, arc_anon); + if (HDR_HAS_L1HDR(hdr)) { + ASSERT(hdr->b_l1hdr.b_buf == NULL || + hdr->b_l1hdr.b_datacnt > 0); + ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt)); + ASSERT3P(hdr->b_l1hdr.b_state, ==, arc_anon); + } ASSERT(!HDR_IO_IN_PROGRESS(hdr)); - l2arc_buf_hdr_t *l2hdr = hdr->b_l2hdr; - - if (l2hdr != NULL) { - boolean_t buflist_held = MUTEX_HELD(&l2arc_buflist_mtx); - /* - * To prevent arc_free() and l2arc_evict() from - * attempting to free the same buffer at the same time, - * a FREE_IN_PROGRESS flag is given to arc_free() to - * give it priority. l2arc_evict() can't destroy this - * header while we are waiting on l2arc_buflist_mtx. - * - * The hdr may be removed from l2ad_buflist before we - * grab l2arc_buflist_mtx, so b_l2hdr is rechecked. - */ + ASSERT(!HDR_IN_HASH_TABLE(hdr)); + + if (HDR_HAS_L2HDR(hdr)) { + l2arc_buf_hdr_t *l2hdr = &hdr->b_l2hdr; + boolean_t buflist_held = MUTEX_HELD(&l2hdr->b_dev->l2ad_mtx); + if (!buflist_held) { - mutex_enter(&l2arc_buflist_mtx); - l2hdr = hdr->b_l2hdr; + mutex_enter(&l2hdr->b_dev->l2ad_mtx); + l2hdr = &hdr->b_l2hdr; } - if (l2hdr != NULL) { - list_remove(l2hdr->b_dev->l2ad_buflist, hdr); - ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size); - ARCSTAT_INCR(arcstat_l2_asize, -l2hdr->b_asize); - vdev_space_update(l2hdr->b_dev->l2ad_vdev, - -l2hdr->b_asize, 0, 0); - kmem_free(l2hdr, sizeof (l2arc_buf_hdr_t)); - if (hdr->b_state == arc_l2c_only) - l2arc_hdr_stat_remove(); - hdr->b_l2hdr = NULL; - } + list_remove(&l2hdr->b_dev->l2ad_buflist, hdr); + + ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size); + ARCSTAT_INCR(arcstat_l2_asize, -l2hdr->b_asize); if (!buflist_held) - mutex_exit(&l2arc_buflist_mtx); - } - - if (!BUF_EMPTY(hdr)) { - ASSERT(!HDR_IN_HASH_TABLE(hdr)); - buf_discard_identity(hdr); + mutex_exit(&l2hdr->b_dev->l2ad_mtx); + + hdr->b_flags &= ~ARC_FLAG_HAS_L2HDR; } - while (hdr->b_buf) { - arc_buf_t *buf = hdr->b_buf; - - if (buf->b_efunc) { - mutex_enter(&arc_eviction_mtx); - mutex_enter(&buf->b_evict_lock); - ASSERT(buf->b_hdr != NULL); - arc_buf_destroy(hdr->b_buf, FALSE, FALSE); - hdr->b_buf = buf->b_next; - buf->b_hdr = &arc_eviction_hdr; - buf->b_next = arc_eviction_list; - arc_eviction_list = buf; - mutex_exit(&buf->b_evict_lock); - mutex_exit(&arc_eviction_mtx); - } else { - arc_buf_destroy(hdr->b_buf, FALSE, TRUE); - } - } + + if (!BUF_EMPTY(hdr)) + buf_discard_identity(hdr); + if (hdr->b_freeze_cksum != NULL) { kmem_free(hdr->b_freeze_cksum, sizeof (zio_cksum_t)); hdr->b_freeze_cksum = NULL; } - if (hdr->b_thawed) { - kmem_free(hdr->b_thawed, 1); - hdr->b_thawed = NULL; + + if (HDR_HAS_L1HDR(hdr)) { + while (hdr->b_l1hdr.b_buf) { + arc_buf_t *buf = hdr->b_l1hdr.b_buf; + + if (buf->b_efunc != NULL) { + mutex_enter(&arc_eviction_mtx); + mutex_enter(&buf->b_evict_lock); + ASSERT(buf->b_hdr != NULL); + arc_buf_destroy(hdr->b_l1hdr.b_buf, FALSE, + FALSE); + hdr->b_l1hdr.b_buf = buf->b_next; + buf->b_hdr = &arc_eviction_hdr; + buf->b_next = arc_eviction_list; + arc_eviction_list = buf; + mutex_exit(&buf->b_evict_lock); + mutex_exit(&arc_eviction_mtx); + } else { + arc_buf_destroy(hdr->b_l1hdr.b_buf, FALSE, + TRUE); + } + } +#ifdef ZFS_DEBUG + if (hdr->b_l1hdr.b_thawed != NULL) { + kmem_free(hdr->b_l1hdr.b_thawed, 1); + hdr->b_l1hdr.b_thawed = NULL; + } +#endif } - ASSERT(!list_link_active(&hdr->b_arc_node)); ASSERT3P(hdr->b_hash_next, ==, NULL); - ASSERT3P(hdr->b_acb, ==, NULL); - kmem_cache_free(hdr_cache, hdr); + if (HDR_HAS_L1HDR(hdr)) { + ASSERT(!list_link_active(&hdr->b_l1hdr.b_arc_node)); + ASSERT3P(hdr->b_l1hdr.b_acb, ==, NULL); + kmem_cache_free(hdr_full_cache, hdr); + } else { + kmem_cache_free(hdr_l2only_cache, hdr); + } } void arc_buf_free(arc_buf_t *buf, void *tag) { arc_buf_hdr_t *hdr = buf->b_hdr; - int hashed = hdr->b_state != arc_anon; + int hashed = hdr->b_l1hdr.b_state != arc_anon; ASSERT(buf->b_efunc == NULL); ASSERT(buf->b_data != NULL); @@ -1635,10 +2047,10 @@ ASSERT3P(hash_lock, ==, HDR_LOCK(hdr)); (void) remove_reference(hdr, hash_lock, tag); - if (hdr->b_datacnt > 1) { + if (hdr->b_l1hdr.b_datacnt > 1) { arc_buf_destroy(buf, FALSE, TRUE); } else { - ASSERT(buf == hdr->b_buf); + ASSERT(buf == hdr->b_l1hdr.b_buf); ASSERT(buf->b_efunc == NULL); hdr->b_flags |= ARC_FLAG_BUF_AVAILABLE; } @@ -1652,7 +2064,7 @@ */ mutex_enter(&arc_eviction_mtx); (void) remove_reference(hdr, NULL, tag); - ASSERT(refcount_is_zero(&hdr->b_refcnt)); + ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt)); destroy_hdr = !HDR_IO_IN_PROGRESS(hdr); mutex_exit(&arc_eviction_mtx); if (destroy_hdr) @@ -1672,34 +2084,35 @@ kmutex_t *hash_lock = HDR_LOCK(hdr); boolean_t no_callback = (buf->b_efunc == NULL); - if (hdr->b_state == arc_anon) { - ASSERT(hdr->b_datacnt == 1); + if (hdr->b_l1hdr.b_state == arc_anon) { + ASSERT(hdr->b_l1hdr.b_datacnt == 1); arc_buf_free(buf, tag); return (no_callback); } mutex_enter(hash_lock); hdr = buf->b_hdr; + ASSERT(hdr->b_l1hdr.b_datacnt > 0); ASSERT3P(hash_lock, ==, HDR_LOCK(hdr)); - ASSERT(hdr->b_state != arc_anon); + ASSERT(hdr->b_l1hdr.b_state != arc_anon); ASSERT(buf->b_data != NULL); (void) remove_reference(hdr, hash_lock, tag); - if (hdr->b_datacnt > 1) { + if (hdr->b_l1hdr.b_datacnt > 1) { if (no_callback) arc_buf_destroy(buf, FALSE, TRUE); } else if (no_callback) { - ASSERT(hdr->b_buf == buf && buf->b_next == NULL); + ASSERT(hdr->b_l1hdr.b_buf == buf && buf->b_next == NULL); ASSERT(buf->b_efunc == NULL); hdr->b_flags |= ARC_FLAG_BUF_AVAILABLE; } - ASSERT(no_callback || hdr->b_datacnt > 1 || - refcount_is_zero(&hdr->b_refcnt)); + ASSERT(no_callback || hdr->b_l1hdr.b_datacnt > 1 || + refcount_is_zero(&hdr->b_l1hdr.b_refcnt)); mutex_exit(hash_lock); return (no_callback); } -int +int32_t arc_buf_size(arc_buf_t *buf) { return (buf->b_hdr->b_size); @@ -1740,7 +2153,7 @@ return (B_TRUE); } - if (hdr->b_datacnt > 1 && hdr->b_type == ARC_BUFC_DATA) + if (hdr->b_l1hdr.b_datacnt > 1 && HDR_ISTYPE_DATA(hdr)) evict_needed = B_TRUE; mutex_exit(&buf->b_evict_lock); @@ -1777,8 +2190,20 @@ evicted_state = (state == arc_mru) ? arc_mru_ghost : arc_mfu_ghost; + /* + * The ghost list lock must be acquired first in order to prevent + * a 3 party deadlock: + * + * - arc_evict_ghost acquires arc_*_ghost->arcs_mtx, followed by + * l2ad_mtx in arc_hdr_realloc + * - l2arc_write_buffers acquires l2ad_mtx, followed by arc_*->arcs_mtx + * - arc_evict acquires arc_*_ghost->arcs_mtx, followed by + * arc_*_ghost->arcs_mtx and forms a deadlock cycle. + * + * This situation is avoided by acquiring the ghost list lock first. + */ + mutex_enter(&evicted_state->arcs_mtx); mutex_enter(&state->arcs_mtx); - mutex_enter(&evicted_state->arcs_mtx); /* * Decide which "type" (data vs metadata) to recycle from. @@ -1794,6 +2219,7 @@ arc_buf_hdr_t *metadata_hdr = list_tail(&state->arcs_list[ARC_BUFC_METADATA]); arc_buf_contents_t realtype; + if (data_hdr == NULL) { realtype = ARC_BUFC_METADATA; } else if (metadata_hdr == NULL) { @@ -1802,13 +2228,13 @@ realtype = ARC_BUFC_METADATA; } else if (arc_meta_used <= arc_meta_min) { realtype = ARC_BUFC_DATA; + } else if (HDR_HAS_L1HDR(data_hdr) && + HDR_HAS_L1HDR(metadata_hdr) && + data_hdr->b_l1hdr.b_arc_access < + metadata_hdr->b_l1hdr.b_arc_access) { + realtype = ARC_BUFC_DATA; } else { - if (data_hdr->b_arc_access < - metadata_hdr->b_arc_access) { - realtype = ARC_BUFC_DATA; - } else { - realtype = ARC_BUFC_METADATA; - } + realtype = ARC_BUFC_METADATA; } if (realtype != type) { /* @@ -1829,8 +2255,8 @@ /* prefetch buffers have a minimum lifespan */ if (HDR_IO_IN_PROGRESS(hdr) || (spa && hdr->b_spa != spa) || - (hdr->b_flags & (ARC_FLAG_PREFETCH | ARC_FLAG_INDIRECT) && - ddi_get_lbolt() - hdr->b_arc_access < + ((hdr->b_flags & (ARC_FLAG_PREFETCH | ARC_FLAG_INDIRECT)) && + ddi_get_lbolt() - hdr->b_l1hdr.b_arc_access < arc_min_prefetch_lifespan)) { skipped++; continue; @@ -1855,11 +2281,11 @@ */ if (!recycle && count++ > arc_evict_iterations) { list_insert_after(list, hdr, &marker); + mutex_exit(&state->arcs_mtx); mutex_exit(&evicted_state->arcs_mtx); - mutex_exit(&state->arcs_mtx); kpreempt(KPREEMPT_SYNC); + mutex_enter(&evicted_state->arcs_mtx); mutex_enter(&state->arcs_mtx); - mutex_enter(&evicted_state->arcs_mtx); hdr_prev = list_prev(list, &marker); list_remove(list, &marker); count = 0; @@ -1869,28 +2295,29 @@ hash_lock = HDR_LOCK(hdr); have_lock = MUTEX_HELD(hash_lock); if (have_lock || mutex_tryenter(hash_lock)) { - ASSERT0(refcount_count(&hdr->b_refcnt)); - ASSERT(hdr->b_datacnt > 0); - while (hdr->b_buf) { - arc_buf_t *buf = hdr->b_buf; + ASSERT0(refcount_count(&hdr->b_l1hdr.b_refcnt)); + ASSERT3U(hdr->b_l1hdr.b_datacnt, >, 0); + while (hdr->b_l1hdr.b_buf) { + arc_buf_t *buf = hdr->b_l1hdr.b_buf; if (!mutex_tryenter(&buf->b_evict_lock)) { missed += 1; break; } - if (buf->b_data) { + if (buf->b_data != NULL) { bytes_evicted += hdr->b_size; - if (recycle && hdr->b_type == type && + if (recycle && + arc_buf_type(hdr) == type && hdr->b_size == bytes && !HDR_L2_WRITING(hdr)) { stolen = buf->b_data; recycle = FALSE; } } - if (buf->b_efunc) { + if (buf->b_efunc != NULL) { mutex_enter(&arc_eviction_mtx); arc_buf_destroy(buf, buf->b_data == stolen, FALSE); - hdr->b_buf = buf->b_next; + hdr->b_l1hdr.b_buf = buf->b_next; buf->b_hdr = &arc_eviction_hdr; buf->b_next = arc_eviction_list; arc_eviction_list = buf; @@ -1903,7 +2330,7 @@ } } - if (hdr->b_l2hdr) { + if (HDR_HAS_L2HDR(hdr)) { ARCSTAT_INCR(arcstat_evict_l2_cached, hdr->b_size); } else { @@ -1917,7 +2344,7 @@ } } - if (hdr->b_datacnt == 0) { + if (hdr->b_l1hdr.b_datacnt == 0) { arc_change_state(evicted_state, hdr, hash_lock); ASSERT(HDR_IN_HASH_TABLE(hdr)); hdr->b_flags |= ARC_FLAG_IN_HASH_TABLE; @@ -1933,8 +2360,8 @@ } } + mutex_exit(&state->arcs_mtx); mutex_exit(&evicted_state->arcs_mtx); - mutex_exit(&state->arcs_mtx); if (bytes_evicted < bytes) dprintf("only evicted %lld bytes from %x", @@ -1976,7 +2403,7 @@ mutex_enter(&state->arcs_mtx); for (hdr = list_tail(list); hdr; hdr = hdr_prev) { hdr_prev = list_prev(list, hdr); - if (hdr->b_type > ARC_BUFC_NUMTYPES) + if (arc_buf_type(hdr) >= ARC_BUFC_NUMTYPES) panic("invalid hdr=%p", (void *)hdr); if (spa && hdr->b_spa != spa) continue; @@ -2008,16 +2435,23 @@ } if (mutex_tryenter(hash_lock)) { ASSERT(!HDR_IO_IN_PROGRESS(hdr)); - ASSERT(hdr->b_buf == NULL); + ASSERT(!HDR_HAS_L1HDR(hdr) || + hdr->b_l1hdr.b_buf == NULL); ARCSTAT_BUMP(arcstat_deleted); bytes_deleted += hdr->b_size; - if (hdr->b_l2hdr != NULL) { + if (HDR_HAS_L2HDR(hdr)) { /* * This buffer is cached on the 2nd Level ARC; * don't destroy the header. */ arc_change_state(arc_l2c_only, hdr, hash_lock); + /* + * dropping from L1+L2 cached to L2-only, + * realloc to remove the L1 header. + */ + hdr = arc_hdr_realloc(hdr, hdr_full_cache, + hdr_l2only_cache); mutex_exit(hash_lock); } else { arc_change_state(arc_anon, hdr, hash_lock); @@ -2160,27 +2594,27 @@ { uint64_t guid = 0; - if (spa) + if (spa != NULL) guid = spa_load_guid(spa); while (list_head(&arc_mru->arcs_list[ARC_BUFC_DATA])) { (void) arc_evict(arc_mru, guid, -1, FALSE, ARC_BUFC_DATA); - if (spa) + if (spa != NULL) break; } while (list_head(&arc_mru->arcs_list[ARC_BUFC_METADATA])) { (void) arc_evict(arc_mru, guid, -1, FALSE, ARC_BUFC_METADATA); - if (spa) + if (spa != NULL) break; } while (list_head(&arc_mfu->arcs_list[ARC_BUFC_DATA])) { (void) arc_evict(arc_mfu, guid, -1, FALSE, ARC_BUFC_DATA); - if (spa) + if (spa != NULL) break; } while (list_head(&arc_mfu->arcs_list[ARC_BUFC_METADATA])) { (void) arc_evict(arc_mfu, guid, -1, FALSE, ARC_BUFC_METADATA); - if (spa) + if (spa != NULL) break; } @@ -2194,16 +2628,10 @@ } void -arc_shrink(void) +arc_shrink(int64_t to_free) { if (arc_c > arc_c_min) { - uint64_t to_free; - -#ifdef _KERNEL - to_free = MAX(arc_c >> arc_shrink_shift, ptob(needfree)); -#else - to_free = arc_c >> arc_shrink_shift; -#endif + if (arc_c > arc_c_min + to_free) atomic_add_64(&arc_c, -to_free); else @@ -2222,25 +2650,49 @@ arc_adjust(); } +typedef enum free_memory_reason_t { + FMR_UNKNOWN, + FMR_NEEDFREE, + FMR_LOTSFREE, + FMR_SWAPFS_MINFREE, + FMR_PAGES_PP_MAXIMUM, + FMR_HEAP_ARENA, + FMR_ZIO_ARENA, +} free_memory_reason_t; + +int64_t last_free_memory; +free_memory_reason_t last_free_reason; + /* - * Determine if the system is under memory pressure and is asking - * to reclaim memory. A return value of 1 indicates that the system - * is under memory pressure and that the arc should adjust accordingly. + * Additional reserve of pages for pp_reserve. */ -static int -arc_reclaim_needed(void) +int64_t arc_pages_pp_reserve = 64; + +/* + * Additional reserve of pages for swapfs. + */ +int64_t arc_swapfs_reserve = 64; + +/* + * Return the amount of memory that can be consumed before reclaim will be + * needed. Positive if there is sufficient free memory, negative indicates + * the amount of memory that needs to be freed up. + */ +static int64_t +arc_available_memory(void) { - uint64_t extra; + int64_t lowest = INT64_MAX; + int64_t n; + free_memory_reason_t r = FMR_UNKNOWN; #ifdef _KERNEL - - if (needfree) - return (1); - - /* - * take 'desfree' extra pages, so we reclaim sooner, rather than later - */ - extra = desfree; + if (needfree > 0) { + n = PAGESIZE * (-needfree); + if (n < lowest) { + lowest = n; + r = FMR_NEEDFREE; + } + } /* * check that we're out of range of the pageout scanner. It starts to @@ -2249,8 +2701,11 @@ * number of needed free pages. We add extra pages here to make sure * the scanner doesn't start up while we're freeing memory. */ - if (freemem < lotsfree + needfree + extra) - return (1); + n = PAGESIZE * (freemem - lotsfree - needfree - desfree); + if (n < lowest) { + lowest = n; + r = FMR_LOTSFREE; + } /* * check to make sure that swapfs has enough space so that anon @@ -2259,8 +2714,13 @@ * swap pages. We also add a bit of extra here just to prevent * circumstances from getting really dire. */ - if (availrmem < swapfs_minfree + swapfs_reserve + extra) - return (1); + n = PAGESIZE * (availrmem - swapfs_minfree - swapfs_reserve - + desfree - arc_swapfs_reserve); + if (n < lowest) { + lowest = n; + r = FMR_SWAPFS_MINFREE; + } + /* * Check that we have enough availrmem that memory locking (e.g., via @@ -2269,8 +2729,12 @@ * drops below pages_pp_maximum, page locking mechanisms such as * page_pp_lock() will fail.) */ - if (availrmem <= pages_pp_maximum) - return (1); + n = PAGESIZE * (availrmem - pages_pp_maximum - + arc_pages_pp_reserve); + if (n < lowest) { + lowest = n; + r = FMR_PAGES_PP_MAXIMUM; + } #if defined(__i386) /* @@ -2284,9 +2748,12 @@ * heap is allocated. (Or, in the calculation, if less than 1/4th is * free) */ - if (vmem_size(heap_arena, VMEM_FREE) < - (vmem_size(heap_arena, VMEM_FREE | VMEM_ALLOC) >> 2)) - return (1); + n = vmem_size(heap_arena, VMEM_FREE) - + (vmem_size(heap_arena, VMEM_FREE | VMEM_ALLOC) >> 2); + if (n < lowest) { + lowest = n; + r = FMR_HEAP_ARENA; + } #endif /* @@ -2298,19 +2765,40 @@ * to aggressively evict memory from the arc in order to avoid * memory fragmentation issues. */ - if (zio_arena != NULL && - vmem_size(zio_arena, VMEM_FREE) < - (vmem_size(zio_arena, VMEM_ALLOC) >> 4)) - return (1); + if (zio_arena != NULL) { + n = vmem_size(zio_arena, VMEM_FREE) - + (vmem_size(zio_arena, VMEM_ALLOC) >> 4); + if (n < lowest) { + lowest = n; + r = FMR_ZIO_ARENA; + } + } #else + /* Every 100 calls, free a small amount */ if (spa_get_random(100) == 0) - return (1); + lowest = -1024; #endif - return (0); + + last_free_memory = lowest; + last_free_reason = r; + + return (lowest); +} + + +/* + * Determine if the system is under memory pressure and is asking + * to reclaim memory. A return value of TRUE indicates that the system + * is under memory pressure and that the arc should adjust accordingly. + */ +static boolean_t +arc_reclaim_needed(void) +{ + return (arc_available_memory() < 0); } static void -arc_kmem_reap_now(arc_reclaim_strategy_t strat) +arc_kmem_reap_now(void) { size_t i; kmem_cache_t *prev_cache = NULL; @@ -2335,13 +2823,6 @@ #endif #endif - /* - * An aggressive reclamation will shrink the cache size as well as - * reap free buffers from the arc kmem caches. - */ - if (strat == ARC_RECLAIM_AGGR) - arc_shrink(); - for (i = 0; i < SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT; i++) { if (zio_buf_cache[i] != prev_cache) { prev_cache = zio_buf_cache[i]; @@ -2353,50 +2834,61 @@ } } kmem_cache_reap_now(buf_cache); - kmem_cache_reap_now(hdr_cache); + kmem_cache_reap_now(hdr_full_cache); + kmem_cache_reap_now(hdr_l2only_cache); kmem_cache_reap_now(range_seg_cache); - /* - * Ask the vmem areana to reclaim unused memory from its - * quantum caches. - */ - if (zio_arena != NULL && strat == ARC_RECLAIM_AGGR) + if (zio_arena != NULL) { + /* + * Ask the vmem arena to reclaim unused memory from its + * quantum caches. + */ vmem_qcache_reap(zio_arena); + } } static void arc_reclaim_thread(void) { clock_t growtime = 0; - arc_reclaim_strategy_t last_reclaim = ARC_RECLAIM_CONS; callb_cpr_t cpr; CALLB_CPR_INIT(&cpr, &arc_reclaim_thr_lock, callb_generic_cpr, FTAG); mutex_enter(&arc_reclaim_thr_lock); while (arc_thread_exit == 0) { - if (arc_reclaim_needed()) { - - if (arc_no_grow) { - if (last_reclaim == ARC_RECLAIM_CONS) { - last_reclaim = ARC_RECLAIM_AGGR; - } else { - last_reclaim = ARC_RECLAIM_CONS; - } - } else { - arc_no_grow = TRUE; - last_reclaim = ARC_RECLAIM_AGGR; - membar_producer(); + int64_t free_memory = arc_available_memory(); + if (free_memory < 0) { + + arc_no_grow = B_TRUE; + arc_warm = B_TRUE; + + /* + * Wait at least zfs_grow_retry (default 60) seconds + * before considering growing. + */ + growtime = ddi_get_lbolt() + (arc_grow_retry * hz); + + arc_kmem_reap_now(); + + /* + * If we are still low on memory, shrink the ARC + * so that we have arc_shrink_min free space. + */ + free_memory = arc_available_memory(); + + int64_t to_free = + (arc_c >> arc_shrink_shift) - free_memory; + if (to_free > 0) { +#ifdef _KERNEL + to_free = MAX(to_free, ptob(needfree)); +#endif + arc_shrink(to_free); } - - /* reset the growth delay for every reclaim */ - growtime = ddi_get_lbolt() + (arc_grow_retry * hz); - - arc_kmem_reap_now(last_reclaim); - arc_warm = B_TRUE; - - } else if (arc_no_grow && ddi_get_lbolt() >= growtime) { - arc_no_grow = FALSE; + } else if (free_memory < arc_c >> arc_no_grow_shift) { + arc_no_grow = B_TRUE; + } else if (ddi_get_lbolt() >= growtime) { + arc_no_grow = B_FALSE; } arc_adjust(); @@ -2404,6 +2896,20 @@ if (arc_eviction_list != NULL) arc_do_user_evicts(); + /* + * This is necessary in order for the mdb ::arc dcmd to + * show up to date information. Since the ::arc command + * does not call the kstat's update function, without + * this call, the command may show stale stats for the + * anon, mru, mru_ghost, mfu, and mfu_ghost lists. Even + * with this change, the data might be up to 1 second + * out of date; but that should suffice. The arc_state_t + * structures can be queried directly if more accurate + * information is needed. + */ + if (arc_ksp != NULL) + arc_ksp->ks_update(arc_ksp, KSTAT_READ); + /* block until needed, or one second, whichever is shorter */ CALLB_CPR_SAFE_BEGIN(&cpr); (void) cv_timedwait(&arc_reclaim_thr_cv, @@ -2527,9 +3033,9 @@ static void arc_get_data_buf(arc_buf_t *buf) { - arc_state_t *state = buf->b_hdr->b_state; + arc_state_t *state = buf->b_hdr->b_l1hdr.b_state; uint64_t size = buf->b_hdr->b_size; - arc_buf_contents_t type = buf->b_hdr->b_type; + arc_buf_contents_t type = arc_buf_type(buf->b_hdr); arc_adapt(size, state); @@ -2540,12 +3046,11 @@ if (!arc_evict_needed(type)) { if (type == ARC_BUFC_METADATA) { buf->b_data = zio_buf_alloc(size); - arc_space_consume(size, ARC_SPACE_DATA); + arc_space_consume(size, ARC_SPACE_META); } else { ASSERT(type == ARC_BUFC_DATA); buf->b_data = zio_data_buf_alloc(size); - ARCSTAT_INCR(arcstat_data_size, size); - atomic_add_64(&arc_size, size); + arc_space_consume(size, ARC_SPACE_DATA); } goto out; } @@ -2555,8 +3060,7 @@ * will end up on the mru list; so steal space from there. */ if (state == arc_mfu_ghost) - state = buf->b_hdr->b_flags & ARC_FLAG_PREFETCH ? - arc_mru : arc_mfu; + state = HDR_PREFETCH(buf->b_hdr) ? arc_mru : arc_mfu; else if (state == arc_mru_ghost) state = arc_mru; @@ -2573,12 +3077,11 @@ if ((buf->b_data = arc_evict(state, NULL, size, TRUE, type)) == NULL) { if (type == ARC_BUFC_METADATA) { buf->b_data = zio_buf_alloc(size); - arc_space_consume(size, ARC_SPACE_DATA); + arc_space_consume(size, ARC_SPACE_META); } else { ASSERT(type == ARC_BUFC_DATA); buf->b_data = zio_data_buf_alloc(size); - ARCSTAT_INCR(arcstat_data_size, size); - atomic_add_64(&arc_size, size); + arc_space_consume(size, ARC_SPACE_DATA); } ARCSTAT_BUMP(arcstat_recycle_miss); } @@ -2588,19 +3091,20 @@ * Update the state size. Note that ghost states have a * "ghost size" and so don't need to be updated. */ - if (!GHOST_STATE(buf->b_hdr->b_state)) { + if (!GHOST_STATE(buf->b_hdr->b_l1hdr.b_state)) { arc_buf_hdr_t *hdr = buf->b_hdr; - atomic_add_64(&hdr->b_state->arcs_size, size); - if (list_link_active(&hdr->b_arc_node)) { - ASSERT(refcount_is_zero(&hdr->b_refcnt)); - atomic_add_64(&hdr->b_state->arcs_lsize[type], size); + atomic_add_64(&hdr->b_l1hdr.b_state->arcs_size, size); + if (list_link_active(&hdr->b_l1hdr.b_arc_node)) { + ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt)); + atomic_add_64(&hdr->b_l1hdr.b_state->arcs_lsize[type], + size); } /* * If we are growing the cache, and we are adding anonymous * data, and we have outgrown arc_p, update arc_p */ - if (arc_size < arc_c && hdr->b_state == arc_anon && + if (arc_size < arc_c && hdr->b_l1hdr.b_state == arc_anon && arc_anon->arcs_size + arc_mru->arcs_size > arc_p) arc_p = MIN(arc_c, arc_p + size); } @@ -2616,20 +3120,21 @@ clock_t now; ASSERT(MUTEX_HELD(hash_lock)); - - if (hdr->b_state == arc_anon) { + ASSERT(HDR_HAS_L1HDR(hdr)); + + if (hdr->b_l1hdr.b_state == arc_anon) { /* * This buffer is not in the cache, and does not * appear in our "ghost" list. Add the new buffer * to the MRU state. */ - ASSERT(hdr->b_arc_access == 0); - hdr->b_arc_access = ddi_get_lbolt(); + ASSERT0(hdr->b_l1hdr.b_arc_access); + hdr->b_l1hdr.b_arc_access = ddi_get_lbolt(); DTRACE_PROBE1(new_state__mru, arc_buf_hdr_t *, hdr); arc_change_state(arc_mru, hdr, hash_lock); - } else if (hdr->b_state == arc_mru) { + } else if (hdr->b_l1hdr.b_state == arc_mru) { now = ddi_get_lbolt(); /* @@ -2640,14 +3145,15 @@ * - move the buffer to the head of the list if this is * another prefetch (to make it less likely to be evicted). */ - if ((hdr->b_flags & ARC_FLAG_PREFETCH) != 0) { - if (refcount_count(&hdr->b_refcnt) == 0) { - ASSERT(list_link_active(&hdr->b_arc_node)); + if (HDR_PREFETCH(hdr)) { + if (refcount_count(&hdr->b_l1hdr.b_refcnt) == 0) { + ASSERT(list_link_active( + &hdr->b_l1hdr.b_arc_node)); } else { hdr->b_flags &= ~ARC_FLAG_PREFETCH; ARCSTAT_BUMP(arcstat_mru_hits); } - hdr->b_arc_access = now; + hdr->b_l1hdr.b_arc_access = now; return; } @@ -2656,18 +3162,18 @@ * but it is still in the cache. Move it to the MFU * state. */ - if (now > hdr->b_arc_access + ARC_MINTIME) { + if (now > hdr->b_l1hdr.b_arc_access + ARC_MINTIME) { /* * More than 125ms have passed since we * instantiated this buffer. Move it to the * most frequently used state. */ - hdr->b_arc_access = now; + hdr->b_l1hdr.b_arc_access = now; DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr); arc_change_state(arc_mfu, hdr, hash_lock); } ARCSTAT_BUMP(arcstat_mru_hits); - } else if (hdr->b_state == arc_mru_ghost) { + } else if (hdr->b_l1hdr.b_state == arc_mru_ghost) { arc_state_t *new_state; /* * This buffer has been "accessed" recently, but @@ -2675,9 +3181,9 @@ * MFU state. */ - if (hdr->b_flags & ARC_FLAG_PREFETCH) { + if (HDR_PREFETCH(hdr)) { new_state = arc_mru; - if (refcount_count(&hdr->b_refcnt) > 0) + if (refcount_count(&hdr->b_l1hdr.b_refcnt) > 0) hdr->b_flags &= ~ARC_FLAG_PREFETCH; DTRACE_PROBE1(new_state__mru, arc_buf_hdr_t *, hdr); } else { @@ -2685,11 +3191,11 @@ DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr); } - hdr->b_arc_access = ddi_get_lbolt(); + hdr->b_l1hdr.b_arc_access = ddi_get_lbolt(); arc_change_state(new_state, hdr, hash_lock); ARCSTAT_BUMP(arcstat_mru_ghost_hits); - } else if (hdr->b_state == arc_mfu) { + } else if (hdr->b_l1hdr.b_state == arc_mfu) { /* * This buffer has been accessed more than once and is * still in the cache. Keep it in the MFU state. @@ -2699,13 +3205,13 @@ * If it was a prefetch, we will explicitly move it to * the head of the list now. */ - if ((hdr->b_flags & ARC_FLAG_PREFETCH) != 0) { - ASSERT(refcount_count(&hdr->b_refcnt) == 0); - ASSERT(list_link_active(&hdr->b_arc_node)); + if ((HDR_PREFETCH(hdr)) != 0) { + ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt)); + ASSERT(list_link_active(&hdr->b_l1hdr.b_arc_node)); } ARCSTAT_BUMP(arcstat_mfu_hits); - hdr->b_arc_access = ddi_get_lbolt(); - } else if (hdr->b_state == arc_mfu_ghost) { + hdr->b_l1hdr.b_arc_access = ddi_get_lbolt(); + } else if (hdr->b_l1hdr.b_state == arc_mfu_ghost) { arc_state_t *new_state = arc_mfu; /* * This buffer has been accessed more than once but has @@ -2713,26 +3219,26 @@ * MFU state. */ - if (hdr->b_flags & ARC_FLAG_PREFETCH) { + if (HDR_PREFETCH(hdr)) { /* * This is a prefetch access... * move this block back to the MRU state. */ - ASSERT0(refcount_count(&hdr->b_refcnt)); + ASSERT0(refcount_count(&hdr->b_l1hdr.b_refcnt)); new_state = arc_mru; } - hdr->b_arc_access = ddi_get_lbolt(); + hdr->b_l1hdr.b_arc_access = ddi_get_lbolt(); DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr); arc_change_state(new_state, hdr, hash_lock); ARCSTAT_BUMP(arcstat_mfu_ghost_hits); - } else if (hdr->b_state == arc_l2c_only) { + } else if (hdr->b_l1hdr.b_state == arc_l2c_only) { /* * This buffer is on the 2nd Level ARC. */ - hdr->b_arc_access = ddi_get_lbolt(); + hdr->b_l1hdr.b_arc_access = ddi_get_lbolt(); DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr); arc_change_state(arc_mfu, hdr, hash_lock); } else { @@ -2803,11 +3309,11 @@ } hdr->b_flags &= ~ARC_FLAG_L2_EVICTED; - if (l2arc_noprefetch && (hdr->b_flags & ARC_FLAG_PREFETCH)) + if (l2arc_noprefetch && HDR_PREFETCH(hdr)) hdr->b_flags &= ~ARC_FLAG_L2CACHE; /* byteswap if necessary */ - callback_list = hdr->b_acb; + callback_list = hdr->b_l1hdr.b_acb; ASSERT(callback_list != NULL); if (BP_SHOULD_BYTESWAP(zio->io_bp) && zio->io_error == 0) { dmu_object_byteswap_t bswap = @@ -2821,7 +3327,8 @@ arc_cksum_compute(buf, B_FALSE); arc_buf_watch(buf); - if (hash_lock && zio->io_error == 0 && hdr->b_state == arc_anon) { + if (hash_lock && zio->io_error == 0 && + hdr->b_l1hdr.b_state == arc_anon) { /* * Only call arc_access on anonymous buffers. This is because * if we've issued an I/O for an evicted buffer, we've already @@ -2843,24 +3350,25 @@ abuf = NULL; } } - hdr->b_acb = NULL; + hdr->b_l1hdr.b_acb = NULL; hdr->b_flags &= ~ARC_FLAG_IO_IN_PROGRESS; ASSERT(!HDR_BUF_AVAILABLE(hdr)); if (abuf == buf) { ASSERT(buf->b_efunc == NULL); - ASSERT(hdr->b_datacnt == 1); + ASSERT(hdr->b_l1hdr.b_datacnt == 1); hdr->b_flags |= ARC_FLAG_BUF_AVAILABLE; } - ASSERT(refcount_is_zero(&hdr->b_refcnt) || callback_list != NULL); + ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt) || + callback_list != NULL); if (zio->io_error != 0) { hdr->b_flags |= ARC_FLAG_IO_ERROR; - if (hdr->b_state != arc_anon) + if (hdr->b_l1hdr.b_state != arc_anon) arc_change_state(arc_anon, hdr, hash_lock); if (HDR_IN_HASH_TABLE(hdr)) buf_hash_remove(hdr); - freeable = refcount_is_zero(&hdr->b_refcnt); + freeable = refcount_is_zero(&hdr->b_l1hdr.b_refcnt); } /* @@ -2868,9 +3376,9 @@ * that the hdr (and hence the cv) might be freed before we get to * the cv_broadcast(). */ - cv_broadcast(&hdr->b_cv); - - if (hash_lock) { + cv_broadcast(&hdr->b_l1hdr.b_cv); + + if (hash_lock != NULL) { mutex_exit(hash_lock); } else { /* @@ -2879,8 +3387,8 @@ * moved to the anonymous state (so that it won't show up * in the cache). */ - ASSERT3P(hdr->b_state, ==, arc_anon); - freeable = refcount_is_zero(&hdr->b_refcnt); + ASSERT3P(hdr->b_l1hdr.b_state, ==, arc_anon); + freeable = refcount_is_zero(&hdr->b_l1hdr.b_refcnt); } /* execute each callback and free its structure */ @@ -2942,14 +3450,14 @@ hdr = buf_hash_find(guid, bp, &hash_lock); } - if (hdr != NULL && hdr->b_datacnt > 0) { + if (hdr != NULL && HDR_HAS_L1HDR(hdr) && hdr->b_l1hdr.b_datacnt > 0) { *arc_flags |= ARC_FLAG_CACHED; if (HDR_IO_IN_PROGRESS(hdr)) { if (*arc_flags & ARC_FLAG_WAIT) { - cv_wait(&hdr->b_cv, hash_lock); + cv_wait(&hdr->b_l1hdr.b_cv, hash_lock); mutex_exit(hash_lock); goto top; } @@ -2967,8 +3475,8 @@ spa, NULL, NULL, NULL, zio_flags); ASSERT(acb->acb_done != NULL); - acb->acb_next = hdr->b_acb; - hdr->b_acb = acb; + acb->acb_next = hdr->b_l1hdr.b_acb; + hdr->b_l1hdr.b_acb = acb; add_reference(hdr, hash_lock, private); mutex_exit(hash_lock); return (0); @@ -2977,7 +3485,8 @@ return (0); } - ASSERT(hdr->b_state == arc_mru || hdr->b_state == arc_mfu); + ASSERT(hdr->b_l1hdr.b_state == arc_mru || + hdr->b_l1hdr.b_state == arc_mfu); if (done) { add_reference(hdr, hash_lock, private); @@ -2986,7 +3495,7 @@ * copy of the data so that we will be guaranteed * that arc_release() will always succeed. */ - buf = hdr->b_buf; + buf = hdr->b_l1hdr.b_buf; ASSERT(buf); ASSERT(buf->b_data); if (HDR_BUF_AVAILABLE(hdr)) { @@ -2997,7 +3506,7 @@ } } else if (*arc_flags & ARC_FLAG_PREFETCH && - refcount_count(&hdr->b_refcnt) == 0) { + refcount_count(&hdr->b_l1hdr.b_refcnt) == 0) { hdr->b_flags |= ARC_FLAG_PREFETCH; } DTRACE_PROBE1(arc__hit, arc_buf_hdr_t *, hdr); @@ -3008,8 +3517,8 @@ hdr->b_flags |= ARC_FLAG_L2COMPRESS; mutex_exit(hash_lock); ARCSTAT_BUMP(arcstat_hits); - ARCSTAT_CONDSTAT(!(hdr->b_flags & ARC_FLAG_PREFETCH), - demand, prefetch, hdr->b_type != ARC_BUFC_METADATA, + ARCSTAT_CONDSTAT(!HDR_PREFETCH(hdr), + demand, prefetch, !HDR_ISTYPE_METADATA(hdr), data, metadata, hits); if (done) @@ -3021,7 +3530,7 @@ uint64_t addr = 0; boolean_t devw = B_FALSE; enum zio_compress b_compress = ZIO_COMPRESS_OFF; - uint64_t b_asize = 0; + int32_t b_asize = 0; if (hdr == NULL) { /* this block is not in the cache */ @@ -3032,7 +3541,6 @@ if (!BP_IS_EMBEDDED(bp)) { hdr->b_dva = *BP_IDENTITY(bp); hdr->b_birth = BP_PHYSICAL_BIRTH(bp); - hdr->b_cksum0 = bp->blk_cksum.zc_word[0]; exists = buf_hash_insert(hdr, &hash_lock); } if (exists != NULL) { @@ -3056,11 +3564,20 @@ if (BP_GET_LEVEL(bp) > 0) hdr->b_flags |= ARC_FLAG_INDIRECT; } else { - /* this block is in the ghost cache */ - ASSERT(GHOST_STATE(hdr->b_state)); + /* + * This block is in the ghost cache. If it was L2-only + * (and thus didn't have an L1 hdr), we realloc the + * header to add an L1 hdr. + */ + if (!HDR_HAS_L1HDR(hdr)) { + hdr = arc_hdr_realloc(hdr, hdr_l2only_cache, + hdr_full_cache); + } + + ASSERT(GHOST_STATE(hdr->b_l1hdr.b_state)); ASSERT(!HDR_IO_IN_PROGRESS(hdr)); - ASSERT0(refcount_count(&hdr->b_refcnt)); - ASSERT(hdr->b_buf == NULL); + ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt)); + ASSERT(hdr->b_l1hdr.b_buf == NULL); /* if this is a prefetch, we don't have a reference */ if (*arc_flags & ARC_FLAG_PREFETCH) @@ -3077,29 +3594,29 @@ buf->b_efunc = NULL; buf->b_private = NULL; buf->b_next = NULL; - hdr->b_buf = buf; - ASSERT(hdr->b_datacnt == 0); - hdr->b_datacnt = 1; + hdr->b_l1hdr.b_buf = buf; + ASSERT0(hdr->b_l1hdr.b_datacnt); + hdr->b_l1hdr.b_datacnt = 1; arc_get_data_buf(buf); arc_access(hdr, hash_lock); } - ASSERT(!GHOST_STATE(hdr->b_state)); + ASSERT(!GHOST_STATE(hdr->b_l1hdr.b_state)); acb = kmem_zalloc(sizeof (arc_callback_t), KM_SLEEP); acb->acb_done = done; acb->acb_private = private; - ASSERT(hdr->b_acb == NULL); - hdr->b_acb = acb; + ASSERT(hdr->b_l1hdr.b_acb == NULL); + hdr->b_l1hdr.b_acb = acb; hdr->b_flags |= ARC_FLAG_IO_IN_PROGRESS; - if (hdr->b_l2hdr != NULL && - (vd = hdr->b_l2hdr->b_dev->l2ad_vdev) != NULL) { - devw = hdr->b_l2hdr->b_dev->l2ad_writing; - addr = hdr->b_l2hdr->b_daddr; - b_compress = hdr->b_l2hdr->b_compress; - b_asize = hdr->b_l2hdr->b_asize; + if (HDR_HAS_L2HDR(hdr) && + (vd = hdr->b_l2hdr.b_dev->l2ad_vdev) != NULL) { + devw = hdr->b_l2hdr.b_dev->l2ad_writing; + addr = hdr->b_l2hdr.b_daddr; + b_compress = HDR_GET_COMPRESS(hdr); + b_asize = hdr->b_l2hdr.b_asize; /* * Lock out device removal. */ @@ -3119,8 +3636,8 @@ DTRACE_PROBE4(arc__miss, arc_buf_hdr_t *, hdr, blkptr_t *, bp, uint64_t, size, zbookmark_phys_t *, zb); ARCSTAT_BUMP(arcstat_misses); - ARCSTAT_CONDSTAT(!(hdr->b_flags & ARC_FLAG_PREFETCH), - demand, prefetch, hdr->b_type != ARC_BUFC_METADATA, + ARCSTAT_CONDSTAT(!HDR_PREFETCH(hdr), + demand, prefetch, !HDR_ISTYPE_METADATA(hdr), data, metadata, misses); if (vd != NULL && l2arc_ndev != 0 && !(l2arc_norw && devw)) { @@ -3133,7 +3650,7 @@ * also have invalidated the vdev. * 5. This isn't prefetch and l2arc_noprefetch is set. */ - if (hdr->b_l2hdr != NULL && + if (HDR_HAS_L2HDR(hdr) && !HDR_L2_WRITING(hdr) && !HDR_L2_EVICTED(hdr) && !(l2arc_noprefetch && HDR_PREFETCH(hdr))) { l2arc_read_callback_t *cb; @@ -3225,8 +3742,9 @@ arc_set_callback(arc_buf_t *buf, arc_evict_func_t *func, void *private) { ASSERT(buf->b_hdr != NULL); - ASSERT(buf->b_hdr->b_state != arc_anon); - ASSERT(!refcount_is_zero(&buf->b_hdr->b_refcnt) || func == NULL); + ASSERT(buf->b_hdr->b_l1hdr.b_state != arc_anon); + ASSERT(!refcount_is_zero(&buf->b_hdr->b_l1hdr.b_refcnt) || + func == NULL); ASSERT(buf->b_efunc == NULL); ASSERT(!HDR_BUF_AVAILABLE(buf->b_hdr)); @@ -3250,7 +3768,7 @@ if (hdr == NULL) return; if (HDR_BUF_AVAILABLE(hdr)) { - arc_buf_t *buf = hdr->b_buf; + arc_buf_t *buf = hdr->b_l1hdr.b_buf; add_reference(hdr, hash_lock, FTAG); hdr->b_flags &= ~ARC_FLAG_BUF_AVAILABLE; mutex_exit(hash_lock); @@ -3308,17 +3826,19 @@ hdr = buf->b_hdr; ASSERT3P(hash_lock, ==, HDR_LOCK(hdr)); - ASSERT3U(refcount_count(&hdr->b_refcnt), <, hdr->b_datacnt); - ASSERT(hdr->b_state == arc_mru || hdr->b_state == arc_mfu); + ASSERT3U(refcount_count(&hdr->b_l1hdr.b_refcnt), <, + hdr->b_l1hdr.b_datacnt); + ASSERT(hdr->b_l1hdr.b_state == arc_mru || + hdr->b_l1hdr.b_state == arc_mfu); buf->b_efunc = NULL; buf->b_private = NULL; - if (hdr->b_datacnt > 1) { + if (hdr->b_l1hdr.b_datacnt > 1) { mutex_exit(&buf->b_evict_lock); arc_buf_destroy(buf, FALSE, TRUE); } else { - ASSERT(buf == hdr->b_buf); + ASSERT(buf == hdr->b_l1hdr.b_buf); hdr->b_flags |= ARC_FLAG_BUF_AVAILABLE; mutex_exit(&buf->b_evict_lock); } @@ -3337,10 +3857,7 @@ void arc_release(arc_buf_t *buf, void *tag) { - arc_buf_hdr_t *hdr; - kmutex_t *hash_lock = NULL; - l2arc_buf_hdr_t *l2hdr; - uint64_t buf_size; + arc_buf_hdr_t *hdr = buf->b_hdr; /* * It would be nice to assert that if it's DMU metadata (level > @@ -3349,56 +3866,87 @@ */ mutex_enter(&buf->b_evict_lock); - hdr = buf->b_hdr; + + /* + * We don't grab the hash lock prior to this check, because if + * the buffer's header is in the arc_anon state, it won't be + * linked into the hash table. + */ + if (hdr->b_l1hdr.b_state == arc_anon) { + mutex_exit(&buf->b_evict_lock); + ASSERT(!HDR_IO_IN_PROGRESS(hdr)); + ASSERT(!HDR_IN_HASH_TABLE(hdr)); + ASSERT(!HDR_HAS_L2HDR(hdr)); + ASSERT(BUF_EMPTY(hdr)); + + ASSERT3U(hdr->b_l1hdr.b_datacnt, ==, 1); + ASSERT3S(refcount_count(&hdr->b_l1hdr.b_refcnt), ==, 1); + ASSERT(!list_link_active(&hdr->b_l1hdr.b_arc_node)); + + ASSERT3P(buf->b_efunc, ==, NULL); + ASSERT3P(buf->b_private, ==, NULL); + + hdr->b_l1hdr.b_arc_access = 0; + arc_buf_thaw(buf); + + return; + } + + kmutex_t *hash_lock = HDR_LOCK(hdr); + mutex_enter(hash_lock); + + /* + * This assignment is only valid as long as the hash_lock is + * held, we must be careful not to reference state or the + * b_state field after dropping the lock. + */ + arc_state_t *state = hdr->b_l1hdr.b_state; + ASSERT3P(hash_lock, ==, HDR_LOCK(hdr)); + ASSERT3P(state, !=, arc_anon); /* this buffer is not on any list */ - ASSERT(refcount_count(&hdr->b_refcnt) > 0); - - if (hdr->b_state == arc_anon) { - /* this buffer is already released */ - ASSERT(buf->b_efunc == NULL); - } else { - hash_lock = HDR_LOCK(hdr); - mutex_enter(hash_lock); - hdr = buf->b_hdr; - ASSERT3P(hash_lock, ==, HDR_LOCK(hdr)); + ASSERT(refcount_count(&hdr->b_l1hdr.b_refcnt) > 0); + + if (HDR_HAS_L2HDR(hdr)) { + ARCSTAT_INCR(arcstat_l2_asize, -hdr->b_l2hdr.b_asize); + ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size); + + mutex_enter(&hdr->b_l2hdr.b_dev->l2ad_mtx); + list_remove(&hdr->b_l2hdr.b_dev->l2ad_buflist, hdr); + mutex_exit(&hdr->b_l2hdr.b_dev->l2ad_mtx); + + hdr->b_flags &= ~ARC_FLAG_HAS_L2HDR; } - l2hdr = hdr->b_l2hdr; - if (l2hdr) { - mutex_enter(&l2arc_buflist_mtx); - hdr->b_l2hdr = NULL; - list_remove(l2hdr->b_dev->l2ad_buflist, hdr); - } - buf_size = hdr->b_size; - /* * Do we have more than one buf? */ - if (hdr->b_datacnt > 1) { + if (hdr->b_l1hdr.b_datacnt > 1) { arc_buf_hdr_t *nhdr; arc_buf_t **bufp; uint64_t blksz = hdr->b_size; uint64_t spa = hdr->b_spa; - arc_buf_contents_t type = hdr->b_type; + arc_buf_contents_t type = arc_buf_type(hdr); uint32_t flags = hdr->b_flags; - ASSERT(hdr->b_buf != buf || buf->b_next != NULL); + ASSERT(hdr->b_l1hdr.b_buf != buf || buf->b_next != NULL); /* * Pull the data off of this hdr and attach it to * a new anonymous hdr. */ (void) remove_reference(hdr, hash_lock, tag); - bufp = &hdr->b_buf; + bufp = &hdr->b_l1hdr.b_buf; while (*bufp != buf) bufp = &(*bufp)->b_next; *bufp = buf->b_next; buf->b_next = NULL; - ASSERT3U(hdr->b_state->arcs_size, >=, hdr->b_size); - atomic_add_64(&hdr->b_state->arcs_size, -hdr->b_size); - if (refcount_is_zero(&hdr->b_refcnt)) { - uint64_t *size = &hdr->b_state->arcs_lsize[hdr->b_type]; + ASSERT3P(state, !=, arc_l2c_only); + ASSERT3U(state->arcs_size, >=, hdr->b_size); + atomic_add_64(&state->arcs_size, -hdr->b_size); + if (refcount_is_zero(&hdr->b_l1hdr.b_refcnt)) { + ASSERT3P(state, !=, arc_l2c_only); + uint64_t *size = &state->arcs_lsize[type]; ASSERT3U(*size, >=, hdr->b_size); atomic_add_64(size, -hdr->b_size); } @@ -3407,57 +3955,50 @@ * We're releasing a duplicate user data buffer, update * our statistics accordingly. */ - if (hdr->b_type == ARC_BUFC_DATA) { + if (HDR_ISTYPE_DATA(hdr)) { ARCSTAT_BUMPDOWN(arcstat_duplicate_buffers); ARCSTAT_INCR(arcstat_duplicate_buffers_size, -hdr->b_size); } - hdr->b_datacnt -= 1; + hdr->b_l1hdr.b_datacnt -= 1; arc_cksum_verify(buf); arc_buf_unwatch(buf); mutex_exit(hash_lock); - nhdr = kmem_cache_alloc(hdr_cache, KM_PUSHPAGE); + nhdr = kmem_cache_alloc(hdr_full_cache, KM_PUSHPAGE); nhdr->b_size = blksz; nhdr->b_spa = spa; - nhdr->b_type = type; - nhdr->b_buf = buf; - nhdr->b_state = arc_anon; - nhdr->b_arc_access = 0; + nhdr->b_flags = flags & ARC_FLAG_L2_WRITING; - nhdr->b_l2hdr = NULL; - nhdr->b_datacnt = 1; + nhdr->b_flags |= arc_bufc_to_flags(type); + nhdr->b_flags |= ARC_FLAG_HAS_L1HDR; + + nhdr->b_l1hdr.b_buf = buf; + nhdr->b_l1hdr.b_datacnt = 1; + nhdr->b_l1hdr.b_state = arc_anon; + nhdr->b_l1hdr.b_arc_access = 0; nhdr->b_freeze_cksum = NULL; - (void) refcount_add(&nhdr->b_refcnt, tag); + + (void) refcount_add(&nhdr->b_l1hdr.b_refcnt, tag); buf->b_hdr = nhdr; mutex_exit(&buf->b_evict_lock); atomic_add_64(&arc_anon->arcs_size, blksz); } else { mutex_exit(&buf->b_evict_lock); - ASSERT(refcount_count(&hdr->b_refcnt) == 1); - ASSERT(!list_link_active(&hdr->b_arc_node)); + ASSERT(refcount_count(&hdr->b_l1hdr.b_refcnt) == 1); + /* protected by hash lock */ + ASSERT(!list_link_active(&hdr->b_l1hdr.b_arc_node)); ASSERT(!HDR_IO_IN_PROGRESS(hdr)); - if (hdr->b_state != arc_anon) - arc_change_state(arc_anon, hdr, hash_lock); - hdr->b_arc_access = 0; - if (hash_lock) - mutex_exit(hash_lock); + arc_change_state(arc_anon, hdr, hash_lock); + hdr->b_l1hdr.b_arc_access = 0; + mutex_exit(hash_lock); buf_discard_identity(hdr); arc_buf_thaw(buf); } buf->b_efunc = NULL; buf->b_private = NULL; - - if (l2hdr) { - ARCSTAT_INCR(arcstat_l2_asize, -l2hdr->b_asize); - vdev_space_update(l2hdr->b_dev->l2ad_vdev, - -l2hdr->b_asize, 0, 0); - kmem_free(l2hdr, sizeof (l2arc_buf_hdr_t)); - ARCSTAT_INCR(arcstat_l2_size, -buf_size); - mutex_exit(&l2arc_buflist_mtx); - } } int @@ -3466,7 +4007,8 @@ int released; mutex_enter(&buf->b_evict_lock); - released = (buf->b_data != NULL && buf->b_hdr->b_state == arc_anon); + released = (buf->b_data != NULL && + buf->b_hdr->b_l1hdr.b_state == arc_anon); mutex_exit(&buf->b_evict_lock); return (released); } @@ -3478,7 +4020,7 @@ int referenced; mutex_enter(&buf->b_evict_lock); - referenced = (refcount_count(&buf->b_hdr->b_refcnt)); + referenced = (refcount_count(&buf->b_hdr->b_l1hdr.b_refcnt)); mutex_exit(&buf->b_evict_lock); return (referenced); } @@ -3491,7 +4033,9 @@ arc_buf_t *buf = callback->awcb_buf; arc_buf_hdr_t *hdr = buf->b_hdr; - ASSERT(!refcount_is_zero(&buf->b_hdr->b_refcnt)); + ASSERT(HDR_HAS_L1HDR(hdr)); + ASSERT(!refcount_is_zero(&buf->b_hdr->b_l1hdr.b_refcnt)); + ASSERT(hdr->b_l1hdr.b_datacnt > 0); callback->awcb_ready(zio, buf, callback->awcb_private); /* @@ -3501,12 +4045,12 @@ * accounting for any re-write attempt. */ if (HDR_IO_IN_PROGRESS(hdr)) { - mutex_enter(&hdr->b_freeze_lock); + mutex_enter(&hdr->b_l1hdr.b_freeze_lock); if (hdr->b_freeze_cksum != NULL) { kmem_free(hdr->b_freeze_cksum, sizeof (zio_cksum_t)); hdr->b_freeze_cksum = NULL; } - mutex_exit(&hdr->b_freeze_lock); + mutex_exit(&hdr->b_l1hdr.b_freeze_lock); } arc_cksum_compute(buf, B_FALSE); hdr->b_flags |= ARC_FLAG_IO_IN_PROGRESS; @@ -3531,7 +4075,7 @@ arc_buf_t *buf = callback->awcb_buf; arc_buf_hdr_t *hdr = buf->b_hdr; - ASSERT(hdr->b_acb == NULL); + ASSERT(hdr->b_l1hdr.b_acb == NULL); if (zio->io_error == 0) { if (BP_IS_HOLE(zio->io_bp) || BP_IS_EMBEDDED(zio->io_bp)) { @@ -3539,7 +4083,6 @@ } else { hdr->b_dva = *BP_IDENTITY(zio->io_bp); hdr->b_birth = BP_PHYSICAL_BIRTH(zio->io_bp); - hdr->b_cksum0 = zio->io_bp->blk_cksum.zc_word[0]; } } else { ASSERT(BUF_EMPTY(hdr)); @@ -3560,7 +4103,7 @@ arc_cksum_verify(buf); exists = buf_hash_insert(hdr, &hash_lock); - if (exists) { + if (exists != NULL) { /* * This can only happen if we overwrite for * sync-to-convergence, because we remove @@ -3570,7 +4113,8 @@ if (!BP_EQUAL(&zio->io_bp_orig, zio->io_bp)) panic("bad overwrite, hdr=%p exists=%p", (void *)hdr, (void *)exists); - ASSERT(refcount_is_zero(&exists->b_refcnt)); + ASSERT(refcount_is_zero( + &exists->b_l1hdr.b_refcnt)); arc_change_state(arc_anon, exists, hash_lock); mutex_exit(hash_lock); arc_hdr_destroy(exists); @@ -3584,22 +4128,22 @@ (void *)hdr, (void *)exists); } else { /* Dedup */ - ASSERT(hdr->b_datacnt == 1); - ASSERT(hdr->b_state == arc_anon); + ASSERT(hdr->b_l1hdr.b_datacnt == 1); + ASSERT(hdr->b_l1hdr.b_state == arc_anon); ASSERT(BP_GET_DEDUP(zio->io_bp)); ASSERT(BP_GET_LEVEL(zio->io_bp) == 0); } } hdr->b_flags &= ~ARC_FLAG_IO_IN_PROGRESS; /* if it's not anon, we are doing a scrub */ - if (!exists && hdr->b_state == arc_anon) + if (exists == NULL && hdr->b_l1hdr.b_state == arc_anon) arc_access(hdr, hash_lock); mutex_exit(hash_lock); } else { hdr->b_flags &= ~ARC_FLAG_IO_IN_PROGRESS; } - ASSERT(!refcount_is_zero(&hdr->b_refcnt)); + ASSERT(!refcount_is_zero(&hdr->b_l1hdr.b_refcnt)); callback->awcb_done(zio, buf, callback->awcb_private); kmem_free(callback, sizeof (arc_write_callback_t)); @@ -3619,8 +4163,9 @@ ASSERT(ready != NULL); ASSERT(done != NULL); ASSERT(!HDR_IO_ERROR(hdr)); - ASSERT((hdr->b_flags & ARC_FLAG_IO_IN_PROGRESS) == 0); - ASSERT(hdr->b_acb == NULL); + ASSERT(!HDR_IO_IN_PROGRESS(hdr)); + ASSERT(hdr->b_l1hdr.b_acb == NULL); + ASSERT(hdr->b_l1hdr.b_datacnt > 0); if (l2arc) hdr->b_flags |= ARC_FLAG_L2CACHE; if (l2arc_compress) @@ -3736,9 +4281,60 @@ return (0); } +static void +arc_kstat_update_state(arc_state_t *state, kstat_named_t *size, + kstat_named_t *evict_data, kstat_named_t *evict_metadata) +{ + size->value.ui64 = state->arcs_size; + evict_data->value.ui64 = state->arcs_lsize[ARC_BUFC_DATA]; + evict_metadata->value.ui64 = state->arcs_lsize[ARC_BUFC_METADATA]; +} + +static int +arc_kstat_update(kstat_t *ksp, int rw) +{ + arc_stats_t *as = ksp->ks_data; + + if (rw == KSTAT_WRITE) { + return (EACCES); + } else { + arc_kstat_update_state(arc_anon, + &as->arcstat_anon_size, + &as->arcstat_anon_evictable_data, + &as->arcstat_anon_evictable_metadata); + arc_kstat_update_state(arc_mru, + &as->arcstat_mru_size, + &as->arcstat_mru_evictable_data, + &as->arcstat_mru_evictable_metadata); + arc_kstat_update_state(arc_mru_ghost, + &as->arcstat_mru_ghost_size, + &as->arcstat_mru_ghost_evictable_data, + &as->arcstat_mru_ghost_evictable_metadata); + arc_kstat_update_state(arc_mfu, + &as->arcstat_mfu_size, + &as->arcstat_mfu_evictable_data, + &as->arcstat_mfu_evictable_metadata); + arc_kstat_update_state(arc_mfu_ghost, + &as->arcstat_mfu_ghost_size, + &as->arcstat_mfu_ghost_evictable_data, + &as->arcstat_mfu_ghost_evictable_metadata); + } + + return (0); +} + void arc_init(void) { + /* + * allmem is "all memory that we could possibly use". + */ +#ifdef _KERNEL + uint64_t allmem = ptob(physmem - swapfs_minfree); +#else + uint64_t allmem = (physmem * PAGESIZE) / 2; +#endif + mutex_init(&arc_reclaim_thr_lock, NULL, MUTEX_DEFAULT, NULL); cv_init(&arc_reclaim_thr_cv, NULL, CV_DEFAULT, NULL); @@ -3746,7 +4342,7 @@ arc_min_prefetch_lifespan = 1 * hz; /* Start out with 1/8 of all memory */ - arc_c = physmem * PAGESIZE / 8; + arc_c = allmem / 8; #ifdef _KERNEL /* @@ -3758,21 +4354,21 @@ #endif /* set min cache to 1/32 of all memory, or 64MB, whichever is more */ - arc_c_min = MAX(arc_c / 4, 64<<20); + arc_c_min = MAX(allmem / 32, 64 << 20); /* set max to 3/4 of all memory, or all but 1GB, whichever is more */ - if (arc_c * 8 >= 1<<30) - arc_c_max = (arc_c * 8) - (1<<30); + if (allmem >= 1 << 30) + arc_c_max = allmem - (1 << 30); else arc_c_max = arc_c_min; - arc_c_max = MAX(arc_c * 6, arc_c_max); + arc_c_max = MAX(allmem * 3 / 4, arc_c_max); /* * Allow the tunables to override our calculations if they are * reasonable (ie. over 64MB) */ - if (zfs_arc_max > 64<<20 && zfs_arc_max < physmem * PAGESIZE) + if (zfs_arc_max > 64 << 20 && zfs_arc_max < allmem) arc_c_max = zfs_arc_max; - if (zfs_arc_min > 64<<20 && zfs_arc_min <= arc_c_max) + if (zfs_arc_min > 64 << 20 && zfs_arc_min <= arc_c_max) arc_c_min = zfs_arc_min; arc_c = arc_c_max; @@ -3800,6 +4396,12 @@ if (zfs_arc_shrink_shift > 0) arc_shrink_shift = zfs_arc_shrink_shift; + /* + * Ensure that arc_no_grow_shift is less than arc_shrink_shift. + */ + if (arc_no_grow_shift >= arc_shrink_shift) + arc_no_grow_shift = arc_shrink_shift - 1; + if (zfs_arc_p_min_shift > 0) arc_p_min_shift = zfs_arc_p_min_shift; @@ -3825,25 +4427,35 @@ mutex_init(&arc_l2c_only->arcs_mtx, NULL, MUTEX_DEFAULT, NULL); list_create(&arc_mru->arcs_list[ARC_BUFC_METADATA], - sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node)); + sizeof (arc_buf_hdr_t), + offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node)); list_create(&arc_mru->arcs_list[ARC_BUFC_DATA], - sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node)); + sizeof (arc_buf_hdr_t), + offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node)); list_create(&arc_mru_ghost->arcs_list[ARC_BUFC_METADATA], - sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node)); + sizeof (arc_buf_hdr_t), + offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node)); list_create(&arc_mru_ghost->arcs_list[ARC_BUFC_DATA], - sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node)); + sizeof (arc_buf_hdr_t), + offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node)); list_create(&arc_mfu->arcs_list[ARC_BUFC_METADATA], - sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node)); + sizeof (arc_buf_hdr_t), + offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node)); list_create(&arc_mfu->arcs_list[ARC_BUFC_DATA], - sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node)); + sizeof (arc_buf_hdr_t), + offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node)); list_create(&arc_mfu_ghost->arcs_list[ARC_BUFC_METADATA], - sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node)); + sizeof (arc_buf_hdr_t), + offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node)); list_create(&arc_mfu_ghost->arcs_list[ARC_BUFC_DATA], - sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node)); + sizeof (arc_buf_hdr_t), + offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node)); list_create(&arc_l2c_only->arcs_list[ARC_BUFC_METADATA], - sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node)); + sizeof (arc_buf_hdr_t), + offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node)); list_create(&arc_l2c_only->arcs_list[ARC_BUFC_DATA], - sizeof (arc_buf_hdr_t), offsetof(arc_buf_hdr_t, b_arc_node)); + sizeof (arc_buf_hdr_t), + offsetof(arc_buf_hdr_t, b_l1hdr.b_arc_node)); buf_init(); @@ -3857,6 +4469,7 @@ if (arc_ksp != NULL) { arc_ksp->ks_data = &arc_stats; + arc_ksp->ks_update = arc_kstat_update; kstat_install(arc_ksp); } @@ -3922,7 +4535,7 @@ buf_fini(); - ASSERT(arc_loaned_bytes == 0); + ASSERT0(arc_loaned_bytes); } /* @@ -4080,7 +4693,7 @@ * 3. has an I/O in progress (it may be an incomplete read). * 4. is flagged not eligible (zfs property). */ - if (hdr->b_spa != spa_guid || hdr->b_l2hdr != NULL || + if (hdr->b_spa != spa_guid || HDR_HAS_L2HDR(hdr) || HDR_IO_IN_PROGRESS(hdr) || !HDR_L2CACHE(hdr)) return (B_FALSE); @@ -4133,20 +4746,6 @@ return (next); } -static void -l2arc_hdr_stat_add(void) -{ - ARCSTAT_INCR(arcstat_l2_hdr_size, HDR_SIZE + L2HDR_SIZE); - ARCSTAT_INCR(arcstat_hdr_size, -HDR_SIZE); -} - -static void -l2arc_hdr_stat_remove(void) -{ - ARCSTAT_INCR(arcstat_l2_hdr_size, -(HDR_SIZE + L2HDR_SIZE)); - ARCSTAT_INCR(arcstat_hdr_size, HDR_SIZE); -} - /* * Cycle through L2ARC devices. This is how L2ARC load balances. * If a device is returned, this also returns holding the spa config lock. @@ -4243,7 +4842,6 @@ l2arc_dev_t *dev; list_t *buflist; arc_buf_hdr_t *head, *hdr, *hdr_prev; - l2arc_buf_hdr_t *abl2; kmutex_t *hash_lock; int64_t bytes_dropped = 0; @@ -4253,7 +4851,7 @@ ASSERT(dev != NULL); head = cb->l2wcb_head; ASSERT(head != NULL); - buflist = dev->l2ad_buflist; + buflist = &dev->l2ad_buflist; ASSERT(buflist != NULL); DTRACE_PROBE2(l2arc__iodone, zio_t *, zio, l2arc_write_callback_t *, cb); @@ -4261,41 +4859,43 @@ if (zio->io_error != 0) ARCSTAT_BUMP(arcstat_l2_writes_error); - mutex_enter(&l2arc_buflist_mtx); + mutex_enter(&dev->l2ad_mtx); /* * All writes completed, or an error was hit. */ for (hdr = list_prev(buflist, head); hdr; hdr = hdr_prev) { hdr_prev = list_prev(buflist, hdr); - abl2 = hdr->b_l2hdr; - - /* - * Release the temporary compressed buffer as soon as possible. - */ - if (abl2->b_compress != ZIO_COMPRESS_OFF) - l2arc_release_cdata_buf(hdr); hash_lock = HDR_LOCK(hdr); if (!mutex_tryenter(hash_lock)) { /* * This buffer misses out. It may be in a stage - * of eviction. Its ARC_L2_WRITING flag will be + * of eviction. Its ARC_FLAG_L2_WRITING flag will be * left set, denying reads to this buffer. */ ARCSTAT_BUMP(arcstat_l2_writes_hdr_miss); continue; } + /* + * It's possible that this buffer got evicted from the L1 cache + * before we grabbed the vdev + hash locks, in which case + * arc_hdr_realloc freed b_tmp_cdata for us if it was allocated. + * Only free the buffer if we still have an L1 hdr. + */ + if (HDR_HAS_L1HDR(hdr) && hdr->b_l1hdr.b_tmp_cdata != NULL && + HDR_GET_COMPRESS(hdr) != ZIO_COMPRESS_OFF) + l2arc_release_cdata_buf(hdr); + if (zio->io_error != 0) { /* * Error - drop L2ARC entry. */ list_remove(buflist, hdr); - ARCSTAT_INCR(arcstat_l2_asize, -abl2->b_asize); - bytes_dropped += abl2->b_asize; - hdr->b_l2hdr = NULL; - kmem_free(abl2, sizeof (l2arc_buf_hdr_t)); + hdr->b_flags &= ~ARC_FLAG_HAS_L2HDR; + + ARCSTAT_INCR(arcstat_l2_asize, -hdr->b_l2hdr.b_asize); ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size); } @@ -4309,8 +4909,9 @@ atomic_inc_64(&l2arc_writes_done); list_remove(buflist, head); - kmem_cache_free(hdr_cache, head); - mutex_exit(&l2arc_buflist_mtx); + ASSERT(!HDR_HAS_L1HDR(head)); + kmem_cache_free(hdr_l2only_cache, head); + mutex_exit(&dev->l2ad_mtx); vdev_space_update(dev->l2ad_vdev, -bytes_dropped, 0, 0); @@ -4448,16 +5049,12 @@ l2arc_evict(l2arc_dev_t *dev, uint64_t distance, boolean_t all) { list_t *buflist; - l2arc_buf_hdr_t *abl2; arc_buf_hdr_t *hdr, *hdr_prev; kmutex_t *hash_lock; uint64_t taddr; int64_t bytes_evicted = 0; - buflist = dev->l2ad_buflist; - - if (buflist == NULL) - return; + buflist = &dev->l2ad_buflist; if (!all && dev->l2ad_first) { /* @@ -4480,7 +5077,7 @@ uint64_t, taddr, boolean_t, all); top: - mutex_enter(&l2arc_buflist_mtx); + mutex_enter(&dev->l2ad_mtx); for (hdr = list_tail(buflist); hdr; hdr = hdr_prev) { hdr_prev = list_prev(buflist, hdr); @@ -4490,7 +5087,7 @@ * Missed the hash lock. Retry. */ ARCSTAT_BUMP(arcstat_l2_evict_lock_retry); - mutex_exit(&l2arc_buflist_mtx); + mutex_exit(&dev->l2ad_mtx); mutex_enter(hash_lock); mutex_exit(hash_lock); goto top; @@ -4506,9 +5103,9 @@ continue; } - if (!all && hdr->b_l2hdr != NULL && - (hdr->b_l2hdr->b_daddr > taddr || - hdr->b_l2hdr->b_daddr < dev->l2ad_hand)) { + if (!all && HDR_HAS_L2HDR(hdr) && + (hdr->b_l2hdr.b_daddr > taddr || + hdr->b_l2hdr.b_daddr < dev->l2ad_hand)) { /* * We've evicted to the target address, * or the end of the device. @@ -4517,15 +5114,8 @@ break; } - if (HDR_FREE_IN_PROGRESS(hdr)) { - /* - * Already on the path to destruction. - */ - mutex_exit(hash_lock); - continue; - } - - if (hdr->b_state == arc_l2c_only) { + ASSERT(HDR_HAS_L2HDR(hdr)); + if (!HDR_HAS_L1HDR(hdr)) { ASSERT(!HDR_L2_READING(hdr)); /* * This doesn't exist in the ARC. Destroy. @@ -4535,6 +5125,8 @@ arc_change_state(arc_anon, hdr, hash_lock); arc_hdr_destroy(hdr); } else { + ASSERT(hdr->b_l1hdr.b_state != arc_l2c_only); + ARCSTAT_BUMP(arcstat_l2_evict_l1cached); /* * Invalidate issued or about to be issued * reads, since we may be about to write @@ -4545,28 +5137,18 @@ hdr->b_flags |= ARC_FLAG_L2_EVICTED; } - /* - * Tell ARC this no longer exists in L2ARC. - */ - if (hdr->b_l2hdr != NULL) { - abl2 = hdr->b_l2hdr; - ARCSTAT_INCR(arcstat_l2_asize, -abl2->b_asize); - bytes_evicted += abl2->b_asize; - hdr->b_l2hdr = NULL; - kmem_free(abl2, sizeof (l2arc_buf_hdr_t)); - ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size); - } + /* Tell ARC this no longer exists in L2ARC. */ + ARCSTAT_INCR(arcstat_l2_asize, -hdr->b_l2hdr.b_asize); + ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size); + hdr->b_flags &= ~ARC_FLAG_HAS_L2HDR; list_remove(buflist, hdr); - /* - * This may have been leftover after a - * failed write. - */ + /* This may have been leftover after a failed write. */ hdr->b_flags &= ~ARC_FLAG_L2_WRITING; } mutex_exit(hash_lock); } - mutex_exit(&l2arc_buflist_mtx); + mutex_exit(&dev->l2ad_mtx); vdev_space_update(dev->l2ad_vdev, -bytes_evicted, 0, 0); dev->l2ad_evict = taddr; @@ -4607,8 +5189,9 @@ pio = NULL; write_sz = write_asize = write_psize = 0; full = B_FALSE; - head = kmem_cache_alloc(hdr_cache, KM_PUSHPAGE); + head = kmem_cache_alloc(hdr_l2only_cache, KM_PUSHPAGE); head->b_flags |= ARC_FLAG_L2_WRITE_HEAD; + head->b_flags |= ARC_FLAG_HAS_L2HDR; /* * We will want to try to compress buffers that are at least 2x the @@ -4619,7 +5202,7 @@ /* * Copy buffers for L2ARC writing. */ - mutex_enter(&l2arc_buflist_mtx); + mutex_enter(&dev->l2ad_mtx); for (int try = 0; try <= 3; try++) { uint64_t passed_sz = 0; @@ -4641,7 +5224,6 @@ headroom = (headroom * l2arc_headroom_boost) / 100; for (; hdr; hdr = hdr_prev) { - l2arc_buf_hdr_t *l2hdr; kmutex_t *hash_lock; uint64_t buf_sz; @@ -4684,7 +5266,7 @@ * l2arc_write_done() can find where the * write buffers begin without searching. */ - list_insert_head(dev->l2ad_buflist, head); + list_insert_head(&dev->l2ad_buflist, head); cb = kmem_alloc( sizeof (l2arc_write_callback_t), KM_SLEEP); @@ -4697,33 +5279,31 @@ /* * Create and add a new L2ARC header. */ - l2hdr = kmem_zalloc(sizeof (l2arc_buf_hdr_t), KM_SLEEP); - l2hdr->b_dev = dev; + hdr->b_l2hdr.b_dev = dev; hdr->b_flags |= ARC_FLAG_L2_WRITING; - /* * Temporarily stash the data buffer in b_tmp_cdata. * The subsequent write step will pick it up from - * there. This is because can't access hdr->b_buf + * there. This is because can't access b_l1hdr.b_buf * without holding the hash_lock, which we in turn * can't access without holding the ARC list locks * (which we want to avoid during compression/writing). */ - l2hdr->b_compress = ZIO_COMPRESS_OFF; - l2hdr->b_asize = hdr->b_size; - l2hdr->b_tmp_cdata = hdr->b_buf->b_data; + HDR_SET_COMPRESS(hdr, ZIO_COMPRESS_OFF); + hdr->b_l2hdr.b_asize = hdr->b_size; + hdr->b_l1hdr.b_tmp_cdata = hdr->b_l1hdr.b_buf->b_data; buf_sz = hdr->b_size; - hdr->b_l2hdr = l2hdr; - - list_insert_head(dev->l2ad_buflist, hdr); + hdr->b_flags |= ARC_FLAG_HAS_L2HDR; + + list_insert_head(&dev->l2ad_buflist, hdr); /* * Compute and store the buffer cksum before * writing. On debug the cksum is verified first. */ - arc_cksum_verify(hdr->b_buf); - arc_cksum_compute(hdr->b_buf, B_TRUE); + arc_cksum_verify(hdr->b_l1hdr.b_buf); + arc_cksum_compute(hdr->b_l1hdr.b_buf, B_TRUE); mutex_exit(hash_lock); @@ -4739,8 +5319,9 @@ /* No buffers selected for writing? */ if (pio == NULL) { ASSERT0(write_sz); - mutex_exit(&l2arc_buflist_mtx); - kmem_cache_free(hdr_cache, head); + mutex_exit(&dev->l2ad_mtx); + ASSERT(!HDR_HAS_L1HDR(head)); + kmem_cache_free(hdr_l2only_cache, head); return (0); } @@ -4749,24 +5330,22 @@ * and work backwards, retracing the course of the buffer selector * loop above. */ - for (hdr = list_prev(dev->l2ad_buflist, head); hdr; - hdr = list_prev(dev->l2ad_buflist, hdr)) { - l2arc_buf_hdr_t *l2hdr; + for (hdr = list_prev(&dev->l2ad_buflist, head); hdr; + hdr = list_prev(&dev->l2ad_buflist, hdr)) { uint64_t buf_sz; /* * We shouldn't need to lock the buffer here, since we flagged * it as ARC_FLAG_L2_WRITING in the previous step, but we must * take care to only access its L2 cache parameters. In - * particular, hdr->b_buf may be invalid by now due to + * particular, hdr->l1hdr.b_buf may be invalid by now due to * ARC eviction. */ - l2hdr = hdr->b_l2hdr; - l2hdr->b_daddr = dev->l2ad_hand; - - if ((hdr->b_flags & ARC_FLAG_L2COMPRESS) && - l2hdr->b_asize >= buf_compress_minsz) { - if (l2arc_compress_buf(l2hdr)) { + hdr->b_l2hdr.b_daddr = dev->l2ad_hand; + + if ((HDR_L2COMPRESS(hdr)) && + hdr->b_l2hdr.b_asize >= buf_compress_minsz) { + if (l2arc_compress_buf(hdr)) { /* * If compression succeeded, enable headroom * boost on the next scan cycle. @@ -4779,8 +5358,8 @@ * Pick up the buffer data we had previously stashed away * (and now potentially also compressed). */ - buf_data = l2hdr->b_tmp_cdata; - buf_sz = l2hdr->b_asize; + buf_data = hdr->b_l1hdr.b_tmp_cdata; + buf_sz = hdr->b_l2hdr.b_asize; /* Compression may have squashed the buffer to zero length. */ if (buf_sz != 0) { @@ -4805,7 +5384,7 @@ } } - mutex_exit(&l2arc_buflist_mtx); + mutex_exit(&dev->l2ad_mtx); ASSERT3U(write_asize, <=, target_sz); ARCSTAT_BUMP(arcstat_l2_writes_sent); @@ -4833,7 +5412,7 @@ /* * Compresses an L2ARC buffer. - * The data to be compressed must be prefilled in l2hdr->b_tmp_cdata and its + * The data to be compressed must be prefilled in l1hdr.b_tmp_cdata and its * size in l2hdr->b_asize. This routine tries to compress the data and * depending on the compression result there are three possible outcomes: * *) The buffer was incompressible. The original l2hdr contents were left @@ -4851,17 +5430,21 @@ * buffer was incompressible). */ static boolean_t -l2arc_compress_buf(l2arc_buf_hdr_t *l2hdr) +l2arc_compress_buf(arc_buf_hdr_t *hdr) { void *cdata; size_t csize, len, rounded; - - ASSERT(l2hdr->b_compress == ZIO_COMPRESS_OFF); - ASSERT(l2hdr->b_tmp_cdata != NULL); + ASSERT(HDR_HAS_L2HDR(hdr)); + l2arc_buf_hdr_t *l2hdr = &hdr->b_l2hdr; + + ASSERT(HDR_HAS_L1HDR(hdr)); + ASSERT(HDR_GET_COMPRESS(hdr) == ZIO_COMPRESS_OFF); + ASSERT(hdr->b_l1hdr.b_tmp_cdata != NULL); len = l2hdr->b_asize; cdata = zio_data_buf_alloc(len); - csize = zio_compress_data(ZIO_COMPRESS_LZ4, l2hdr->b_tmp_cdata, + ASSERT3P(cdata, !=, NULL); + csize = zio_compress_data(ZIO_COMPRESS_LZ4, hdr->b_l1hdr.b_tmp_cdata, cdata, l2hdr->b_asize); rounded = P2ROUNDUP(csize, (size_t)SPA_MINBLOCKSIZE); @@ -4873,9 +5456,9 @@ if (csize == 0) { /* zero block, indicate that there's nothing to write */ zio_data_buf_free(cdata, len); - l2hdr->b_compress = ZIO_COMPRESS_EMPTY; + HDR_SET_COMPRESS(hdr, ZIO_COMPRESS_EMPTY); l2hdr->b_asize = 0; - l2hdr->b_tmp_cdata = NULL; + hdr->b_l1hdr.b_tmp_cdata = NULL; ARCSTAT_BUMP(arcstat_l2_compress_zeros); return (B_TRUE); } else if (csize > 0 && csize < len) { @@ -4883,9 +5466,9 @@ * Compression succeeded, we'll keep the cdata around for * writing and release it afterwards. */ - l2hdr->b_compress = ZIO_COMPRESS_LZ4; + HDR_SET_COMPRESS(hdr, ZIO_COMPRESS_LZ4); l2hdr->b_asize = csize; - l2hdr->b_tmp_cdata = cdata; + hdr->b_l1hdr.b_tmp_cdata = cdata; ARCSTAT_BUMP(arcstat_l2_compress_successes); return (B_TRUE); } else { @@ -4930,9 +5513,9 @@ * need to fill its io_data after we're done restoring the * buffer's contents. */ - ASSERT(hdr->b_buf != NULL); - bzero(hdr->b_buf->b_data, hdr->b_size); - zio->io_data = zio->io_orig_data = hdr->b_buf->b_data; + ASSERT(hdr->b_l1hdr.b_buf != NULL); + bzero(hdr->b_l1hdr.b_buf->b_data, hdr->b_size); + zio->io_data = zio->io_orig_data = hdr->b_l1hdr.b_buf->b_data; } else { ASSERT(zio->io_data != NULL); /* @@ -4970,17 +5553,17 @@ static void l2arc_release_cdata_buf(arc_buf_hdr_t *hdr) { - l2arc_buf_hdr_t *l2hdr = hdr->b_l2hdr; - - if (l2hdr->b_compress == ZIO_COMPRESS_LZ4) { + ASSERT(HDR_HAS_L1HDR(hdr)); + if (HDR_GET_COMPRESS(hdr) != ZIO_COMPRESS_EMPTY) { /* * If the data was compressed, then we've allocated a * temporary buffer for it, so now we need to release it. */ - ASSERT(l2hdr->b_tmp_cdata != NULL); - zio_data_buf_free(l2hdr->b_tmp_cdata, hdr->b_size); + ASSERT(hdr->b_l1hdr.b_tmp_cdata != NULL); + zio_data_buf_free(hdr->b_l1hdr.b_tmp_cdata, + hdr->b_size); } - l2hdr->b_tmp_cdata = NULL; + hdr->b_l1hdr.b_tmp_cdata = NULL; } /* @@ -5121,13 +5704,13 @@ adddev->l2ad_first = B_TRUE; adddev->l2ad_writing = B_FALSE; + mutex_init(&adddev->l2ad_mtx, NULL, MUTEX_DEFAULT, NULL); /* * This is a list of all ARC buffers that are still valid on the * device. */ - adddev->l2ad_buflist = kmem_zalloc(sizeof (list_t), KM_SLEEP); - list_create(adddev->l2ad_buflist, sizeof (arc_buf_hdr_t), - offsetof(arc_buf_hdr_t, b_l2node)); + list_create(&adddev->l2ad_buflist, sizeof (arc_buf_hdr_t), + offsetof(arc_buf_hdr_t, b_l2hdr.b_l2node)); vdev_space_update(vd, 0, 0, adddev->l2ad_end - adddev->l2ad_hand); @@ -5173,8 +5756,8 @@ * Clear all buflists and ARC references. L2ARC device flush. */ l2arc_evict(remdev, 0, B_TRUE); - list_destroy(remdev->l2ad_buflist); - kmem_free(remdev->l2ad_buflist, sizeof (list_t)); + list_destroy(&remdev->l2ad_buflist); + mutex_destroy(&remdev->l2ad_mtx); kmem_free(remdev, sizeof (l2arc_dev_t)); } @@ -5189,7 +5772,6 @@ mutex_init(&l2arc_feed_thr_lock, NULL, MUTEX_DEFAULT, NULL); cv_init(&l2arc_feed_thr_cv, NULL, CV_DEFAULT, NULL); mutex_init(&l2arc_dev_mtx, NULL, MUTEX_DEFAULT, NULL); - mutex_init(&l2arc_buflist_mtx, NULL, MUTEX_DEFAULT, NULL); mutex_init(&l2arc_free_on_write_mtx, NULL, MUTEX_DEFAULT, NULL); l2arc_dev_list = &L2ARC_dev_list; @@ -5214,7 +5796,6 @@ mutex_destroy(&l2arc_feed_thr_lock); cv_destroy(&l2arc_feed_thr_cv); mutex_destroy(&l2arc_dev_mtx); - mutex_destroy(&l2arc_buflist_mtx); mutex_destroy(&l2arc_free_on_write_mtx); list_destroy(l2arc_dev_list);
--- a/usr/src/uts/common/fs/zfs/dnode.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/common/fs/zfs/dnode.c Sun Jan 04 07:19:22 2015 -0800 @@ -79,16 +79,14 @@ return (1); } - if (d1->db_state < d2->db_state) { + if (d1->db_state == DB_SEARCH) { + ASSERT3S(d2->db_state, !=, DB_SEARCH); return (-1); - } - if (d1->db_state > d2->db_state) { + } else if (d2->db_state == DB_SEARCH) { + ASSERT3S(d1->db_state, !=, DB_SEARCH); return (1); } - ASSERT3S(d1->db_state, !=, DB_SEARCH); - ASSERT3S(d2->db_state, !=, DB_SEARCH); - if ((uintptr_t)d1 < (uintptr_t)d2) { return (-1); }
--- a/usr/src/uts/common/fs/zfs/sys/arc.h Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/common/fs/zfs/sys/arc.h Sun Jan 04 07:19:22 2015 -0800 @@ -70,10 +70,29 @@ ARC_FLAG_FREED_IN_READ = 1 << 10, /* freed during read */ ARC_FLAG_BUF_AVAILABLE = 1 << 11, /* block not in use */ ARC_FLAG_INDIRECT = 1 << 12, /* indirect block */ - ARC_FLAG_FREE_IN_PROGRESS = 1 << 13, /* about to be freed */ - ARC_FLAG_L2_WRITING = 1 << 14, /* write in progress */ - ARC_FLAG_L2_EVICTED = 1 << 15, /* evicted during I/O */ - ARC_FLAG_L2_WRITE_HEAD = 1 << 16, /* head of write list */ + ARC_FLAG_L2_WRITING = 1 << 13, /* write in progress */ + ARC_FLAG_L2_EVICTED = 1 << 14, /* evicted during I/O */ + ARC_FLAG_L2_WRITE_HEAD = 1 << 15, /* head of write list */ + /* indicates that the buffer contains metadata (otherwise, data) */ + ARC_FLAG_BUFC_METADATA = 1 << 16, + + /* Flags specifying whether optional hdr struct fields are defined */ + ARC_FLAG_HAS_L1HDR = 1 << 17, + ARC_FLAG_HAS_L2HDR = 1 << 18, + + /* + * The arc buffer's compression mode is stored in the top 7 bits of the + * flags field, so these dummy flags are included so that MDB can + * interpret the enum properly. + */ + ARC_FLAG_COMPRESS_0 = 1 << 24, + ARC_FLAG_COMPRESS_1 = 1 << 25, + ARC_FLAG_COMPRESS_2 = 1 << 26, + ARC_FLAG_COMPRESS_3 = 1 << 27, + ARC_FLAG_COMPRESS_4 = 1 << 28, + ARC_FLAG_COMPRESS_5 = 1 << 29, + ARC_FLAG_COMPRESS_6 = 1 << 30 + } arc_flags_t; struct arc_buf { @@ -96,6 +115,7 @@ */ typedef enum arc_space_type { ARC_SPACE_DATA, + ARC_SPACE_META, ARC_SPACE_HDRS, ARC_SPACE_L2HDRS, ARC_SPACE_OTHER,
--- a/usr/src/uts/common/inet/ipf/fil.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/common/inet/ipf/fil.c Sun Jan 04 07:19:22 2015 -0800 @@ -4,6 +4,8 @@ * See the IPFILTER.LICENCE file for details on licencing. * * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #if defined(KERNEL) || defined(_KERNEL) @@ -134,6 +136,9 @@ # endif #endif #include "netinet/ipl.h" +#if defined(_KERNEL) +#include <sys/sunddi.h> +#endif /* END OF INCLUDES */ #if !defined(lint) @@ -5696,6 +5701,54 @@ /* ------------------------------------------------------------------------ */ +/* Function: fr_getzoneid */ +/* Returns: int - 0 = success, else failure */ +/* Parameters: idsp(I) - pointer to ipf_devstate_t */ +/* data(I) - pointer to ioctl data */ +/* */ +/* Set the zone ID in idsp based on the zone name in ipfzoneobj. Further */ +/* ioctls will act on the IPF stack for that zone ID. */ +/* ------------------------------------------------------------------------ */ +#if defined(_KERNEL) +int fr_setzoneid(idsp, data) +ipf_devstate_t *idsp; +void *data; +{ + int error = 0; + ipfzoneobj_t ipfzo; + zone_t *zone; + + error = BCOPYIN(data, &ipfzo, sizeof(ipfzo)); + if (error != 0) + return EFAULT; + + if (memchr(ipfzo.ipfz_zonename, '\0', ZONENAME_MAX) == NULL) + return EFAULT; + + /* + * The global zone doesn't have a GZ-controlled stack, so no + * sense in going any further + */ + if (strcmp(ipfzo.ipfz_zonename, "global") == 0) + return ENODEV; + + if ((zone = zone_find_by_name(ipfzo.ipfz_zonename)) == NULL) + return ENODEV; + + /* + * Store the zone ID that to control, and whether it's the + * GZ-controlled stack that's wanted + */ + idsp->ipfs_zoneid = zone->zone_id; + idsp->ipfs_gz = (ipfzo.ipfz_gz == 1) ? B_TRUE : B_FALSE; + zone_rele(zone); + + return error; +} +#endif + + +/* ------------------------------------------------------------------------ */ /* Function: fr_inobj */ /* Returns: int - 0 = success, else failure */ /* Parameters: data(I) - pointer to ioctl data */
--- a/usr/src/uts/common/inet/ipf/ip_fil_solaris.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/common/inet/ipf/ip_fil_solaris.c Sun Jan 04 07:19:22 2015 -0800 @@ -4,6 +4,8 @@ * See the IPFILTER.LICENCE file for details on licencing. * * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #if !defined(lint) @@ -101,6 +103,54 @@ #endif #endif +vmem_t *ipf_minor; /* minor number arena */ +void *ipf_state; /* DDI state */ + +/* + * GZ-controlled and per-zone stacks: + * + * For each non-global zone, we create two ipf stacks: the per-zone stack and + * the GZ-controlled stack. The per-zone stack can be controlled and observed + * from inside the zone or from the global zone. The GZ-controlled stack can + * only be controlled and observed from the global zone (though the rules + * still only affect that non-global zone). + * + * The two hooks are always arranged so that the GZ-controlled stack is always + * "outermost" with respect to the zone. The traffic flow then looks like + * this: + * + * Inbound: + * + * nic ---> [ GZ-controlled rules ] ---> [ per-zone rules ] ---> zone + * + * Outbound: + * + * nic <--- [ GZ-controlled rules ] <--- [ per-zone rules ] <--- zone + */ + +/* IPv4 hook names */ +char *hook4_nicevents = "ipfilter_hook4_nicevents"; +char *hook4_nicevents_gz = "ipfilter_hook4_nicevents_gz"; +char *hook4_in = "ipfilter_hook4_in"; +char *hook4_in_gz = "ipfilter_hook4_in_gz"; +char *hook4_out = "ipfilter_hook4_out"; +char *hook4_out_gz = "ipfilter_hook4_out_gz"; +char *hook4_loop_in = "ipfilter_hook4_loop_in"; +char *hook4_loop_in_gz = "ipfilter_hook4_loop_in_gz"; +char *hook4_loop_out = "ipfilter_hook4_loop_out"; +char *hook4_loop_out_gz = "ipfilter_hook4_loop_out_gz"; + +/* IPv6 hook names */ +char *hook6_nicevents = "ipfilter_hook6_nicevents"; +char *hook6_nicevents_gz = "ipfilter_hook6_nicevents_gz"; +char *hook6_in = "ipfilter_hook6_in"; +char *hook6_in_gz = "ipfilter_hook6_in_gz"; +char *hook6_out = "ipfilter_hook6_out"; +char *hook6_out_gz = "ipfilter_hook6_out_gz"; +char *hook6_loop_in = "ipfilter_hook6_loop_in"; +char *hook6_loop_in_gz = "ipfilter_hook6_loop_in_gz"; +char *hook6_loop_out = "ipfilter_hook6_loop_out"; +char *hook6_loop_out_gz = "ipfilter_hook6_loop_out_gz"; /* ------------------------------------------------------------------------ */ /* Function: ipldetach */ @@ -117,7 +167,7 @@ ipf_stack_t *ifs; { - ASSERT(rw_read_locked(&ifs->ifs_ipf_global.ipf_lk) == 0); + ASSERT(RW_WRITE_HELD(&ifs->ifs_ipf_global.ipf_lk)); #if SOLARIS2 < 10 @@ -143,9 +193,10 @@ do { \ if (ifs->_f != NULL) { \ if (ifs->_b) { \ - ifs->_b = (net_hook_unregister(ifs->_f, \ - _e, ifs->_h) != 0); \ - if (!ifs->_b) { \ + int tmp = net_hook_unregister(ifs->_f, \ + _e, ifs->_h); \ + ifs->_b = (tmp != 0 && tmp != ENXIO); \ + if (!ifs->_b && ifs->_h != NULL) { \ hook_free(ifs->_h); \ ifs->_h = NULL; \ } \ @@ -243,7 +294,7 @@ cmn_err(CE_CONT, "iplattach()\n"); #endif - ASSERT(rw_read_locked(&ifs->ifs_ipf_global.ipf_lk) == 0); + ASSERT(RW_WRITE_HELD(&ifs->ifs_ipf_global.ipf_lk)); ifs->ifs_fr_flags = IPF_LOGGING; #ifdef _KERNEL ifs->ifs_fr_update_ipid = 0; @@ -268,16 +319,39 @@ if (fr_initialise(ifs) < 0) return -1; - HOOK_INIT(ifs->ifs_ipfhook4_nicevents, ipf_nic_event_v4, - "ipfilter_hook4_nicevents", ifs); - HOOK_INIT(ifs->ifs_ipfhook4_in, ipf_hook4_in, - "ipfilter_hook4_in", ifs); - HOOK_INIT(ifs->ifs_ipfhook4_out, ipf_hook4_out, - "ipfilter_hook4_out", ifs); - HOOK_INIT(ifs->ifs_ipfhook4_loop_in, ipf_hook4_loop_in, - "ipfilter_hook4_loop_in", ifs); - HOOK_INIT(ifs->ifs_ipfhook4_loop_out, ipf_hook4_loop_out, - "ipfilter_hook4_loop_out", ifs); + /* + * For incoming packets, we want the GZ-controlled hooks to run before + * the per-zone hooks, regardless of what order they're are installed. + * See the "GZ-controlled and per-zone stacks" comment block at the top + * of this file. + */ +#define HOOK_INIT_GZ_BEFORE(x, fn, n, gzn, a) \ + HOOK_INIT(x, fn, ifs->ifs_gz_controlled ? gzn : n, ifs); \ + (x)->h_hint = ifs->ifs_gz_controlled ? HH_BEFORE : HH_AFTER; \ + (x)->h_hintvalue = (uintptr_t) (ifs->ifs_gz_controlled ? n : gzn); + + HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook4_nicevents, ipf_nic_event_v4, + hook4_nicevents, hook4_nicevents_gz, ifs); + HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook4_in, ipf_hook4_in, + hook4_in, hook4_in_gz, ifs); + HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook4_loop_in, ipf_hook4_loop_in, + hook4_loop_in, hook4_loop_in_gz, ifs); + + /* + * For outgoing packets, we want the GZ-controlled hooks to run after + * the per-zone hooks, regardless of what order they're are installed. + * See the "GZ-controlled and per-zone stacks" comment block at the top + * of this file. + */ +#define HOOK_INIT_GZ_AFTER(x, fn, n, gzn, a) \ + HOOK_INIT(x, fn, ifs->ifs_gz_controlled ? gzn : n, ifs); \ + (x)->h_hint = ifs->ifs_gz_controlled ? HH_AFTER : HH_BEFORE; \ + (x)->h_hintvalue = (uintptr_t) (ifs->ifs_gz_controlled ? n : gzn); + + HOOK_INIT_GZ_AFTER(ifs->ifs_ipfhook4_out, ipf_hook4_out, + hook4_out, hook4_out_gz, ifs); + HOOK_INIT_GZ_AFTER(ifs->ifs_ipfhook4_loop_out, ipf_hook4_loop_out, + hook4_loop_out, hook4_loop_out_gz, ifs); /* * If we hold this lock over all of the net_hook_register calls, we @@ -322,6 +396,7 @@ if (!ifs->ifs_hook4_loopback_out) goto hookup_failed; } + /* * Add IPv6 hooks */ @@ -329,16 +404,16 @@ if (ifs->ifs_ipf_ipv6 == NULL) goto hookup_failed; - HOOK_INIT(ifs->ifs_ipfhook6_nicevents, ipf_nic_event_v6, - "ipfilter_hook6_nicevents", ifs); - HOOK_INIT(ifs->ifs_ipfhook6_in, ipf_hook6_in, - "ipfilter_hook6_in", ifs); - HOOK_INIT(ifs->ifs_ipfhook6_out, ipf_hook6_out, - "ipfilter_hook6_out", ifs); - HOOK_INIT(ifs->ifs_ipfhook6_loop_in, ipf_hook6_loop_in, - "ipfilter_hook6_loop_in", ifs); - HOOK_INIT(ifs->ifs_ipfhook6_loop_out, ipf_hook6_loop_out, - "ipfilter_hook6_loop_out", ifs); + HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook6_nicevents, ipf_nic_event_v6, + hook6_nicevents, hook6_nicevents_gz, ifs); + HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook6_in, ipf_hook6_in, + hook6_in, hook6_in_gz, ifs); + HOOK_INIT_GZ_BEFORE(ifs->ifs_ipfhook6_loop_in, ipf_hook6_loop_in, + hook6_loop_in, hook6_loop_in_gz, ifs); + HOOK_INIT_GZ_AFTER(ifs->ifs_ipfhook6_out, ipf_hook6_out, + hook6_out, hook6_out_gz, ifs); + HOOK_INIT_GZ_AFTER(ifs->ifs_ipfhook6_loop_out, ipf_hook6_loop_out, + hook6_loop_out, hook6_loop_out_gz, ifs); ifs->ifs_hook6_nic_events = (net_hook_register(ifs->ifs_ipf_ipv6, NH_NIC_EVENTS, ifs->ifs_ipfhook6_nicevents) == 0); @@ -518,35 +593,47 @@ minor_t unit; u_int enable; ipf_stack_t *ifs; + zoneid_t zid; + ipf_devstate_t *isp; #ifdef IPFDEBUG cmn_err(CE_CONT, "iplioctl(%x,%x,%x,%d,%x,%d)\n", dev, cmd, data, mode, cp, rp); #endif unit = getminor(dev); - if (IPL_LOGMAX < unit) + + isp = ddi_get_soft_state(ipf_state, unit); + if (isp == NULL) return ENXIO; + unit = isp->ipfs_minor; + + zid = crgetzoneid(cp); + if (cmd == SIOCIPFZONESET) { + if (zid == GLOBAL_ZONEID) + return fr_setzoneid(isp, (caddr_t) data); + return EACCES; + } /* - * As we're calling ipf_find_stack in user space, from a given zone - * to find the stack pointer for this zone, there is no need to have - * a hold/refence count here. + * ipf_find_stack returns with a read lock on ifs_ipf_global */ - ifs = ipf_find_stack(crgetzoneid(cp)); - ASSERT(ifs != NULL); + ifs = ipf_find_stack(zid, isp); + if (ifs == NULL) + return ENXIO; if (ifs->ifs_fr_running <= 0) { if (unit != IPL_LOGIPF) { + RWLOCK_EXIT(&ifs->ifs_ipf_global); return EIO; } if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && cmd != SIOCIPFSET && cmd != SIOCFRENB && cmd != SIOCGETFS && cmd != SIOCGETFF) { + RWLOCK_EXIT(&ifs->ifs_ipf_global); return EIO; } } - READ_ENTER(&ifs->ifs_ipf_global); if (ifs->ifs_fr_enable_active != 0) { RWLOCK_EXIT(&ifs->ifs_ipf_global); return EBUSY; @@ -847,7 +934,9 @@ int flags, otype; cred_t *cred; { + ipf_devstate_t *isp; minor_t min = getminor(*devp); + minor_t minor; #ifdef IPFDEBUG cmn_err(CE_CONT, "iplopen(%x,%x,%x,%x)\n", devp, flags, otype, cred); @@ -855,8 +944,25 @@ if (!(otype & OTYP_CHR)) return ENXIO; - min = (IPL_LOGMAX < min) ? ENXIO : 0; - return min; + if (IPL_LOGMAX < min) + return ENXIO; + + minor = (minor_t)(uintptr_t)vmem_alloc(ipf_minor, 1, + VM_BESTFIT | VM_SLEEP); + + if (ddi_soft_state_zalloc(ipf_state, minor) != 0) { + vmem_free(ipf_minor, (void *)(uintptr_t)minor, 1); + return ENXIO; + } + + *devp = makedevice(getmajor(*devp), minor); + isp = ddi_get_soft_state(ipf_state, minor); + VERIFY(isp != NULL); + + isp->ipfs_minor = min; + isp->ipfs_zoneid = IPFS_ZONE_UNSET; + + return 0; } @@ -872,8 +978,13 @@ cmn_err(CE_CONT, "iplclose(%x,%x,%x,%x)\n", dev, flags, otype, cred); #endif - min = (IPL_LOGMAX < min) ? ENXIO : 0; - return min; + if (IPL_LOGMAX < min) + return ENXIO; + + ddi_soft_state_free(ipf_state, min); + vmem_free(ipf_minor, (void *)(uintptr_t)min, 1); + + return 0; } #ifdef IPFILTER_LOG @@ -891,30 +1002,41 @@ { ipf_stack_t *ifs; int ret; + minor_t unit; + ipf_devstate_t *isp; + + unit = getminor(dev); + isp = ddi_get_soft_state(ipf_state, unit); + if (isp == NULL) + return ENXIO; + unit = isp->ipfs_minor; + /* - * As we're calling ipf_find_stack in user space, from a given zone - * to find the stack pointer for this zone, there is no need to have - * a hold/refence count here. + * ipf_find_stack returns with a read lock on ifs_ipf_global */ - ifs = ipf_find_stack(crgetzoneid(cp)); - ASSERT(ifs != NULL); + ifs = ipf_find_stack(crgetzoneid(cp), isp); + if (ifs == NULL) + return ENXIO; # ifdef IPFDEBUG cmn_err(CE_CONT, "iplread(%x,%x,%x)\n", dev, uio, cp); # endif if (ifs->ifs_fr_running < 1) { + RWLOCK_EXIT(&ifs->ifs_ipf_global); return EIO; } # ifdef IPFILTER_SYNC - if (getminor(dev) == IPL_LOGSYNC) { + if (unit == IPL_LOGSYNC) { + RWLOCK_EXIT(&ifs->ifs_ipf_global); return ipfsync_read(uio); } # endif - ret = ipflog_read(getminor(dev), uio, ifs); + ret = ipflog_read(unit, uio, ifs); + RWLOCK_EXIT(&ifs->ifs_ipf_global); return ret; } #endif /* IPFILTER_LOG */ @@ -932,30 +1054,41 @@ cred_t *cp; { ipf_stack_t *ifs; + minor_t unit; + ipf_devstate_t *isp; + + unit = getminor(dev); + isp = ddi_get_soft_state(ipf_state, unit); + if (isp == NULL) + return ENXIO; + unit = isp->ipfs_minor; /* - * As we're calling ipf_find_stack in user space, from a given zone - * to find the stack pointer for this zone, there is no need to have - * a hold/refence count here. + * ipf_find_stack returns with a read lock on ifs_ipf_global */ - ifs = ipf_find_stack(crgetzoneid(cp)); - ASSERT(ifs != NULL); + ifs = ipf_find_stack(crgetzoneid(cp), isp); + if (ifs == NULL) + return ENXIO; #ifdef IPFDEBUG cmn_err(CE_CONT, "iplwrite(%x,%x,%x)\n", dev, uio, cp); #endif if (ifs->ifs_fr_running < 1) { + RWLOCK_EXIT(&ifs->ifs_ipf_global); return EIO; } #ifdef IPFILTER_SYNC - if (getminor(dev) == IPL_LOGSYNC) + if (getminor(dev) == IPL_LOGSYNC) { + RWLOCK_EXIT(&ifs->ifs_ipf_global); return ipfsync_write(uio); + } #endif /* IPFILTER_SYNC */ dev = dev; /* LINT */ uio = uio; /* LINT */ cp = cp; /* LINT */ + RWLOCK_EXIT(&ifs->ifs_ipf_global); return ENXIO; } @@ -1997,7 +2130,6 @@ fw->hpe_mb = qpi.qpi_m; fw->hpe_hdr = qpi.qpi_data; return rval; - }
--- a/usr/src/uts/common/inet/ipf/ip_log.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/common/inet/ipf/ip_log.c Sun Jan 04 07:19:22 2015 -0800 @@ -7,6 +7,8 @@ * * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #include <sys/param.h> @@ -572,10 +574,18 @@ while (ifs->ifs_iplt[unit] == NULL) { # if SOLARIS && defined(_KERNEL) + /* + * Prevent a deadlock with ipldetach() - see the "ipfilter + * kernel module mutexes and locking" comment block in solaris.c + * for details. + */ + RWLOCK_EXIT(&ifs->ifs_ipf_global); if (!cv_wait_sig(&ifs->ifs_iplwait, &ifs->ifs_ipl_mutex.ipf_lk)) { + READ_ENTER(&ifs->ifs_ipf_global); MUTEX_EXIT(&ifs->ifs_ipl_mutex); return EINTR; } + READ_ENTER(&ifs->ifs_ipf_global); # else # if defined(__hpux) && defined(_KERNEL) lock_t *l;
--- a/usr/src/uts/common/inet/ipf/ip_state.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/common/inet/ipf/ip_state.c Sun Jan 04 07:19:22 2015 -0800 @@ -4,6 +4,8 @@ * See the IPFILTER.LICENCE file for details on licencing. * * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #if defined(KERNEL) || defined(_KERNEL) @@ -1285,6 +1287,7 @@ switch (ic->icmp_type) { case ICMP_ECHO : + case ICMP_ECHOREPLY : case ICMP_TSTAMP : case ICMP_IREQ : case ICMP_MASKREQ :
--- a/usr/src/uts/common/inet/ipf/netinet/ip_fil.h Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/common/inet/ipf/netinet/ip_fil.h Sun Jan 04 07:19:22 2015 -0800 @@ -7,12 +7,15 @@ * $Id: ip_fil.h,v 2.170.2.22 2005/07/16 05:55:35 darrenr Exp $ * * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #ifndef __IP_FIL_H__ #define __IP_FIL_H__ #include "netinet/ip_compat.h" +#include <sys/zone.h> #ifndef SOLARIS # define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) @@ -106,6 +109,7 @@ #define SIOCADDFR SIOCADAFR #define SIOCDELFR SIOCRMAFR #define SIOCINSFR SIOCINAFR +# define SIOCIPFZONESET _IOWR('r', 97, struct ipfzoneobj) /* * What type of table is getting flushed? @@ -1165,6 +1169,26 @@ u_char ipfo_xxxpad[32]; /* reserved for future use */ } ipfobj_t; +/* + * ioctl struct for setting what zone further ioctls will act on. ipfz_gz is a + * boolean: set it to 1 to operate on the GZ-controlled stack. + */ +typedef struct ipfzoneobj { + u_32_t ipfz_gz; /* GZ stack boolean */ + char ipfz_zonename[ZONENAME_MAX]; /* zone to act on */ +} ipfzoneobj_t; + +#if defined(_KERNEL) +/* Set ipfs_zoneid to this if no zone has been set: */ +#define IPFS_ZONE_UNSET -2 + +typedef struct ipf_devstate { + zoneid_t ipfs_zoneid; + minor_t ipfs_minor; + boolean_t ipfs_gz; +} ipf_devstate_t; +#endif + #define IPFOBJ_FRENTRY 0 /* struct frentry */ #define IPFOBJ_IPFSTAT 1 /* struct friostat */ #define IPFOBJ_IPFINFO 2 /* struct fr_info */ @@ -1352,7 +1376,6 @@ extern int ipl_enable __P((void)); extern int ipl_disable __P((void)); # ifdef MENTAT -extern ipf_stack_t *ipf_find_stack(const zoneid_t zone); extern int fr_check __P((struct ip *, int, void *, int, void *, mblk_t **, ipf_stack_t *)); # if SOLARIS @@ -1365,6 +1388,7 @@ extern int fr_make_rst __P((fr_info_t *)); extern int fr_make_icmp __P((fr_info_t *)); extern void fr_calc_chksum __P((fr_info_t *, mb_t *)); +extern ipf_stack_t *ipf_find_stack(const zoneid_t, ipf_devstate_t *); # endif extern int iplopen __P((dev_t *, int, int, cred_t *)); extern int iplclose __P((dev_t, int, int, cred_t *)); @@ -1576,6 +1600,10 @@ extern u_32_t ipf_random __P((void)); #endif +#if defined(_KERNEL) +extern int fr_setzoneid __P((ipf_devstate_t *, void *)); +#endif + extern char ipfilter_version[]; #ifdef USE_INET6 extern int icmptoicmp6types[ICMP_MAXTYPE+1];
--- a/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h Sun Jan 04 07:19:22 2015 -0800 @@ -5,6 +5,8 @@ * * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2014 Joyent, Inc. All rights reserved. */ #ifndef __IPF_STACK_H__ @@ -41,8 +43,10 @@ struct ipf_stack { struct ipf_stack *ifs_next; struct ipf_stack **ifs_pnext; + struct ipf_stack *ifs_gz_cont_ifs; netid_t ifs_netid; zoneid_t ifs_zone; + boolean_t ifs_gz_controlled; /* ipf module */ fr_info_t ifs_frcache[2][8];
--- a/usr/src/uts/common/inet/ipf/solaris.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/common/inet/ipf/solaris.c Sun Jan 04 07:19:22 2015 -0800 @@ -5,6 +5,50 @@ * * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2014, Joyent, Inc. All rights reserved. + */ + +/* + * ipfilter kernel module mutexes and locking: + * + * Enabling ipfilter creates a per-netstack ipf_stack_t object that is + * stored in the ipf_stacks list, which is protected by ipf_stack_lock. + * ipf_stack_t objects are accessed in three contexts: + * + * 1) administering that filter (eg: ioctls handled with iplioctl()) + * 2) reading log data (eg: iplread() / iplwrite()) + * 3) filtering packets (eg: ipf_hook4_* and ipf_hook6_* pfhooks + * functions) + * + * Each ipf_stack_t has a RW lock, ifs_ipf_global, protecting access to the + * whole structure. The structure also has locks protecting the various + * data structures used for filtering. The following guidelines should be + * followed for ipf_stack_t locks: + * + * - ipf_stack_lock must be held when accessing the ipf_stacks list + * - ipf_stack_lock should be held before acquiring ifs_ipf_global for + * a stack (the exception to this is ipf_stack_destroy(), which removes + * the ipf_stack_t from the list, then drops ipf_stack_lock before + * acquiring ifs_ipf_global) + * - ifs_ipf_global must be held when accessing an ipf_stack_t in that list: + * - The write lock is held only during stack creation / destruction + * - The read lock should be held for all other accesses + * - To alter the filtering data in the administrative context, one must: + * - acquire the read lock for ifs_ipf_global + * - then acquire the write lock for the data in question + * - In the filtering path, the read lock needs to be held for each type of + * filtering data used + * - ifs_ipf_global does not need to be held in the filtering path: + * - The filtering hooks don't need to modify the stack itself + * - The ipf_stack_t will not be destroyed until the hooks are unregistered. + * This requires a write lock on the hook, ensuring that no active hooks + * (eg: the filtering path) are running, and that the hooks won't be run + * afterward. + * + * Note that there is a deadlock possible when calling net_hook_register() + * or net_hook_unregister() with ifs_ipf_global held: see the comments in + * iplattach() and ipldetach() for details. */ #include <sys/systm.h> @@ -73,7 +117,8 @@ static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL }; - +extern void *ipf_state; /* DDI state */ +extern vmem_t *ipf_minor; /* minor number arena */ static struct cb_ops ipf_cb_ops = { iplopen, @@ -221,10 +266,11 @@ static int ipf_kstat_update(kstat_t *ksp, int rwflag); static void -ipf_kstat_init(ipf_stack_t *ifs) +ipf_kstat_init(ipf_stack_t *ifs, boolean_t from_gz) { - ifs->ifs_kstatp[0] = net_kstat_create(ifs->ifs_netid, "ipf", 0, - "inbound", "net", KSTAT_TYPE_NAMED, + ifs->ifs_kstatp[0] = net_kstat_create(ifs->ifs_netid, + (from_gz ? "ipf_gz" : "ipf"), + 0, "inbound", "net", KSTAT_TYPE_NAMED, sizeof (filter_kstats_t) / sizeof (kstat_named_t), 0); if (ifs->ifs_kstatp[0] != NULL) { bcopy(&ipf_kstat_tmp, ifs->ifs_kstatp[0]->ks_data, @@ -234,8 +280,9 @@ kstat_install(ifs->ifs_kstatp[0]); } - ifs->ifs_kstatp[1] = net_kstat_create(ifs->ifs_netid, "ipf", 0, - "outbound", "net", KSTAT_TYPE_NAMED, + ifs->ifs_kstatp[1] = net_kstat_create(ifs->ifs_netid, + (from_gz ? "ipf_gz" : "ipf"), + 0, "outbound", "net", KSTAT_TYPE_NAMED, sizeof (filter_kstats_t) / sizeof (kstat_named_t), 0); if (ifs->ifs_kstatp[1] != NULL) { bcopy(&ipf_kstat_tmp, ifs->ifs_kstatp[1]->ks_data, @@ -369,12 +416,14 @@ * Initialize things for IPF for each stack instance */ static void * -ipf_stack_create(const netid_t id) +ipf_stack_create_one(const netid_t id, const zoneid_t zid, boolean_t from_gz, + ipf_stack_t *ifs_gz) { ipf_stack_t *ifs; #ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter:stack_create id=%d", id); + cmn_err(CE_NOTE, "IP Filter:stack_create_one id=%d global=%d", id, + global); #endif ifs = (ipf_stack_t *)kmem_alloc(sizeof (*ifs), KM_SLEEP); @@ -398,8 +447,11 @@ RWLOCK_INIT(&ifs->ifs_ipf_mutex, "ipf filter rwlock"); RWLOCK_INIT(&ifs->ifs_ipf_frcache, "ipf cache rwlock"); ifs->ifs_netid = id; - ifs->ifs_zone = net_getzoneidbynetid(id); - ipf_kstat_init(ifs); + ifs->ifs_zone = zid; + ifs->ifs_gz_controlled = from_gz; + ifs->ifs_gz_cont_ifs = ifs_gz; + + ipf_kstat_init(ifs, from_gz); #ifdef IPFDEBUG cmn_err(CE_CONT, "IP Filter:stack_create zone=%d", ifs->ifs_zone); @@ -427,31 +479,84 @@ return (ifs); } +static void * +ipf_stack_create(const netid_t id) +{ + ipf_stack_t *ifs = NULL; + zoneid_t zid = net_getzoneidbynetid(id); + + /* + * Create two ipfilter stacks for a zone - the first can only be + * controlled from the global zone, and the second is owned by + * the zone itself. There is no need to create a GZ-controlled + * stack for the global zone, since we're already in the global + * zone. See the "GZ-controlled and per-zone stacks" comment block in + * ip_fil_solaris.c for details. + */ + if (zid != GLOBAL_ZONEID) + ifs = ipf_stack_create_one(id, zid, B_TRUE, NULL); + + return (ipf_stack_create_one(id, zid, B_FALSE, ifs)); +} /* - * This function should only ever be used to find the pointer to the - * ipfilter stack structure for the zone that is currently being - * executed... so if you're running in the context of zone 1, you - * should not attempt to find the ipf_stack_t for zone 0 or 2 or - * anything else but 1. In that way, the returned pointer is safe - * as it will only be nuked when the instance is destroyed as part - * of the final shutdown of a zone. + * Find an ipfilter stack for the given zone. Return the GZ-controlled or + * per-zone stack if set by an earlier SIOCIPFZONESET ioctl call. See the + * "GZ-controlled and per-zone stacks" comment block in ip_fil_solaris.c for + * details. + * + * This function returns with the ipf_stack_t's ifs_ipf_global + * read lock held (if the stack is found). See the "ipfilter kernel module + * mutexes and locking" comment block at the top of this file. */ ipf_stack_t * -ipf_find_stack(const zoneid_t zone) +ipf_find_stack(const zoneid_t orig_zone, ipf_devstate_t *isp) { ipf_stack_t *ifs; + boolean_t gz_stack; + zoneid_t zone; + + /* + * If we're in the GZ, determine if we're acting on a zone's stack, + * and whether or not that stack is the GZ-controlled or in-zone + * one. See the "GZ and per-zone stacks" note at the top of this + * file. + */ + if (orig_zone == GLOBAL_ZONEID && + (isp->ipfs_zoneid != IPFS_ZONE_UNSET)) { + /* Global zone, and we've set the zoneid for this fd already */ + + if (orig_zone == isp->ipfs_zoneid) { + /* There's only a per-zone stack for the GZ */ + gz_stack = B_FALSE; + } else { + gz_stack = isp->ipfs_gz; + } + + zone = isp->ipfs_zoneid; + } else { + /* + * Non-global zone or GZ without having set a zoneid: act on + * the per-zone stack of the zone that this ioctl originated + * from. + */ + gz_stack = B_FALSE; + zone = orig_zone; + } mutex_enter(&ipf_stack_lock); for (ifs = ipf_stacks; ifs != NULL; ifs = ifs->ifs_next) { - if (ifs->ifs_zone == zone) + if (ifs->ifs_zone == zone && ifs->ifs_gz_controlled == gz_stack) break; } + + if (ifs != NULL) { + READ_ENTER(&ifs->ifs_ipf_global); + } mutex_exit(&ipf_stack_lock); return (ifs); } - static int ipf_detach_check_zone(ipf_stack_t *ifs) { /* @@ -495,7 +600,8 @@ /* - * Destroy things for ipf for one stack. + * Remove ipf kstats for both the per-zone ipf stack and the + * GZ-controlled stack for the same zone, if it exists. */ /* ARGSUSED */ static void @@ -503,6 +609,15 @@ { ipf_stack_t *ifs = (ipf_stack_t *)arg; + /* + * The GZ-controlled stack + */ + if (ifs->ifs_gz_cont_ifs != NULL) + ipf_kstat_fini(ifs->ifs_gz_cont_ifs); + + /* + * The per-zone stack + */ ipf_kstat_fini(ifs); } @@ -512,13 +627,12 @@ */ /* ARGSUSED */ static void -ipf_stack_destroy(const netid_t id, void *arg) +ipf_stack_destroy_one(const netid_t id, ipf_stack_t *ifs) { - ipf_stack_t *ifs = (ipf_stack_t *)arg; timeout_id_t tid; #ifdef IPFDEBUG - (void) printf("ipf_stack_destroy(%p)\n", (void *)ifs); + (void) printf("ipf_stack_destroy_one(%p)\n", (void *)ifs); #endif /* @@ -546,7 +660,7 @@ WRITE_ENTER(&ifs->ifs_ipf_global); if (ipldetach(ifs) != 0) { - printf("ipf_stack_destroy: ipldetach failed\n"); + printf("ipf_stack_destroy_one: ipldetach failed\n"); } ipftuneable_free(ifs); @@ -560,6 +674,30 @@ } +/* + * Destroy things for ipf for both the per-zone ipf stack and the + * GZ-controlled stack for the same zone, if it exists. See the "GZ-controlled + * and per-zone stacks" comment block in ip_fil_solaris.c for details. + */ +/* ARGSUSED */ +static void +ipf_stack_destroy(const netid_t id, void *arg) +{ + ipf_stack_t *ifs = (ipf_stack_t *)arg; + + /* + * The GZ-controlled stack + */ + if (ifs->ifs_gz_cont_ifs != NULL) + ipf_stack_destroy_one(id, ifs->ifs_gz_cont_ifs); + + /* + * The per-zone stack + */ + ipf_stack_destroy_one(id, ifs); +} + + static int ipf_attach(dip, cmd) dev_info_t *dip; ddi_attach_cmd_t cmd; @@ -586,27 +724,39 @@ (void) ipf_property_g_update(dip); + if (ddi_soft_state_init(&ipf_state, sizeof (ipf_devstate_t), 1) + != 0) { + ddi_prop_remove_all(dip); + return (DDI_FAILURE); + } + for (i = 0; ((s = ipf_devfiles[i]) != NULL); i++) { s = strrchr(s, '/'); if (s == NULL) continue; s++; if (ddi_create_minor_node(dip, s, S_IFCHR, i, - DDI_PSEUDO, 0) == - DDI_FAILURE) { - ddi_remove_minor_node(dip, NULL); + DDI_PSEUDO, 0) == DDI_FAILURE) goto attach_failed; - } } ipf_dev_info = dip; ipfncb = net_instance_alloc(NETINFO_VERSION); + if (ipfncb == NULL) + goto attach_failed; + ipfncb->nin_name = "ipf"; ipfncb->nin_create = ipf_stack_create; ipfncb->nin_destroy = ipf_stack_destroy; ipfncb->nin_shutdown = ipf_stack_shutdown; - i = net_instance_register(ipfncb); + if (net_instance_register(ipfncb) == DDI_FAILURE) { + net_instance_free(ipfncb); + goto attach_failed; + } + + ipf_minor = vmem_create("ipf_minor", (void *)1, UINT32_MAX - 1, + 1, NULL, NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER); #ifdef IPFDEBUG cmn_err(CE_CONT, "IP Filter:stack_create callback_reg=%d", i); @@ -619,7 +769,9 @@ } attach_failed: + ddi_remove_minor_node(dip, NULL); ddi_prop_remove_all(dip); + ddi_soft_state_fini(&ipf_state); return (DDI_FAILURE); } @@ -652,6 +804,9 @@ return (DDI_FAILURE); } + vmem_destroy(ipf_minor); + ddi_soft_state_fini(&ipf_state); + (void) net_instance_unregister(ipfncb); net_instance_free(ipfncb);
--- a/usr/src/uts/common/os/zone.c Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/common/os/zone.c Sun Jan 04 07:19:22 2015 -0800 @@ -378,13 +378,6 @@ rctl_hndl_t rc_zone_shmmni; rctl_hndl_t rc_zone_semmni; rctl_hndl_t rc_zone_msgmni; -/* - * Synchronization primitives used to synchronize between mounts and zone - * creation/destruction. - */ -static int mounts_in_progress; -static kcondvar_t mount_cv; -static kmutex_t mount_lock; const char * const zone_default_initname = "/sbin/init"; static char * const zone_prefix = "/zone/"; @@ -430,17 +423,20 @@ /* * Certain filesystems (such as NFS and autofs) need to know which zone * the mount is being placed in. Because of this, we need to be able to - * ensure that a zone isn't in the process of being created such that - * nfs_mount() thinks it is in the global zone, while by the time it - * gets added the list of mounted zones, it ends up on zoneA's mount - * list. + * ensure that a zone isn't in the process of being created/destroyed such + * that nfs_mount() thinks it is in the global/NGZ zone, while by the time + * it gets added the list of mounted zones, it ends up on the wrong zone's + * mount list. Since a zone can't reside on an NFS file system, we don't + * have to worry about the zonepath itself. * * The following functions: block_mounts()/resume_mounts() and * mount_in_progress()/mount_completed() are used by zones and the VFS - * layer (respectively) to synchronize zone creation and new mounts. + * layer (respectively) to synchronize zone state transitions and new + * mounts within a zone. This syncronization is on a per-zone basis, so + * activity for one zone will not interfere with activity for another zone. * * The semantics are like a reader-reader lock such that there may - * either be multiple mounts (or zone creations, if that weren't + * either be multiple mounts (or zone state transitions, if that weren't * serialized by zonehash_lock) in progress at the same time, but not * both. * @@ -448,10 +444,8 @@ * taking too long. * * The semantics are such that there is unfair bias towards the - * "current" operation. This means that zone creations may starve if - * there is a rapid succession of new mounts coming in to the system, or - * there is a remote possibility that zones will be created at such a - * rate that new mounts will not be able to proceed. + * "current" operation. This means that zone halt may starve if + * there is a rapid succession of new mounts coming in to the zone. */ /* * Prevent new mounts from progressing to the point of calling @@ -459,7 +453,7 @@ * them to complete. */ static int -block_mounts(void) +block_mounts(zone_t *zp) { int retval = 0; @@ -468,19 +462,21 @@ * called with zonehash_lock held. */ ASSERT(MUTEX_NOT_HELD(&zonehash_lock)); - mutex_enter(&mount_lock); - while (mounts_in_progress > 0) { - if (cv_wait_sig(&mount_cv, &mount_lock) == 0) + mutex_enter(&zp->zone_mount_lock); + while (zp->zone_mounts_in_progress > 0) { + if (cv_wait_sig(&zp->zone_mount_cv, &zp->zone_mount_lock) == 0) goto signaled; } /* * A negative value of mounts_in_progress indicates that mounts - * have been blocked by (-mounts_in_progress) different callers. - */ - mounts_in_progress--; + * have been blocked by (-mounts_in_progress) different callers + * (remotely possible if two threads enter zone_shutdown at the same + * time). + */ + zp->zone_mounts_in_progress--; retval = 1; signaled: - mutex_exit(&mount_lock); + mutex_exit(&zp->zone_mount_lock); return (retval); } @@ -489,26 +485,26 @@ * Allow them to progress if we were the last obstacle. */ static void -resume_mounts(void) -{ - mutex_enter(&mount_lock); - if (++mounts_in_progress == 0) - cv_broadcast(&mount_cv); - mutex_exit(&mount_lock); +resume_mounts(zone_t *zp) +{ + mutex_enter(&zp->zone_mount_lock); + if (++zp->zone_mounts_in_progress == 0) + cv_broadcast(&zp->zone_mount_cv); + mutex_exit(&zp->zone_mount_lock); } /* - * The VFS layer is busy with a mount; zones should wait until all - * mounts are completed to progress. + * The VFS layer is busy with a mount; this zone should wait until all + * of its mounts are completed to progress. */ void -mount_in_progress(void) -{ - mutex_enter(&mount_lock); - while (mounts_in_progress < 0) - cv_wait(&mount_cv, &mount_lock); - mounts_in_progress++; - mutex_exit(&mount_lock); +mount_in_progress(zone_t *zp) +{ + mutex_enter(&zp->zone_mount_lock); + while (zp->zone_mounts_in_progress < 0) + cv_wait(&zp->zone_mount_cv, &zp->zone_mount_lock); + zp->zone_mounts_in_progress++; + mutex_exit(&zp->zone_mount_lock); } /* @@ -516,12 +512,12 @@ * callers if this is the last mount. */ void -mount_completed(void) -{ - mutex_enter(&mount_lock); - if (--mounts_in_progress == 0) - cv_broadcast(&mount_cv); - mutex_exit(&mount_lock); +mount_completed(zone_t *zp) +{ + mutex_enter(&zp->zone_mount_lock); + if (--zp->zone_mounts_in_progress == 0) + cv_broadcast(&zp->zone_mount_cv); + mutex_exit(&zp->zone_mount_lock); } /* @@ -4410,7 +4406,7 @@ return (zone_create_error(error, 0, extended_error)); } - if (block_mounts() == 0) { + if (block_mounts(zone) == 0) { mutex_enter(&pp->p_lock); if (curthread != pp->p_agenttp) continuelwps(pp); @@ -4561,7 +4557,7 @@ /* * The zone is fully visible, so we can let mounts progress. */ - resume_mounts(); + resume_mounts(zone); if (rctls) nvlist_free(rctls); @@ -4577,7 +4573,7 @@ continuelwps(pp); mutex_exit(&pp->p_lock); - resume_mounts(); + resume_mounts(zone); if (rctls) nvlist_free(rctls); /* @@ -4732,15 +4728,6 @@ if (zoneid < MIN_USERZONEID || zoneid > MAX_ZONEID) return (set_errno(EINVAL)); - /* - * Block mounts so that VFS_MOUNT() can get an accurate view of - * the zone's status with regards to ZONE_IS_SHUTTING down. - * - * e.g. NFS can fail the mount if it determines that the zone - * has already begun the shutdown sequence. - */ - if (block_mounts() == 0) - return (set_errno(EINTR)); mutex_enter(&zonehash_lock); /* * Look for zone under hash lock to prevent races with other @@ -4748,9 +4735,30 @@ */ if ((zone = zone_find_all_by_id(zoneid)) == NULL) { mutex_exit(&zonehash_lock); - resume_mounts(); return (set_errno(EINVAL)); } + + /* + * We have to drop zonehash_lock before calling block_mounts. + * Hold the zone so we can continue to use the zone_t. + */ + zone_hold(zone); + mutex_exit(&zonehash_lock); + + /* + * Block mounts so that VFS_MOUNT() can get an accurate view of + * the zone's status with regards to ZONE_IS_SHUTTING down. + * + * e.g. NFS can fail the mount if it determines that the zone + * has already begun the shutdown sequence. + * + */ + if (block_mounts(zone) == 0) { + zone_rele(zone); + return (set_errno(EINTR)); + } + + mutex_enter(&zonehash_lock); mutex_enter(&zone_status_lock); status = zone_status_get(zone); /* @@ -4759,7 +4767,8 @@ if (status < ZONE_IS_READY) { mutex_exit(&zone_status_lock); mutex_exit(&zonehash_lock); - resume_mounts(); + resume_mounts(zone); + zone_rele(zone); return (set_errno(EINVAL)); } /* @@ -4769,7 +4778,8 @@ if (status >= ZONE_IS_DOWN) { mutex_exit(&zone_status_lock); mutex_exit(&zonehash_lock); - resume_mounts(); + resume_mounts(zone); + zone_rele(zone); return (0); } /* @@ -4804,10 +4814,9 @@ } } } - zone_hold(zone); /* so we can use the zone_t later */ mutex_exit(&zone_status_lock); mutex_exit(&zonehash_lock); - resume_mounts(); + resume_mounts(zone); if (error = zone_empty(zone)) { zone_rele(zone);
--- a/usr/src/uts/common/sys/zone.h Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/common/sys/zone.h Sun Jan 04 07:19:22 2015 -0800 @@ -600,6 +600,14 @@ * DTrace-private per-zone state */ int zone_dtrace_getf; /* # of unprivileged getf()s */ + + /* + * Synchronization primitives used to synchronize between mounts and + * zone creation/destruction. + */ + int zone_mounts_in_progress; + kcondvar_t zone_mount_cv; + kmutex_t zone_mount_lock; } zone_t; /* @@ -819,8 +827,8 @@ extern int zone_kadmin(int, int, const char *, cred_t *); extern void zone_shutdown_global(void); -extern void mount_in_progress(void); -extern void mount_completed(void); +extern void mount_in_progress(zone_t *); +extern void mount_completed(zone_t *); extern int zone_walk(int (*)(zone_t *, void *), void *);
--- a/usr/src/uts/intel/ipf/ipf.global-objs.debug64 Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/intel/ipf/ipf.global-objs.debug64 Sun Jan 04 07:19:22 2015 -0800 @@ -22,11 +22,33 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2013 Joyent, Inc. All rights reserved +# fr_availfuncs fr_features fr_objbytes hdrsizes +hook4_in +hook4_in_gz +hook4_loop_in +hook4_loop_in_gz +hook4_loop_out +hook4_loop_out_gz +hook4_nicevents +hook4_nicevents_gz +hook4_out +hook4_out_gz +hook6_in +hook6_in_gz +hook6_loop_in +hook6_loop_in_gz +hook6_loop_out +hook6_loop_out_gz +hook6_nicevents +hook6_nicevents_gz +hook6_out +hook6_out_gz icmpreplytype4 icmpreplytype6 icmptoicmp6types @@ -37,10 +59,12 @@ ipf_dev_info ipf_devfiles ipf_kstat_tmp +ipf_minor ipf_ops ipf_proxy_debug ipf_stack_lock ipf_stacks +ipf_state ipfilter_version ipfncb ipl_magic
--- a/usr/src/uts/sparc/ipf/ipf.global-objs.debug64 Sun Dec 28 13:11:10 2014 -0800 +++ b/usr/src/uts/sparc/ipf/ipf.global-objs.debug64 Sun Jan 04 07:19:22 2015 -0800 @@ -22,11 +22,33 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2013 Joyent, Inc. All rights reserved +# fr_availfuncs fr_features fr_objbytes hdrsizes +hook4_in +hook4_in_gz +hook4_loop_in +hook4_loop_in_gz +hook4_loop_out +hook4_loop_out_gz +hook4_nicevents +hook4_nicevents_gz +hook4_out +hook4_out_gz +hook6_in +hook6_in_gz +hook6_loop_in +hook6_loop_in_gz +hook6_loop_out +hook6_loop_out_gz +hook6_nicevents +hook6_nicevents_gz +hook6_out +hook6_out_gz icmpreplytype4 icmpreplytype6 icmptoicmp6types @@ -37,10 +59,12 @@ ipf_dev_info ipf_devfiles ipf_kstat_tmp +ipf_minor ipf_ops ipf_proxy_debug ipf_stack_lock ipf_stacks +ipf_state ipfilter_version ipfncb ipl_magic @@ -56,9 +80,9 @@ sccsid secopt tcpopts +lastx _drand48_a _drand48_c _drand48_x init48done seed_lock -lastx