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

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/zfs/zfs_main.c
          +++ new/usr/src/cmd/zfs/zfs_main.c
↓ open down ↓ 20 lines elided ↑ open up ↑
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
  25   25   * Copyright 2012 Milan Jurik. All rights reserved.
  26   26   * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  27   27   * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
  28   28   * Copyright (c) 2013 Steven Hartland.  All rights reserved.
  29   29   * Copyright (c) 2014 Integros [integros.com]
  30   30   * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
  31      - * Copyright 2016 Nexenta Systems, Inc.
       31 + * Copyright 2018 Nexenta Systems, Inc.
  32   32   */
  33   33  
  34   34  #include <assert.h>
  35   35  #include <ctype.h>
  36   36  #include <errno.h>
  37   37  #include <getopt.h>
  38   38  #include <libgen.h>
  39   39  #include <libintl.h>
  40   40  #include <libuutil.h>
  41   41  #include <libnvpair.h>
↓ open down ↓ 58 lines elided ↑ open up ↑
 100  100  static int zfs_do_receive(int argc, char **argv);
 101  101  static int zfs_do_promote(int argc, char **argv);
 102  102  static int zfs_do_userspace(int argc, char **argv);
 103  103  static int zfs_do_allow(int argc, char **argv);
 104  104  static int zfs_do_unallow(int argc, char **argv);
 105  105  static int zfs_do_hold(int argc, char **argv);
 106  106  static int zfs_do_holds(int argc, char **argv);
 107  107  static int zfs_do_release(int argc, char **argv);
 108  108  static int zfs_do_diff(int argc, char **argv);
 109  109  static int zfs_do_bookmark(int argc, char **argv);
 110      -static int zfs_do_remap(int argc, char **argv);
 111  110  static int zfs_do_channel_program(int argc, char **argv);
 112  111  
 113  112  /*
 114  113   * Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
 115  114   */
 116  115  
 117  116  #ifdef DEBUG
 118  117  const char *
 119  118  _umem_debug_init(void)
 120  119  {
↓ open down ↓ 27 lines elided ↑ open up ↑
 148  147          HELP_UNMOUNT,
 149  148          HELP_UNSHARE,
 150  149          HELP_ALLOW,
 151  150          HELP_UNALLOW,
 152  151          HELP_USERSPACE,
 153  152          HELP_GROUPSPACE,
 154  153          HELP_HOLD,
 155  154          HELP_HOLDS,
 156  155          HELP_RELEASE,
 157  156          HELP_DIFF,
 158      -        HELP_REMAP,
 159  157          HELP_BOOKMARK,
 160  158          HELP_CHANNEL_PROGRAM,
 161  159  } zfs_help_t;
 162  160  
 163  161  typedef struct zfs_command {
 164  162          const char      *name;
 165  163          int             (*func)(int argc, char **argv);
 166  164          zfs_help_t      usage;
 167  165  } zfs_command_t;
 168  166  
↓ open down ↓ 36 lines elided ↑ open up ↑
 205  203          { "receive",    zfs_do_receive,         HELP_RECEIVE            },
 206  204          { NULL },
 207  205          { "allow",      zfs_do_allow,           HELP_ALLOW              },
 208  206          { NULL },
 209  207          { "unallow",    zfs_do_unallow,         HELP_UNALLOW            },
 210  208          { NULL },
 211  209          { "hold",       zfs_do_hold,            HELP_HOLD               },
 212  210          { "holds",      zfs_do_holds,           HELP_HOLDS              },
 213  211          { "release",    zfs_do_release,         HELP_RELEASE            },
 214  212          { "diff",       zfs_do_diff,            HELP_DIFF               },
 215      -        { "remap",      zfs_do_remap,           HELP_REMAP              },
 216  213  };
 217  214  
 218  215  #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 219  216  
 220  217  zfs_command_t *current_command;
 221  218  
 222  219  static const char *
 223  220  get_usage(zfs_help_t idx)
 224  221  {
 225  222          switch (idx) {
↓ open down ↓ 18 lines elided ↑ open up ↑
 244  241                      "[filesystem|volume|snapshot|bookmark] ...\n"));
 245  242          case HELP_INHERIT:
 246  243                  return (gettext("\tinherit [-rS] <property> "
 247  244                      "<filesystem|volume|snapshot> ...\n"));
 248  245          case HELP_UPGRADE:
 249  246                  return (gettext("\tupgrade [-v]\n"
 250  247                      "\tupgrade [-r] [-V version] <-a | filesystem ...>\n"));
 251  248          case HELP_LIST:
 252  249                  return (gettext("\tlist [-Hp] [-r|-d max] [-o property[,...]] "
 253  250                      "[-s property]...\n\t    [-S property]... [-t type[,...]] "
 254      -                    "[filesystem|volume|snapshot] ...\n"));
      251 +                    "[filesystem|volume|snapshot|autosnapshot] ...\n"));
 255  252          case HELP_MOUNT:
 256  253                  return (gettext("\tmount\n"
 257  254                      "\tmount [-vO] [-o opts] <-a | filesystem>\n"));
 258  255          case HELP_PROMOTE:
 259  256                  return (gettext("\tpromote <clone-filesystem>\n"));
 260  257          case HELP_RECEIVE:
 261      -                return (gettext("\treceive [-vnsFu] <filesystem|volume|"
      258 +                return (gettext("\treceive [-vnsFKu] <filesystem|volume|"
 262  259                      "snapshot>\n"
 263      -                    "\treceive [-vnsFu] [-o origin=<snapshot>] [-d | -e] "
 264      -                    "<filesystem>\n"
      260 +                    "\treceive [-vnsFKu] [-d |-e] [-o <property=value>]... "
      261 +                    "[-x <property>]... [-l <filesystem|volume>] ...  "
      262 +                    "<filesystem|volume|snapshot>\n"
 265  263                      "\treceive -A <filesystem|volume>\n"));
 266  264          case HELP_RENAME:
 267  265                  return (gettext("\trename [-f] <filesystem|volume|snapshot> "
 268  266                      "<filesystem|volume|snapshot>\n"
 269  267                      "\trename [-f] -p <filesystem|volume> <filesystem|volume>\n"
 270  268                      "\trename -r <snapshot> <snapshot>\n"));
 271  269          case HELP_ROLLBACK:
 272  270                  return (gettext("\trollback [-rRf] <snapshot>\n"));
 273  271          case HELP_SEND:
 274      -                return (gettext("\tsend [-DnPpRvLec] [-[iI] snapshot] "
      272 +                return (gettext("\tsend [-DnPpRvLesc] [-[iI] snapshot] "
 275  273                      "<snapshot>\n"
 276  274                      "\tsend [-Le] [-i snapshot|bookmark] "
 277  275                      "<filesystem|volume|snapshot>\n"
 278  276                      "\tsend [-nvPe] -t <receive_resume_token>\n"));
 279  277          case HELP_SET:
 280  278                  return (gettext("\tset <property=value> ... "
 281  279                      "<filesystem|volume|snapshot> ...\n"));
 282  280          case HELP_SHARE:
 283  281                  return (gettext("\tshare <-a | filesystem>\n"));
 284  282          case HELP_SNAPSHOT:
↓ open down ↓ 37 lines elided ↑ open up ↑
 322  320                      "<filesystem|snapshot>\n"));
 323  321          case HELP_HOLD:
 324  322                  return (gettext("\thold [-r] <tag> <snapshot> ...\n"));
 325  323          case HELP_HOLDS:
 326  324                  return (gettext("\tholds [-r] <snapshot> ...\n"));
 327  325          case HELP_RELEASE:
 328  326                  return (gettext("\trelease [-r] <tag> <snapshot> ...\n"));
 329  327          case HELP_DIFF:
 330  328                  return (gettext("\tdiff [-FHt] <snapshot> "
 331  329                      "[snapshot|filesystem]\n"));
 332      -        case HELP_REMAP:
 333      -                return (gettext("\tremap <filesystem | volume>\n"));
 334  330          case HELP_BOOKMARK:
 335  331                  return (gettext("\tbookmark <snapshot> <bookmark>\n"));
 336  332          case HELP_CHANNEL_PROGRAM:
 337  333                  return (gettext("\tprogram [-n] [-t <instruction limit>] "
 338  334                      "[-m <memory limit (b)>] <pool> <program file> "
 339  335                      "[lua args...]\n"));
 340  336          }
 341  337  
 342  338          abort();
 343  339          /* NOTREACHED */
↓ open down ↓ 160 lines elided ↑ open up ↑
 504  500           */
 505  501          if (getenv("ZFS_ABORT") != NULL) {
 506  502                  (void) printf("dumping core by request\n");
 507  503                  abort();
 508  504          }
 509  505  
 510  506          exit(requested ? 0 : 2);
 511  507  }
 512  508  
 513  509  /*
      510 + * Add parameter to the list if it's not in there already
      511 + */
      512 +static void
      513 +add_unique_option(nvlist_t *props, char *propname)
      514 +{
      515 +        if (nvlist_lookup_string(props, propname, NULL) != 0) {
      516 +                if (nvlist_add_boolean(props, propname) != 0) {
      517 +                        nomem();
      518 +                }
      519 +        }
      520 +}
      521 +
      522 +/*
 514  523   * Take a property=value argument string and add it to the given nvlist.
 515  524   * Modifies the argument inplace.
 516  525   */
 517  526  static int
 518  527  parseprop(nvlist_t *props, char *propname)
 519  528  {
 520  529          char *propval, *strval;
 521  530  
 522  531          if ((propval = strchr(propname, '=')) == NULL) {
 523  532                  (void) fprintf(stderr, gettext("missing "
↓ open down ↓ 14 lines elided ↑ open up ↑
 538  547  
 539  548  static int
 540  549  parse_depth(char *opt, int *flags)
 541  550  {
 542  551          char *tmp;
 543  552          int depth;
 544  553  
 545  554          depth = (int)strtol(opt, &tmp, 0);
 546  555          if (*tmp) {
 547  556                  (void) fprintf(stderr,
 548      -                    gettext("%s is not an integer\n"), optarg);
      557 +                    gettext("%s is not an integer\n"), opt);
 549  558                  usage(B_FALSE);
 550  559          }
 551  560          if (depth < 0) {
 552  561                  (void) fprintf(stderr,
 553  562                      gettext("Depth can not be negative.\n"));
 554  563                  usage(B_FALSE);
 555  564          }
 556  565          *flags |= (ZFS_ITER_DEPTH_LIMIT|ZFS_ITER_RECURSE);
 557  566          return (depth);
 558  567  }
↓ open down ↓ 510 lines elided ↑ open up ↑
1069 1078                  zfs_close(zhp);
1070 1079                  return (0);
1071 1080          }
1072 1081  
1073 1082          /*
1074 1083           * We batch up all contiguous snapshots (even of different
1075 1084           * filesystems) and destroy them with one ioctl.  We can't
1076 1085           * simply do all snap deletions and then all fs deletions,
1077 1086           * because we must delete a clone before its origin.
1078 1087           */
1079      -        if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) {
     1088 +        if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT ||
     1089 +            zfs_get_type(zhp) == ZFS_TYPE_AUTOSNAP) {
1080 1090                  fnvlist_add_boolean(cb->cb_batchedsnaps, name);
1081 1091          } else {
1082 1092                  int error = zfs_destroy_snaps_nvl(g_zfs,
1083 1093                      cb->cb_batchedsnaps, B_FALSE);
1084 1094                  fnvlist_free(cb->cb_batchedsnaps);
1085 1095                  cb->cb_batchedsnaps = fnvlist_alloc();
1086 1096  
1087 1097                  if (error != 0 ||
1088 1098                      zfs_unmount(zhp, NULL, cb->cb_force ? MS_FORCE : 0) != 0 ||
1089 1099                      zfs_destroy(zhp, cb->cb_defer_destroy) != 0) {
↓ open down ↓ 141 lines elided ↑ open up ↑
1231 1241                          cb->cb_defer_destroy = defer;
1232 1242                          zfs_close(zhp);
1233 1243                          if (err != 0)
1234 1244                                  return (err);
1235 1245                  }
1236 1246          }
1237 1247          return (0);
1238 1248  }
1239 1249  
1240 1250  static int
     1251 +unmount_callback(zfs_handle_t *zhp, void *arg)
     1252 +{
     1253 +        destroy_cbdata_t *cb = arg;
     1254 +        int err = 0;
     1255 +
     1256 +        if (zfs_is_mounted(zhp, NULL))
     1257 +                err = zfs_unmount(zhp, NULL, cb->cb_force ? MS_FORCE : 0);
     1258 +
     1259 +        zfs_close(zhp);
     1260 +
     1261 +        return (err);
     1262 +}
     1263 +
     1264 +static int
1241 1265  zfs_do_destroy(int argc, char **argv)
1242 1266  {
1243 1267          destroy_cbdata_t cb = { 0 };
1244 1268          int rv = 0;
1245 1269          int err = 0;
1246 1270          int c;
1247 1271          zfs_handle_t *zhp = NULL;
1248 1272          char *at, *pound;
1249 1273          zfs_type_t type = ZFS_TYPE_DATASET;
1250 1274  
↓ open down ↓ 148 lines elided ↑ open up ↑
1399 1423                  nvlist_free(cb.cb_nvl);
1400 1424  
1401 1425                  return (err);
1402 1426          } else {
1403 1427                  /* Open the given dataset */
1404 1428                  if ((zhp = zfs_open(g_zfs, argv[0], type)) == NULL)
1405 1429                          return (1);
1406 1430  
1407 1431                  cb.cb_target = zhp;
1408 1432  
     1433 +                err = zfs_check_krrp(g_zfs, argv[0]);
     1434 +
1409 1435                  /*
     1436 +                 * ENOTSUP means that autosnaper doesn't handle this dataset
     1437 +                 * and the basic detruction can be used.
     1438 +                 */
     1439 +                if (err != ENOTSUP) {
     1440 +                        rv = 1;
     1441 +                        if (!cb.cb_recurse || !cb.cb_doclones) {
     1442 +                                (void) fprintf(stderr,
     1443 +                                    gettext("cannot destroy '%s': "
     1444 +                                    "dataset under autosnap can be destroyed "
     1445 +                                    "with -R only\n"), zfs_get_name(zhp));
     1446 +                        } else if (err == ECHILD) {
     1447 +                                (void) fprintf(stderr,
     1448 +                                    gettext("cannot destroy '%s': "
     1449 +                                    "dataset has children under krrp\n"),
     1450 +                                    zfs_get_name(zhp));
     1451 +                        } else if (err == EBUSY) {
     1452 +                                (void) fprintf(stderr,
     1453 +                                    gettext("cannot destroy '%s': "
     1454 +                                    "dataset is root of a krrp task\n"),
     1455 +                                    zfs_get_name(zhp));
     1456 +                        } else if (err && err != EUSERS) {
     1457 +                                (void) fprintf(stderr,
     1458 +                                    gettext("cannot destroy '%s': "
     1459 +                                    "unexpected error : %d\n"),
     1460 +                                    zfs_get_name(zhp), err);
     1461 +                        } else {
     1462 +                                /*
     1463 +                                 * err == 0 || err == EUSERS means the ds can
     1464 +                                 * be destroyed with atomical destroy
     1465 +                                 */
     1466 +                                err = zfs_iter_dependents(zhp, B_FALSE,
     1467 +                                    unmount_callback, &cb);
     1468 +                                if (!err) {
     1469 +                                        err = unmount_callback(
     1470 +                                            zfs_handle_dup(zhp), &cb);
     1471 +                                }
     1472 +                                if (!err) {
     1473 +                                        err = zfs_destroy_atomically(
     1474 +                                            zhp, B_TRUE);
     1475 +                                }
     1476 +
     1477 +                                if (!err)
     1478 +                                        rv = 0;
     1479 +                        }
     1480 +                        goto out;
     1481 +                }
     1482 +
     1483 +                err = 0;
     1484 +
     1485 +                /*
1410 1486                   * Perform an explicit check for pools before going any further.
1411 1487                   */
1412 1488                  if (!cb.cb_recurse && strchr(zfs_get_name(zhp), '/') == NULL &&
1413 1489                      zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
1414 1490                          (void) fprintf(stderr, gettext("cannot destroy '%s': "
1415 1491                              "operation does not apply to pools\n"),
1416 1492                              zfs_get_name(zhp));
1417 1493                          (void) fprintf(stderr, gettext("use 'zfs destroy -r "
1418 1494                              "%s' to destroy all datasets in the pool\n"),
1419 1495                              zfs_get_name(zhp));
↓ open down ↓ 652 lines elided ↑ open up ↑
2072 2148                  (void) snprintf(verstr, sizeof (verstr),
2073 2149                      "%llu", cb->cb_version);
2074 2150                  if (cb->cb_lastfs[0] && !same_pool(zhp, cb->cb_lastfs)) {
2075 2151                          /*
2076 2152                           * If they did "zfs upgrade -a", then we could
2077 2153                           * be doing ioctls to different pools.  We need
2078 2154                           * to log this history once to each pool, and bypass
2079 2155                           * the normal history logging that happens in main().
2080 2156                           */
2081 2157                          (void) zpool_log_history(g_zfs, history_str);
     2158 +                        verify(zpool_stage_history(g_zfs, history_str) == 0);
2082 2159                          log_history = B_FALSE;
2083 2160                  }
2084 2161                  if (zfs_prop_set(zhp, "version", verstr) == 0)
2085 2162                          cb->cb_numupgraded++;
2086 2163                  else
2087 2164                          cb->cb_numfailed++;
2088 2165                  (void) strcpy(cb->cb_lastfs, zfs_get_name(zhp));
2089 2166          } else if (version > cb->cb_version) {
2090 2167                  /* can't downgrade */
2091 2168                  (void) printf(gettext("%s: can not be downgraded; "
↓ open down ↓ 1027 lines elided ↑ open up ↑
3119 3196                                  usage(B_FALSE);
3120 3197                          }
3121 3198                          break;
3122 3199                  case 't':
3123 3200                          types = 0;
3124 3201                          types_specified = B_TRUE;
3125 3202                          flags &= ~ZFS_ITER_PROP_LISTSNAPS;
3126 3203                          while (*optarg != '\0') {
3127 3204                                  static char *type_subopts[] = { "filesystem",
3128 3205                                      "volume", "snapshot", "snap", "bookmark",
3129      -                                    "all", NULL };
     3206 +                                    "all", "autosnapshot", NULL };
3130 3207  
3131 3208                                  switch (getsubopt(&optarg, type_subopts,
3132 3209                                      &value)) {
3133 3210                                  case 0:
3134 3211                                          types |= ZFS_TYPE_FILESYSTEM;
3135 3212                                          break;
3136 3213                                  case 1:
3137 3214                                          types |= ZFS_TYPE_VOLUME;
3138 3215                                          break;
3139 3216                                  case 2:
3140 3217                                  case 3:
3141 3218                                          types |= ZFS_TYPE_SNAPSHOT;
3142 3219                                          break;
3143 3220                                  case 4:
3144 3221                                          types |= ZFS_TYPE_BOOKMARK;
3145 3222                                          break;
3146 3223                                  case 5:
3147 3224                                          types = ZFS_TYPE_DATASET |
3148      -                                            ZFS_TYPE_BOOKMARK;
     3225 +                                            ZFS_TYPE_BOOKMARK |
     3226 +                                            ZFS_TYPE_AUTOSNAP;
3149 3227                                          break;
     3228 +                                case 6:
     3229 +                                        types |= ZFS_TYPE_AUTOSNAP;
     3230 +                                        break;
3150 3231                                  default:
3151 3232                                          (void) fprintf(stderr,
3152 3233                                              gettext("invalid type '%s'\n"),
3153 3234                                              value);
3154 3235                                          usage(B_FALSE);
3155 3236                                  }
3156 3237                          }
3157 3238                          break;
3158 3239                  case ':':
3159 3240                          (void) fprintf(stderr, gettext("missing argument for "
↓ open down ↓ 579 lines elided ↑ open up ↑
3739 3820                  {"verbose",     no_argument,            NULL, 'v'},
3740 3821                  {"dryrun",      no_argument,            NULL, 'n'},
3741 3822                  {"large-block", no_argument,            NULL, 'L'},
3742 3823                  {"embed",       no_argument,            NULL, 'e'},
3743 3824                  {"resume",      required_argument,      NULL, 't'},
3744 3825                  {"compressed",  no_argument,            NULL, 'c'},
3745 3826                  {0, 0, 0, 0}
3746 3827          };
3747 3828  
3748 3829          /* check options */
3749      -        while ((c = getopt_long(argc, argv, ":i:I:RbDpvnPLet:c", long_options,
     3830 +        while ((c = getopt_long(argc, argv, ":i:I:RbDpvnPLest:c", long_options,
3750 3831              NULL)) != -1) {
3751 3832                  switch (c) {
3752 3833                  case 'i':
3753 3834                          if (fromname)
3754 3835                                  usage(B_FALSE);
3755 3836                          fromname = optarg;
3756 3837                          break;
3757 3838                  case 'I':
3758 3839                          if (fromname)
3759 3840                                  usage(B_FALSE);
↓ open down ↓ 21 lines elided ↑ open up ↑
3781 3862                          break;
3782 3863                  case 'n':
3783 3864                          flags.dryrun = B_TRUE;
3784 3865                          break;
3785 3866                  case 'L':
3786 3867                          flags.largeblock = B_TRUE;
3787 3868                          break;
3788 3869                  case 'e':
3789 3870                          flags.embed_data = B_TRUE;
3790 3871                          break;
     3872 +                case 's':
     3873 +                        flags.sendsize = B_TRUE;
     3874 +                        break;
3791 3875                  case 't':
3792 3876                          resume_token = optarg;
3793 3877                          break;
3794 3878                  case 'c':
3795 3879                          flags.compress = B_TRUE;
3796 3880                          break;
3797 3881                  case ':':
3798 3882                          /*
3799 3883                           * If a parameter was not passed, optopt contains the
3800 3884                           * value that would normally lead us into the
↓ open down ↓ 54 lines elided ↑ open up ↑
3855 3939                          (void) fprintf(stderr,
3856 3940                              gettext("missing snapshot argument\n"));
3857 3941                          usage(B_FALSE);
3858 3942                  }
3859 3943                  if (argc > 1) {
3860 3944                          (void) fprintf(stderr, gettext("too many arguments\n"));
3861 3945                          usage(B_FALSE);
3862 3946                  }
3863 3947          }
3864 3948  
3865      -        if (!flags.dryrun && isatty(STDOUT_FILENO)) {
     3949 +        if (flags.sendsize) {
     3950 +                int fd = open("/dev/null", O_WRONLY|O_LARGEFILE);
     3951 +                if (fd < 0) {
     3952 +                        perror("failed to open /dev/null");
     3953 +                        return (1);
     3954 +                }
     3955 +                if ((dup2(fd, STDOUT_FILENO)) < 0) {
     3956 +                        perror("failed to dup2(/dev/null,STDOUT_FILENO)");
     3957 +                        return (1);
     3958 +                }
     3959 +        } else if (!flags.dryrun && isatty(STDOUT_FILENO)) {
3866 3960                  (void) fprintf(stderr,
3867 3961                      gettext("Error: Stream can not be written to a terminal.\n"
3868 3962                      "You must redirect standard output.\n"));
3869 3963                  return (1);
3870 3964          }
3871 3965  
3872 3966          if (resume_token != NULL) {
3873 3967                  return (zfs_send_resume(g_zfs, &flags, STDOUT_FILENO,
3874 3968                      resume_token));
3875 3969          }
↓ open down ↓ 104 lines elided ↑ open up ↑
3980 4074          return (err != 0);
3981 4075  }
3982 4076  
3983 4077  /*
3984 4078   * Restore a backup stream from stdin.
3985 4079   */
3986 4080  static int
3987 4081  zfs_do_receive(int argc, char **argv)
3988 4082  {
3989 4083          int c, err = 0;
     4084 +        nvlist_t *exprops, *limitds;
3990 4085          recvflags_t flags = { 0 };
3991 4086          boolean_t abort_resumable = B_FALSE;
3992 4087  
3993      -        nvlist_t *props;
3994      -        nvpair_t *nvp = NULL;
3995      -
3996      -        if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
     4088 +        if (nvlist_alloc(&exprops, NV_UNIQUE_NAME, 0) != 0)
3997 4089                  nomem();
     4090 +        if (nvlist_alloc(&limitds, NV_UNIQUE_NAME, 0) != 0)
     4091 +                nomem();
3998 4092  
3999 4093          /* check options */
4000      -        while ((c = getopt(argc, argv, ":o:denuvFsA")) != -1) {
     4094 +        while ((c = getopt(argc, argv, ":del:no:uvx:FsAK")) != -1) {
4001 4095                  switch (c) {
4002 4096                  case 'o':
4003      -                        if (parseprop(props, optarg) != 0)
4004      -                                return (1);
     4097 +                        if (parseprop(exprops, optarg) != 0) {
     4098 +                                err = 1;
     4099 +                                goto recverror;
     4100 +                        }
4005 4101                          break;
4006 4102                  case 'd':
4007 4103                          flags.isprefix = B_TRUE;
4008 4104                          break;
4009 4105                  case 'e':
4010 4106                          flags.isprefix = B_TRUE;
4011 4107                          flags.istail = B_TRUE;
4012 4108                          break;
     4109 +                case 'l':
     4110 +                        add_unique_option(limitds, optarg);
     4111 +                        break;
4013 4112                  case 'n':
4014 4113                          flags.dryrun = B_TRUE;
4015 4114                          break;
4016 4115                  case 'u':
4017 4116                          flags.nomount = B_TRUE;
4018 4117                          break;
4019 4118                  case 'v':
4020 4119                          flags.verbose = B_TRUE;
4021 4120                          break;
     4121 +                case 'x':
     4122 +                        add_unique_option(exprops, optarg);
     4123 +                        break;
4022 4124                  case 's':
4023 4125                          flags.resumable = B_TRUE;
4024 4126                          break;
4025 4127                  case 'F':
4026 4128                          flags.force = B_TRUE;
4027 4129                          break;
4028 4130                  case 'A':
4029 4131                          abort_resumable = B_TRUE;
4030 4132                          break;
     4133 +                case 'K':
     4134 +                        flags.keepsnap = B_TRUE;
     4135 +                        break;
4031 4136                  case ':':
4032 4137                          (void) fprintf(stderr, gettext("missing argument for "
4033 4138                              "'%c' option\n"), optopt);
4034 4139                          usage(B_FALSE);
4035 4140                          break;
4036 4141                  case '?':
4037 4142                          (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4038 4143                              optopt);
4039 4144                          usage(B_FALSE);
4040 4145                  }
↓ open down ↓ 5 lines elided ↑ open up ↑
4046 4151          /* check number of arguments */
4047 4152          if (argc < 1) {
4048 4153                  (void) fprintf(stderr, gettext("missing snapshot argument\n"));
4049 4154                  usage(B_FALSE);
4050 4155          }
4051 4156          if (argc > 1) {
4052 4157                  (void) fprintf(stderr, gettext("too many arguments\n"));
4053 4158                  usage(B_FALSE);
4054 4159          }
4055 4160  
4056      -        while ((nvp = nvlist_next_nvpair(props, nvp))) {
4057      -                if (strcmp(nvpair_name(nvp), "origin") != 0) {
4058      -                        (void) fprintf(stderr, gettext("invalid option"));
4059      -                        usage(B_FALSE);
4060      -                }
4061      -        }
4062      -
4063 4161          if (abort_resumable) {
4064 4162                  if (flags.isprefix || flags.istail || flags.dryrun ||
4065 4163                      flags.resumable || flags.nomount) {
4066 4164                          (void) fprintf(stderr, gettext("invalid option"));
4067 4165                          usage(B_FALSE);
4068 4166                  }
4069 4167  
4070 4168                  char namebuf[ZFS_MAX_DATASET_NAME_LEN];
4071 4169                  (void) snprintf(namebuf, sizeof (namebuf),
4072 4170                      "%s/%%recv", argv[0]);
↓ open down ↓ 25 lines elided ↑ open up ↑
4098 4196                  return (err != 0);
4099 4197          }
4100 4198  
4101 4199          if (isatty(STDIN_FILENO)) {
4102 4200                  (void) fprintf(stderr,
4103 4201                      gettext("Error: Backup stream can not be read "
4104 4202                      "from a terminal.\n"
4105 4203                      "You must redirect standard input.\n"));
4106 4204                  return (1);
4107 4205          }
4108      -        err = zfs_receive(g_zfs, argv[0], props, &flags, STDIN_FILENO, NULL);
4109 4206  
     4207 +        err = zfs_receive(g_zfs, argv[0], &flags, STDIN_FILENO, exprops,
     4208 +            limitds, NULL);
     4209 +
     4210 +recverror:
     4211 +        nvlist_free(exprops);
     4212 +        nvlist_free(limitds);
     4213 +
4110 4214          return (err != 0);
4111 4215  }
4112 4216  
4113 4217  /*
4114 4218   * allow/unallow stuff
4115 4219   */
4116 4220  /* copied from zfs/sys/dsl_deleg.h */
4117 4221  #define ZFS_DELEG_PERM_CREATE           "create"
4118 4222  #define ZFS_DELEG_PERM_DESTROY          "destroy"
4119 4223  #define ZFS_DELEG_PERM_SNAPSHOT         "snapshot"
↓ open down ↓ 9 lines elided ↑ open up ↑
4129 4233  #define ZFS_DELEG_PERM_USERPROP         "userprop"
4130 4234  #define ZFS_DELEG_PERM_VSCAN            "vscan" /* ??? */
4131 4235  #define ZFS_DELEG_PERM_USERQUOTA        "userquota"
4132 4236  #define ZFS_DELEG_PERM_GROUPQUOTA       "groupquota"
4133 4237  #define ZFS_DELEG_PERM_USERUSED         "userused"
4134 4238  #define ZFS_DELEG_PERM_GROUPUSED        "groupused"
4135 4239  #define ZFS_DELEG_PERM_HOLD             "hold"
4136 4240  #define ZFS_DELEG_PERM_RELEASE          "release"
4137 4241  #define ZFS_DELEG_PERM_DIFF             "diff"
4138 4242  #define ZFS_DELEG_PERM_BOOKMARK         "bookmark"
4139      -#define ZFS_DELEG_PERM_REMAP            "remap"
4140 4243  
4141 4244  #define ZFS_NUM_DELEG_NOTES ZFS_DELEG_NOTE_NONE
4142 4245  
4143 4246  static zfs_deleg_perm_tab_t zfs_deleg_perm_tbl[] = {
4144 4247          { ZFS_DELEG_PERM_ALLOW, ZFS_DELEG_NOTE_ALLOW },
4145 4248          { ZFS_DELEG_PERM_CLONE, ZFS_DELEG_NOTE_CLONE },
4146 4249          { ZFS_DELEG_PERM_CREATE, ZFS_DELEG_NOTE_CREATE },
4147 4250          { ZFS_DELEG_PERM_DESTROY, ZFS_DELEG_NOTE_DESTROY },
4148 4251          { ZFS_DELEG_PERM_DIFF, ZFS_DELEG_NOTE_DIFF},
4149 4252          { ZFS_DELEG_PERM_HOLD, ZFS_DELEG_NOTE_HOLD },
4150 4253          { ZFS_DELEG_PERM_MOUNT, ZFS_DELEG_NOTE_MOUNT },
4151 4254          { ZFS_DELEG_PERM_PROMOTE, ZFS_DELEG_NOTE_PROMOTE },
4152 4255          { ZFS_DELEG_PERM_RECEIVE, ZFS_DELEG_NOTE_RECEIVE },
4153 4256          { ZFS_DELEG_PERM_RELEASE, ZFS_DELEG_NOTE_RELEASE },
4154 4257          { ZFS_DELEG_PERM_RENAME, ZFS_DELEG_NOTE_RENAME },
4155 4258          { ZFS_DELEG_PERM_ROLLBACK, ZFS_DELEG_NOTE_ROLLBACK },
4156 4259          { ZFS_DELEG_PERM_SEND, ZFS_DELEG_NOTE_SEND },
4157 4260          { ZFS_DELEG_PERM_SHARE, ZFS_DELEG_NOTE_SHARE },
4158 4261          { ZFS_DELEG_PERM_SNAPSHOT, ZFS_DELEG_NOTE_SNAPSHOT },
4159 4262          { ZFS_DELEG_PERM_BOOKMARK, ZFS_DELEG_NOTE_BOOKMARK },
4160      -        { ZFS_DELEG_PERM_REMAP, ZFS_DELEG_NOTE_REMAP },
4161 4263  
4162 4264          { ZFS_DELEG_PERM_GROUPQUOTA, ZFS_DELEG_NOTE_GROUPQUOTA },
4163 4265          { ZFS_DELEG_PERM_GROUPUSED, ZFS_DELEG_NOTE_GROUPUSED },
4164 4266          { ZFS_DELEG_PERM_USERPROP, ZFS_DELEG_NOTE_USERPROP },
4165 4267          { ZFS_DELEG_PERM_USERQUOTA, ZFS_DELEG_NOTE_USERQUOTA },
4166 4268          { ZFS_DELEG_PERM_USERUSED, ZFS_DELEG_NOTE_USERUSED },
4167 4269          { NULL, ZFS_DELEG_NOTE_NONE }
4168 4270  };
4169 4271  
4170 4272  /* permission structure */
↓ open down ↓ 1425 lines elided ↑ open up ↑
5596 5698                  char *zname = nvpair_name(nvp);
5597 5699                  nvlist_t *nvl2;
5598 5700                  nvpair_t *nvp2 = NULL;
5599 5701                  (void) nvpair_value_nvlist(nvp, &nvl2);
5600 5702                  while ((nvp2 = nvlist_next_nvpair(nvl2, nvp2)) != NULL) {
5601 5703                          char tsbuf[DATETIME_BUF_LEN];
5602 5704                          char *tagname = nvpair_name(nvp2);
5603 5705                          uint64_t val = 0;
5604 5706                          time_t time;
5605 5707                          struct tm t;
     5708 +                        char sep = scripted ? '\t' : ' ';
     5709 +                        size_t sepnum = scripted ? 1 : 2;
5606 5710  
5607 5711                          (void) nvpair_value_uint64(nvp2, &val);
5608 5712                          time = (time_t)val;
5609 5713                          (void) localtime_r(&time, &t);
5610 5714                          (void) strftime(tsbuf, DATETIME_BUF_LEN,
5611 5715                              gettext(STRFTIME_FMT_STR), &t);
5612 5716  
5613      -                        if (scripted) {
5614      -                                (void) printf("%s\t%s\t%s\n", zname,
5615      -                                    tagname, tsbuf);
5616      -                        } else {
5617      -                                (void) printf("%-*s  %-*s  %s\n", nwidth,
5618      -                                    zname, tagwidth, tagname, tsbuf);
5619      -                        }
     5717 +                        (void) printf("%-*s%*c%-*s%*c%s\n", nwidth, zname,
     5718 +                            sepnum, sep, tagwidth, tagname, sepnum, sep, tsbuf);
5620 5719                  }
5621 5720          }
5622 5721  }
5623 5722  
5624 5723  /*
5625 5724   * Generic callback function to list a dataset or snapshot.
5626 5725   */
5627 5726  static int
5628 5727  holds_callback(zfs_handle_t *zhp, void *data)
5629 5728  {
↓ open down ↓ 897 lines elided ↑ open up ↑
6527 6626                          if (uu_avl_find(tree, node, NULL, &idx) == NULL) {
6528 6627                                  uu_avl_insert(tree, node, idx);
6529 6628                          } else {
6530 6629                                  zfs_close(node->un_zhp);
6531 6630                                  free(node->un_mountp);
6532 6631                                  free(node);
6533 6632                          }
6534 6633                  }
6535 6634  
6536 6635                  /*
     6636 +                 * Initilialize libshare SA_INIT_SHARE_API_SELECTIVE here
     6637 +                 * to avoid unneccesary load/unload of the libshare API
     6638 +                 * per shared dataset downstream.
     6639 +                 */
     6640 +                if (op == OP_SHARE) {
     6641 +                        zfs_handle_t **dslist = NULL;
     6642 +                        size_t count = 0;
     6643 +                        get_all_datasets(&dslist, &count, B_FALSE);
     6644 +
     6645 +                        if (count > 0) {
     6646 +                                sa_init_selective_arg_t sharearg;
     6647 +                                sharearg.zhandle_arr = dslist;
     6648 +                                sharearg.zhandle_len = count;
     6649 +                                if ((ret = zfs_init_libshare_arg(
     6650 +                                    zfs_get_handle(dslist[0]),
     6651 +                                    SA_INIT_SHARE_API_SELECTIVE, &sharearg))
     6652 +                                    != SA_OK) {
     6653 +                                        (void) fprintf(stderr, gettext(
     6654 +                                            "Could not initialize libshare,"
     6655 +                                            "%d"), ret);
     6656 +                                        return (1);
     6657 +                                }
     6658 +                        }
     6659 +                }
     6660 +
     6661 +                /*
6537 6662                   * Walk the AVL tree in reverse, unmounting each filesystem and
6538 6663                   * removing it from the AVL tree in the process.
6539 6664                   */
6540 6665                  if ((walk = uu_avl_walk_start(tree,
6541 6666                      UU_WALK_REVERSE | UU_WALK_ROBUST)) == NULL)
6542 6667                          nomem();
6543 6668  
6544 6669                  while ((node = uu_avl_walk_next(walk)) != NULL) {
6545 6670                          uu_avl_remove(tree, node);
6546 6671  
↓ open down ↓ 309 lines elided ↑ open up ↑
6856 6981                              gettext("invalid option '%c'\n"), optopt);
6857 6982                          usage(B_FALSE);
6858 6983                  }
6859 6984          }
6860 6985  
6861 6986          argc -= optind;
6862 6987          argv += optind;
6863 6988  
6864 6989          if (argc < 1) {
6865 6990                  (void) fprintf(stderr,
6866      -                    gettext("must provide at least one snapshot name\n"));
     6991 +                gettext("must provide at least one snapshot name\n"));
6867 6992                  usage(B_FALSE);
6868 6993          }
6869 6994  
6870 6995          if (argc > 2) {
6871 6996                  (void) fprintf(stderr, gettext("too many arguments\n"));
6872 6997                  usage(B_FALSE);
6873 6998          }
6874 6999  
6875 7000          fromsnap = argv[0];
6876 7001          tosnap = (argc == 2) ? argv[1] : NULL;
↓ open down ↓ 20 lines elided ↑ open up ↑
6897 7022           */
6898 7023          (void) sigignore(SIGPIPE);
6899 7024  
6900 7025          err = zfs_show_diffs(zhp, STDOUT_FILENO, fromsnap, tosnap, flags);
6901 7026  
6902 7027          zfs_close(zhp);
6903 7028  
6904 7029          return (err != 0);
6905 7030  }
6906 7031  
6907      -static int
6908      -zfs_do_remap(int argc, char **argv)
6909      -{
6910      -        const char *fsname;
6911      -        int err = 0;
6912      -        if (argc != 2) {
6913      -                (void) fprintf(stderr, gettext("wrong number of arguments\n"));
6914      -                usage(B_FALSE);
6915      -        }
6916      -
6917      -        fsname = argv[1];
6918      -        err = zfs_remap_indirects(g_zfs, fsname);
6919      -
6920      -        return (err);
6921      -}
6922      -
6923 7032  /*
6924 7033   * zfs bookmark <fs@snap> <fs#bmark>
6925 7034   *
6926 7035   * Creates a bookmark with the given name from the given snapshot.
6927 7036   */
6928 7037  static int
6929 7038  zfs_do_bookmark(int argc, char **argv)
6930 7039  {
6931 7040          char snapname[ZFS_MAX_DATASET_NAME_LEN];
6932 7041          zfs_handle_t *zhp;
↓ open down ↓ 299 lines elided ↑ open up ↑
7232 7341  
7233 7342          opterr = 0;
7234 7343  
7235 7344          if ((g_zfs = libzfs_init()) == NULL) {
7236 7345                  (void) fprintf(stderr, gettext("internal error: failed to "
7237 7346                      "initialize ZFS library\n"));
7238 7347                  return (1);
7239 7348          }
7240 7349  
7241 7350          zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
     7351 +        verify(zpool_stage_history(g_zfs, history_str) == 0);
7242 7352  
7243 7353          libzfs_print_on_error(g_zfs, B_TRUE);
7244 7354  
7245 7355          if ((mnttab_file = fopen(MNTTAB, "r")) == NULL) {
7246 7356                  (void) fprintf(stderr, gettext("internal error: unable to "
7247 7357                      "open %s\n"), MNTTAB);
7248 7358                  return (1);
7249 7359          }
7250 7360  
7251 7361          /*
↓ open down ↓ 80 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX