summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_ctf.c61
-rw-r--r--usr/src/cmd/zdb/zdb.c46
-rw-r--r--usr/src/cmd/zfs/zfs_main.c10
-rw-r--r--usr/src/common/smbsrv/smb_string.c16
-rw-r--r--usr/src/lib/libshare/Makefile.com2
-rw-r--r--usr/src/lib/libshare/common/libshare.c96
-rw-r--r--usr/src/lib/libshare/common/libshare.h25
-rw-r--r--usr/src/lib/libshare/common/libshare_impl.h5
-rw-r--r--usr/src/lib/libshare/common/libshare_zfs.c387
-rw-r--r--usr/src/lib/libshare/common/libsharecore.c292
-rw-r--r--usr/src/lib/libshare/common/mapfile-vers2
-rw-r--r--usr/src/lib/libzfs/common/libzfs.h11
-rw-r--r--usr/src/lib/libzfs/common/libzfs_changelist.c32
-rw-r--r--usr/src/lib/libzfs/common/libzfs_impl.h1
-rw-r--r--usr/src/lib/libzfs/common/libzfs_mount.c54
-rw-r--r--usr/src/lib/libzfs/common/mapfile-vers2
-rw-r--r--usr/src/man/man1m/zdb.1m15
-rw-r--r--usr/src/test/zfs-tests/tests/functional/cli_root/zdb/zdb_001_neg.ksh2
-rw-r--r--usr/src/test/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_server.c2
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_pool.c3
-rw-r--r--usr/src/uts/common/fs/zfs/sa.c11
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_ioctl.c3
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vfsops.c4
-rw-r--r--usr/src/uts/common/io/virtio/virtio.c3
-rw-r--r--usr/src/uts/common/smbsrv/string.h2
-rw-r--r--usr/src/uts/i86pc/os/cpuid.c13
27 files changed, 755 insertions, 347 deletions
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c
index 9b6d54c7b1..af8fc7b0fd 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c
@@ -24,7 +24,7 @@
*/
/*
* Copyright (c) 2015, Joyent, Inc. All rights reserved.
- * Copyright (c) 2013, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2013, 2016 by Delphix. All rights reserved.
*/
#include <mdb/mdb_ctf.h>
@@ -1267,7 +1267,7 @@ vread_helper(mdb_ctf_id_t modid, char *modbuf,
mdb_ctf_id_t tgtid, char *tgtbuf, const char *tgtname, uint_t flags)
{
size_t modsz, tgtsz;
- int modkind, tgtkind;
+ int modkind, tgtkind, mod_members;
member_t mbr;
enum_value_t ev;
int ret;
@@ -1470,29 +1470,52 @@ vread_helper(mdb_ctf_id_t modid, char *modbuf,
return (mdb_ctf_member_iter(modid, member_cb, &mbr));
case CTF_K_UNION:
+ mbr.m_modbuf = modbuf;
+ mbr.m_tgtbuf = tgtbuf;
+ mbr.m_tgtid = tgtid;
+ mbr.m_flags = flags;
+ mbr.m_tgtname = typename;
/*
- * Unions are a little tricky. The only time it's truly
- * safe to read in a union is if no part of the union or
- * any of its component types have changed. The correct
- * use of this feature is to read the containing structure,
- * figure out which component of the union is valid, compute
- * the location of that in the target and then read in
- * that part of the structure.
+ * Not all target union members need to be present in the
+ * mdb type. If there is only a single union member in the
+ * mdb type, its actual type does not need to match with
+ * its target's type. On the other hand, if more than one
+ * union members are specified in the mdb type, their types
+ * must match with the types of their relevant union members
+ * of the target union.
*/
+ mod_members = mdb_ctf_num_members(modid);
+ if (mod_members == 1) {
+ return (mdb_ctf_member_iter(modid, member_cb, &mbr));
+ } else if (mod_members > 1) {
+ if (mdb_ctf_member_iter(modid, type_equals_cb,
+ &tgtid)) {
+ mdb_ctf_warn(flags,
+ "inexact match for union %s (%s)\n",
+ typename, tgtname);
+ return (set_errno(EMDB_INCOMPAT));
+ }
- if (!type_equals(modid, tgtid)) {
- mdb_ctf_warn(flags, "inexact match for union %s (%s)\n",
- typename, tgtname);
- return (set_errno(EMDB_INCOMPAT));
+ /*
+ * From the check above we know that the members
+ * which are present in the mdb type are equal to
+ * the types in the target. Thus, the member_cb
+ * callback below will not move anything around and
+ * it is equivalent to:
+ *
+ * bcopy(tgtbuf, modbuf, MAX(module member's sizes))
+ */
+ return (mdb_ctf_member_iter(modid, member_cb, &mbr));
+ } else {
+ /*
+ * We either got 0 or -1. In any case that number
+ * should be returned right away. For the error
+ * case of -1, errno has been set for us.
+ */
+ return (mod_members);
}
- ASSERT(modsz == tgtsz);
-
- bcopy(tgtbuf, modbuf, modsz);
-
- return (0);
-
case CTF_K_ARRAY:
if (mdb_ctf_array_info(tgtid, &tar) != 0) {
mdb_ctf_warn(flags,
diff --git a/usr/src/cmd/zdb/zdb.c b/usr/src/cmd/zdb/zdb.c
index 8337982284..9ddf5e1021 100644
--- a/usr/src/cmd/zdb/zdb.c
+++ b/usr/src/cmd/zdb/zdb.c
@@ -120,20 +120,21 @@ static void
usage(void)
{
(void) fprintf(stderr,
- "Usage:\t%s [-AbcdDFGhiLMPsvX] [-e [-p <path> ...]] "
+ "Usage:\t%s [-AbcdDFGhiLMPsvX] [-e [-V] [-p <path> ...]] "
"[-I <inflight I/Os>]\n"
"\t\t[-o <var>=<value>]... [-t <txg>] [-U <cache>] [-x <dumpdir>]\n"
"\t\t[<poolname> [<object> ...]]\n"
- "\t%s [-AdiPv] [-e [-p <path> ...]] [-U <cache>] <dataset> "
+ "\t%s [-AdiPv] [-e [-V] [-p <path> ...]] [-U <cache>] <dataset> "
"[<object> ...]\n"
"\t%s -C [-A] [-U <cache>]\n"
"\t%s -l [-Aqu] <device>\n"
- "\t%s -m [-AFLPX] [-e [-p <path> ...]] [-t <txg>] [-U <cache>]\n"
- "\t\t<poolname> [<vdev> [<metaslab> ...]]\n"
+ "\t%s -m [-AFLPX] [-e [-V] [-p <path> ...]] [-t <txg>] "
+ "[-U <cache>]\n\t\t<poolname> [<vdev> [<metaslab> ...]]\n"
"\t%s -O <dataset> <path>\n"
- "\t%s -R [-A] [-e [-p <path> ...]] [-U <cache>]\n"
+ "\t%s -R [-A] [-e [-V] [-p <path> ...]] [-U <cache>]\n"
"\t\t<poolname> <vdev>:<offset>:<size>[:<flags>]\n"
- "\t%s -S [-AP] [-e [-p <path> ...]] [-U <cache>] <poolname>\n\n",
+ "\t%s -S [-AP] [-e [-V] [-p <path> ...]] [-U <cache>] "
+ "<poolname>\n\n",
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname,
cmdname);
@@ -188,6 +189,7 @@ usage(void)
(void) fprintf(stderr, " -u uberblock\n");
(void) fprintf(stderr, " -U <cachefile_path> -- use alternate "
"cachefile\n");
+ (void) fprintf(stderr, " -V do verbatim import\n");
(void) fprintf(stderr, " -x <dumpdir> -- "
"dump all read blocks into specified directory\n");
(void) fprintf(stderr, " -X attempt extreme rewind (does not "
@@ -1737,23 +1739,19 @@ dump_znode(objset_t *os, uint64_t object, void *data, size_t size)
return;
}
- error = zfs_obj_to_path(os, object, path, sizeof (path));
- if (error != 0) {
- (void) snprintf(path, sizeof (path), "\?\?\?<object#%llu>",
- (u_longlong_t)object);
- }
- if (dump_opt['d'] < 3) {
- (void) printf("\t%s\n", path);
- (void) sa_handle_destroy(hdl);
- return;
- }
-
z_crtime = (time_t)crtm[0];
z_atime = (time_t)acctm[0];
z_mtime = (time_t)modtm[0];
z_ctime = (time_t)chgtm[0];
- (void) printf("\tpath %s\n", path);
+ if (dump_opt['d'] > 4) {
+ error = zfs_obj_to_path(os, object, path, sizeof (path));
+ if (error != 0) {
+ (void) snprintf(path, sizeof (path),
+ "\?\?\?<object#%llu>", (u_longlong_t)object);
+ }
+ (void) printf("\tpath %s\n", path);
+ }
dump_uidgid(os, uid, gid);
(void) printf("\tatime %s", ctime(&z_atime));
(void) printf("\tmtime %s", ctime(&z_mtime));
@@ -3714,6 +3712,7 @@ main(int argc, char **argv)
char *target;
nvlist_t *policy = NULL;
uint64_t max_txg = UINT64_MAX;
+ int flags = ZFS_IMPORT_MISSING_LOG;
int rewind = ZPOOL_NEVER_REWIND;
char *spa_config_path_env;
boolean_t target_is_spa = B_TRUE;
@@ -3733,7 +3732,7 @@ main(int argc, char **argv)
spa_config_path = spa_config_path_env;
while ((c = getopt(argc, argv,
- "AbcCdDeFGhiI:lLmMo:Op:PqRsSt:uU:vx:X")) != -1) {
+ "AbcCdDeFGhiI:lLmMo:Op:PqRsSt:uU:vVx:X")) != -1) {
switch (c) {
case 'b':
case 'c':
@@ -3807,6 +3806,9 @@ main(int argc, char **argv)
case 'v':
verbose++;
break;
+ case 'V':
+ flags = ZFS_IMPORT_VERBATIM;
+ break;
case 'x':
vn_dumpdir = optarg;
break;
@@ -3906,11 +3908,7 @@ main(int argc, char **argv)
fatal("can't open '%s': %s",
target, strerror(ENOMEM));
}
- if ((error = spa_import(name, cfg, NULL,
- ZFS_IMPORT_MISSING_LOG)) != 0) {
- error = spa_import(name, cfg, NULL,
- ZFS_IMPORT_VERBATIM);
- }
+ error = spa_import(name, cfg, NULL, flags);
}
}
diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c
index fa66039fba..2a7a9a6ec2 100644
--- a/usr/src/cmd/zfs/zfs_main.c
+++ b/usr/src/cmd/zfs/zfs_main.c
@@ -68,6 +68,7 @@
#include <aclutils.h>
#include <directory.h>
#include <idmap.h>
+#include <libshare.h>
#include "zfs_iter.h"
#include "zfs_util.h"
@@ -6218,6 +6219,15 @@ share_mount(int op, int argc, char **argv)
return (0);
qsort(dslist, count, sizeof (void *), libzfs_dataset_cmp);
+ sa_init_selective_arg_t sharearg;
+ sharearg.zhandle_arr = dslist;
+ sharearg.zhandle_len = count;
+ if ((ret = zfs_init_libshare_arg(zfs_get_handle(dslist[0]),
+ SA_INIT_SHARE_API_SELECTIVE, &sharearg)) != SA_OK) {
+ (void) fprintf(stderr,
+ gettext("Could not initialize libshare, %d"), ret);
+ return (ret);
+ }
for (i = 0; i < count; i++) {
if (verbose)
diff --git a/usr/src/common/smbsrv/smb_string.c b/usr/src/common/smbsrv/smb_string.c
index 8400c51ea1..3d2abc474b 100644
--- a/usr/src/common/smbsrv/smb_string.c
+++ b/usr/src/common/smbsrv/smb_string.c
@@ -23,6 +23,7 @@
* Use is subject to license terms.
*
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2017 by Delphix. All rights reserved.
*/
#if defined(_KERNEL) || defined(_FAKE_KERNEL)
@@ -50,6 +51,8 @@
static const smb_codepage_t *current_codepage = usascii_codepage;
static boolean_t is_unicode = B_FALSE;
+static smb_codepage_t *unicode_codepage = NULL;
+
static smb_codepage_t *smb_unicode_init(void);
/*
@@ -115,13 +118,14 @@ strcanon(char *buf, const char *class)
void
smb_codepage_init(void)
{
- const smb_codepage_t *cp;
+ smb_codepage_t *cp;
if (is_unicode)
return;
if ((cp = smb_unicode_init()) != NULL) {
current_codepage = cp;
+ unicode_codepage = cp;
is_unicode = B_TRUE;
} else {
current_codepage = usascii_codepage;
@@ -129,6 +133,16 @@ smb_codepage_init(void)
}
}
+void
+smb_codepage_fini(void)
+{
+ if (unicode_codepage != NULL) {
+ MEM_FREE("unicode", unicode_codepage);
+ unicode_codepage = NULL;
+ current_codepage = NULL;
+ }
+}
+
/*
* Determine whether or not a character is an uppercase character.
* This function operates on the current codepage table. Returns
diff --git a/usr/src/lib/libshare/Makefile.com b/usr/src/lib/libshare/Makefile.com
index 328ffb353a..2f8aad345f 100644
--- a/usr/src/lib/libshare/Makefile.com
+++ b/usr/src/lib/libshare/Makefile.com
@@ -19,6 +19,7 @@
# CDDL HEADER END
#
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2016 by Delphix. All rights reserved.
#
LIBRARY = libshare.a
VERS = .1
@@ -42,6 +43,7 @@ $(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
#add nfs/lib directory as part of the include path
CFLAGS += $(CCVERBOSE)
+C99MODE += $(C99_ENABLE)
CERRWARN += -_gcc=-Wno-parentheses
CERRWARN += -_gcc=-Wno-uninitialized
CERRWARN += -_gcc=-Wno-switch
diff --git a/usr/src/lib/libshare/common/libshare.c b/usr/src/lib/libshare/common/libshare.c
index 6950031978..5a58e0268e 100644
--- a/usr/src/lib/libshare/common/libshare.c
+++ b/usr/src/lib/libshare/common/libshare.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2016 by Delphix. All rights reserved.
*/
/*
@@ -68,6 +69,7 @@ extern struct sa_proto_plugin *sap_proto_list;
/* current SMF/SVC repository handle */
extern void getlegacyconfig(sa_handle_t, char *, xmlNodePtr *);
extern int gettransients(sa_handle_impl_t, xmlNodePtr *);
+extern int get_one_transient(sa_handle_impl_t, xmlNodePtr *, char **, size_t);
extern char *sa_fstype(char *);
extern int sa_is_share(void *);
extern int sa_is_resource(void *);
@@ -814,21 +816,23 @@ verifydefgroupopts(sa_handle_t handle)
}
/*
- * sa_init(init_service)
+ * sa_init_impl(init_service, arg)
* Initialize the API
* find all the shared objects
* init the tables with all objects
* read in the current configuration
+ *
+ * arg is a parameter passed in whose meaning is based on the init_service.
+ * See libshare.h under API initialization.
*/
-
#define GETPROP(prop) scf_simple_prop_next_astring(prop)
#define CHECKTSTAMP(st, tval) stat(SA_LEGACY_DFSTAB, &st) >= 0 && \
tval != TSTAMP(st.st_ctim)
-
-sa_handle_t
-sa_init(int init_service)
+static sa_handle_t
+sa_init_impl(int init_service, void *arg)
{
struct stat st;
+ /* legacy is used for debugging only as far as I can tell */
int legacy = 0;
uint64_t tval = 0;
int lockfd;
@@ -841,6 +845,7 @@ sa_init(int init_service)
handle = calloc(sizeof (struct sa_handle_impl), 1);
if (handle != NULL) {
+ handle->sa_service = init_service;
/*
* Get protocol specific structures, but only if this
* is the only handle.
@@ -849,7 +854,9 @@ sa_init(int init_service)
if (sa_global_handles == NULL)
(void) proto_plugin_init();
(void) mutex_unlock(&sa_global_lock);
- if (init_service & SA_INIT_SHARE_API) {
+ if (init_service & (SA_INIT_SHARE_API |
+ SA_INIT_SHARE_API_SELECTIVE | SA_INIT_ONE_SHARE_FROM_NAME |
+ SA_INIT_ONE_SHARE_FROM_HANDLE)) {
/*
* initialize access into libzfs. We use this
* when collecting info about ZFS datasets and
@@ -1025,8 +1032,60 @@ sa_init(int init_service)
handle->tstrans = 0;
scf_simple_prop_free(prop);
}
- legacy |= sa_get_zfs_shares(handle, "zfs");
- legacy |= gettransients(handle, &handle->tree);
+ /*
+ * In this conditional the library reads from
+ * zfs and /etc/dfs/sharetab to find datasets
+ * that must be shared. The result is a tree of
+ * groups that are stored in the handle for
+ * libshare to utilize later when asked to share
+ * or unshare datasets.
+ */
+ if (init_service &
+ SA_INIT_SHARE_API_SELECTIVE) {
+ char **paths;
+ size_t paths_len, i;
+
+ legacy |= sa_get_one_zfs_share(handle,
+ "zfs",
+ (sa_init_selective_arg_t *)arg,
+ &paths, &paths_len);
+ legacy |= get_one_transient(handle,
+ &handle->tree, paths, paths_len);
+ for (i = 0; i < paths_len; ++i) {
+ free(paths[i]);
+ }
+ free(paths);
+ } else if (init_service &
+ SA_INIT_ONE_SHARE_FROM_NAME) {
+ char path[ZFS_MAXPROPLEN];
+ char *ptr = path;
+ char **ptr_to_path = &ptr;
+
+ legacy |=
+ sa_get_zfs_share_for_name(handle,
+ "zfs", (char *)arg, path);
+ legacy |= get_one_transient(handle,
+ &handle->tree, ptr_to_path, 1);
+ } else if (init_service &
+ SA_INIT_ONE_SHARE_FROM_HANDLE) {
+ char path[ZFS_MAXPROPLEN];
+ char *ptr = path;
+ char **ptr_to_path = &ptr;
+
+ legacy |=
+ sa_get_zfs_share_for_name(handle,
+ "zfs",
+ zfs_get_name(
+ (zfs_handle_t *)arg),
+ path);
+ legacy |= get_one_transient(handle,
+ &handle->tree, ptr_to_path, 1);
+ } else {
+ legacy |= sa_get_zfs_shares(handle,
+ "zfs");
+ legacy |= gettransients(handle,
+ &handle->tree);
+ }
}
}
}
@@ -1034,6 +1093,25 @@ sa_init(int init_service)
}
/*
+ * sa_init exists as a legacy interface, new consumers should use sa_init_arg.
+ */
+sa_handle_t
+sa_init(int init_service)
+{
+ return (sa_init_impl(init_service, NULL));
+}
+
+/*
+ * See libshare.h "API Initialization" section for valid values of init_service
+ * as well as the appropriate argument type for a given init_service.
+ */
+sa_handle_t
+sa_init_arg(int init_service, void *arg)
+{
+ return (sa_init_impl(init_service, arg));
+}
+
+/*
* sa_fini(handle)
* Uninitialize the API structures including the configuration
* data structures and ZFS related data.
@@ -3066,7 +3144,7 @@ add_or_update(scfutilhandle_t *scf_handle, int type, scf_value_t *value,
static int
sa_set_prop_by_prop(sa_optionset_t optionset, sa_group_t group,
- sa_property_t prop, int type)
+ sa_property_t prop, int type)
{
char *name;
char *valstr;
diff --git a/usr/src/lib/libshare/common/libshare.h b/usr/src/lib/libshare/common/libshare.h
index 9348e76341..7ad9fefdcd 100644
--- a/usr/src/lib/libshare/common/libshare.h
+++ b/usr/src/lib/libshare/common/libshare.h
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2016 by Delphix. All rights reserved.
*/
/*
@@ -37,6 +38,7 @@ extern "C" {
#include <sys/types.h>
#include <sys/nvpair.h>
+#include <libzfs.h>
/*
* Basic datatypes for most functions
@@ -91,9 +93,31 @@ typedef void *sa_handle_t; /* opaque handle to access core functions */
#define SA_SHARE_EXISTS 33 /* path or file is already shared */
/* API Initialization */
+/* Both of these do not care about the value of arg in sa_init_arg */
#define SA_INIT_SHARE_API 0x0001 /* init share specific interface */
#define SA_INIT_CONTROL_API 0x0002 /* init control specific interface */
+/* expects an sa_init_selective_arg_t as an argument */
+#define SA_INIT_SHARE_API_SELECTIVE 0x0004 /* only some shares */
+struct sa_init_selective_arg {
+ zfs_handle_t **zhandle_arr;
+ size_t zhandle_len;
+};
+typedef struct sa_init_selective_arg sa_init_selective_arg_t;
+
+
+/*
+ * The SA_INIT_ONE_SHARE* initialization options to sa_init* will cause
+ * sa_needs_refrsh() to return true even if nothing else in the system has
+ * changed. If writing code that could possibly need to share/unshare multiple
+ * shares, it is recommended to use SA_INIT_SHARE_API_SELECTIVE.
+ */
+/* Expects a single char * as input, the name of the share. */
+#define SA_INIT_ONE_SHARE_FROM_NAME 0x0008
+
+/* Expects a single zfs_handle_t as input, the handle of the share. */
+#define SA_INIT_ONE_SHARE_FROM_HANDLE 0x0010
+
/* not part of API returns */
#define SA_LEGACY_ERR 32 /* share/unshare error return */
@@ -145,6 +169,7 @@ typedef void *sa_handle_t; /* opaque handle to access core functions */
/* initialization */
extern sa_handle_t sa_init(int);
+extern sa_handle_t sa_init_arg(int, void *);
extern void sa_fini(sa_handle_t);
extern int sa_update_config(sa_handle_t);
extern boolean_t sa_needs_refresh(sa_handle_t);
diff --git a/usr/src/lib/libshare/common/libshare_impl.h b/usr/src/lib/libshare/common/libshare_impl.h
index 1fcffa95d9..1b326e73eb 100644
--- a/usr/src/lib/libshare/common/libshare_impl.h
+++ b/usr/src/lib/libshare/common/libshare_impl.h
@@ -22,6 +22,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright (c) 2016 by Delphix. All rights reserved.
*/
/*
@@ -110,6 +111,7 @@ typedef struct sa_handle_impl {
xmlDocPtr doc;
uint64_t tssharetab;
uint64_t tstrans;
+ int sa_service;
} *sa_handle_impl_t;
extern int sa_proto_share(char *, sa_share_t);
@@ -142,7 +144,10 @@ extern void sa_fillshare(sa_share_t share, char *proto, struct share *sh);
extern void sa_emptyshare(struct share *sh);
/* ZFS functions */
+extern int sa_get_one_zfs_share(sa_handle_t, char *, sa_init_selective_arg_t *,
+ char ***, size_t *);
extern int sa_get_zfs_shares(sa_handle_t, char *);
+extern int sa_get_zfs_share_for_name(sa_handle_t, char *, const char *, char *);
extern int sa_zfs_update(sa_share_t);
extern int sa_share_zfs(sa_share_t, sa_resource_t, char *, share_t *,
void *, zfs_share_op_t);
diff --git a/usr/src/lib/libshare/common/libshare_zfs.c b/usr/src/lib/libshare/common/libshare_zfs.c
index 08b5a00e9d..488841fcff 100644
--- a/usr/src/lib/libshare/common/libshare_zfs.c
+++ b/usr/src/lib/libshare/common/libshare_zfs.c
@@ -264,6 +264,10 @@ get_legacy_mountpoint(const char *path, char *dataset, size_t dlen,
}
+/*
+ * Verifies that a specific zfs filesystem handle meets the criteria necessary
+ * to be used by libshare operations. See get_zfs_dataset.
+ */
static char *
verify_zfs_handle(zfs_handle_t *hdl, const char *path, boolean_t search_mnttab)
{
@@ -338,19 +342,16 @@ get_zfs_dataset(sa_handle_impl_t impl_handle, char *path,
assert(impl_handle->zfs_libhandle != NULL);
libzfs_print_on_error(impl_handle->zfs_libhandle, B_FALSE);
- if ((handle_from_path = zfs_open(impl_handle->zfs_libhandle, cutpath,
- ZFS_TYPE_FILESYSTEM)) != NULL) {
- if ((ret = verify_zfs_handle(handle_from_path, path,
- search_mnttab)) != NULL) {
- zfs_close(handle_from_path);
- libzfs_print_on_error(impl_handle->zfs_libhandle,
- B_TRUE);
+ handle_from_path = zfs_open(impl_handle->zfs_libhandle, cutpath,
+ ZFS_TYPE_FILESYSTEM);
+ libzfs_print_on_error(impl_handle->zfs_libhandle, B_TRUE);
+ if (handle_from_path != NULL) {
+ ret = verify_zfs_handle(handle_from_path, path, search_mnttab);
+ zfs_close(handle_from_path);
+ if (ret != NULL) {
return (ret);
}
- zfs_close(handle_from_path);
}
- libzfs_print_on_error(impl_handle->zfs_libhandle, B_TRUE);
-
/*
* Couldn't find a filesystem optimistically, check all the handles we
* can.
@@ -764,8 +765,6 @@ sa_zfs_process_share(sa_handle_t handle, sa_group_t group, sa_share_t share,
}
/*
- * sa_get_zfs_shares(handle, groupname)
- *
* Walk the mnttab for all zfs mounts and determine which are
* shared. Find or create the appropriate group/sub-group to contain
* the shares.
@@ -778,170 +777,197 @@ sa_zfs_process_share(sa_handle_t handle, sa_group_t group, sa_share_t share,
* a sub-group must be formed at the lower level for both
* protocols. That is the nature of the problem in CR 6667349.
*/
-
-int
-sa_get_zfs_shares(sa_handle_t handle, char *groupname)
+static int
+sa_get_zfs_share_common(sa_handle_t handle, zfs_handle_t *fs_handle, char *path,
+ sa_group_t zfsgroup)
{
- sa_group_t zfsgroup;
- boolean_t nfs;
- boolean_t nfs_inherited;
- boolean_t smb;
- boolean_t smb_inherited;
- zfs_handle_t **zlist;
+ boolean_t smb, nfs;
+ boolean_t smb_inherited, nfs_inherited;
char nfsshareopts[ZFS_MAXPROPLEN];
char smbshareopts[ZFS_MAXPROPLEN];
- sa_share_t share;
- zprop_source_t source;
char nfssourcestr[ZFS_MAXPROPLEN];
char smbsourcestr[ZFS_MAXPROPLEN];
char mountpoint[ZFS_MAXPROPLEN];
- size_t count = 0, i;
- libzfs_handle_t *zfs_libhandle;
int err = SA_OK;
+ zprop_source_t source;
+ sa_share_t share;
+ char *dataset;
+
+ source = ZPROP_SRC_ALL;
+ /* If no mountpoint, skip. */
+ if (zfs_prop_get(fs_handle, ZFS_PROP_MOUNTPOINT,
+ mountpoint, sizeof (mountpoint), NULL, NULL, 0,
+ B_FALSE) != 0)
+ return (SA_SYSTEM_ERR);
+ if (path != NULL)
+ (void) strncpy(path, mountpoint, sizeof (mountpoint));
/*
- * If we can't access libzfs, don't bother doing anything.
+ * zfs_get_name value must not be freed. It is just a
+ * pointer to a value in the handle.
*/
- zfs_libhandle = ((sa_handle_impl_t)handle)->zfs_libhandle;
- if (zfs_libhandle == NULL)
+ if ((dataset = (char *)zfs_get_name(fs_handle)) == NULL)
return (SA_SYSTEM_ERR);
- zfsgroup = find_or_create_group(handle, groupname, NULL, &err);
- /* Not an error, this could be a legacy condition */
- if (zfsgroup == NULL)
- return (SA_OK);
-
/*
- * need to walk the mounted ZFS pools and datasets to
- * find shares that are possible.
+ * only deal with "mounted" file systems since
+ * unmounted file systems can't actually be shared.
*/
- get_all_filesystems((sa_handle_impl_t)handle, &zlist, &count);
- qsort(zlist, count, sizeof (void *), mountpoint_compare);
-
- for (i = 0; i < count; i++) {
- char *dataset;
- source = ZPROP_SRC_ALL;
- /* If no mountpoint, skip. */
- if (zfs_prop_get(zlist[i], ZFS_PROP_MOUNTPOINT,
- mountpoint, sizeof (mountpoint), NULL, NULL, 0,
- B_FALSE) != 0)
- continue;
-
- /*
- * zfs_get_name value must not be freed. It is just a
- * pointer to a value in the handle.
- */
- if ((dataset = (char *)zfs_get_name(zlist[i])) == NULL)
- continue;
+ if (!zfs_is_mounted(fs_handle, NULL))
+ return (SA_SYSTEM_ERR);
- /*
- * only deal with "mounted" file systems since
- * unmounted file systems can't actually be shared.
- */
+ nfs = nfs_inherited = B_FALSE;
- if (!zfs_is_mounted(zlist[i], NULL))
- continue;
-
- nfs = nfs_inherited = B_FALSE;
+ if (zfs_prop_get(fs_handle, ZFS_PROP_SHARENFS, nfsshareopts,
+ sizeof (nfsshareopts), &source, nfssourcestr,
+ ZFS_MAXPROPLEN, B_FALSE) == 0 &&
+ strcmp(nfsshareopts, "off") != 0) {
+ if (source & ZPROP_SRC_INHERITED)
+ nfs_inherited = B_TRUE;
+ else
+ nfs = B_TRUE;
+ }
- if (zfs_prop_get(zlist[i], ZFS_PROP_SHARENFS, nfsshareopts,
- sizeof (nfsshareopts), &source, nfssourcestr,
- ZFS_MAXPROPLEN, B_FALSE) == 0 &&
- strcmp(nfsshareopts, "off") != 0) {
- if (source & ZPROP_SRC_INHERITED)
- nfs_inherited = B_TRUE;
- else
- nfs = B_TRUE;
- }
+ smb = smb_inherited = B_FALSE;
+ if (zfs_prop_get(fs_handle, ZFS_PROP_SHARESMB, smbshareopts,
+ sizeof (smbshareopts), &source, smbsourcestr,
+ ZFS_MAXPROPLEN, B_FALSE) == 0 &&
+ strcmp(smbshareopts, "off") != 0) {
+ if (source & ZPROP_SRC_INHERITED)
+ smb_inherited = B_TRUE;
+ else
+ smb = B_TRUE;
+ }
- smb = smb_inherited = B_FALSE;
- if (zfs_prop_get(zlist[i], ZFS_PROP_SHARESMB, smbshareopts,
- sizeof (smbshareopts), &source, smbsourcestr,
- ZFS_MAXPROPLEN, B_FALSE) == 0 &&
- strcmp(smbshareopts, "off") != 0) {
- if (source & ZPROP_SRC_INHERITED)
- smb_inherited = B_TRUE;
- else
- smb = B_TRUE;
- }
+ /*
+ * If the mountpoint is already shared, it must be a
+ * non-ZFS share. We want to remove the share from its
+ * parent group and reshare it under ZFS.
+ */
+ share = sa_find_share(handle, mountpoint);
+ if (share != NULL &&
+ (nfs || smb || nfs_inherited || smb_inherited)) {
+ err = sa_remove_share(share);
+ share = NULL;
+ }
+ /*
+ * At this point, we have the information needed to
+ * determine what to do with the share.
+ *
+ * If smb or nfs is set, we have a new sub-group.
+ * If smb_inherit and/or nfs_inherit is set, then
+ * place on an existing sub-group. If both are set,
+ * the existing sub-group is the closest up the tree.
+ */
+ if (nfs || smb) {
/*
- * If the mountpoint is already shared, it must be a
- * non-ZFS share. We want to remove the share from its
- * parent group and reshare it under ZFS.
+ * Non-inherited is the straightforward
+ * case. sa_zfs_process_share handles it
+ * directly. Make sure that if the "other"
+ * protocol is inherited, that we treat it as
+ * non-inherited as well.
*/
- share = sa_find_share(handle, mountpoint);
- if (share != NULL &&
- (nfs || smb || nfs_inherited || smb_inherited)) {
- err = sa_remove_share(share);
- share = NULL;
+ if (nfs || nfs_inherited) {
+ err = sa_zfs_process_share(handle, zfsgroup,
+ share, mountpoint, "nfs",
+ 0, nfsshareopts,
+ nfssourcestr, dataset);
+ share = sa_find_share(handle, mountpoint);
}
-
+ if (smb || smb_inherited) {
+ err = sa_zfs_process_share(handle, zfsgroup,
+ share, mountpoint, "smb",
+ 0, smbshareopts,
+ smbsourcestr, dataset);
+ }
+ } else if (nfs_inherited || smb_inherited) {
+ char *grpdataset;
/*
- * At this point, we have the information needed to
- * determine what to do with the share.
- *
- * If smb or nfs is set, we have a new sub-group.
- * If smb_inherit and/or nfs_inherit is set, then
- * place on an existing sub-group. If both are set,
- * the existing sub-group is the closest up the tree.
+ * If we only have inherited groups, it is
+ * important to find the closer of the two if
+ * the protocols are set at different
+ * levels. The closest sub-group is the one we
+ * want to work with.
*/
- if (nfs || smb) {
- /*
- * Non-inherited is the straightforward
- * case. sa_zfs_process_share handles it
- * directly. Make sure that if the "other"
- * protocol is inherited, that we treat it as
- * non-inherited as well.
- */
- if (nfs || nfs_inherited) {
- err = sa_zfs_process_share(handle, zfsgroup,
- share, mountpoint, "nfs",
- 0, nfsshareopts,
- nfssourcestr, dataset);
- share = sa_find_share(handle, mountpoint);
- }
- if (smb || smb_inherited) {
- err = sa_zfs_process_share(handle, zfsgroup,
- share, mountpoint, "smb",
- 0, smbshareopts,
- smbsourcestr, dataset);
- }
- } else if (nfs_inherited || smb_inherited) {
- char *grpdataset;
- /*
- * If we only have inherited groups, it is
- * important to find the closer of the two if
- * the protocols are set at different
- * levels. The closest sub-group is the one we
- * want to work with.
- */
- if (nfs_inherited && smb_inherited) {
- if (strcmp(nfssourcestr, smbsourcestr) <= 0)
- grpdataset = nfssourcestr;
- else
- grpdataset = smbsourcestr;
- } else if (nfs_inherited) {
+ if (nfs_inherited && smb_inherited) {
+ if (strcmp(nfssourcestr, smbsourcestr) <= 0)
grpdataset = nfssourcestr;
- } else if (smb_inherited) {
+ else
grpdataset = smbsourcestr;
- }
- if (nfs_inherited) {
- err = sa_zfs_process_share(handle, zfsgroup,
- share, mountpoint, "nfs",
- ZPROP_SRC_INHERITED, nfsshareopts,
- grpdataset, dataset);
- share = sa_find_share(handle, mountpoint);
- }
- if (smb_inherited) {
- err = sa_zfs_process_share(handle, zfsgroup,
- share, mountpoint, "smb",
- ZPROP_SRC_INHERITED, smbshareopts,
- grpdataset, dataset);
- }
+ } else if (nfs_inherited) {
+ grpdataset = nfssourcestr;
+ } else if (smb_inherited) {
+ grpdataset = smbsourcestr;
+ }
+ if (nfs_inherited) {
+ err = sa_zfs_process_share(handle, zfsgroup,
+ share, mountpoint, "nfs",
+ ZPROP_SRC_INHERITED, nfsshareopts,
+ grpdataset, dataset);
+ share = sa_find_share(handle, mountpoint);
+ }
+ if (smb_inherited) {
+ err = sa_zfs_process_share(handle, zfsgroup,
+ share, mountpoint, "smb",
+ ZPROP_SRC_INHERITED, smbshareopts,
+ grpdataset, dataset);
}
}
+ return (err);
+}
+
+/*
+ * Handles preparing generic objects such as the libzfs handle and group for
+ * sa_get_one_zfs_share, sa_get_zfs_share_for_name, and sa_get_zfs_shares.
+ */
+static int
+prep_zfs_handle_and_group(sa_handle_t handle, char *groupname,
+ libzfs_handle_t **zfs_libhandle, sa_group_t *zfsgroup, int *err)
+{
+ /*
+ * If we can't access libzfs, don't bother doing anything.
+ */
+ *zfs_libhandle = ((sa_handle_impl_t)handle)->zfs_libhandle;
+ if (*zfs_libhandle == NULL)
+ return (SA_SYSTEM_ERR);
+
+ *zfsgroup = find_or_create_group(handle, groupname, NULL, err);
+ return (SA_OK);
+}
+
+/*
+ * The O.G. zfs share preparation function. This initializes all zfs shares for
+ * use with libshare.
+ */
+int
+sa_get_zfs_shares(sa_handle_t handle, char *groupname)
+{
+ sa_group_t zfsgroup;
+ zfs_handle_t **zlist;
+ size_t count = 0;
+ libzfs_handle_t *zfs_libhandle;
+ int err;
+
+ if ((err = prep_zfs_handle_and_group(handle, groupname, &zfs_libhandle,
+ &zfsgroup, &err)) != SA_OK) {
+ return (err);
+ }
+ /* Not an error, this could be a legacy condition */
+ if (zfsgroup == NULL)
+ return (SA_OK);
+
+ /*
+ * need to walk the mounted ZFS pools and datasets to
+ * find shares that are possible.
+ */
+ get_all_filesystems((sa_handle_impl_t)handle, &zlist, &count);
+ qsort(zlist, count, sizeof (void *), mountpoint_compare);
+
+ for (int i = 0; i < count; i++) {
+ err = sa_get_zfs_share_common(handle, zlist[i], NULL, zfsgroup);
+ }
/*
* Don't need to free the "zlist" variable since it is only a
* pointer to a cached value that will be freed when
@@ -950,6 +976,73 @@ sa_get_zfs_shares(sa_handle_t handle, char *groupname)
return (err);
}
+/*
+ * Initializes only the handles specified in the sharearg for use with libshare.
+ * This is used as a performance optimization relative to sa_get_zfs_shares.
+ */
+int
+sa_get_one_zfs_share(sa_handle_t handle, char *groupname,
+ sa_init_selective_arg_t *sharearg, char ***paths, size_t *paths_len)
+{
+ sa_group_t zfsgroup;
+ libzfs_handle_t *zfs_libhandle;
+ int err;
+
+ if ((err = prep_zfs_handle_and_group(handle, groupname, &zfs_libhandle,
+ &zfsgroup, &err)) != SA_OK) {
+ return (err);
+ }
+ /* Not an error, this could be a legacy condition */
+ if (zfsgroup == NULL)
+ return (SA_OK);
+
+ *paths_len = sharearg->zhandle_len;
+ *paths = malloc(sizeof (char *) * (*paths_len));
+ for (int i = 0; i < sharearg->zhandle_len; ++i) {
+ zfs_handle_t *fs_handle =
+ ((zfs_handle_t **)(sharearg->zhandle_arr))[i];
+ if (fs_handle == NULL) {
+ return (SA_SYSTEM_ERR);
+ }
+ (*paths)[i] = malloc(sizeof (char) * ZFS_MAXPROPLEN);
+ err |= sa_get_zfs_share_common(handle, fs_handle, (*paths)[i],
+ zfsgroup);
+ }
+ return (err);
+}
+
+/*
+ * Initializes only the share with the specified sharename for use with
+ * libshare.
+ */
+int
+sa_get_zfs_share_for_name(sa_handle_t handle, char *groupname,
+ const char *sharename, char *outpath)
+{
+ sa_group_t zfsgroup;
+ libzfs_handle_t *zfs_libhandle;
+ int err;
+
+ if ((err = prep_zfs_handle_and_group(handle, groupname, &zfs_libhandle,
+ &zfsgroup, &err)) != SA_OK) {
+ return (err);
+ }
+ /* Not an error, this could be a legacy condition */
+ if (zfsgroup == NULL)
+ return (SA_OK);
+
+ zfs_handle_t *fs_handle = zfs_open(zfs_libhandle,
+ sharename + strspn(sharename, "/"), ZFS_TYPE_DATASET);
+ if (fs_handle == NULL)
+ return (SA_SYSTEM_ERR);
+
+ err = sa_get_zfs_share_common(handle, fs_handle, outpath, zfsgroup);
+ zfs_close(fs_handle);
+ return (err);
+}
+
+
+
#define COMMAND "/usr/sbin/zfs"
/*
diff --git a/usr/src/lib/libshare/common/libsharecore.c b/usr/src/lib/libshare/common/libsharecore.c
index 87657a13bf..b8bd1156b1 100644
--- a/usr/src/lib/libshare/common/libsharecore.c
+++ b/usr/src/lib/libshare/common/libsharecore.c
@@ -1433,146 +1433,221 @@ err:
}
/*
- * parse_sharetab(handle)
+ * parse_sharetab_impl(handle, tmplist, lgroup)
*
* Read the /etc/dfs/sharetab file and see which entries don't exist
* in the repository. These shares are marked transient. We also need
* to see if they are ZFS shares since ZFS bypasses the SMF
* repository.
+ *
+ * The return value is used to contribute to values indicating if it is a legacy
+ * share. Right now this is 0 or 1, but as multiple systems become legacy that
+ * could change.
*/
-int
-parse_sharetab(sa_handle_t handle)
+static int
+parse_sharetab_impl(sa_handle_t handle, xfs_sharelist_t *tmplist,
+ sa_group_t lgroup)
{
- xfs_sharelist_t *list, *tmplist;
int err = 0;
sa_share_t share;
sa_group_t group;
- sa_group_t lgroup;
char *groupname;
int legacy = 0;
char shareopts[MAXNAMLEN];
- list = get_share_list(&err);
- if (list == NULL)
- return (legacy);
-
- lgroup = sa_get_group(handle, "default");
+ group = NULL;
+ share = sa_find_share(handle, tmplist->path);
+ if (share != NULL) {
+ /*
+ * If this is a legacy share, mark as shared so we only update
+ * sharetab appropriately. We also keep the sharetab options in
+ * order to display for legacy share with no arguments.
+ */
+ set_node_attr(share, "shared", "true");
+ (void) snprintf(shareopts, MAXNAMLEN, "shareopts-%s",
+ tmplist->fstype);
+ set_node_attr(share, shareopts, tmplist->options);
+ return (1);
+ }
- for (tmplist = list; tmplist != NULL; tmplist = tmplist->next) {
- group = NULL;
- share = sa_find_share(handle, tmplist->path);
- if (share != NULL) {
+ /*
+ * This share is transient so needs to be added. Initially, this will be
+ * under default(legacy) unless it is a ZFS share. If zfs, we need a zfs
+ * group.
+ */
+ if (tmplist->resource != NULL &&
+ (groupname = strchr(tmplist->resource, '@')) != NULL) {
+ /* There is a defined group */
+ *groupname++ = '\0';
+ group = sa_get_group(handle, groupname);
+ if (group != NULL) {
+ share = _sa_add_share(group, tmplist->path,
+ SA_SHARE_TRANSIENT, &err,
+ (uint64_t)SA_FEATURE_NONE);
+ } else {
/*
- * If this is a legacy share, mark as shared so we
- * only update sharetab appropriately. We also keep
- * the sharetab options in order to display for legacy
- * share with no arguments.
+ * While this case shouldn't occur very often, it does
+ * occur out of a "zfs set sharenfs=off" when the
+ * dataset is also set to canmount=off. A warning will
+ * then cause the zfs command to abort. Since we add it
+ * to the default list, everything works properly anyway
+ * and the library doesn't need to give a warning.
*/
- set_node_attr(share, "shared", "true");
- (void) snprintf(shareopts, MAXNAMLEN, "shareopts-%s",
- tmplist->fstype);
- set_node_attr(share, shareopts, tmplist->options);
- continue;
+ share = _sa_add_share(lgroup,
+ tmplist->path, SA_SHARE_TRANSIENT,
+ &err, (uint64_t)SA_FEATURE_NONE);
}
-
- /*
- * This share is transient so needs to be
- * added. Initially, this will be under
- * default(legacy) unless it is a ZFS
- * share. If zfs, we need a zfs group.
- */
- if (tmplist->resource != NULL &&
- (groupname = strchr(tmplist->resource, '@')) != NULL) {
- /* There is a defined group */
- *groupname++ = '\0';
- group = sa_get_group(handle, groupname);
+ } else {
+ if (sa_zfs_is_shared(handle, tmplist->path)) {
+ group = sa_get_group(handle, "zfs");
+ if (group == NULL) {
+ group = sa_create_group(handle,
+ "zfs", &err);
+ if (group == NULL &&
+ err == SA_NO_PERMISSION) {
+ group = _sa_create_group(
+ (sa_handle_impl_t)
+ handle,
+ "zfs");
+ }
+ if (group != NULL) {
+ (void) sa_create_optionset(
+ group, tmplist->fstype);
+ (void) sa_set_group_attr(group,
+ "zfs", "true");
+ }
+ }
if (group != NULL) {
- share = _sa_add_share(group, tmplist->path,
- SA_SHARE_TRANSIENT, &err,
- (uint64_t)SA_FEATURE_NONE);
- } else {
- /*
- * While this case shouldn't
- * occur very often, it does
- * occur out of a "zfs set
- * sharenfs=off" when the
- * dataset is also set to
- * canmount=off. A warning
- * will then cause the zfs
- * command to abort. Since we
- * add it to the default list,
- * everything works properly
- * anyway and the library
- * doesn't need to give a
- * warning.
- */
- share = _sa_add_share(lgroup,
+ share = _sa_add_share(group,
tmplist->path, SA_SHARE_TRANSIENT,
&err, (uint64_t)SA_FEATURE_NONE);
}
} else {
- if (sa_zfs_is_shared(handle, tmplist->path)) {
- group = sa_get_group(handle, "zfs");
- if (group == NULL) {
- group = sa_create_group(handle,
- "zfs", &err);
- if (group == NULL &&
- err == SA_NO_PERMISSION) {
- group = _sa_create_group(
- (sa_handle_impl_t)
- handle,
- "zfs");
- }
- if (group != NULL) {
- (void) sa_create_optionset(
- group, tmplist->fstype);
- (void) sa_set_group_attr(group,
- "zfs", "true");
- }
- }
- if (group != NULL) {
- share = _sa_add_share(group,
- tmplist->path, SA_SHARE_TRANSIENT,
- &err, (uint64_t)SA_FEATURE_NONE);
- }
- } else {
- share = _sa_add_share(lgroup, tmplist->path,
- SA_SHARE_TRANSIENT, &err,
- (uint64_t)SA_FEATURE_NONE);
- }
+ share = _sa_add_share(lgroup, tmplist->path,
+ SA_SHARE_TRANSIENT, &err,
+ (uint64_t)SA_FEATURE_NONE);
}
- if (share == NULL)
- (void) printf(dgettext(TEXT_DOMAIN,
- "Problem with transient: %s\n"), sa_errorstr(err));
- if (share != NULL)
- set_node_attr(share, "shared", "true");
- if (err == SA_OK) {
- if (tmplist->options != NULL &&
- strlen(tmplist->options) > 0) {
- (void) sa_parse_legacy_options(share,
- tmplist->options, tmplist->fstype);
- }
- if (tmplist->resource != NULL &&
- strcmp(tmplist->resource, "-") != 0)
- set_node_attr(share, "resource",
- tmplist->resource);
- if (tmplist->description != NULL) {
- xmlNodePtr node;
- node = xmlNewChild((xmlNodePtr)share, NULL,
- (xmlChar *)"description", NULL);
- xmlNodeSetContent(node,
- (xmlChar *)tmplist->description);
+ }
+ if (share == NULL)
+ (void) printf(dgettext(TEXT_DOMAIN,
+ "Problem with transient: %s\n"), sa_errorstr(err));
+ if (share != NULL)
+ set_node_attr(share, "shared", "true");
+ if (err == SA_OK) {
+ if (tmplist->options != NULL &&
+ strlen(tmplist->options) > 0) {
+ (void) sa_parse_legacy_options(share,
+ tmplist->options, tmplist->fstype);
+ }
+ if (tmplist->resource != NULL &&
+ strcmp(tmplist->resource, "-") != 0)
+ set_node_attr(share, "resource",
+ tmplist->resource);
+ if (tmplist->description != NULL) {
+ xmlNodePtr node;
+ node = xmlNewChild((xmlNodePtr)share, NULL,
+ (xmlChar *)"description", NULL);
+ xmlNodeSetContent(node,
+ (xmlChar *)tmplist->description);
+ }
+ legacy = 1;
+ }
+ return (legacy);
+}
+
+/*
+ * Given an array of paths, parses the sharetab in /etc/dfs/sharetab looking for
+ * matches to each path that could be transients from that file.
+ *
+ * parse_sharetab_impl has more information on what exactly it is looking for.
+ */
+int
+parse_sharetab_for_paths(sa_handle_t handle, char **paths, size_t paths_len)
+{
+ int err = 0;
+ int legacy = 0;
+ sa_group_t lgroup;
+ xfs_sharelist_t *list = get_share_list(&err);
+
+ if (list == NULL)
+ return (legacy);
+
+ lgroup = sa_get_group(handle, "default");
+ for (int i = 0; i < paths_len; ++i) {
+ xfs_sharelist_t *tmplist;
+
+ for (tmplist = list; tmplist != NULL; tmplist = tmplist->next) {
+ if (strcmp(tmplist->path, paths[i]) == 0) {
+ break;
}
- legacy = 1;
}
+ if (tmplist == NULL) {
+ continue;
+ }
+
+ legacy = parse_sharetab_impl(handle, tmplist, lgroup);
+
+ }
+ dfs_free_list(list);
+ return (legacy);
+}
+
+/*
+ * Runs parse_sharetab_impl on all the different share lists on the system.
+ */
+int
+parse_sharetab(sa_handle_t handle)
+{
+ int err = 0;
+ int legacy = 0;
+ sa_group_t lgroup;
+ xfs_sharelist_t *list = get_share_list(&err);
+
+ list = get_share_list(&err);
+ if (list == NULL)
+ return (legacy);
+
+ lgroup = sa_get_group(handle, "default");
+
+ for (xfs_sharelist_t *tmplist = list; tmplist != NULL;
+ tmplist = tmplist->next) {
+ legacy |= parse_sharetab_impl(handle, tmplist, lgroup);
}
dfs_free_list(list);
return (legacy);
}
/*
- * Get the transient shares from the sharetab (or other) file. since
+ * This is the same as gettransients except when parsing sharetab the entries
+ * are only processed if the path matches an element of paths.
+ */
+int
+get_one_transient(sa_handle_impl_t ihandle, xmlNodePtr *root, char **paths,
+ size_t paths_len)
+{
+ int legacy = 0;
+ char **protocols = NULL;
+
+ if (root != NULL) {
+ if (*root == NULL)
+ *root = xmlNewNode(NULL, (xmlChar *)"sharecfg");
+ if (*root != NULL) {
+ legacy = parse_sharetab_for_paths(ihandle, paths,
+ paths_len);
+ int numproto = sa_get_protocols(&protocols);
+ for (int i = 0; i < numproto; i++)
+ legacy |= sa_proto_get_transients(
+ (sa_handle_t)ihandle, protocols[i]);
+ if (protocols != NULL)
+ free(protocols);
+ }
+ }
+ return (legacy);
+}
+
+/*
+ * Get the transient shares from the sharetab (or other) file. Since
* these are transient, they only appear in the working file and not
* in a repository.
*/
@@ -2183,7 +2258,8 @@ sa_needs_refresh(sa_handle_t handle)
uint64_t tstamp;
scf_simple_prop_t *prop;
- if (handle == NULL)
+ if (handle == NULL || implhandle->sa_service &
+ (SA_INIT_ONE_SHARE_FROM_NAME | SA_INIT_ONE_SHARE_FROM_HANDLE))
return (B_TRUE);
/*
diff --git a/usr/src/lib/libshare/common/mapfile-vers b/usr/src/lib/libshare/common/mapfile-vers
index 7314caf827..de74d62038 100644
--- a/usr/src/lib/libshare/common/mapfile-vers
+++ b/usr/src/lib/libshare/common/mapfile-vers
@@ -20,6 +20,7 @@
#
#
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2016 by Delphix. All rights reserved.
#
#
@@ -112,6 +113,7 @@ SYMBOL_VERSION SUNWprivate {
sa_get_next_security;
sa_get_protocol_status;
sa_init;
+ sa_init_arg;
sa_find_share;
sa_set_protocol_property;
sa_fini;
diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h
index 5b823c9525..11b4d68721 100644
--- a/usr/src/lib/libzfs/common/libzfs.h
+++ b/usr/src/lib/libzfs/common/libzfs.h
@@ -785,6 +785,17 @@ extern int zpool_fru_set(zpool_handle_t *, uint64_t, const char *);
extern int zfs_get_hole_count(const char *, uint64_t *, uint64_t *);
+/* Allow consumers to initialize libshare externally for optimal performance */
+extern int zfs_init_libshare_arg(libzfs_handle_t *, int, void *);
+/*
+ * For most consumers, zfs_init_libshare_arg is sufficient on its own, and
+ * zfs_uninit_libshare is unnecessary. zfs_uninit_libshare should only be called
+ * if the caller has already initialized libshare for one set of zfs handles,
+ * and wishes to share or unshare filesystems outside of that set. In that case,
+ * the caller should uninitialize libshare, and then re-initialize it with the
+ * new handles being shared or unshared.
+ */
+extern void zfs_uninit_libshare(libzfs_handle_t *);
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libzfs/common/libzfs_changelist.c b/usr/src/lib/libzfs/common/libzfs_changelist.c
index 04666cce99..af5cb35f9d 100644
--- a/usr/src/lib/libzfs/common/libzfs_changelist.c
+++ b/usr/src/lib/libzfs/common/libzfs_changelist.c
@@ -24,7 +24,7 @@
* Use is subject to license terms.
*
* Portions Copyright 2007 Ramprakash Jelari
- * Copyright (c) 2014, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2014, 2016 by Delphix. All rights reserved.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
*/
@@ -162,6 +162,9 @@ changelist_postfix(prop_changelist_t *clp)
char shareopts[ZFS_MAXPROPLEN];
int errors = 0;
libzfs_handle_t *hdl;
+ size_t num_datasets = 0, i;
+ zfs_handle_t **zhandle_arr;
+ sa_init_selective_arg_t sharearg;
/*
* If we're changing the mountpoint, attempt to destroy the underlying
@@ -186,8 +189,31 @@ changelist_postfix(prop_changelist_t *clp)
hdl = cn->cn_handle->zfs_hdl;
assert(hdl != NULL);
zfs_uninit_libshare(hdl);
- }
+ /*
+ * For efficiencies sake, we initialize libshare for only a few
+ * shares (the ones affected here). Future initializations in
+ * this process should just use the cached initialization.
+ */
+ for (cn = uu_list_last(clp->cl_list); cn != NULL;
+ cn = uu_list_prev(clp->cl_list, cn)) {
+ num_datasets++;
+ }
+
+ zhandle_arr = zfs_alloc(hdl,
+ num_datasets * sizeof (zfs_handle_t *));
+ for (i = 0, cn = uu_list_last(clp->cl_list); cn != NULL;
+ cn = uu_list_prev(clp->cl_list, cn)) {
+ zhandle_arr[i++] = cn->cn_handle;
+ zfs_refresh_properties(cn->cn_handle);
+ }
+ assert(i == num_datasets);
+ sharearg.zhandle_arr = zhandle_arr;
+ sharearg.zhandle_len = num_datasets;
+ errors = zfs_init_libshare_arg(hdl, SA_INIT_SHARE_API_SELECTIVE,
+ &sharearg);
+ free(zhandle_arr);
+ }
/*
* We walk the datasets in reverse, because we want to mount any parent
* datasets before mounting the children. We walk all datasets even if
@@ -212,8 +238,6 @@ changelist_postfix(prop_changelist_t *clp)
continue;
cn->cn_needpost = B_FALSE;
- zfs_refresh_properties(cn->cn_handle);
-
if (ZFS_IS_VOLUME(cn->cn_handle))
continue;
diff --git a/usr/src/lib/libzfs/common/libzfs_impl.h b/usr/src/lib/libzfs/common/libzfs_impl.h
index 1581fa656a..e45aed3d29 100644
--- a/usr/src/lib/libzfs/common/libzfs_impl.h
+++ b/usr/src/lib/libzfs/common/libzfs_impl.h
@@ -206,7 +206,6 @@ void namespace_clear(libzfs_handle_t *);
*/
extern int zfs_init_libshare(libzfs_handle_t *, int);
-extern void zfs_uninit_libshare(libzfs_handle_t *);
extern int zfs_parse_options(char *, zfs_share_proto_t);
extern int zfs_unshare_proto(zfs_handle_t *,
diff --git a/usr/src/lib/libzfs/common/libzfs_mount.c b/usr/src/lib/libzfs/common/libzfs_mount.c
index d1419fb3a8..ae6df7fa16 100644
--- a/usr/src/lib/libzfs/common/libzfs_mount.c
+++ b/usr/src/lib/libzfs/common/libzfs_mount.c
@@ -567,6 +567,7 @@ zfs_is_shared_smb(zfs_handle_t *zhp, char **where)
*/
static sa_handle_t (*_sa_init)(int);
+static sa_handle_t (*_sa_init_arg)(int, void *);
static void (*_sa_fini)(sa_handle_t);
static sa_share_t (*_sa_find_share)(sa_handle_t, char *);
static int (*_sa_enable_share)(sa_share_t, char *);
@@ -606,6 +607,8 @@ _zfs_init_libshare(void)
if ((libshare = dlopen(path, RTLD_LAZY | RTLD_GLOBAL)) != NULL) {
_sa_init = (sa_handle_t (*)(int))dlsym(libshare, "sa_init");
+ _sa_init_arg = (sa_handle_t (*)(int, void *))dlsym(libshare,
+ "sa_init_arg");
_sa_fini = (void (*)(sa_handle_t))dlsym(libshare, "sa_fini");
_sa_find_share = (sa_share_t (*)(sa_handle_t, char *))
dlsym(libshare, "sa_find_share");
@@ -625,14 +628,15 @@ _zfs_init_libshare(void)
char *, char *))dlsym(libshare, "sa_zfs_process_share");
_sa_update_sharetab_ts = (void (*)(sa_handle_t))
dlsym(libshare, "sa_update_sharetab_ts");
- if (_sa_init == NULL || _sa_fini == NULL ||
- _sa_find_share == NULL || _sa_enable_share == NULL ||
- _sa_disable_share == NULL || _sa_errorstr == NULL ||
- _sa_parse_legacy_options == NULL ||
+ if (_sa_init == NULL || _sa_init_arg == NULL ||
+ _sa_fini == NULL || _sa_find_share == NULL ||
+ _sa_enable_share == NULL || _sa_disable_share == NULL ||
+ _sa_errorstr == NULL || _sa_parse_legacy_options == NULL ||
_sa_needs_refresh == NULL || _sa_get_zfs_handle == NULL ||
_sa_zfs_process_share == NULL ||
_sa_update_sharetab_ts == NULL) {
_sa_init = NULL;
+ _sa_init_arg = NULL;
_sa_fini = NULL;
_sa_disable_share = NULL;
_sa_enable_share = NULL;
@@ -655,8 +659,8 @@ _zfs_init_libshare(void)
* service value is which part(s) of the API to initialize and is a
* direct map to the libshare sa_init(service) interface.
*/
-int
-zfs_init_libshare(libzfs_handle_t *zhandle, int service)
+static int
+zfs_init_libshare_impl(libzfs_handle_t *zhandle, int service, void *arg)
{
if (_sa_init == NULL)
return (SA_CONFIG_ERR);
@@ -672,17 +676,29 @@ zfs_init_libshare(libzfs_handle_t *zhandle, int service)
if (_sa_needs_refresh != NULL &&
_sa_needs_refresh(zhandle->libzfs_sharehdl)) {
zfs_uninit_libshare(zhandle);
- zhandle->libzfs_sharehdl = _sa_init(service);
+ zhandle->libzfs_sharehdl = _sa_init_arg(service, arg);
}
if (zhandle && zhandle->libzfs_sharehdl == NULL)
- zhandle->libzfs_sharehdl = _sa_init(service);
+ zhandle->libzfs_sharehdl = _sa_init_arg(service, arg);
if (zhandle->libzfs_sharehdl == NULL)
return (SA_NO_MEMORY);
return (SA_OK);
}
+int
+zfs_init_libshare(libzfs_handle_t *zhandle, int service)
+{
+ return (zfs_init_libshare_impl(zhandle, service, NULL));
+}
+
+int
+zfs_init_libshare_arg(libzfs_handle_t *zhandle, int service, void *arg)
+{
+ return (zfs_init_libshare_impl(zhandle, service, arg));
+}
+
/*
* zfs_uninit_libshare(zhandle)
@@ -787,8 +803,8 @@ zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto)
ZFS_MAXPROPLEN, B_FALSE) != 0 ||
strcmp(shareopts, "off") == 0)
continue;
-
- ret = zfs_init_libshare(hdl, SA_INIT_SHARE_API);
+ ret = zfs_init_libshare_arg(hdl, SA_INIT_ONE_SHARE_FROM_HANDLE,
+ zhp);
if (ret != SA_OK) {
(void) zfs_error_fmt(hdl, EZFS_SHARENFSFAILED,
dgettext(TEXT_DOMAIN, "cannot share '%s': %s"),
@@ -882,6 +898,7 @@ unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint,
sa_share_t share;
int err;
char *mntpt;
+
/*
* Mountpoint could get trashed if libshare calls getmntany
* which it does during API initialization, so strdup the
@@ -889,8 +906,14 @@ unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint,
*/
mntpt = zfs_strdup(hdl, mountpoint);
- /* make sure libshare initialized */
- if ((err = zfs_init_libshare(hdl, SA_INIT_SHARE_API)) != SA_OK) {
+ /*
+ * make sure libshare initialized, initialize everything because we
+ * don't know what other unsharing may happen later. Functions up the
+ * stack are allowed to initialize instead a subset of shares at the
+ * time the set is known.
+ */
+ if ((err = zfs_init_libshare_arg(hdl, SA_INIT_ONE_SHARE_FROM_NAME,
+ (void *)name)) != SA_OK) {
free(mntpt); /* don't need the copy anymore */
return (zfs_error_fmt(hdl, EZFS_UNSHARENFSFAILED,
dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"),
@@ -1222,6 +1245,7 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
int i;
int ret = -1;
int flags = (force ? MS_FORCE : 0);
+ sa_init_selective_arg_t sharearg;
namelen = strlen(zhp->zpool_name);
@@ -1296,6 +1320,12 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
* At this point, we have the entire list of filesystems, so sort it by
* mountpoint.
*/
+ sharearg.zhandle_arr = datasets;
+ sharearg.zhandle_len = used;
+ ret = zfs_init_libshare_arg(hdl, SA_INIT_SHARE_API_SELECTIVE,
+ &sharearg);
+ if (ret != 0)
+ goto out;
qsort(mountpoints, used, sizeof (char *), mountpoint_compare);
/*
diff --git a/usr/src/lib/libzfs/common/mapfile-vers b/usr/src/lib/libzfs/common/mapfile-vers
index ffc32be5d3..8feff24f87 100644
--- a/usr/src/lib/libzfs/common/mapfile-vers
+++ b/usr/src/lib/libzfs/common/mapfile-vers
@@ -90,6 +90,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zfs_handle_dup;
zfs_history_event_names;
zfs_hold;
+ zfs_init_libshare_arg;
zfs_is_mounted;
zfs_is_shared;
zfs_is_shared_nfs;
@@ -164,6 +165,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zfs_spa_version_map;
zfs_standard_error;
zfs_type_to_name;
+ zfs_uninit_libshare;
zfs_unmount;
zfs_unmountall;
zfs_unshare;
diff --git a/usr/src/man/man1m/zdb.1m b/usr/src/man/man1m/zdb.1m
index 44c1b5848f..1bd47bbfa4 100644
--- a/usr/src/man/man1m/zdb.1m
+++ b/usr/src/man/man1m/zdb.1m
@@ -22,7 +22,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl AbcdDFGhiLMPsvX
-.Op Fl e Op Fl p Ar path ...
+.Op Fl e Oo Fl V Oc Op Fl p Ar path ...
.Op Fl I Ar inflight I/Os
.Oo Fl o Ar var Ns = Ns Ar value Oc Ns ...
.Op Fl t Ar txg
@@ -31,7 +31,7 @@
.Op Ar poolname Op Ar object ...
.Nm
.Op Fl AdiPv
-.Op Fl e Op Fl p Ar path ...
+.Op Fl e Oo Fl V Oc Op Fl p Ar path ...
.Op Fl U Ar cache
.Ar dataset Op Ar object ...
.Nm
@@ -45,8 +45,8 @@
.Nm
.Fl m
.Op Fl AFLPX
+.Op Fl e Oo Fl V Oc Op Fl p Ar path ...
.Op Fl t Ar txg
-.Op Fl e Op Fl p Ar path ...
.Op Fl U Ar cache
.Ar poolname Op Ar vdev Op Ar metaslab ...
.Nm
@@ -55,13 +55,13 @@
.Nm
.Fl R
.Op Fl A
-.Op Fl e Op Fl p Ar path ...
+.Op Fl e Oo Fl V Oc Op Fl p Ar path ...
.Op Fl U Ar cache
.Ar poolname vdev Ns : Ns Ar offset Ns : Ns Ar size Ns Op : Ns Ar flags
.Nm
.Fl S
.Op Fl AP
-.Op Fl e Op Fl p Ar path ...
+.Op Fl e Oo Fl V Oc Op Fl p Ar path ...
.Op Fl U Ar cache
.Ar poolname
.Sh DESCRIPTION
@@ -316,6 +316,11 @@ Use a cache file other than
.It Fl v
Enable verbosity.
Specify multiple times for increased verbosity.
+.It Fl V
+Attempt verbatim import.
+This mimics the behavior of the kernel when loading a pool from a cachefile.
+Only usable with
+.Fl e .
.It Fl X
Attempt
.Qq extreme
diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zdb/zdb_001_neg.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zdb/zdb_001_neg.ksh
index 9776447097..da818b49bc 100644
--- a/usr/src/test/zfs-tests/tests/functional/cli_root/zdb/zdb_001_neg.ksh
+++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zdb/zdb_001_neg.ksh
@@ -59,7 +59,7 @@ set -A args "create" "add" "destroy" "import fakepool" \
"-a" "-f" "-g" "-h" "-j" "-k" "-m" "-n" "-o" "-p" \
"-p /tmp" "-r" "-t" "-w" "-x" "-y" "-z" \
"-D" "-E" "-G" "-H" "-I" "-J" "-K" "-M" \
- "-N" "-Q" "-R" "-S" "-T" "-V" "-W" "-Y" "-Z"
+ "-N" "-Q" "-R" "-S" "-T" "-W" "-Y" "-Z"
log_assert "Execute zdb using invalid parameters."
diff --git a/usr/src/test/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh b/usr/src/test/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh
index 84e82f9eb8..497529f94f 100644
--- a/usr/src/test/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh
+++ b/usr/src/test/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh
@@ -331,7 +331,7 @@ function scan_state { #state-file
if [[ $op == "-" ]]; then
log_note "No operation specified"
else
- export __ZFS_POOL_RESTRICT="$TESTPOOL"
+ export __ZFS_POOL_RESTRICT="TESTPOOL"
log_must zfs unmount -a
unset __ZFS_POOL_RESTRICT
diff --git a/usr/src/uts/common/fs/smbsrv/smb_server.c b/usr/src/uts/common/fs/smbsrv/smb_server.c
index 176a35aae7..64699cc799 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_server.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_server.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2017 by Delphix. All rights reserved.
*/
/*
@@ -362,6 +363,7 @@ smb_server_g_fini(void)
smb_node_fini();
smb_mbc_fini();
+ smb_codepage_fini();
smb_kshare_g_fini();
smb_fem_fini();
diff --git a/usr/src/uts/common/fs/zfs/dsl_pool.c b/usr/src/uts/common/fs/zfs/dsl_pool.c
index a8dc1e818c..38b8390f93 100644
--- a/usr/src/uts/common/fs/zfs/dsl_pool.c
+++ b/usr/src/uts/common/fs/zfs/dsl_pool.c
@@ -133,9 +133,6 @@ uint64_t zfs_delay_scale = 1000 * 1000 * 1000 / 2000;
*/
int zfs_sync_taskq_batch_pct = 75;
-hrtime_t zfs_throttle_delay = MSEC2NSEC(10);
-hrtime_t zfs_throttle_resolution = MSEC2NSEC(10);
-
int
dsl_pool_open_special_dir(dsl_pool_t *dp, const char *name, dsl_dir_t **ddp)
{
diff --git a/usr/src/uts/common/fs/zfs/sa.c b/usr/src/uts/common/fs/zfs/sa.c
index 2fc6acacf0..1b8ee58880 100644
--- a/usr/src/uts/common/fs/zfs/sa.c
+++ b/usr/src/uts/common/fs/zfs/sa.c
@@ -22,7 +22,7 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Portions Copyright 2011 iXsystems, Inc
- * Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+ * Copyright (c) 2013, 2017 by Delphix. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
* Copyright (c) 2015 Joyent, Inc. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
@@ -132,8 +132,8 @@ typedef void (sa_iterfunc_t)(void *hdr, void *addr, sa_attr_type_t,
static int sa_build_index(sa_handle_t *hdl, sa_buf_type_t buftype);
static void sa_idx_tab_hold(objset_t *os, sa_idx_tab_t *idx_tab);
-static void *sa_find_idx_tab(objset_t *os, dmu_object_type_t bonustype,
- void *data);
+static sa_idx_tab_t *sa_find_idx_tab(objset_t *os, dmu_object_type_t bonustype,
+ sa_hdr_phys_t *hdr);
static void sa_idx_tab_rele(objset_t *os, void *arg);
static void sa_copy_data(sa_data_locator_t *func, void *start, void *target,
int buflen);
@@ -1487,11 +1487,10 @@ sa_lookup_uio(sa_handle_t *hdl, sa_attr_type_t attr, uio_t *uio)
}
#endif
-void *
-sa_find_idx_tab(objset_t *os, dmu_object_type_t bonustype, void *data)
+static sa_idx_tab_t *
+sa_find_idx_tab(objset_t *os, dmu_object_type_t bonustype, sa_hdr_phys_t *hdr)
{
sa_idx_tab_t *idx_tab;
- sa_hdr_phys_t *hdr = (sa_hdr_phys_t *)data;
sa_os_t *sa = os->os_sa;
sa_lot_t *tb, search;
avl_index_t loc;
diff --git a/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
index c3cf3bc6d5..6403fb3ea7 100644
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
@@ -3070,6 +3070,9 @@ zfs_fill_zplprops_impl(objset_t *os, uint64_t zplver,
ASSERT(zplprops != NULL);
+ if (os != NULL && os->os_phys->os_type != DMU_OST_ZFS)
+ return (SET_ERROR(EINVAL));
+
/*
* Pull out creator prop choices, if any.
*/
diff --git a/usr/src/uts/common/fs/zfs/zfs_vfsops.c b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
index 8b4cde4bed..7478a4ea6b 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
@@ -2255,8 +2255,10 @@ zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
else
pname = zfs_prop_to_name(prop);
- if (os != NULL)
+ if (os != NULL) {
+ ASSERT3U(os->os_phys->os_type, ==, DMU_OST_ZFS);
error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value);
+ }
if (error == ENOENT) {
/* No value set, use the default value */
diff --git a/usr/src/uts/common/io/virtio/virtio.c b/usr/src/uts/common/io/virtio/virtio.c
index adaab62aec..adcd14f2b5 100644
--- a/usr/src/uts/common/io/virtio/virtio.c
+++ b/usr/src/uts/common/io/virtio/virtio.c
@@ -22,6 +22,7 @@
/*
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
* Copyright 2012 Alexey Zaytsev <alexey.zaytsev@gmail.com>
+ * Copyright (c) 2016 by Delphix. All rights reserved.
*/
/* Based on the NetBSD virtio driver by Minoura Makoto. */
@@ -644,7 +645,7 @@ virtio_ve_set(struct vq_entry *qe, uint64_t paddr, uint32_t len,
unsigned int
virtio_ve_indirect_available(struct vq_entry *qe)
{
- return (qe->qe_queue->vq_indirect_num - (qe->qe_indirect_next - 1));
+ return (qe->qe_queue->vq_indirect_num - qe->qe_indirect_next);
}
void
diff --git a/usr/src/uts/common/smbsrv/string.h b/usr/src/uts/common/smbsrv/string.h
index 14b9cac8b8..92c4fc91b4 100644
--- a/usr/src/uts/common/smbsrv/string.h
+++ b/usr/src/uts/common/smbsrv/string.h
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2017 by Delphix. All rights reserved.
*/
#ifndef _SMBSRV_STRING_H
@@ -113,6 +114,7 @@ typedef struct smb_codepage {
} smb_codepage_t;
void smb_codepage_init(void);
+void smb_codepage_fini(void);
int smb_isupper(int);
int smb_islower(int);
diff --git a/usr/src/uts/i86pc/os/cpuid.c b/usr/src/uts/i86pc/os/cpuid.c
index 8f4f3694a7..f5541353a4 100644
--- a/usr/src/uts/i86pc/os/cpuid.c
+++ b/usr/src/uts/i86pc/os/cpuid.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
* Copyright 2014 Josef "Jeff" Sipek <jeffpc@josefsipek.net>
*/
@@ -423,9 +423,8 @@ static struct cpuid_info cpuid_info0;
* (loosely defined as "pre-Pentium-4"):
* P6, PII, Mobile PII, PII Xeon, PIII, Mobile PIII, PIII Xeon
*/
-
#define IS_LEGACY_P6(cpi) ( \
- cpi->cpi_family == 6 && \
+ cpi->cpi_family == 6 && \
(cpi->cpi_model == 1 || \
cpi->cpi_model == 3 || \
cpi->cpi_model == 5 || \
@@ -1465,7 +1464,13 @@ cpuid_pass1(cpu_t *cpu, uchar_t *featureset)
xcpuid = 0;
switch (cpi->cpi_vendor) {
case X86_VENDOR_Intel:
- if (IS_NEW_F6(cpi) || cpi->cpi_family >= 0xf)
+ /*
+ * On KVM we know we will have proper support for extended
+ * cpuid.
+ */
+ if (IS_NEW_F6(cpi) || cpi->cpi_family >= 0xf ||
+ (get_hwenv() == HW_KVM && cpi->cpi_family == 6 &&
+ (cpi->cpi_model == 6 || cpi->cpi_model == 2)))
xcpuid++;
break;
case X86_VENDOR_AMD: