Print this page
NEX-16219 pool import performance regression due to repeated libshare initialization
Reviewd by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15937 zpool import performance degradation in filesystem sharing
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-15937 zpool import performance degradation in filesystem sharing
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-5728 Autosync Destination retention policy not being honoured
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
5984 zfs clone should not mount the clone if canmount == noauto
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Justin Gibbs <gibbs@scsiguy.com>
Reviewed by: Richard Elling <Richard.Elling@richardelling.com>
Approved by: Matthew Ahrens <mahrens@delphix.com>
6298 zfs_create_008_neg and zpool_create_023_neg need to be updated for large block support
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: John Kennedy <john.kennedy@delphix.com>
Approved by: Robert Mustacchi <rm@joyent.com>
2605 want to resume interrupted zfs send
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Paul Dagnelie <pcd@delphix.com>
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Xin Li <delphij@freebsd.org>
Reviewed by: Arne Jansen <sensille@gmx.net>
Approved by: Dan McDonald <danmcd@omniti.com>
NEX-4582 update wrc test cases for allow to use write back cache per tree of datasets
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
5960 zfs recv should prefetch indirect blocks
5925 zfs receive -o origin=
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
5745 zfs set allows only one dataset property to be set at a time
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Reviewed by: George Wilson <george@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Bayard Bell <buffer.g.overflow@gmail.com>
Reviewed by: Richard PALO <richard@NetBSD.org>
Reviewed by: Steven Hartland <killing@multiplay.co.uk>
Approved by: Rich Lowe <richlowe@richlowe.net>
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Revert "NEX-4476 WRC: Allow to use write back cache per tree of datasets"
This reverts commit fe97b74444278a6f36fec93179133641296312da.
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
NEX-3669 Faults for fans that don't exist
Reviewed by: Jeffry Molanus <jeffry.molanus@nexenta.com>
NEX-3891 Hide the snapshots that belong to in-kernel autosnap-service
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Alek Pinchuk <alek@nexenta.com>
NEX-3558 KRRP Integration
NEX-1456 Part 2, port FreeBSD patch - new zfs recv options support
4206 history_003_pos relies on exact size of history log and entries
4207 history_008_pos depends on obsolete internal history log message
4208 Typo in zfs_main.c: "posxiuser"
4209 Populate zfstest with the remainder of the STF tests
Reviewed by: Sonu Pillai <sonu.pillai@delphix.com>
Reviewed by: Will Guyette <will.guyette@delphix.com>
Reviewed by: Eric Diven <eric.diven@delphix.com>
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
SUP-642 Regression leading to AD usernames not being displayed... (fix lint)
SUP-642 Regression leading to AD usernames not being displayed by zfs userspace command.
re #8279 rb3915 need a mechanism to notify NMS about ZFS config changes (Opened code)
Bug 10481 - cstyle/lint cleanup
Bug 10481 - Dry run option in 'zfs send' isn't the same as in NexentaStor 3.1

@@ -26,11 +26,11 @@
  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
  * Copyright (c) 2013 Steven Hartland.  All rights reserved.
  * Copyright (c) 2014 Integros [integros.com]
  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
- * Copyright 2016 Nexenta Systems, Inc.
+ * Copyright 2018 Nexenta Systems, Inc.
  */
 
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>

@@ -105,11 +105,10 @@
 static int zfs_do_hold(int argc, char **argv);
 static int zfs_do_holds(int argc, char **argv);
 static int zfs_do_release(int argc, char **argv);
 static int zfs_do_diff(int argc, char **argv);
 static int zfs_do_bookmark(int argc, char **argv);
-static int zfs_do_remap(int argc, char **argv);
 static int zfs_do_channel_program(int argc, char **argv);
 
 /*
  * Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
  */

@@ -153,11 +152,10 @@
         HELP_GROUPSPACE,
         HELP_HOLD,
         HELP_HOLDS,
         HELP_RELEASE,
         HELP_DIFF,
-        HELP_REMAP,
         HELP_BOOKMARK,
         HELP_CHANNEL_PROGRAM,
 } zfs_help_t;
 
 typedef struct zfs_command {

@@ -210,11 +208,10 @@
         { NULL },
         { "hold",       zfs_do_hold,            HELP_HOLD               },
         { "holds",      zfs_do_holds,           HELP_HOLDS              },
         { "release",    zfs_do_release,         HELP_RELEASE            },
         { "diff",       zfs_do_diff,            HELP_DIFF               },
-        { "remap",      zfs_do_remap,           HELP_REMAP              },
 };
 
 #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 
 zfs_command_t *current_command;

@@ -249,31 +246,32 @@
                 return (gettext("\tupgrade [-v]\n"
                     "\tupgrade [-r] [-V version] <-a | filesystem ...>\n"));
         case HELP_LIST:
                 return (gettext("\tlist [-Hp] [-r|-d max] [-o property[,...]] "
                     "[-s property]...\n\t    [-S property]... [-t type[,...]] "
-                    "[filesystem|volume|snapshot] ...\n"));
+                    "[filesystem|volume|snapshot|autosnapshot] ...\n"));
         case HELP_MOUNT:
                 return (gettext("\tmount\n"
                     "\tmount [-vO] [-o opts] <-a | filesystem>\n"));
         case HELP_PROMOTE:
                 return (gettext("\tpromote <clone-filesystem>\n"));
         case HELP_RECEIVE:
-                return (gettext("\treceive [-vnsFu] <filesystem|volume|"
+                return (gettext("\treceive [-vnsFKu] <filesystem|volume|"
                     "snapshot>\n"
-                    "\treceive [-vnsFu] [-o origin=<snapshot>] [-d | -e] "
-                    "<filesystem>\n"
+                    "\treceive [-vnsFKu] [-d |-e] [-o <property=value>]... "
+                    "[-x <property>]... [-l <filesystem|volume>] ...  "
+                    "<filesystem|volume|snapshot>\n"
                     "\treceive -A <filesystem|volume>\n"));
         case HELP_RENAME:
                 return (gettext("\trename [-f] <filesystem|volume|snapshot> "
                     "<filesystem|volume|snapshot>\n"
                     "\trename [-f] -p <filesystem|volume> <filesystem|volume>\n"
                     "\trename -r <snapshot> <snapshot>\n"));
         case HELP_ROLLBACK:
                 return (gettext("\trollback [-rRf] <snapshot>\n"));
         case HELP_SEND:
-                return (gettext("\tsend [-DnPpRvLec] [-[iI] snapshot] "
+                return (gettext("\tsend [-DnPpRvLesc] [-[iI] snapshot] "
                     "<snapshot>\n"
                     "\tsend [-Le] [-i snapshot|bookmark] "
                     "<filesystem|volume|snapshot>\n"
                     "\tsend [-nvPe] -t <receive_resume_token>\n"));
         case HELP_SET:

@@ -327,12 +325,10 @@
         case HELP_RELEASE:
                 return (gettext("\trelease [-r] <tag> <snapshot> ...\n"));
         case HELP_DIFF:
                 return (gettext("\tdiff [-FHt] <snapshot> "
                     "[snapshot|filesystem]\n"));
-        case HELP_REMAP:
-                return (gettext("\tremap <filesystem | volume>\n"));
         case HELP_BOOKMARK:
                 return (gettext("\tbookmark <snapshot> <bookmark>\n"));
         case HELP_CHANNEL_PROGRAM:
                 return (gettext("\tprogram [-n] [-t <instruction limit>] "
                     "[-m <memory limit (b)>] <pool> <program file> "

@@ -509,10 +505,23 @@
 
         exit(requested ? 0 : 2);
 }
 
 /*
+ * Add parameter to the list if it's not in there already
+ */
+static void
+add_unique_option(nvlist_t *props, char *propname)
+{
+        if (nvlist_lookup_string(props, propname, NULL) != 0) {
+                if (nvlist_add_boolean(props, propname) != 0) {
+                        nomem();
+                }
+        }
+}
+
+/*
  * Take a property=value argument string and add it to the given nvlist.
  * Modifies the argument inplace.
  */
 static int
 parseprop(nvlist_t *props, char *propname)

@@ -543,11 +552,11 @@
         int depth;
 
         depth = (int)strtol(opt, &tmp, 0);
         if (*tmp) {
                 (void) fprintf(stderr,
-                    gettext("%s is not an integer\n"), optarg);
+                    gettext("%s is not an integer\n"), opt);
                 usage(B_FALSE);
         }
         if (depth < 0) {
                 (void) fprintf(stderr,
                     gettext("Depth can not be negative.\n"));

@@ -1074,11 +1083,12 @@
          * We batch up all contiguous snapshots (even of different
          * filesystems) and destroy them with one ioctl.  We can't
          * simply do all snap deletions and then all fs deletions,
          * because we must delete a clone before its origin.
          */
-        if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) {
+        if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT ||
+            zfs_get_type(zhp) == ZFS_TYPE_AUTOSNAP) {
                 fnvlist_add_boolean(cb->cb_batchedsnaps, name);
         } else {
                 int error = zfs_destroy_snaps_nvl(g_zfs,
                     cb->cb_batchedsnaps, B_FALSE);
                 fnvlist_free(cb->cb_batchedsnaps);

@@ -1236,10 +1246,24 @@
         }
         return (0);
 }
 
 static int
+unmount_callback(zfs_handle_t *zhp, void *arg)
+{
+        destroy_cbdata_t *cb = arg;
+        int err = 0;
+
+        if (zfs_is_mounted(zhp, NULL))
+                err = zfs_unmount(zhp, NULL, cb->cb_force ? MS_FORCE : 0);
+
+        zfs_close(zhp);
+
+        return (err);
+}
+
+static int
 zfs_do_destroy(int argc, char **argv)
 {
         destroy_cbdata_t cb = { 0 };
         int rv = 0;
         int err = 0;

@@ -1404,11 +1428,63 @@
                 if ((zhp = zfs_open(g_zfs, argv[0], type)) == NULL)
                         return (1);
 
                 cb.cb_target = zhp;
 
+                err = zfs_check_krrp(g_zfs, argv[0]);
+
                 /*
+                 * ENOTSUP means that autosnaper doesn't handle this dataset
+                 * and the basic detruction can be used.
+                 */
+                if (err != ENOTSUP) {
+                        rv = 1;
+                        if (!cb.cb_recurse || !cb.cb_doclones) {
+                                (void) fprintf(stderr,
+                                    gettext("cannot destroy '%s': "
+                                    "dataset under autosnap can be destroyed "
+                                    "with -R only\n"), zfs_get_name(zhp));
+                        } else if (err == ECHILD) {
+                                (void) fprintf(stderr,
+                                    gettext("cannot destroy '%s': "
+                                    "dataset has children under krrp\n"),
+                                    zfs_get_name(zhp));
+                        } else if (err == EBUSY) {
+                                (void) fprintf(stderr,
+                                    gettext("cannot destroy '%s': "
+                                    "dataset is root of a krrp task\n"),
+                                    zfs_get_name(zhp));
+                        } else if (err && err != EUSERS) {
+                                (void) fprintf(stderr,
+                                    gettext("cannot destroy '%s': "
+                                    "unexpected error : %d\n"),
+                                    zfs_get_name(zhp), err);
+                        } else {
+                                /*
+                                 * err == 0 || err == EUSERS means the ds can
+                                 * be destroyed with atomical destroy
+                                 */
+                                err = zfs_iter_dependents(zhp, B_FALSE,
+                                    unmount_callback, &cb);
+                                if (!err) {
+                                        err = unmount_callback(
+                                            zfs_handle_dup(zhp), &cb);
+                                }
+                                if (!err) {
+                                        err = zfs_destroy_atomically(
+                                            zhp, B_TRUE);
+                                }
+
+                                if (!err)
+                                        rv = 0;
+                        }
+                        goto out;
+                }
+
+                err = 0;
+
+                /*
                  * Perform an explicit check for pools before going any further.
                  */
                 if (!cb.cb_recurse && strchr(zfs_get_name(zhp), '/') == NULL &&
                     zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
                         (void) fprintf(stderr, gettext("cannot destroy '%s': "

@@ -2077,10 +2153,11 @@
                          * be doing ioctls to different pools.  We need
                          * to log this history once to each pool, and bypass
                          * the normal history logging that happens in main().
                          */
                         (void) zpool_log_history(g_zfs, history_str);
+                        verify(zpool_stage_history(g_zfs, history_str) == 0);
                         log_history = B_FALSE;
                 }
                 if (zfs_prop_set(zhp, "version", verstr) == 0)
                         cb->cb_numupgraded++;
                 else

@@ -3124,11 +3201,11 @@
                         types_specified = B_TRUE;
                         flags &= ~ZFS_ITER_PROP_LISTSNAPS;
                         while (*optarg != '\0') {
                                 static char *type_subopts[] = { "filesystem",
                                     "volume", "snapshot", "snap", "bookmark",
-                                    "all", NULL };
+                                    "all", "autosnapshot", NULL };
 
                                 switch (getsubopt(&optarg, type_subopts,
                                     &value)) {
                                 case 0:
                                         types |= ZFS_TYPE_FILESYSTEM;

@@ -3143,12 +3220,16 @@
                                 case 4:
                                         types |= ZFS_TYPE_BOOKMARK;
                                         break;
                                 case 5:
                                         types = ZFS_TYPE_DATASET |
-                                            ZFS_TYPE_BOOKMARK;
+                                            ZFS_TYPE_BOOKMARK |
+                                            ZFS_TYPE_AUTOSNAP;
                                         break;
+                                case 6:
+                                        types |= ZFS_TYPE_AUTOSNAP;
+                                        break;
                                 default:
                                         (void) fprintf(stderr,
                                             gettext("invalid type '%s'\n"),
                                             value);
                                         usage(B_FALSE);

@@ -3744,11 +3825,11 @@
                 {"compressed",  no_argument,            NULL, 'c'},
                 {0, 0, 0, 0}
         };
 
         /* check options */
-        while ((c = getopt_long(argc, argv, ":i:I:RbDpvnPLet:c", long_options,
+        while ((c = getopt_long(argc, argv, ":i:I:RbDpvnPLest:c", long_options,
             NULL)) != -1) {
                 switch (c) {
                 case 'i':
                         if (fromname)
                                 usage(B_FALSE);

@@ -3786,10 +3867,13 @@
                         flags.largeblock = B_TRUE;
                         break;
                 case 'e':
                         flags.embed_data = B_TRUE;
                         break;
+                case 's':
+                        flags.sendsize = B_TRUE;
+                        break;
                 case 't':
                         resume_token = optarg;
                         break;
                 case 'c':
                         flags.compress = B_TRUE;

@@ -3860,11 +3944,21 @@
                         (void) fprintf(stderr, gettext("too many arguments\n"));
                         usage(B_FALSE);
                 }
         }
 
-        if (!flags.dryrun && isatty(STDOUT_FILENO)) {
+        if (flags.sendsize) {
+                int fd = open("/dev/null", O_WRONLY|O_LARGEFILE);
+                if (fd < 0) {
+                        perror("failed to open /dev/null");
+                        return (1);
+                }
+                if ((dup2(fd, STDOUT_FILENO)) < 0) {
+                        perror("failed to dup2(/dev/null,STDOUT_FILENO)");
+                        return (1);
+                }
+        } else if (!flags.dryrun && isatty(STDOUT_FILENO)) {
                 (void) fprintf(stderr,
                     gettext("Error: Stream can not be written to a terminal.\n"
                     "You must redirect standard output.\n"));
                 return (1);
         }

@@ -3985,51 +4079,62 @@
  */
 static int
 zfs_do_receive(int argc, char **argv)
 {
         int c, err = 0;
+        nvlist_t *exprops, *limitds;
         recvflags_t flags = { 0 };
         boolean_t abort_resumable = B_FALSE;
 
-        nvlist_t *props;
-        nvpair_t *nvp = NULL;
-
-        if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
+        if (nvlist_alloc(&exprops, NV_UNIQUE_NAME, 0) != 0)
                 nomem();
+        if (nvlist_alloc(&limitds, NV_UNIQUE_NAME, 0) != 0)
+                nomem();
 
         /* check options */
-        while ((c = getopt(argc, argv, ":o:denuvFsA")) != -1) {
+        while ((c = getopt(argc, argv, ":del:no:uvx:FsAK")) != -1) {
                 switch (c) {
                 case 'o':
-                        if (parseprop(props, optarg) != 0)
-                                return (1);
+                        if (parseprop(exprops, optarg) != 0) {
+                                err = 1;
+                                goto recverror;
+                        }
                         break;
                 case 'd':
                         flags.isprefix = B_TRUE;
                         break;
                 case 'e':
                         flags.isprefix = B_TRUE;
                         flags.istail = B_TRUE;
                         break;
+                case 'l':
+                        add_unique_option(limitds, optarg);
+                        break;
                 case 'n':
                         flags.dryrun = B_TRUE;
                         break;
                 case 'u':
                         flags.nomount = B_TRUE;
                         break;
                 case 'v':
                         flags.verbose = B_TRUE;
                         break;
+                case 'x':
+                        add_unique_option(exprops, optarg);
+                        break;
                 case 's':
                         flags.resumable = B_TRUE;
                         break;
                 case 'F':
                         flags.force = B_TRUE;
                         break;
                 case 'A':
                         abort_resumable = B_TRUE;
                         break;
+                case 'K':
+                        flags.keepsnap = B_TRUE;
+                        break;
                 case ':':
                         (void) fprintf(stderr, gettext("missing argument for "
                             "'%c' option\n"), optopt);
                         usage(B_FALSE);
                         break;

@@ -4051,17 +4156,10 @@
         if (argc > 1) {
                 (void) fprintf(stderr, gettext("too many arguments\n"));
                 usage(B_FALSE);
         }
 
-        while ((nvp = nvlist_next_nvpair(props, nvp))) {
-                if (strcmp(nvpair_name(nvp), "origin") != 0) {
-                        (void) fprintf(stderr, gettext("invalid option"));
-                        usage(B_FALSE);
-                }
-        }
-
         if (abort_resumable) {
                 if (flags.isprefix || flags.istail || flags.dryrun ||
                     flags.resumable || flags.nomount) {
                         (void) fprintf(stderr, gettext("invalid option"));
                         usage(B_FALSE);

@@ -4103,12 +4201,18 @@
                     gettext("Error: Backup stream can not be read "
                     "from a terminal.\n"
                     "You must redirect standard input.\n"));
                 return (1);
         }
-        err = zfs_receive(g_zfs, argv[0], props, &flags, STDIN_FILENO, NULL);
 
+        err = zfs_receive(g_zfs, argv[0], &flags, STDIN_FILENO, exprops,
+            limitds, NULL);
+
+recverror:
+        nvlist_free(exprops);
+        nvlist_free(limitds);
+
         return (err != 0);
 }
 
 /*
  * allow/unallow stuff

@@ -4134,11 +4238,10 @@
 #define ZFS_DELEG_PERM_GROUPUSED        "groupused"
 #define ZFS_DELEG_PERM_HOLD             "hold"
 #define ZFS_DELEG_PERM_RELEASE          "release"
 #define ZFS_DELEG_PERM_DIFF             "diff"
 #define ZFS_DELEG_PERM_BOOKMARK         "bookmark"
-#define ZFS_DELEG_PERM_REMAP            "remap"
 
 #define ZFS_NUM_DELEG_NOTES ZFS_DELEG_NOTE_NONE
 
 static zfs_deleg_perm_tab_t zfs_deleg_perm_tbl[] = {
         { ZFS_DELEG_PERM_ALLOW, ZFS_DELEG_NOTE_ALLOW },

@@ -4155,11 +4258,10 @@
         { ZFS_DELEG_PERM_ROLLBACK, ZFS_DELEG_NOTE_ROLLBACK },
         { ZFS_DELEG_PERM_SEND, ZFS_DELEG_NOTE_SEND },
         { ZFS_DELEG_PERM_SHARE, ZFS_DELEG_NOTE_SHARE },
         { ZFS_DELEG_PERM_SNAPSHOT, ZFS_DELEG_NOTE_SNAPSHOT },
         { ZFS_DELEG_PERM_BOOKMARK, ZFS_DELEG_NOTE_BOOKMARK },
-        { ZFS_DELEG_PERM_REMAP, ZFS_DELEG_NOTE_REMAP },
 
         { ZFS_DELEG_PERM_GROUPQUOTA, ZFS_DELEG_NOTE_GROUPQUOTA },
         { ZFS_DELEG_PERM_GROUPUSED, ZFS_DELEG_NOTE_GROUPUSED },
         { ZFS_DELEG_PERM_USERPROP, ZFS_DELEG_NOTE_USERPROP },
         { ZFS_DELEG_PERM_USERQUOTA, ZFS_DELEG_NOTE_USERQUOTA },

@@ -5601,26 +5703,23 @@
                         char tsbuf[DATETIME_BUF_LEN];
                         char *tagname = nvpair_name(nvp2);
                         uint64_t val = 0;
                         time_t time;
                         struct tm t;
+                        char sep = scripted ? '\t' : ' ';
+                        size_t sepnum = scripted ? 1 : 2;
 
                         (void) nvpair_value_uint64(nvp2, &val);
                         time = (time_t)val;
                         (void) localtime_r(&time, &t);
                         (void) strftime(tsbuf, DATETIME_BUF_LEN,
                             gettext(STRFTIME_FMT_STR), &t);
 
-                        if (scripted) {
-                                (void) printf("%s\t%s\t%s\n", zname,
-                                    tagname, tsbuf);
-                        } else {
-                                (void) printf("%-*s  %-*s  %s\n", nwidth,
-                                    zname, tagwidth, tagname, tsbuf);
+                        (void) printf("%-*s%*c%-*s%*c%s\n", nwidth, zname,
+                            sepnum, sep, tagwidth, tagname, sepnum, sep, tsbuf);
                         }
                 }
-        }
 }
 
 /*
  * Generic callback function to list a dataset or snapshot.
  */

@@ -6532,10 +6631,36 @@
                                 free(node);
                         }
                 }
 
                 /*
+                 * Initilialize libshare SA_INIT_SHARE_API_SELECTIVE here
+                 * to avoid unneccesary load/unload of the libshare API
+                 * per shared dataset downstream.
+                 */
+                if (op == OP_SHARE) {
+                        zfs_handle_t **dslist = NULL;
+                        size_t count = 0;
+                        get_all_datasets(&dslist, &count, B_FALSE);
+
+                        if (count > 0) {
+                                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 (1);
+                                }
+                        }
+                }
+
+                /*
                  * Walk the AVL tree in reverse, unmounting each filesystem and
                  * removing it from the AVL tree in the process.
                  */
                 if ((walk = uu_avl_walk_start(tree,
                     UU_WALK_REVERSE | UU_WALK_ROBUST)) == NULL)

@@ -6902,26 +7027,10 @@
         zfs_close(zhp);
 
         return (err != 0);
 }
 
-static int
-zfs_do_remap(int argc, char **argv)
-{
-        const char *fsname;
-        int err = 0;
-        if (argc != 2) {
-                (void) fprintf(stderr, gettext("wrong number of arguments\n"));
-                usage(B_FALSE);
-        }
-
-        fsname = argv[1];
-        err = zfs_remap_indirects(g_zfs, fsname);
-
-        return (err);
-}
-
 /*
  * zfs bookmark <fs@snap> <fs#bmark>
  *
  * Creates a bookmark with the given name from the given snapshot.
  */

@@ -7237,10 +7346,11 @@
                     "initialize ZFS library\n"));
                 return (1);
         }
 
         zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
+        verify(zpool_stage_history(g_zfs, history_str) == 0);
 
         libzfs_print_on_error(g_zfs, B_TRUE);
 
         if ((mnttab_file = fopen(MNTTAB, "r")) == NULL) {
                 (void) fprintf(stderr, gettext("internal error: unable to "