Print this page
2882 implement libzfs_core
2883 changing "canmount" property to "on" should not always remount dataset
2900 "zfs snapshot" should be able to create multiple, arbitrary snapshots at once
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Chris Siden <christopher.siden@delphix.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Bill Pijewski <wdp@joyent.com>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/zfs_ioctl.c
          +++ new/usr/src/uts/common/fs/zfs/zfs_ioctl.c
↓ open down ↓ 15 lines elided ↑ open up ↑
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Portions Copyright 2011 Martin Matuska
  25   25   * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  26      - * Copyright (c) 2012 by Delphix. All rights reserved.
  27   26   * Copyright (c) 2012, Joyent, Inc. All rights reserved.
       27 + * Copyright (c) 2012 by Delphix. All rights reserved.
       28 + */
       29 +
       30 +/*
       31 + * ZFS ioctls.
       32 + *
       33 + * This file handles the ioctls to /dev/zfs, used for configuring ZFS storage
       34 + * pools and filesystems, e.g. with /sbin/zfs and /sbin/zpool.
       35 + *
       36 + * There are two ways that we handle ioctls: the legacy way where almost
       37 + * all of the logic is in the ioctl callback, and the new way where most
       38 + * of the marshalling is handled in the common entry point, zfsdev_ioctl().
       39 + *
       40 + * Non-legacy ioctls should be registered by calling
       41 + * zfs_ioctl_register() from zfs_ioctl_init().  The ioctl is invoked
       42 + * from userland by lzc_ioctl().
       43 + *
       44 + * The registration arguments are as follows:
       45 + *
       46 + * const char *name
       47 + *   The name of the ioctl.  This is used for history logging.  If the
       48 + *   ioctl returns successfully (the callback returns 0), and allow_log
       49 + *   is true, then a history log entry will be recorded with the input &
       50 + *   output nvlists.  The log entry can be printed with "zpool history -i".
       51 + *
       52 + * zfs_ioc_t ioc
       53 + *   The ioctl request number, which userland will pass to ioctl(2).
       54 + *   The ioctl numbers can change from release to release, because
       55 + *   the caller (libzfs) must be matched to the kernel.
       56 + *
       57 + * zfs_secpolicy_func_t *secpolicy
       58 + *   This function will be called before the zfs_ioc_func_t, to
       59 + *   determine if this operation is permitted.  It should return EPERM
       60 + *   on failure, and 0 on success.  Checks include determining if the
       61 + *   dataset is visible in this zone, and if the user has either all
       62 + *   zfs privileges in the zone (SYS_MOUNT), or has been granted permission
       63 + *   to do this operation on this dataset with "zfs allow".
       64 + *
       65 + * zfs_ioc_namecheck_t namecheck
       66 + *   This specifies what to expect in the zfs_cmd_t:zc_name -- a pool
       67 + *   name, a dataset name, or nothing.  If the name is not well-formed,
       68 + *   the ioctl will fail and the callback will not be called.
       69 + *   Therefore, the callback can assume that the name is well-formed
       70 + *   (e.g. is null-terminated, doesn't have more than one '@' character,
       71 + *   doesn't have invalid characters).
       72 + *
       73 + * zfs_ioc_poolcheck_t pool_check
       74 + *   This specifies requirements on the pool state.  If the pool does
       75 + *   not meet them (is suspended or is readonly), the ioctl will fail
       76 + *   and the callback will not be called.  If any checks are specified
       77 + *   (i.e. it is not POOL_CHECK_NONE), namecheck must not be NO_NAME.
       78 + *   Multiple checks can be or-ed together (e.g. POOL_CHECK_SUSPENDED |
       79 + *   POOL_CHECK_READONLY).
       80 + *
       81 + * boolean_t smush_outnvlist
       82 + *   If smush_outnvlist is true, then the output is presumed to be a
       83 + *   list of errors, and it will be "smushed" down to fit into the
       84 + *   caller's buffer, by removing some entries and replacing them with a
       85 + *   single "N_MORE_ERRORS" entry indicating how many were removed.  See
       86 + *   nvlist_smush() for details.  If smush_outnvlist is false, and the
       87 + *   outnvlist does not fit into the userland-provided buffer, then the
       88 + *   ioctl will fail with ENOMEM.
       89 + *
       90 + * zfs_ioc_func_t *func
       91 + *   The callback function that will perform the operation.
       92 + *
       93 + *   The callback should return 0 on success, or an error number on
       94 + *   failure.  If the function fails, the userland ioctl will return -1,
       95 + *   and errno will be set to the callback's return value.  The callback
       96 + *   will be called with the following arguments:
       97 + *
       98 + *   const char *name
       99 + *     The name of the pool or dataset to operate on, from
      100 + *     zfs_cmd_t:zc_name.  The 'namecheck' argument specifies the
      101 + *     expected type (pool, dataset, or none).
      102 + *
      103 + *   nvlist_t *innvl
      104 + *     The input nvlist, deserialized from zfs_cmd_t:zc_nvlist_src.  Or
      105 + *     NULL if no input nvlist was provided.  Changes to this nvlist are
      106 + *     ignored.  If the input nvlist could not be deserialized, the
      107 + *     ioctl will fail and the callback will not be called.
      108 + *
      109 + *   nvlist_t *outnvl
      110 + *     The output nvlist, initially empty.  The callback can fill it in,
      111 + *     and it will be returned to userland by serializing it into
      112 + *     zfs_cmd_t:zc_nvlist_dst.  If it is non-empty, and serialization
      113 + *     fails (e.g. because the caller didn't supply a large enough
      114 + *     buffer), then the overall ioctl will fail.  See the
      115 + *     'smush_nvlist' argument above for additional behaviors.
      116 + *
      117 + *     There are two typical uses of the output nvlist:
      118 + *       - To return state, e.g. property values.  In this case,
      119 + *         smush_outnvlist should be false.  If the buffer was not large
      120 + *         enough, the caller will reallocate a larger buffer and try
      121 + *         the ioctl again.
      122 + *
      123 + *       - To return multiple errors from an ioctl which makes on-disk
      124 + *         changes.  In this case, smush_outnvlist should be true.
      125 + *         Ioctls which make on-disk modifications should generally not
      126 + *         use the outnvl if they succeed, because the caller can not
      127 + *         distinguish between the operation failing, and
      128 + *         deserialization failing.
  28  129   */
  29  130  
  30  131  #include <sys/types.h>
  31  132  #include <sys/param.h>
  32  133  #include <sys/errno.h>
  33  134  #include <sys/uio.h>
  34  135  #include <sys/buf.h>
  35  136  #include <sys/modctl.h>
  36  137  #include <sys/open.h>
  37  138  #include <sys/file.h>
↓ open down ↓ 40 lines elided ↑ open up ↑
  78  179  #include "zfs_comutil.h"
  79  180  
  80  181  extern struct modlfs zfs_modlfs;
  81  182  
  82  183  extern void zfs_init(void);
  83  184  extern void zfs_fini(void);
  84  185  
  85  186  ldi_ident_t zfs_li = NULL;
  86  187  dev_info_t *zfs_dip;
  87  188  
  88      -typedef int zfs_ioc_func_t(zfs_cmd_t *);
  89      -typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *);
      189 +uint_t zfs_fsyncer_key;
      190 +extern uint_t rrw_tsd_key;
      191 +static uint_t zfs_allow_log_key;
      192 +
      193 +typedef int zfs_ioc_legacy_func_t(zfs_cmd_t *);
      194 +typedef int zfs_ioc_func_t(const char *, nvlist_t *, nvlist_t *);
      195 +typedef int zfs_secpolicy_func_t(zfs_cmd_t *, nvlist_t *, cred_t *);
  90  196  
  91  197  typedef enum {
  92  198          NO_NAME,
  93  199          POOL_NAME,
  94  200          DATASET_NAME
  95  201  } zfs_ioc_namecheck_t;
  96  202  
  97  203  typedef enum {
  98  204          POOL_CHECK_NONE         = 1 << 0,
  99  205          POOL_CHECK_SUSPENDED    = 1 << 1,
 100      -        POOL_CHECK_READONLY     = 1 << 2
      206 +        POOL_CHECK_READONLY     = 1 << 2,
 101  207  } zfs_ioc_poolcheck_t;
 102  208  
 103  209  typedef struct zfs_ioc_vec {
      210 +        zfs_ioc_legacy_func_t   *zvec_legacy_func;
 104  211          zfs_ioc_func_t          *zvec_func;
 105  212          zfs_secpolicy_func_t    *zvec_secpolicy;
 106  213          zfs_ioc_namecheck_t     zvec_namecheck;
 107      -        boolean_t               zvec_his_log;
      214 +        boolean_t               zvec_allow_log;
 108  215          zfs_ioc_poolcheck_t     zvec_pool_check;
      216 +        boolean_t               zvec_smush_outnvlist;
      217 +        const char              *zvec_name;
 109  218  } zfs_ioc_vec_t;
 110  219  
 111  220  /* This array is indexed by zfs_userquota_prop_t */
 112  221  static const char *userquota_perms[] = {
 113  222          ZFS_DELEG_PERM_USERUSED,
 114  223          ZFS_DELEG_PERM_USERQUOTA,
 115  224          ZFS_DELEG_PERM_GROUPUSED,
 116  225          ZFS_DELEG_PERM_GROUPQUOTA,
 117  226  };
 118  227  
 119  228  static int zfs_ioc_userspace_upgrade(zfs_cmd_t *zc);
 120  229  static int zfs_check_settable(const char *name, nvpair_t *property,
 121  230      cred_t *cr);
 122  231  static int zfs_check_clearable(char *dataset, nvlist_t *props,
 123  232      nvlist_t **errors);
 124  233  static int zfs_fill_zplprops_root(uint64_t, nvlist_t *, nvlist_t *,
 125  234      boolean_t *);
 126      -int zfs_set_prop_nvlist(const char *, zprop_source_t, nvlist_t *, nvlist_t **);
      235 +int zfs_set_prop_nvlist(const char *, zprop_source_t, nvlist_t *, nvlist_t *);
      236 +static int get_nvlist(uint64_t nvl, uint64_t size, int iflag, nvlist_t **nvp);
 127  237  
 128  238  /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */
 129  239  void
 130  240  __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
 131  241  {
 132  242          const char *newfile;
 133  243          char buf[512];
 134  244          va_list adx;
 135  245  
 136  246          /*
↓ open down ↓ 117 lines elided ↑ open up ↑
 254  364  zfs_log_history(zfs_cmd_t *zc)
 255  365  {
 256  366          spa_t *spa;
 257  367          char *buf;
 258  368  
 259  369          if ((buf = history_str_get(zc)) == NULL)
 260  370                  return;
 261  371  
 262  372          if (spa_open(zc->zc_name, &spa, FTAG) == 0) {
 263  373                  if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY)
 264      -                        (void) spa_history_log(spa, buf, LOG_CMD_NORMAL);
      374 +                        (void) spa_history_log(spa, buf);
 265  375                  spa_close(spa, FTAG);
 266  376          }
 267  377          history_str_free(buf);
 268  378  }
 269  379  
 270  380  /*
 271  381   * Policy for top-level read operations (list pools).  Requires no privileges,
 272  382   * and can be used in the local zone, as there is no associated dataset.
 273  383   */
 274  384  /* ARGSUSED */
 275  385  static int
 276      -zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr)
      386 +zfs_secpolicy_none(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 277  387  {
 278  388          return (0);
 279  389  }
 280  390  
 281  391  /*
 282  392   * Policy for dataset read operations (list children, get statistics).  Requires
 283  393   * no privileges, but must be visible in the local zone.
 284  394   */
 285  395  /* ARGSUSED */
 286  396  static int
 287      -zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr)
      397 +zfs_secpolicy_read(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 288  398  {
 289  399          if (INGLOBALZONE(curproc) ||
 290  400              zone_dataset_visible(zc->zc_name, NULL))
 291  401                  return (0);
 292  402  
 293  403          return (ENOENT);
 294  404  }
 295  405  
 296  406  static int
 297  407  zfs_dozonecheck_impl(const char *dataset, uint64_t zoned, cred_t *cr)
↓ open down ↓ 48 lines elided ↑ open up ↑
 346  456          rw_enter(&ds->ds_dir->dd_pool->dp_config_rwlock, RW_READER);
 347  457          if (dsl_prop_get_ds(ds, "zoned", 8, 1, &zoned, NULL)) {
 348  458                  rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock);
 349  459                  return (ENOENT);
 350  460          }
 351  461          rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock);
 352  462  
 353  463          return (zfs_dozonecheck_impl(dataset, zoned, cr));
 354  464  }
 355  465  
 356      -/*
 357      - * If name ends in a '@', then require recursive permissions.
 358      - */
 359      -int
      466 +static int
 360  467  zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr)
 361  468  {
 362  469          int error;
 363      -        boolean_t descendent = B_FALSE;
 364  470          dsl_dataset_t *ds;
 365      -        char *at;
 366      -
 367      -        at = strchr(name, '@');
 368      -        if (at != NULL && at[1] == '\0') {
 369      -                *at = '\0';
 370      -                descendent = B_TRUE;
 371      -        }
 372  471  
 373  472          error = dsl_dataset_hold(name, FTAG, &ds);
 374      -        if (at != NULL)
 375      -                *at = '@';
 376  473          if (error != 0)
 377  474                  return (error);
 378  475  
 379  476          error = zfs_dozonecheck_ds(name, ds, cr);
 380  477          if (error == 0) {
 381  478                  error = secpolicy_zfs(cr);
 382  479                  if (error)
 383      -                        error = dsl_deleg_access_impl(ds, descendent, perm, cr);
      480 +                        error = dsl_deleg_access_impl(ds, perm, cr);
 384  481          }
 385  482  
 386  483          dsl_dataset_rele(ds, FTAG);
 387  484          return (error);
 388  485  }
 389  486  
 390      -int
      487 +static int
 391  488  zfs_secpolicy_write_perms_ds(const char *name, dsl_dataset_t *ds,
 392  489      const char *perm, cred_t *cr)
 393  490  {
 394  491          int error;
 395  492  
 396  493          error = zfs_dozonecheck_ds(name, ds, cr);
 397  494          if (error == 0) {
 398  495                  error = secpolicy_zfs(cr);
 399  496                  if (error)
 400      -                        error = dsl_deleg_access_impl(ds, B_FALSE, perm, cr);
      497 +                        error = dsl_deleg_access_impl(ds, perm, cr);
 401  498          }
 402  499          return (error);
 403  500  }
 404  501  
 405  502  /*
 406  503   * Policy for setting the security label property.
 407  504   *
 408  505   * Returns 0 for success, non-zero for access and other errors.
 409  506   */
 410  507  static int
↓ open down ↓ 133 lines elided ↑ open up ↑
 544  641                          err = zfs_set_slabel_policy(dsname, strval, CRED());
 545  642                          if (err != 0)
 546  643                                  return (err);
 547  644                  }
 548  645                  break;
 549  646          }
 550  647  
 551  648          return (zfs_secpolicy_write_perms(dsname, zfs_prop_to_name(prop), cr));
 552  649  }
 553  650  
 554      -int
 555      -zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr)
      651 +/* ARGSUSED */
      652 +static int
      653 +zfs_secpolicy_set_fsacl(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 556  654  {
 557  655          int error;
 558  656  
 559  657          error = zfs_dozonecheck(zc->zc_name, cr);
 560  658          if (error)
 561  659                  return (error);
 562  660  
 563  661          /*
 564  662           * permission to set permissions will be evaluated later in
 565  663           * dsl_deleg_can_allow()
 566  664           */
 567  665          return (0);
 568  666  }
 569  667  
 570      -int
 571      -zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr)
      668 +/* ARGSUSED */
      669 +static int
      670 +zfs_secpolicy_rollback(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 572  671  {
 573  672          return (zfs_secpolicy_write_perms(zc->zc_name,
 574  673              ZFS_DELEG_PERM_ROLLBACK, cr));
 575  674  }
 576  675  
 577      -int
 578      -zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr)
      676 +/* ARGSUSED */
      677 +static int
      678 +zfs_secpolicy_send(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 579  679  {
 580  680          spa_t *spa;
 581  681          dsl_pool_t *dp;
 582  682          dsl_dataset_t *ds;
 583  683          char *cp;
 584  684          int error;
 585  685  
 586  686          /*
 587  687           * Generate the current snapshot name from the given objsetid, then
 588  688           * use that name for the secpolicy/zone checks.
↓ open down ↓ 15 lines elided ↑ open up ↑
 604  704  
 605  705          dsl_dataset_name(ds, zc->zc_name);
 606  706  
 607  707          error = zfs_secpolicy_write_perms_ds(zc->zc_name, ds,
 608  708              ZFS_DELEG_PERM_SEND, cr);
 609  709          dsl_dataset_rele(ds, FTAG);
 610  710  
 611  711          return (error);
 612  712  }
 613  713  
      714 +/* ARGSUSED */
      715 +static int
      716 +zfs_secpolicy_send_new(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
      717 +{
      718 +        return (zfs_secpolicy_write_perms(zc->zc_name,
      719 +            ZFS_DELEG_PERM_SEND, cr));
      720 +}
      721 +
      722 +/* ARGSUSED */
 614  723  static int
 615      -zfs_secpolicy_deleg_share(zfs_cmd_t *zc, cred_t *cr)
      724 +zfs_secpolicy_deleg_share(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 616  725  {
 617  726          vnode_t *vp;
 618  727          int error;
 619  728  
 620  729          if ((error = lookupname(zc->zc_value, UIO_SYSSPACE,
 621  730              NO_FOLLOW, NULL, &vp)) != 0)
 622  731                  return (error);
 623  732  
 624  733          /* Now make sure mntpnt and dataset are ZFS */
 625  734  
↓ open down ↓ 3 lines elided ↑ open up ↑
 629  738                  VN_RELE(vp);
 630  739                  return (EPERM);
 631  740          }
 632  741  
 633  742          VN_RELE(vp);
 634  743          return (dsl_deleg_access(zc->zc_name,
 635  744              ZFS_DELEG_PERM_SHARE, cr));
 636  745  }
 637  746  
 638  747  int
 639      -zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr)
      748 +zfs_secpolicy_share(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 640  749  {
 641  750          if (!INGLOBALZONE(curproc))
 642  751                  return (EPERM);
 643  752  
 644  753          if (secpolicy_nfs(cr) == 0) {
 645  754                  return (0);
 646  755          } else {
 647      -                return (zfs_secpolicy_deleg_share(zc, cr));
      756 +                return (zfs_secpolicy_deleg_share(zc, innvl, cr));
 648  757          }
 649  758  }
 650  759  
 651  760  int
 652      -zfs_secpolicy_smb_acl(zfs_cmd_t *zc, cred_t *cr)
      761 +zfs_secpolicy_smb_acl(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 653  762  {
 654  763          if (!INGLOBALZONE(curproc))
 655  764                  return (EPERM);
 656  765  
 657  766          if (secpolicy_smb(cr) == 0) {
 658  767                  return (0);
 659  768          } else {
 660      -                return (zfs_secpolicy_deleg_share(zc, cr));
      769 +                return (zfs_secpolicy_deleg_share(zc, innvl, cr));
 661  770          }
 662  771  }
 663  772  
 664  773  static int
 665  774  zfs_get_parent(const char *datasetname, char *parent, int parentsize)
 666  775  {
 667  776          char *cp;
 668  777  
 669  778          /*
 670  779           * Remove the @bla or /bla from the end of the name to get the parent.
↓ open down ↓ 17 lines elided ↑ open up ↑
 688  797  {
 689  798          int error;
 690  799  
 691  800          if ((error = zfs_secpolicy_write_perms(name,
 692  801              ZFS_DELEG_PERM_MOUNT, cr)) != 0)
 693  802                  return (error);
 694  803  
 695  804          return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr));
 696  805  }
 697  806  
      807 +/* ARGSUSED */
 698  808  static int
 699      -zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr)
      809 +zfs_secpolicy_destroy(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 700  810  {
 701  811          return (zfs_secpolicy_destroy_perms(zc->zc_name, cr));
 702  812  }
 703  813  
 704  814  /*
 705  815   * Destroying snapshots with delegated permissions requires
 706      - * descendent mount and destroy permissions.
      816 + * descendant mount and destroy permissions.
 707  817   */
      818 +/* ARGSUSED */
 708  819  static int
 709      -zfs_secpolicy_destroy_recursive(zfs_cmd_t *zc, cred_t *cr)
      820 +zfs_secpolicy_destroy_snaps(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 710  821  {
 711      -        int error;
 712      -        char *dsname;
      822 +        nvlist_t *snaps;
      823 +        nvpair_t *pair, *nextpair;
      824 +        int error = 0;
 713  825  
 714      -        dsname = kmem_asprintf("%s@", zc->zc_name);
      826 +        if (nvlist_lookup_nvlist(innvl, "snaps", &snaps) != 0)
      827 +                return (EINVAL);
      828 +        for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
      829 +            pair = nextpair) {
      830 +                dsl_dataset_t *ds;
 715  831  
 716      -        error = zfs_secpolicy_destroy_perms(dsname, cr);
      832 +                nextpair = nvlist_next_nvpair(snaps, pair);
      833 +                error = dsl_dataset_hold(nvpair_name(pair), FTAG, &ds);
      834 +                if (error == 0) {
      835 +                        dsl_dataset_rele(ds, FTAG);
      836 +                } else if (error == ENOENT) {
      837 +                        /*
      838 +                         * Ignore any snapshots that don't exist (we consider
      839 +                         * them "already destroyed").  Remove the name from the
      840 +                         * nvl here in case the snapshot is created between
      841 +                         * now and when we try to destroy it (in which case
      842 +                         * we don't want to destroy it since we haven't
      843 +                         * checked for permission).
      844 +                         */
      845 +                        fnvlist_remove_nvpair(snaps, pair);
      846 +                        error = 0;
      847 +                        continue;
      848 +                } else {
      849 +                        break;
      850 +                }
      851 +                error = zfs_secpolicy_destroy_perms(nvpair_name(pair), cr);
      852 +                if (error != 0)
      853 +                        break;
      854 +        }
 717  855  
 718      -        strfree(dsname);
 719  856          return (error);
 720  857  }
 721  858  
 722  859  int
 723  860  zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
 724  861  {
 725  862          char    parentname[MAXNAMELEN];
 726  863          int     error;
 727  864  
 728  865          if ((error = zfs_secpolicy_write_perms(from,
↓ open down ↓ 12 lines elided ↑ open up ↑
 741  878              ZFS_DELEG_PERM_CREATE, cr)) != 0)
 742  879                  return (error);
 743  880  
 744  881          if ((error = zfs_secpolicy_write_perms(parentname,
 745  882              ZFS_DELEG_PERM_MOUNT, cr)) != 0)
 746  883                  return (error);
 747  884  
 748  885          return (error);
 749  886  }
 750  887  
      888 +/* ARGSUSED */
 751  889  static int
 752      -zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr)
      890 +zfs_secpolicy_rename(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 753  891  {
 754  892          return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr));
 755  893  }
 756  894  
      895 +/* ARGSUSED */
 757  896  static int
 758      -zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr)
      897 +zfs_secpolicy_promote(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 759  898  {
 760  899          char    parentname[MAXNAMELEN];
 761  900          objset_t *clone;
 762  901          int error;
 763  902  
 764  903          error = zfs_secpolicy_write_perms(zc->zc_name,
 765  904              ZFS_DELEG_PERM_PROMOTE, cr);
 766  905          if (error)
 767  906                  return (error);
 768  907  
↓ open down ↓ 19 lines elided ↑ open up ↑
 788  927                  dsl_dataset_name(pclone, parentname);
 789  928                  dmu_objset_rele(clone, FTAG);
 790  929                  dsl_dataset_rele(pclone, FTAG);
 791  930                  if (error == 0)
 792  931                          error = zfs_secpolicy_write_perms(parentname,
 793  932                              ZFS_DELEG_PERM_PROMOTE, cr);
 794  933          }
 795  934          return (error);
 796  935  }
 797  936  
      937 +/* ARGSUSED */
 798  938  static int
 799      -zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr)
      939 +zfs_secpolicy_recv(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 800  940  {
 801  941          int error;
 802  942  
 803  943          if ((error = zfs_secpolicy_write_perms(zc->zc_name,
 804  944              ZFS_DELEG_PERM_RECEIVE, cr)) != 0)
 805  945                  return (error);
 806  946  
 807  947          if ((error = zfs_secpolicy_write_perms(zc->zc_name,
 808  948              ZFS_DELEG_PERM_MOUNT, cr)) != 0)
 809  949                  return (error);
↓ open down ↓ 2 lines elided ↑ open up ↑
 812  952              ZFS_DELEG_PERM_CREATE, cr));
 813  953  }
 814  954  
 815  955  int
 816  956  zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
 817  957  {
 818  958          return (zfs_secpolicy_write_perms(name,
 819  959              ZFS_DELEG_PERM_SNAPSHOT, cr));
 820  960  }
 821  961  
      962 +/*
      963 + * Check for permission to create each snapshot in the nvlist.
      964 + */
      965 +/* ARGSUSED */
 822  966  static int
 823      -zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr)
      967 +zfs_secpolicy_snapshot(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 824  968  {
      969 +        nvlist_t *snaps;
      970 +        int error;
      971 +        nvpair_t *pair;
 825  972  
 826      -        return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr));
      973 +        if (nvlist_lookup_nvlist(innvl, "snaps", &snaps) != 0)
      974 +                return (EINVAL);
      975 +        for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
      976 +            pair = nvlist_next_nvpair(snaps, pair)) {
      977 +                char *name = nvpair_name(pair);
      978 +                char *atp = strchr(name, '@');
      979 +
      980 +                if (atp == NULL) {
      981 +                        error = EINVAL;
      982 +                        break;
      983 +                }
      984 +                *atp = '\0';
      985 +                error = zfs_secpolicy_snapshot_perms(name, cr);
      986 +                *atp = '@';
      987 +                if (error != 0)
      988 +                        break;
      989 +        }
      990 +        return (error);
      991 +}
      992 +
      993 +/* ARGSUSED */
      994 +static int
      995 +zfs_secpolicy_log_history(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
      996 +{
      997 +        /*
      998 +         * Even root must have a proper TSD so that we know what pool
      999 +         * to log to.
     1000 +         */
     1001 +        if (tsd_get(zfs_allow_log_key) == NULL)
     1002 +                return (EPERM);
     1003 +        return (0);
 827 1004  }
 828 1005  
 829 1006  static int
 830      -zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr)
     1007 +zfs_secpolicy_create_clone(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 831 1008  {
 832 1009          char    parentname[MAXNAMELEN];
 833 1010          int     error;
     1011 +        char    *origin;
 834 1012  
 835 1013          if ((error = zfs_get_parent(zc->zc_name, parentname,
 836 1014              sizeof (parentname))) != 0)
 837 1015                  return (error);
 838 1016  
 839      -        if (zc->zc_value[0] != '\0') {
 840      -                if ((error = zfs_secpolicy_write_perms(zc->zc_value,
 841      -                    ZFS_DELEG_PERM_CLONE, cr)) != 0)
 842      -                        return (error);
 843      -        }
     1017 +        if (nvlist_lookup_string(innvl, "origin", &origin) == 0 &&
     1018 +            (error = zfs_secpolicy_write_perms(origin,
     1019 +            ZFS_DELEG_PERM_CLONE, cr)) != 0)
     1020 +                return (error);
 844 1021  
 845 1022          if ((error = zfs_secpolicy_write_perms(parentname,
 846 1023              ZFS_DELEG_PERM_CREATE, cr)) != 0)
 847 1024                  return (error);
 848 1025  
 849      -        error = zfs_secpolicy_write_perms(parentname,
 850      -            ZFS_DELEG_PERM_MOUNT, cr);
 851      -
 852      -        return (error);
 853      -}
 854      -
 855      -static int
 856      -zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr)
 857      -{
 858      -        int error;
 859      -
 860      -        error = secpolicy_fs_unmount(cr, NULL);
 861      -        if (error) {
 862      -                error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr);
 863      -        }
 864      -        return (error);
     1026 +        return (zfs_secpolicy_write_perms(parentname,
     1027 +            ZFS_DELEG_PERM_MOUNT, cr));
 865 1028  }
 866 1029  
 867 1030  /*
 868 1031   * Policy for pool operations - create/destroy pools, add vdevs, etc.  Requires
 869 1032   * SYS_CONFIG privilege, which is not available in a local zone.
 870 1033   */
 871 1034  /* ARGSUSED */
 872 1035  static int
 873      -zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr)
     1036 +zfs_secpolicy_config(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 874 1037  {
 875 1038          if (secpolicy_sys_config(cr, B_FALSE) != 0)
 876 1039                  return (EPERM);
 877 1040  
 878 1041          return (0);
 879 1042  }
 880 1043  
 881 1044  /*
 882 1045   * Policy for object to name lookups.
 883 1046   */
 884 1047  /* ARGSUSED */
 885 1048  static int
 886      -zfs_secpolicy_diff(zfs_cmd_t *zc, cred_t *cr)
     1049 +zfs_secpolicy_diff(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 887 1050  {
 888 1051          int error;
 889 1052  
 890 1053          if ((error = secpolicy_sys_config(cr, B_FALSE)) == 0)
 891 1054                  return (0);
 892 1055  
 893 1056          error = zfs_secpolicy_write_perms(zc->zc_name, ZFS_DELEG_PERM_DIFF, cr);
 894 1057          return (error);
 895 1058  }
 896 1059  
 897 1060  /*
 898 1061   * Policy for fault injection.  Requires all privileges.
 899 1062   */
 900 1063  /* ARGSUSED */
 901 1064  static int
 902      -zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr)
     1065 +zfs_secpolicy_inject(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 903 1066  {
 904 1067          return (secpolicy_zinject(cr));
 905 1068  }
 906 1069  
     1070 +/* ARGSUSED */
 907 1071  static int
 908      -zfs_secpolicy_inherit(zfs_cmd_t *zc, cred_t *cr)
     1072 +zfs_secpolicy_inherit_prop(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 909 1073  {
 910 1074          zfs_prop_t prop = zfs_name_to_prop(zc->zc_value);
 911 1075  
 912 1076          if (prop == ZPROP_INVAL) {
 913 1077                  if (!zfs_prop_user(zc->zc_value))
 914 1078                          return (EINVAL);
 915 1079                  return (zfs_secpolicy_write_perms(zc->zc_name,
 916 1080                      ZFS_DELEG_PERM_USERPROP, cr));
 917 1081          } else {
 918 1082                  return (zfs_secpolicy_setprop(zc->zc_name, prop,
 919 1083                      NULL, cr));
 920 1084          }
 921 1085  }
 922 1086  
 923 1087  static int
 924      -zfs_secpolicy_userspace_one(zfs_cmd_t *zc, cred_t *cr)
     1088 +zfs_secpolicy_userspace_one(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 925 1089  {
 926      -        int err = zfs_secpolicy_read(zc, cr);
     1090 +        int err = zfs_secpolicy_read(zc, innvl, cr);
 927 1091          if (err)
 928 1092                  return (err);
 929 1093  
 930 1094          if (zc->zc_objset_type >= ZFS_NUM_USERQUOTA_PROPS)
 931 1095                  return (EINVAL);
 932 1096  
 933 1097          if (zc->zc_value[0] == 0) {
 934 1098                  /*
 935 1099                   * They are asking about a posix uid/gid.  If it's
 936 1100                   * themself, allow it.
↓ open down ↓ 6 lines elided ↑ open up ↑
 943 1107                          if (groupmember(zc->zc_guid, cr))
 944 1108                                  return (0);
 945 1109                  }
 946 1110          }
 947 1111  
 948 1112          return (zfs_secpolicy_write_perms(zc->zc_name,
 949 1113              userquota_perms[zc->zc_objset_type], cr));
 950 1114  }
 951 1115  
 952 1116  static int
 953      -zfs_secpolicy_userspace_many(zfs_cmd_t *zc, cred_t *cr)
     1117 +zfs_secpolicy_userspace_many(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 954 1118  {
 955      -        int err = zfs_secpolicy_read(zc, cr);
     1119 +        int err = zfs_secpolicy_read(zc, innvl, cr);
 956 1120          if (err)
 957 1121                  return (err);
 958 1122  
 959 1123          if (zc->zc_objset_type >= ZFS_NUM_USERQUOTA_PROPS)
 960 1124                  return (EINVAL);
 961 1125  
 962 1126          return (zfs_secpolicy_write_perms(zc->zc_name,
 963 1127              userquota_perms[zc->zc_objset_type], cr));
 964 1128  }
 965 1129  
     1130 +/* ARGSUSED */
 966 1131  static int
 967      -zfs_secpolicy_userspace_upgrade(zfs_cmd_t *zc, cred_t *cr)
     1132 +zfs_secpolicy_userspace_upgrade(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 968 1133  {
 969 1134          return (zfs_secpolicy_setprop(zc->zc_name, ZFS_PROP_VERSION,
 970 1135              NULL, cr));
 971 1136  }
 972 1137  
     1138 +/* ARGSUSED */
 973 1139  static int
 974      -zfs_secpolicy_hold(zfs_cmd_t *zc, cred_t *cr)
     1140 +zfs_secpolicy_hold(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 975 1141  {
 976 1142          return (zfs_secpolicy_write_perms(zc->zc_name,
 977 1143              ZFS_DELEG_PERM_HOLD, cr));
 978 1144  }
 979 1145  
     1146 +/* ARGSUSED */
 980 1147  static int
 981      -zfs_secpolicy_release(zfs_cmd_t *zc, cred_t *cr)
     1148 +zfs_secpolicy_release(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 982 1149  {
 983 1150          return (zfs_secpolicy_write_perms(zc->zc_name,
 984 1151              ZFS_DELEG_PERM_RELEASE, cr));
 985 1152  }
 986 1153  
 987 1154  /*
 988 1155   * Policy for allowing temporary snapshots to be taken or released
 989 1156   */
 990 1157  static int
 991      -zfs_secpolicy_tmp_snapshot(zfs_cmd_t *zc, cred_t *cr)
     1158 +zfs_secpolicy_tmp_snapshot(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 992 1159  {
 993 1160          /*
 994 1161           * A temporary snapshot is the same as a snapshot,
 995 1162           * hold, destroy and release all rolled into one.
 996 1163           * Delegated diff alone is sufficient that we allow this.
 997 1164           */
 998 1165          int error;
 999 1166  
1000 1167          if ((error = zfs_secpolicy_write_perms(zc->zc_name,
1001 1168              ZFS_DELEG_PERM_DIFF, cr)) == 0)
1002 1169                  return (0);
1003 1170  
1004      -        error = zfs_secpolicy_snapshot(zc, cr);
     1171 +        error = zfs_secpolicy_snapshot_perms(zc->zc_name, cr);
1005 1172          if (!error)
1006      -                error = zfs_secpolicy_hold(zc, cr);
     1173 +                error = zfs_secpolicy_hold(zc, innvl, cr);
1007 1174          if (!error)
1008      -                error = zfs_secpolicy_release(zc, cr);
     1175 +                error = zfs_secpolicy_release(zc, innvl, cr);
1009 1176          if (!error)
1010      -                error = zfs_secpolicy_destroy(zc, cr);
     1177 +                error = zfs_secpolicy_destroy(zc, innvl, cr);
1011 1178          return (error);
1012 1179  }
1013 1180  
1014 1181  /*
1015 1182   * Returns the nvlist as specified by the user in the zfs_cmd_t.
1016 1183   */
1017 1184  static int
1018 1185  get_nvlist(uint64_t nvl, uint64_t size, int iflag, nvlist_t **nvp)
1019 1186  {
1020 1187          char *packed;
↓ open down ↓ 18 lines elided ↑ open up ↑
1039 1206                  kmem_free(packed, size);
1040 1207                  return (error);
1041 1208          }
1042 1209  
1043 1210          kmem_free(packed, size);
1044 1211  
1045 1212          *nvp = list;
1046 1213          return (0);
1047 1214  }
1048 1215  
     1216 +/*
     1217 + * Reduce the size of this nvlist until it can be serialized in 'max' bytes.
     1218 + * Entries will be removed from the end of the nvlist, and one int32 entry
     1219 + * named "N_MORE_ERRORS" will be added indicating how many entries were
     1220 + * removed.
     1221 + */
1049 1222  static int
1050      -fit_error_list(zfs_cmd_t *zc, nvlist_t **errors)
     1223 +nvlist_smush(nvlist_t *errors, size_t max)
1051 1224  {
1052 1225          size_t size;
1053 1226  
1054      -        VERIFY(nvlist_size(*errors, &size, NV_ENCODE_NATIVE) == 0);
     1227 +        size = fnvlist_size(errors);
1055 1228  
1056      -        if (size > zc->zc_nvlist_dst_size) {
     1229 +        if (size > max) {
1057 1230                  nvpair_t *more_errors;
1058 1231                  int n = 0;
1059 1232  
1060      -                if (zc->zc_nvlist_dst_size < 1024)
     1233 +                if (max < 1024)
1061 1234                          return (ENOMEM);
1062 1235  
1063      -                VERIFY(nvlist_add_int32(*errors, ZPROP_N_MORE_ERRORS, 0) == 0);
1064      -                more_errors = nvlist_prev_nvpair(*errors, NULL);
     1236 +                fnvlist_add_int32(errors, ZPROP_N_MORE_ERRORS, 0);
     1237 +                more_errors = nvlist_prev_nvpair(errors, NULL);
1065 1238  
1066 1239                  do {
1067      -                        nvpair_t *pair = nvlist_prev_nvpair(*errors,
     1240 +                        nvpair_t *pair = nvlist_prev_nvpair(errors,
1068 1241                              more_errors);
1069      -                        VERIFY(nvlist_remove_nvpair(*errors, pair) == 0);
     1242 +                        fnvlist_remove_nvpair(errors, pair);
1070 1243                          n++;
1071      -                        VERIFY(nvlist_size(*errors, &size,
1072      -                            NV_ENCODE_NATIVE) == 0);
1073      -                } while (size > zc->zc_nvlist_dst_size);
1074      -
1075      -                VERIFY(nvlist_remove_nvpair(*errors, more_errors) == 0);
1076      -                VERIFY(nvlist_add_int32(*errors, ZPROP_N_MORE_ERRORS, n) == 0);
1077      -                ASSERT(nvlist_size(*errors, &size, NV_ENCODE_NATIVE) == 0);
1078      -                ASSERT(size <= zc->zc_nvlist_dst_size);
     1244 +                        size = fnvlist_size(errors);
     1245 +                } while (size > max);
     1246 +
     1247 +                fnvlist_remove_nvpair(errors, more_errors);
     1248 +                fnvlist_add_int32(errors, ZPROP_N_MORE_ERRORS, n);
     1249 +                ASSERT3U(fnvlist_size(errors), <=, max);
1079 1250          }
1080 1251  
1081 1252          return (0);
1082 1253  }
1083 1254  
1084 1255  static int
1085 1256  put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl)
1086 1257  {
1087 1258          char *packed = NULL;
1088 1259          int error = 0;
1089 1260          size_t size;
1090 1261  
1091      -        VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0);
     1262 +        size = fnvlist_size(nvl);
1092 1263  
1093 1264          if (size > zc->zc_nvlist_dst_size) {
1094 1265                  error = ENOMEM;
1095 1266          } else {
1096      -                packed = kmem_alloc(size, KM_SLEEP);
1097      -                VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
1098      -                    KM_SLEEP) == 0);
     1267 +                packed = fnvlist_pack(nvl, &size);
1099 1268                  if (ddi_copyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst,
1100 1269                      size, zc->zc_iflags) != 0)
1101 1270                          error = EFAULT;
1102      -                kmem_free(packed, size);
     1271 +                fnvlist_pack_free(packed, size);
1103 1272          }
1104 1273  
1105 1274          zc->zc_nvlist_dst_size = size;
     1275 +        zc->zc_nvlist_dst_filled = B_TRUE;
1106 1276          return (error);
1107 1277  }
1108 1278  
1109 1279  static int
1110 1280  getzfsvfs(const char *dsname, zfsvfs_t **zfvp)
1111 1281  {
1112 1282          objset_t *os;
1113 1283          int error;
1114 1284  
1115 1285          error = dmu_objset_hold(dsname, FTAG, &os);
↓ open down ↓ 58 lines elided ↑ open up ↑
1174 1344          }
1175 1345  }
1176 1346  
1177 1347  static int
1178 1348  zfs_ioc_pool_create(zfs_cmd_t *zc)
1179 1349  {
1180 1350          int error;
1181 1351          nvlist_t *config, *props = NULL;
1182 1352          nvlist_t *rootprops = NULL;
1183 1353          nvlist_t *zplprops = NULL;
1184      -        char *buf;
1185 1354  
1186 1355          if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
1187 1356              zc->zc_iflags, &config))
1188 1357                  return (error);
1189 1358  
1190 1359          if (zc->zc_nvlist_src_size != 0 && (error =
1191 1360              get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
1192 1361              zc->zc_iflags, &props))) {
1193 1362                  nvlist_free(config);
1194 1363                  return (error);
↓ open down ↓ 19 lines elided ↑ open up ↑
1214 1383                          }
1215 1384                          (void) nvlist_remove_all(props, ZPOOL_ROOTFS_PROPS);
1216 1385                  }
1217 1386                  VERIFY(nvlist_alloc(&zplprops, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1218 1387                  error = zfs_fill_zplprops_root(version, rootprops,
1219 1388                      zplprops, NULL);
1220 1389                  if (error)
1221 1390                          goto pool_props_bad;
1222 1391          }
1223 1392  
1224      -        buf = history_str_get(zc);
1225      -
1226      -        error = spa_create(zc->zc_name, config, props, buf, zplprops);
     1393 +        error = spa_create(zc->zc_name, config, props, zplprops);
1227 1394  
1228 1395          /*
1229 1396           * Set the remaining root properties
1230 1397           */
1231 1398          if (!error && (error = zfs_set_prop_nvlist(zc->zc_name,
1232 1399              ZPROP_SRC_LOCAL, rootprops, NULL)) != 0)
1233 1400                  (void) spa_destroy(zc->zc_name);
1234 1401  
1235      -        if (buf != NULL)
1236      -                history_str_free(buf);
1237      -
1238 1402  pool_props_bad:
1239 1403          nvlist_free(rootprops);
1240 1404          nvlist_free(zplprops);
1241 1405          nvlist_free(config);
1242 1406          nvlist_free(props);
1243 1407  
1244 1408          return (error);
1245 1409  }
1246 1410  
1247 1411  static int
↓ open down ↓ 974 lines elided ↑ open up ↑
2222 2386  
2223 2387          default:
2224 2388                  err = -1;
2225 2389          }
2226 2390  
2227 2391          return (err);
2228 2392  }
2229 2393  
2230 2394  /*
2231 2395   * This function is best effort. If it fails to set any of the given properties,
2232      - * it continues to set as many as it can and returns the first error
2233      - * encountered. If the caller provides a non-NULL errlist, it also gives the
2234      - * complete list of names of all the properties it failed to set along with the
2235      - * corresponding error numbers. The caller is responsible for freeing the
2236      - * returned errlist.
     2396 + * it continues to set as many as it can and returns the last error
     2397 + * encountered. If the caller provides a non-NULL errlist, it will be filled in
     2398 + * with the list of names of all the properties that failed along with the
     2399 + * corresponding error numbers.
2237 2400   *
2238      - * If every property is set successfully, zero is returned and the list pointed
2239      - * at by errlist is NULL.
     2401 + * If every property is set successfully, zero is returned and errlist is not
     2402 + * modified.
2240 2403   */
2241 2404  int
2242 2405  zfs_set_prop_nvlist(const char *dsname, zprop_source_t source, nvlist_t *nvl,
2243      -    nvlist_t **errlist)
     2406 +    nvlist_t *errlist)
2244 2407  {
2245 2408          nvpair_t *pair;
2246 2409          nvpair_t *propval;
2247 2410          int rv = 0;
2248 2411          uint64_t intval;
2249 2412          char *strval;
2250      -        nvlist_t *genericnvl;
2251      -        nvlist_t *errors;
2252      -        nvlist_t *retrynvl;
2253      -
2254      -        VERIFY(nvlist_alloc(&genericnvl, NV_UNIQUE_NAME, KM_SLEEP) == 0);
2255      -        VERIFY(nvlist_alloc(&errors, NV_UNIQUE_NAME, KM_SLEEP) == 0);
2256      -        VERIFY(nvlist_alloc(&retrynvl, NV_UNIQUE_NAME, KM_SLEEP) == 0);
     2413 +        nvlist_t *genericnvl = fnvlist_alloc();
     2414 +        nvlist_t *retrynvl = fnvlist_alloc();
2257 2415  
2258 2416  retry:
2259 2417          pair = NULL;
2260 2418          while ((pair = nvlist_next_nvpair(nvl, pair)) != NULL) {
2261 2419                  const char *propname = nvpair_name(pair);
2262 2420                  zfs_prop_t prop = zfs_name_to_prop(propname);
2263 2421                  int err = 0;
2264 2422  
2265 2423                  /* decode the property value */
2266 2424                  propval = pair;
2267 2425                  if (nvpair_type(pair) == DATA_TYPE_NVLIST) {
2268 2426                          nvlist_t *attrs;
2269      -                        VERIFY(nvpair_value_nvlist(pair, &attrs) == 0);
     2427 +                        attrs = fnvpair_value_nvlist(pair);
2270 2428                          if (nvlist_lookup_nvpair(attrs, ZPROP_VALUE,
2271 2429                              &propval) != 0)
2272 2430                                  err = EINVAL;
2273 2431                  }
2274 2432  
2275 2433                  /* Validate value type */
2276 2434                  if (err == 0 && prop == ZPROP_INVAL) {
2277 2435                          if (zfs_prop_user(propname)) {
2278 2436                                  if (nvpair_type(propval) != DATA_TYPE_STRING)
2279 2437                                          err = EINVAL;
↓ open down ↓ 4 lines elided ↑ open up ↑
2284 2442                          } else {
2285 2443                                  err = EINVAL;
2286 2444                          }
2287 2445                  } else if (err == 0) {
2288 2446                          if (nvpair_type(propval) == DATA_TYPE_STRING) {
2289 2447                                  if (zfs_prop_get_type(prop) != PROP_TYPE_STRING)
2290 2448                                          err = EINVAL;
2291 2449                          } else if (nvpair_type(propval) == DATA_TYPE_UINT64) {
2292 2450                                  const char *unused;
2293 2451  
2294      -                                VERIFY(nvpair_value_uint64(propval,
2295      -                                    &intval) == 0);
     2452 +                                intval = fnvpair_value_uint64(propval);
2296 2453  
2297 2454                                  switch (zfs_prop_get_type(prop)) {
2298 2455                                  case PROP_TYPE_NUMBER:
2299 2456                                          break;
2300 2457                                  case PROP_TYPE_STRING:
2301 2458                                          err = EINVAL;
2302 2459                                          break;
2303 2460                                  case PROP_TYPE_INDEX:
2304 2461                                          if (zfs_prop_index_to_string(prop,
2305 2462                                              intval, &unused) != 0)
↓ open down ↓ 23 lines elided ↑ open up ↑
2329 2486                          } else if (err != 0 && nvl != retrynvl) {
2330 2487                                  /*
2331 2488                                   * This may be a spurious error caused by
2332 2489                                   * receiving quota and reservation out of order.
2333 2490                                   * Try again in a second pass.
2334 2491                                   */
2335 2492                                  err = nvlist_add_nvpair(retrynvl, pair);
2336 2493                          }
2337 2494                  }
2338 2495  
2339      -                if (err != 0)
2340      -                        VERIFY(nvlist_add_int32(errors, propname, err) == 0);
     2496 +                if (err != 0) {
     2497 +                        if (errlist != NULL)
     2498 +                                fnvlist_add_int32(errlist, propname, err);
     2499 +                        rv = err;
     2500 +                }
2341 2501          }
2342 2502  
2343 2503          if (nvl != retrynvl && !nvlist_empty(retrynvl)) {
2344 2504                  nvl = retrynvl;
2345 2505                  goto retry;
2346 2506          }
2347 2507  
2348 2508          if (!nvlist_empty(genericnvl) &&
2349 2509              dsl_props_set(dsname, source, genericnvl) != 0) {
2350 2510                  /*
↓ open down ↓ 1 lines elided ↑ open up ↑
2352 2512                   * can, so try setting them individually.
2353 2513                   */
2354 2514                  pair = NULL;
2355 2515                  while ((pair = nvlist_next_nvpair(genericnvl, pair)) != NULL) {
2356 2516                          const char *propname = nvpair_name(pair);
2357 2517                          int err = 0;
2358 2518  
2359 2519                          propval = pair;
2360 2520                          if (nvpair_type(pair) == DATA_TYPE_NVLIST) {
2361 2521                                  nvlist_t *attrs;
2362      -                                VERIFY(nvpair_value_nvlist(pair, &attrs) == 0);
2363      -                                VERIFY(nvlist_lookup_nvpair(attrs, ZPROP_VALUE,
2364      -                                    &propval) == 0);
     2522 +                                attrs = fnvpair_value_nvlist(pair);
     2523 +                                propval = fnvlist_lookup_nvpair(attrs,
     2524 +                                    ZPROP_VALUE);
2365 2525                          }
2366 2526  
2367 2527                          if (nvpair_type(propval) == DATA_TYPE_STRING) {
2368      -                                VERIFY(nvpair_value_string(propval,
2369      -                                    &strval) == 0);
     2528 +                                strval = fnvpair_value_string(propval);
2370 2529                                  err = dsl_prop_set(dsname, propname, source, 1,
2371 2530                                      strlen(strval) + 1, strval);
2372 2531                          } else {
2373      -                                VERIFY(nvpair_value_uint64(propval,
2374      -                                    &intval) == 0);
     2532 +                                intval = fnvpair_value_uint64(propval);
2375 2533                                  err = dsl_prop_set(dsname, propname, source, 8,
2376 2534                                      1, &intval);
2377 2535                          }
2378 2536  
2379 2537                          if (err != 0) {
2380      -                                VERIFY(nvlist_add_int32(errors, propname,
2381      -                                    err) == 0);
     2538 +                                if (errlist != NULL) {
     2539 +                                        fnvlist_add_int32(errlist, propname,
     2540 +                                            err);
     2541 +                                }
     2542 +                                rv = err;
2382 2543                          }
2383 2544                  }
2384 2545          }
2385 2546          nvlist_free(genericnvl);
2386 2547          nvlist_free(retrynvl);
2387 2548  
2388      -        if ((pair = nvlist_next_nvpair(errors, NULL)) == NULL) {
2389      -                nvlist_free(errors);
2390      -                errors = NULL;
2391      -        } else {
2392      -                VERIFY(nvpair_value_int32(pair, &rv) == 0);
2393      -        }
2394      -
2395      -        if (errlist == NULL)
2396      -                nvlist_free(errors);
2397      -        else
2398      -                *errlist = errors;
2399      -
2400 2549          return (rv);
2401 2550  }
2402 2551  
2403 2552  /*
2404 2553   * Check that all the properties are valid user properties.
2405 2554   */
2406 2555  static int
2407      -zfs_check_userprops(char *fsname, nvlist_t *nvl)
     2556 +zfs_check_userprops(const char *fsname, nvlist_t *nvl)
2408 2557  {
2409 2558          nvpair_t *pair = NULL;
2410 2559          int error = 0;
2411 2560  
2412 2561          while ((pair = nvlist_next_nvpair(nvl, pair)) != NULL) {
2413 2562                  const char *propname = nvpair_name(pair);
2414 2563                  char *valstr;
2415 2564  
2416 2565                  if (!zfs_prop_user(propname) ||
2417 2566                      nvpair_type(pair) != DATA_TYPE_STRING)
↓ open down ↓ 59 lines elided ↑ open up ↑
2477 2626   * outputs:
2478 2627   * zc_nvlist_dst{_size} error for each unapplied received property
2479 2628   */
2480 2629  static int
2481 2630  zfs_ioc_set_prop(zfs_cmd_t *zc)
2482 2631  {
2483 2632          nvlist_t *nvl;
2484 2633          boolean_t received = zc->zc_cookie;
2485 2634          zprop_source_t source = (received ? ZPROP_SRC_RECEIVED :
2486 2635              ZPROP_SRC_LOCAL);
2487      -        nvlist_t *errors = NULL;
     2636 +        nvlist_t *errors;
2488 2637          int error;
2489 2638  
2490 2639          if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
2491 2640              zc->zc_iflags, &nvl)) != 0)
2492 2641                  return (error);
2493 2642  
2494 2643          if (received) {
2495 2644                  nvlist_t *origprops;
2496 2645                  objset_t *os;
2497 2646  
↓ open down ↓ 2 lines elided ↑ open up ↑
2500 2649                                  (void) clear_received_props(os,
2501 2650                                      zc->zc_name, origprops, nvl);
2502 2651                                  nvlist_free(origprops);
2503 2652                          }
2504 2653  
2505 2654                          dsl_prop_set_hasrecvd(os);
2506 2655                          dmu_objset_rele(os, FTAG);
2507 2656                  }
2508 2657          }
2509 2658  
2510      -        error = zfs_set_prop_nvlist(zc->zc_name, source, nvl, &errors);
     2659 +        errors = fnvlist_alloc();
     2660 +        error = zfs_set_prop_nvlist(zc->zc_name, source, nvl, errors);
2511 2661  
2512 2662          if (zc->zc_nvlist_dst != NULL && errors != NULL) {
2513 2663                  (void) put_nvlist(zc, errors);
2514 2664          }
2515 2665  
2516 2666          nvlist_free(errors);
2517 2667          nvlist_free(nvl);
2518 2668          return (error);
2519 2669  }
2520 2670  
↓ open down ↓ 61 lines elided ↑ open up ↑
2582 2732                  /*
2583 2733                   * Only check this in the non-received case. We want to allow
2584 2734                   * 'inherit -S' to revert non-inheritable properties like quota
2585 2735                   * and reservation to the received or default values even though
2586 2736                   * they are not considered inheritable.
2587 2737                   */
2588 2738                  if (prop != ZPROP_INVAL && !zfs_prop_inheritable(prop))
2589 2739                          return (EINVAL);
2590 2740          }
2591 2741  
2592      -        /* the property name has been validated by zfs_secpolicy_inherit() */
     2742 +        /* property name has been validated by zfs_secpolicy_inherit_prop() */
2593 2743          return (dsl_prop_set(zc->zc_name, zc->zc_value, source, 0, 0, NULL));
2594 2744  }
2595 2745  
2596 2746  static int
2597 2747  zfs_ioc_pool_set_props(zfs_cmd_t *zc)
2598 2748  {
2599 2749          nvlist_t *props;
2600 2750          spa_t *spa;
2601 2751          int error;
2602 2752          nvpair_t *pair;
↓ open down ↓ 322 lines elided ↑ open up ↑
2925 3075          zplver = zfs_zpl_version_map(spa_vers);
2926 3076          fuids_ok = (zplver >= ZPL_VERSION_FUID);
2927 3077          sa_ok = (zplver >= ZPL_VERSION_SA);
2928 3078  
2929 3079          error = zfs_fill_zplprops_impl(NULL, zplver, fuids_ok, sa_ok,
2930 3080              createprops, zplprops, is_ci);
2931 3081          return (error);
2932 3082  }
2933 3083  
2934 3084  /*
2935      - * inputs:
2936      - * zc_objset_type       type of objset to create (fs vs zvol)
2937      - * zc_name              name of new objset
2938      - * zc_value             name of snapshot to clone from (may be empty)
2939      - * zc_nvlist_src{_size} nvlist of properties to apply
     3085 + * innvl: {
     3086 + *     "type" -> dmu_objset_type_t (int32)
     3087 + *     (optional) "props" -> { prop -> value }
     3088 + * }
2940 3089   *
2941      - * outputs: none
     3090 + * outnvl: propname -> error code (int32)
2942 3091   */
2943 3092  static int
2944      -zfs_ioc_create(zfs_cmd_t *zc)
     3093 +zfs_ioc_create(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
2945 3094  {
2946      -        objset_t *clone;
2947 3095          int error = 0;
2948      -        zfs_creat_t zct;
     3096 +        zfs_creat_t zct = { 0 };
2949 3097          nvlist_t *nvprops = NULL;
2950 3098          void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx);
2951      -        dmu_objset_type_t type = zc->zc_objset_type;
     3099 +        int32_t type32;
     3100 +        dmu_objset_type_t type;
     3101 +        boolean_t is_insensitive = B_FALSE;
2952 3102  
2953      -        switch (type) {
     3103 +        if (nvlist_lookup_int32(innvl, "type", &type32) != 0)
     3104 +                return (EINVAL);
     3105 +        type = type32;
     3106 +        (void) nvlist_lookup_nvlist(innvl, "props", &nvprops);
2954 3107  
     3108 +        switch (type) {
2955 3109          case DMU_OST_ZFS:
2956 3110                  cbfunc = zfs_create_cb;
2957 3111                  break;
2958 3112  
2959 3113          case DMU_OST_ZVOL:
2960 3114                  cbfunc = zvol_create_cb;
2961 3115                  break;
2962 3116  
2963 3117          default:
2964 3118                  cbfunc = NULL;
2965 3119                  break;
2966 3120          }
2967      -        if (strchr(zc->zc_name, '@') ||
2968      -            strchr(zc->zc_name, '%'))
     3121 +        if (strchr(fsname, '@') ||
     3122 +            strchr(fsname, '%'))
2969 3123                  return (EINVAL);
2970 3124  
2971      -        if (zc->zc_nvlist_src != NULL &&
2972      -            (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
2973      -            zc->zc_iflags, &nvprops)) != 0)
2974      -                return (error);
2975      -
2976      -        zct.zct_zplprops = NULL;
2977 3125          zct.zct_props = nvprops;
2978 3126  
2979      -        if (zc->zc_value[0] != '\0') {
2980      -                /*
2981      -                 * We're creating a clone of an existing snapshot.
2982      -                 */
2983      -                zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
2984      -                if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) {
2985      -                        nvlist_free(nvprops);
2986      -                        return (EINVAL);
2987      -                }
2988      -
2989      -                error = dmu_objset_hold(zc->zc_value, FTAG, &clone);
2990      -                if (error) {
2991      -                        nvlist_free(nvprops);
2992      -                        return (error);
2993      -                }
     3127 +        if (cbfunc == NULL)
     3128 +                return (EINVAL);
2994 3129  
2995      -                error = dmu_objset_clone(zc->zc_name, dmu_objset_ds(clone), 0);
2996      -                dmu_objset_rele(clone, FTAG);
2997      -                if (error) {
2998      -                        nvlist_free(nvprops);
2999      -                        return (error);
3000      -                }
3001      -        } else {
3002      -                boolean_t is_insensitive = B_FALSE;
     3130 +        if (type == DMU_OST_ZVOL) {
     3131 +                uint64_t volsize, volblocksize;
3003 3132  
3004      -                if (cbfunc == NULL) {
3005      -                        nvlist_free(nvprops);
     3133 +                if (nvprops == NULL)
     3134 +                        return (EINVAL);
     3135 +                if (nvlist_lookup_uint64(nvprops,
     3136 +                    zfs_prop_to_name(ZFS_PROP_VOLSIZE), &volsize) != 0)
3006 3137                          return (EINVAL);
3007      -                }
3008      -
3009      -                if (type == DMU_OST_ZVOL) {
3010      -                        uint64_t volsize, volblocksize;
3011 3138  
3012      -                        if (nvprops == NULL ||
3013      -                            nvlist_lookup_uint64(nvprops,
3014      -                            zfs_prop_to_name(ZFS_PROP_VOLSIZE),
3015      -                            &volsize) != 0) {
3016      -                                nvlist_free(nvprops);
3017      -                                return (EINVAL);
3018      -                        }
     3139 +                if ((error = nvlist_lookup_uint64(nvprops,
     3140 +                    zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
     3141 +                    &volblocksize)) != 0 && error != ENOENT)
     3142 +                        return (EINVAL);
3019 3143  
3020      -                        if ((error = nvlist_lookup_uint64(nvprops,
3021      -                            zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
3022      -                            &volblocksize)) != 0 && error != ENOENT) {
3023      -                                nvlist_free(nvprops);
3024      -                                return (EINVAL);
3025      -                        }
     3144 +                if (error != 0)
     3145 +                        volblocksize = zfs_prop_default_numeric(
     3146 +                            ZFS_PROP_VOLBLOCKSIZE);
3026 3147  
3027      -                        if (error != 0)
3028      -                                volblocksize = zfs_prop_default_numeric(
3029      -                                    ZFS_PROP_VOLBLOCKSIZE);
3030      -
3031      -                        if ((error = zvol_check_volblocksize(
3032      -                            volblocksize)) != 0 ||
3033      -                            (error = zvol_check_volsize(volsize,
3034      -                            volblocksize)) != 0) {
3035      -                                nvlist_free(nvprops);
3036      -                                return (error);
3037      -                        }
3038      -                } else if (type == DMU_OST_ZFS) {
3039      -                        int error;
     3148 +                if ((error = zvol_check_volblocksize(
     3149 +                    volblocksize)) != 0 ||
     3150 +                    (error = zvol_check_volsize(volsize,
     3151 +                    volblocksize)) != 0)
     3152 +                        return (error);
     3153 +        } else if (type == DMU_OST_ZFS) {
     3154 +                int error;
3040 3155  
3041      -                        /*
3042      -                         * We have to have normalization and
3043      -                         * case-folding flags correct when we do the
3044      -                         * file system creation, so go figure them out
3045      -                         * now.
3046      -                         */
3047      -                        VERIFY(nvlist_alloc(&zct.zct_zplprops,
3048      -                            NV_UNIQUE_NAME, KM_SLEEP) == 0);
3049      -                        error = zfs_fill_zplprops(zc->zc_name, nvprops,
3050      -                            zct.zct_zplprops, &is_insensitive);
3051      -                        if (error != 0) {
3052      -                                nvlist_free(nvprops);
3053      -                                nvlist_free(zct.zct_zplprops);
3054      -                                return (error);
3055      -                        }
     3156 +                /*
     3157 +                 * We have to have normalization and
     3158 +                 * case-folding flags correct when we do the
     3159 +                 * file system creation, so go figure them out
     3160 +                 * now.
     3161 +                 */
     3162 +                VERIFY(nvlist_alloc(&zct.zct_zplprops,
     3163 +                    NV_UNIQUE_NAME, KM_SLEEP) == 0);
     3164 +                error = zfs_fill_zplprops(fsname, nvprops,
     3165 +                    zct.zct_zplprops, &is_insensitive);
     3166 +                if (error != 0) {
     3167 +                        nvlist_free(zct.zct_zplprops);
     3168 +                        return (error);
3056 3169                  }
3057      -                error = dmu_objset_create(zc->zc_name, type,
3058      -                    is_insensitive ? DS_FLAG_CI_DATASET : 0, cbfunc, &zct);
3059      -                nvlist_free(zct.zct_zplprops);
3060 3170          }
3061 3171  
     3172 +        error = dmu_objset_create(fsname, type,
     3173 +            is_insensitive ? DS_FLAG_CI_DATASET : 0, cbfunc, &zct);
     3174 +        nvlist_free(zct.zct_zplprops);
     3175 +
3062 3176          /*
3063 3177           * It would be nice to do this atomically.
3064 3178           */
3065 3179          if (error == 0) {
3066      -                error = zfs_set_prop_nvlist(zc->zc_name, ZPROP_SRC_LOCAL,
3067      -                    nvprops, NULL);
     3180 +                error = zfs_set_prop_nvlist(fsname, ZPROP_SRC_LOCAL,
     3181 +                    nvprops, outnvl);
3068 3182                  if (error != 0)
3069      -                        (void) dmu_objset_destroy(zc->zc_name, B_FALSE);
     3183 +                        (void) dmu_objset_destroy(fsname, B_FALSE);
3070 3184          }
3071      -        nvlist_free(nvprops);
3072 3185          return (error);
3073 3186  }
3074 3187  
3075 3188  /*
3076      - * inputs:
3077      - * zc_name      name of filesystem
3078      - * zc_value     short name of snapshot
3079      - * zc_cookie    recursive flag
3080      - * zc_nvlist_src[_size] property list
     3189 + * innvl: {
     3190 + *     "origin" -> name of origin snapshot
     3191 + *     (optional) "props" -> { prop -> value }
     3192 + * }
3081 3193   *
3082      - * outputs:
3083      - * zc_value     short snapname (i.e. part after the '@')
     3194 + * outnvl: propname -> error code (int32)
3084 3195   */
3085 3196  static int
3086      -zfs_ioc_snapshot(zfs_cmd_t *zc)
     3197 +zfs_ioc_clone(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
3087 3198  {
     3199 +        int error = 0;
3088 3200          nvlist_t *nvprops = NULL;
3089      -        int error;
3090      -        boolean_t recursive = zc->zc_cookie;
     3201 +        char *origin_name;
     3202 +        dsl_dataset_t *origin;
3091 3203  
3092      -        if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0)
     3204 +        if (nvlist_lookup_string(innvl, "origin", &origin_name) != 0)
3093 3205                  return (EINVAL);
     3206 +        (void) nvlist_lookup_nvlist(innvl, "props", &nvprops);
3094 3207  
3095      -        if (zc->zc_nvlist_src != NULL &&
3096      -            (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
3097      -            zc->zc_iflags, &nvprops)) != 0)
     3208 +        if (strchr(fsname, '@') ||
     3209 +            strchr(fsname, '%'))
     3210 +                return (EINVAL);
     3211 +
     3212 +        if (dataset_namecheck(origin_name, NULL, NULL) != 0)
     3213 +                return (EINVAL);
     3214 +
     3215 +        error = dsl_dataset_hold(origin_name, FTAG, &origin);
     3216 +        if (error)
3098 3217                  return (error);
3099 3218  
3100      -        error = zfs_check_userprops(zc->zc_name, nvprops);
     3219 +        error = dmu_objset_clone(fsname, origin, 0);
     3220 +        dsl_dataset_rele(origin, FTAG);
3101 3221          if (error)
3102      -                goto out;
     3222 +                return (error);
3103 3223  
3104      -        if (!nvlist_empty(nvprops) &&
3105      -            zfs_earlier_version(zc->zc_name, SPA_VERSION_SNAP_PROPS)) {
3106      -                error = ENOTSUP;
3107      -                goto out;
     3224 +        /*
     3225 +         * It would be nice to do this atomically.
     3226 +         */
     3227 +        if (error == 0) {
     3228 +                error = zfs_set_prop_nvlist(fsname, ZPROP_SRC_LOCAL,
     3229 +                    nvprops, outnvl);
     3230 +                if (error != 0)
     3231 +                        (void) dmu_objset_destroy(fsname, B_FALSE);
3108 3232          }
     3233 +        return (error);
     3234 +}
3109 3235  
3110      -        error = dmu_objset_snapshot(zc->zc_name, zc->zc_value, NULL,
3111      -            nvprops, recursive, B_FALSE, -1);
     3236 +/*
     3237 + * innvl: {
     3238 + *     "snaps" -> { snapshot1, snapshot2 }
     3239 + *     (optional) "props" -> { prop -> value (string) }
     3240 + * }
     3241 + *
     3242 + * outnvl: snapshot -> error code (int32)
     3243 + *
     3244 + */
     3245 +static int
     3246 +zfs_ioc_snapshot(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
     3247 +{
     3248 +        nvlist_t *snaps;
     3249 +        nvlist_t *props = NULL;
     3250 +        int error, poollen;
     3251 +        nvpair_t *pair;
3112 3252  
3113      -out:
3114      -        nvlist_free(nvprops);
     3253 +        (void) nvlist_lookup_nvlist(innvl, "props", &props);
     3254 +        if ((error = zfs_check_userprops(poolname, props)) != 0)
     3255 +                return (error);
     3256 +
     3257 +        if (!nvlist_empty(props) &&
     3258 +            zfs_earlier_version(poolname, SPA_VERSION_SNAP_PROPS))
     3259 +                return (ENOTSUP);
     3260 +
     3261 +        if (nvlist_lookup_nvlist(innvl, "snaps", &snaps) != 0)
     3262 +                return (EINVAL);
     3263 +        poollen = strlen(poolname);
     3264 +        for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
     3265 +            pair = nvlist_next_nvpair(snaps, pair)) {
     3266 +                const char *name = nvpair_name(pair);
     3267 +                const char *cp = strchr(name, '@');
     3268 +
     3269 +                /*
     3270 +                 * The snap name must contain an @, and the part after it must
     3271 +                 * contain only valid characters.
     3272 +                 */
     3273 +                if (cp == NULL || snapshot_namecheck(cp + 1, NULL, NULL) != 0)
     3274 +                        return (EINVAL);
     3275 +
     3276 +                /*
     3277 +                 * The snap must be in the specified pool.
     3278 +                 */
     3279 +                if (strncmp(name, poolname, poollen) != 0 ||
     3280 +                    (name[poollen] != '/' && name[poollen] != '@'))
     3281 +                        return (EXDEV);
     3282 +
     3283 +                /* This must be the only snap of this fs. */
     3284 +                for (nvpair_t *pair2 = nvlist_next_nvpair(snaps, pair);
     3285 +                    pair2 != NULL; pair2 = nvlist_next_nvpair(snaps, pair2)) {
     3286 +                        if (strncmp(name, nvpair_name(pair2), cp - name + 1)
     3287 +                            == 0) {
     3288 +                                return (EXDEV);
     3289 +                        }
     3290 +                }
     3291 +        }
     3292 +
     3293 +        error = dmu_objset_snapshot(snaps, props, outnvl);
     3294 +        return (error);
     3295 +}
     3296 +
     3297 +/*
     3298 + * innvl: "message" -> string
     3299 + */
     3300 +/* ARGSUSED */
     3301 +static int
     3302 +zfs_ioc_log_history(const char *unused, nvlist_t *innvl, nvlist_t *outnvl)
     3303 +{
     3304 +        char *message;
     3305 +        spa_t *spa;
     3306 +        int error;
     3307 +        char *poolname;
     3308 +
     3309 +        /*
     3310 +         * The poolname in the ioctl is not set, we get it from the TSD,
     3311 +         * which was set at the end of the last successful ioctl that allows
     3312 +         * logging.  The secpolicy func already checked that it is set.
     3313 +         * Only one log ioctl is allowed after each successful ioctl, so
     3314 +         * we clear the TSD here.
     3315 +         */
     3316 +        poolname = tsd_get(zfs_allow_log_key);
     3317 +        (void) tsd_set(zfs_allow_log_key, NULL);
     3318 +        error = spa_open(poolname, &spa, FTAG);
     3319 +        strfree(poolname);
     3320 +        if (error != 0)
     3321 +                return (error);
     3322 +
     3323 +        if (nvlist_lookup_string(innvl, "message", &message) != 0)  {
     3324 +                spa_close(spa, FTAG);
     3325 +                return (EINVAL);
     3326 +        }
     3327 +
     3328 +        if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) {
     3329 +                spa_close(spa, FTAG);
     3330 +                return (ENOTSUP);
     3331 +        }
     3332 +
     3333 +        error = spa_history_log(spa, message);
     3334 +        spa_close(spa, FTAG);
3115 3335          return (error);
3116 3336  }
3117 3337  
     3338 +/* ARGSUSED */
3118 3339  int
3119 3340  zfs_unmount_snap(const char *name, void *arg)
3120 3341  {
3121      -        vfs_t *vfsp = NULL;
     3342 +        vfs_t *vfsp;
     3343 +        int err;
3122 3344  
3123      -        if (arg) {
3124      -                char *snapname = arg;
3125      -                char *fullname = kmem_asprintf("%s@%s", name, snapname);
3126      -                vfsp = zfs_get_vfs(fullname);
3127      -                strfree(fullname);
3128      -        } else if (strchr(name, '@')) {
3129      -                vfsp = zfs_get_vfs(name);
3130      -        }
     3345 +        if (strchr(name, '@') == NULL)
     3346 +                return (0);
3131 3347  
3132      -        if (vfsp) {
3133      -                /*
3134      -                 * Always force the unmount for snapshots.
3135      -                 */
3136      -                int flag = MS_FORCE;
3137      -                int err;
     3348 +        vfsp = zfs_get_vfs(name);
     3349 +        if (vfsp == NULL)
     3350 +                return (0);
3138 3351  
3139      -                if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) {
3140      -                        VFS_RELE(vfsp);
3141      -                        return (err);
3142      -                }
     3352 +        if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) {
3143 3353                  VFS_RELE(vfsp);
3144      -                if ((err = dounmount(vfsp, flag, kcred)) != 0)
3145      -                        return (err);
     3354 +                return (err);
3146 3355          }
3147      -        return (0);
     3356 +        VFS_RELE(vfsp);
     3357 +
     3358 +        /*
     3359 +         * Always force the unmount for snapshots.
     3360 +         */
     3361 +        return (dounmount(vfsp, MS_FORCE, kcred));
3148 3362  }
3149 3363  
3150 3364  /*
3151      - * inputs:
3152      - * zc_name              name of filesystem, snaps must be under it
3153      - * zc_nvlist_src[_size] full names of snapshots to destroy
3154      - * zc_defer_destroy     mark for deferred destroy
     3365 + * innvl: {
     3366 + *     "snaps" -> { snapshot1, snapshot2 }
     3367 + *     (optional boolean) "defer"
     3368 + * }
     3369 + *
     3370 + * outnvl: snapshot -> error code (int32)
3155 3371   *
3156      - * outputs:
3157      - * zc_name              on failure, name of failed snapshot
3158 3372   */
3159 3373  static int
3160      -zfs_ioc_destroy_snaps_nvl(zfs_cmd_t *zc)
     3374 +zfs_ioc_destroy_snaps(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
3161 3375  {
3162      -        int err, len;
3163      -        nvlist_t *nvl;
     3376 +        int poollen;
     3377 +        nvlist_t *snaps;
3164 3378          nvpair_t *pair;
     3379 +        boolean_t defer;
3165 3380  
3166      -        if ((err = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
3167      -            zc->zc_iflags, &nvl)) != 0)
3168      -                return (err);
     3381 +        if (nvlist_lookup_nvlist(innvl, "snaps", &snaps) != 0)
     3382 +                return (EINVAL);
     3383 +        defer = nvlist_exists(innvl, "defer");
3169 3384  
3170      -        len = strlen(zc->zc_name);
3171      -        for (pair = nvlist_next_nvpair(nvl, NULL); pair != NULL;
3172      -            pair = nvlist_next_nvpair(nvl, pair)) {
     3385 +        poollen = strlen(poolname);
     3386 +        for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
     3387 +            pair = nvlist_next_nvpair(snaps, pair)) {
3173 3388                  const char *name = nvpair_name(pair);
     3389 +
3174 3390                  /*
3175      -                 * The snap name must be underneath the zc_name.  This ensures
3176      -                 * that our permission checks were legitimate.
     3391 +                 * The snap must be in the specified pool.
3177 3392                   */
3178      -                if (strncmp(zc->zc_name, name, len) != 0 ||
3179      -                    (name[len] != '@' && name[len] != '/')) {
3180      -                        nvlist_free(nvl);
3181      -                        return (EINVAL);
3182      -                }
     3393 +                if (strncmp(name, poolname, poollen) != 0 ||
     3394 +                    (name[poollen] != '/' && name[poollen] != '@'))
     3395 +                        return (EXDEV);
3183 3396  
     3397 +                /*
     3398 +                 * Ignore failures to unmount; dmu_snapshots_destroy_nvl()
     3399 +                 * will deal with this gracefully (by filling in outnvl).
     3400 +                 */
3184 3401                  (void) zfs_unmount_snap(name, NULL);
3185 3402          }
3186 3403  
3187      -        err = dmu_snapshots_destroy_nvl(nvl, zc->zc_defer_destroy,
3188      -            zc->zc_name);
3189      -        nvlist_free(nvl);
3190      -        return (err);
     3404 +        return (dmu_snapshots_destroy_nvl(snaps, defer, outnvl));
3191 3405  }
3192 3406  
3193 3407  /*
3194 3408   * inputs:
3195 3409   * zc_name              name of dataset to destroy
3196 3410   * zc_objset_type       type of objset
3197 3411   * zc_defer_destroy     mark for deferred destroy
3198 3412   *
3199 3413   * outputs:             none
3200 3414   */
↓ open down ↓ 283 lines elided ↑ open up ↑
3484 3698          VERIFY(nvlist_alloc(&errors, NV_UNIQUE_NAME, KM_SLEEP) == 0);
3485 3699  
3486 3700          zc = kmem_alloc(sizeof (zfs_cmd_t), KM_SLEEP);
3487 3701          (void) strcpy(zc->zc_name, dataset);
3488 3702          pair = nvlist_next_nvpair(props, NULL);
3489 3703          while (pair != NULL) {
3490 3704                  next_pair = nvlist_next_nvpair(props, pair);
3491 3705  
3492 3706                  (void) strcpy(zc->zc_value, nvpair_name(pair));
3493 3707                  if ((err = zfs_check_settable(dataset, pair, CRED())) != 0 ||
3494      -                    (err = zfs_secpolicy_inherit(zc, CRED())) != 0) {
     3708 +                    (err = zfs_secpolicy_inherit_prop(zc, NULL, CRED())) != 0) {
3495 3709                          VERIFY(nvlist_remove_nvpair(props, pair) == 0);
3496 3710                          VERIFY(nvlist_add_int32(errors,
3497 3711                              zc->zc_value, err) == 0);
3498 3712                  }
3499 3713                  pair = next_pair;
3500 3714          }
3501 3715          kmem_free(zc, sizeof (zfs_cmd_t));
3502 3716  
3503 3717          if ((pair = nvlist_next_nvpair(errors, NULL)) == NULL) {
3504 3718                  nvlist_free(errors);
↓ open down ↓ 187 lines elided ↑ open up ↑
3692 3906                  dmu_objset_rele(origin, FTAG);
3693 3907          if (error)
3694 3908                  goto out;
3695 3909  
3696 3910          /*
3697 3911           * Set properties before we receive the stream so that they are applied
3698 3912           * to the new data. Note that we must call dmu_recv_stream() if
3699 3913           * dmu_recv_begin() succeeds.
3700 3914           */
3701 3915          if (props) {
3702      -                nvlist_t *errlist;
3703      -
3704 3916                  if (dmu_objset_from_ds(drc.drc_logical_ds, &os) == 0) {
3705 3917                          if (drc.drc_newfs) {
3706 3918                                  if (spa_version(os->os_spa) >=
3707 3919                                      SPA_VERSION_RECVD_PROPS)
3708 3920                                          first_recvd_props = B_TRUE;
3709 3921                          } else if (origprops != NULL) {
3710 3922                                  if (clear_received_props(os, tofs, origprops,
3711 3923                                      first_recvd_props ? NULL : props) != 0)
3712 3924                                          zc->zc_obj |= ZPROP_ERR_NOCLEAR;
3713 3925                          } else {
3714 3926                                  zc->zc_obj |= ZPROP_ERR_NOCLEAR;
3715 3927                          }
3716 3928                          dsl_prop_set_hasrecvd(os);
3717 3929                  } else if (!drc.drc_newfs) {
3718 3930                          zc->zc_obj |= ZPROP_ERR_NOCLEAR;
3719 3931                  }
3720 3932  
3721 3933                  (void) zfs_set_prop_nvlist(tofs, ZPROP_SRC_RECEIVED,
3722      -                    props, &errlist);
3723      -                (void) nvlist_merge(errors, errlist, 0);
3724      -                nvlist_free(errlist);
     3934 +                    props, errors);
3725 3935          }
3726 3936  
3727      -        if (fit_error_list(zc, &errors) != 0 || put_nvlist(zc, errors) != 0) {
     3937 +        if (zc->zc_nvlist_dst_size != 0 &&
     3938 +            (nvlist_smush(errors, zc->zc_nvlist_dst_size) != 0 ||
     3939 +            put_nvlist(zc, errors) != 0)) {
3728 3940                  /*
3729 3941                   * Caller made zc->zc_nvlist_dst less than the minimum expected
3730 3942                   * size or supplied an invalid address.
3731 3943                   */
3732 3944                  props_error = EINVAL;
3733 3945          }
3734 3946  
3735 3947          off = fp->f_offset;
3736 3948          error = dmu_recv_stream(&drc, fp->f_vnode, &off, zc->zc_cleanup_fd,
3737 3949              &zc->zc_action_handle);
↓ open down ↓ 111 lines elided ↑ open up ↑
3849 4061          boolean_t estimate = (zc->zc_guid != 0);
3850 4062  
3851 4063          error = spa_open(zc->zc_name, &spa, FTAG);
3852 4064          if (error)
3853 4065                  return (error);
3854 4066  
3855 4067          dp = spa_get_dsl(spa);
3856 4068          rw_enter(&dp->dp_config_rwlock, RW_READER);
3857 4069          error = dsl_dataset_hold_obj(dp, zc->zc_sendobj, FTAG, &ds);
3858 4070          rw_exit(&dp->dp_config_rwlock);
3859      -        if (error) {
3860      -                spa_close(spa, FTAG);
     4071 +        spa_close(spa, FTAG);
     4072 +        if (error)
3861 4073                  return (error);
3862      -        }
3863 4074  
3864 4075          error = dmu_objset_from_ds(ds, &tosnap);
3865 4076          if (error) {
3866 4077                  dsl_dataset_rele(ds, FTAG);
3867      -                spa_close(spa, FTAG);
3868 4078                  return (error);
3869 4079          }
3870 4080  
3871 4081          if (zc->zc_fromobj != 0) {
3872 4082                  rw_enter(&dp->dp_config_rwlock, RW_READER);
3873 4083                  error = dsl_dataset_hold_obj(dp, zc->zc_fromobj, FTAG, &dsfrom);
3874 4084                  rw_exit(&dp->dp_config_rwlock);
3875      -                spa_close(spa, FTAG);
3876 4085                  if (error) {
3877 4086                          dsl_dataset_rele(ds, FTAG);
3878 4087                          return (error);
3879 4088                  }
3880 4089                  error = dmu_objset_from_ds(dsfrom, &fromsnap);
3881 4090                  if (error) {
3882 4091                          dsl_dataset_rele(dsfrom, FTAG);
3883 4092                          dsl_dataset_rele(ds, FTAG);
3884 4093                          return (error);
3885 4094                  }
3886      -        } else {
3887      -                spa_close(spa, FTAG);
     4095 +        }
     4096 +
     4097 +        if (zc->zc_obj) {
     4098 +                dsl_pool_t *dp = ds->ds_dir->dd_pool;
     4099 +
     4100 +                if (fromsnap != NULL) {
     4101 +                        dsl_dataset_rele(dsfrom, FTAG);
     4102 +                        dsl_dataset_rele(ds, FTAG);
     4103 +                        return (EINVAL);
     4104 +                }
     4105 +
     4106 +                if (dsl_dir_is_clone(ds->ds_dir)) {
     4107 +                        rw_enter(&dp->dp_config_rwlock, RW_READER);
     4108 +                        error = dsl_dataset_hold_obj(dp,
     4109 +                            ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &dsfrom);
     4110 +                        rw_exit(&dp->dp_config_rwlock);
     4111 +                        if (error) {
     4112 +                                dsl_dataset_rele(ds, FTAG);
     4113 +                                return (error);
     4114 +                        }
     4115 +                        error = dmu_objset_from_ds(dsfrom, &fromsnap);
     4116 +                        if (error) {
     4117 +                                dsl_dataset_rele(dsfrom, FTAG);
     4118 +                                dsl_dataset_rele(ds, FTAG);
     4119 +                                return (error);
     4120 +                        }
     4121 +                }
3888 4122          }
3889 4123  
3890 4124          if (estimate) {
3891      -                error = dmu_send_estimate(tosnap, fromsnap, zc->zc_obj,
     4125 +                error = dmu_send_estimate(tosnap, fromsnap,
3892 4126                      &zc->zc_objset_type);
3893 4127          } else {
3894 4128                  file_t *fp = getf(zc->zc_cookie);
3895 4129                  if (fp == NULL) {
3896 4130                          dsl_dataset_rele(ds, FTAG);
3897 4131                          if (dsfrom)
3898 4132                                  dsl_dataset_rele(dsfrom, FTAG);
3899 4133                          return (EBADF);
3900 4134                  }
3901 4135  
3902 4136                  off = fp->f_offset;
3903      -                error = dmu_send(tosnap, fromsnap, zc->zc_obj,
     4137 +                error = dmu_send(tosnap, fromsnap,
3904 4138                      zc->zc_cookie, fp->f_vnode, &off);
3905 4139  
3906 4140                  if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
3907 4141                          fp->f_offset = off;
3908 4142                  releasef(zc->zc_cookie);
3909 4143          }
3910 4144          if (dsfrom)
3911 4145                  dsl_dataset_rele(dsfrom, FTAG);
3912 4146          dsl_dataset_rele(ds, FTAG);
3913 4147          return (error);
↓ open down ↓ 493 lines elided ↑ open up ↑
4407 4641          return (error);
4408 4642  }
4409 4643  
4410 4644  /*
4411 4645   * inputs:
4412 4646   * zc_name              name of filesystem
4413 4647   * zc_value             prefix name for snapshot
4414 4648   * zc_cleanup_fd        cleanup-on-exit file descriptor for calling process
4415 4649   *
4416 4650   * outputs:
     4651 + * zc_value             short name of new snapshot
4417 4652   */
4418 4653  static int
4419 4654  zfs_ioc_tmp_snapshot(zfs_cmd_t *zc)
4420 4655  {
4421 4656          char *snap_name;
4422 4657          int error;
4423 4658  
4424      -        snap_name = kmem_asprintf("%s-%016llx", zc->zc_value,
     4659 +        snap_name = kmem_asprintf("%s@%s-%016llx", zc->zc_name, zc->zc_value,
4425 4660              (u_longlong_t)ddi_get_lbolt64());
4426 4661  
4427      -        if (strlen(snap_name) >= MAXNAMELEN) {
     4662 +        if (strlen(snap_name) >= MAXPATHLEN) {
4428 4663                  strfree(snap_name);
4429 4664                  return (E2BIG);
4430 4665          }
4431 4666  
4432      -        error = dmu_objset_snapshot(zc->zc_name, snap_name, snap_name,
4433      -            NULL, B_FALSE, B_TRUE, zc->zc_cleanup_fd);
     4667 +        error = dmu_objset_snapshot_tmp(snap_name, "%temp", zc->zc_cleanup_fd);
4434 4668          if (error != 0) {
4435 4669                  strfree(snap_name);
4436 4670                  return (error);
4437 4671          }
4438 4672  
4439      -        (void) strcpy(zc->zc_value, snap_name);
     4673 +        (void) strcpy(zc->zc_value, strchr(snap_name, '@') + 1);
4440 4674          strfree(snap_name);
4441 4675          return (0);
4442 4676  }
4443 4677  
4444 4678  /*
4445 4679   * inputs:
4446 4680   * zc_name              name of "to" snapshot
4447 4681   * zc_value             name of "from" snapshot
4448 4682   * zc_cookie            file descriptor to write diff data on
4449 4683   *
↓ open down ↓ 333 lines elided ↑ open up ↑
4783 5017                  dsl_dataset_rele(new, FTAG);
4784 5018                  return (error);
4785 5019          }
4786 5020  
4787 5021          error = dsl_dataset_space_written(old, new, &zc->zc_cookie,
4788 5022              &zc->zc_objset_type, &zc->zc_perm_action);
4789 5023          dsl_dataset_rele(old, FTAG);
4790 5024          dsl_dataset_rele(new, FTAG);
4791 5025          return (error);
4792 5026  }
4793      -
4794 5027  /*
4795      - * inputs:
4796      - * zc_name              full name of last snapshot
4797      - * zc_value             full name of first snapshot
4798      - *
4799      - * outputs:
4800      - * zc_cookie            space in bytes
4801      - * zc_objset_type       compressed space in bytes
4802      - * zc_perm_action       uncompressed space in bytes
     5028 + * innvl: {
     5029 + *     "firstsnap" -> snapshot name
     5030 + * }
     5031 + *
     5032 + * outnvl: {
     5033 + *     "used" -> space in bytes
     5034 + *     "compressed" -> compressed space in bytes
     5035 + *     "uncompressed" -> uncompressed space in bytes
     5036 + * }
4803 5037   */
4804 5038  static int
4805      -zfs_ioc_space_snaps(zfs_cmd_t *zc)
     5039 +zfs_ioc_space_snaps(const char *lastsnap, nvlist_t *innvl, nvlist_t *outnvl)
4806 5040  {
4807 5041          int error;
4808 5042          dsl_dataset_t *new, *old;
     5043 +        char *firstsnap;
     5044 +        uint64_t used, comp, uncomp;
4809 5045  
4810      -        error = dsl_dataset_hold(zc->zc_name, FTAG, &new);
     5046 +        if (nvlist_lookup_string(innvl, "firstsnap", &firstsnap) != 0)
     5047 +                return (EINVAL);
     5048 +
     5049 +        error = dsl_dataset_hold(lastsnap, FTAG, &new);
4811 5050          if (error != 0)
4812 5051                  return (error);
4813      -        error = dsl_dataset_hold(zc->zc_value, FTAG, &old);
     5052 +        error = dsl_dataset_hold(firstsnap, FTAG, &old);
4814 5053          if (error != 0) {
4815 5054                  dsl_dataset_rele(new, FTAG);
4816 5055                  return (error);
4817 5056          }
4818 5057  
4819      -        error = dsl_dataset_space_wouldfree(old, new, &zc->zc_cookie,
4820      -            &zc->zc_objset_type, &zc->zc_perm_action);
     5058 +        error = dsl_dataset_space_wouldfree(old, new, &used, &comp, &uncomp);
4821 5059          dsl_dataset_rele(old, FTAG);
4822 5060          dsl_dataset_rele(new, FTAG);
     5061 +        fnvlist_add_uint64(outnvl, "used", used);
     5062 +        fnvlist_add_uint64(outnvl, "compressed", comp);
     5063 +        fnvlist_add_uint64(outnvl, "uncompressed", uncomp);
4823 5064          return (error);
4824 5065  }
4825 5066  
4826 5067  /*
4827      - * pool create, destroy, and export don't log the history as part of
4828      - * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export
4829      - * do the logging of those commands.
4830      - */
4831      -static zfs_ioc_vec_t zfs_ioc_vec[] = {
4832      -        { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE,
4833      -            POOL_CHECK_NONE },
4834      -        { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE,
4835      -            POOL_CHECK_NONE },
4836      -        { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE,
4837      -            POOL_CHECK_NONE },
4838      -        { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE,
4839      -            POOL_CHECK_NONE },
4840      -        { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE,
4841      -            POOL_CHECK_NONE },
4842      -        { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE,
4843      -            POOL_CHECK_NONE },
4844      -        { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE,
4845      -            POOL_CHECK_NONE },
4846      -        { zfs_ioc_pool_scan, zfs_secpolicy_config, POOL_NAME, B_TRUE,
4847      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4848      -        { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE,
4849      -            POOL_CHECK_READONLY },
4850      -        { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE,
4851      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4852      -        { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE,
4853      -            POOL_CHECK_NONE },
4854      -        { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE,
4855      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4856      -        { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE,
4857      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4858      -        { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE,
4859      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4860      -        { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE,
4861      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4862      -        { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE,
4863      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4864      -        { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE,
4865      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4866      -        { zfs_ioc_vdev_setfru,  zfs_secpolicy_config, POOL_NAME, B_FALSE,
4867      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4868      -        { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE,
4869      -            POOL_CHECK_SUSPENDED },
4870      -        { zfs_ioc_objset_zplprops, zfs_secpolicy_read, DATASET_NAME, B_FALSE,
4871      -            POOL_CHECK_NONE },
4872      -        { zfs_ioc_dataset_list_next, zfs_secpolicy_read, DATASET_NAME, B_FALSE,
4873      -            POOL_CHECK_SUSPENDED },
4874      -        { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, DATASET_NAME, B_FALSE,
4875      -            POOL_CHECK_SUSPENDED },
4876      -        { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE,
4877      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4878      -        { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE,
4879      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4880      -        { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE,
4881      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4882      -        { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE,
4883      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4884      -        { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE,
4885      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4886      -        { zfs_ioc_recv, zfs_secpolicy_receive, DATASET_NAME, B_TRUE,
4887      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4888      -        { zfs_ioc_send, zfs_secpolicy_send, DATASET_NAME, B_FALSE,
4889      -            POOL_CHECK_NONE },
4890      -        { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE,
4891      -            POOL_CHECK_NONE },
4892      -        { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE,
4893      -            POOL_CHECK_NONE },
4894      -        { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE,
4895      -            POOL_CHECK_NONE },
4896      -        { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE,
4897      -            POOL_CHECK_NONE },
4898      -        { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE,
4899      -            POOL_CHECK_NONE },
4900      -        { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE,
4901      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4902      -        { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE,
4903      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4904      -        { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_diff, POOL_NAME, B_FALSE,
4905      -            POOL_CHECK_NONE },
4906      -        { zfs_ioc_obj_to_path, zfs_secpolicy_diff, DATASET_NAME, B_FALSE,
4907      -            POOL_CHECK_SUSPENDED },
4908      -        { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE,
4909      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4910      -        { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE,
4911      -            POOL_CHECK_NONE },
4912      -        { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE,
4913      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4914      -        { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE,
4915      -            POOL_CHECK_NONE },
4916      -        { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE,
4917      -            POOL_CHECK_NONE },
4918      -        { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE,
4919      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4920      -        { zfs_ioc_smb_acl, zfs_secpolicy_smb_acl, DATASET_NAME, B_FALSE,
4921      -            POOL_CHECK_NONE },
4922      -        { zfs_ioc_userspace_one, zfs_secpolicy_userspace_one, DATASET_NAME,
4923      -            B_FALSE, POOL_CHECK_NONE },
4924      -        { zfs_ioc_userspace_many, zfs_secpolicy_userspace_many, DATASET_NAME,
4925      -            B_FALSE, POOL_CHECK_NONE },
4926      -        { zfs_ioc_userspace_upgrade, zfs_secpolicy_userspace_upgrade,
4927      -            DATASET_NAME, B_FALSE, POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4928      -        { zfs_ioc_hold, zfs_secpolicy_hold, DATASET_NAME, B_TRUE,
4929      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4930      -        { zfs_ioc_release, zfs_secpolicy_release, DATASET_NAME, B_TRUE,
4931      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4932      -        { zfs_ioc_get_holds, zfs_secpolicy_read, DATASET_NAME, B_FALSE,
4933      -            POOL_CHECK_SUSPENDED },
4934      -        { zfs_ioc_objset_recvd_props, zfs_secpolicy_read, DATASET_NAME, B_FALSE,
4935      -            POOL_CHECK_NONE },
4936      -        { zfs_ioc_vdev_split, zfs_secpolicy_config, POOL_NAME, B_TRUE,
4937      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4938      -        { zfs_ioc_next_obj, zfs_secpolicy_read, DATASET_NAME, B_FALSE,
4939      -            POOL_CHECK_NONE },
4940      -        { zfs_ioc_diff, zfs_secpolicy_diff, DATASET_NAME, B_FALSE,
4941      -            POOL_CHECK_NONE },
4942      -        { zfs_ioc_tmp_snapshot, zfs_secpolicy_tmp_snapshot, DATASET_NAME,
4943      -            B_FALSE, POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4944      -        { zfs_ioc_obj_to_stats, zfs_secpolicy_diff, DATASET_NAME, B_FALSE,
4945      -            POOL_CHECK_SUSPENDED },
4946      -        { zfs_ioc_space_written, zfs_secpolicy_read, DATASET_NAME, B_FALSE,
4947      -            POOL_CHECK_SUSPENDED },
4948      -        { zfs_ioc_space_snaps, zfs_secpolicy_read, DATASET_NAME, B_FALSE,
4949      -            POOL_CHECK_SUSPENDED },
4950      -        { zfs_ioc_destroy_snaps_nvl, zfs_secpolicy_destroy_recursive,
4951      -            DATASET_NAME, B_TRUE, POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4952      -        { zfs_ioc_pool_reguid, zfs_secpolicy_config, POOL_NAME, B_TRUE,
4953      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY },
4954      -        { zfs_ioc_pool_reopen, zfs_secpolicy_config, POOL_NAME, B_TRUE,
4955      -            POOL_CHECK_SUSPENDED },
4956      -        { zfs_ioc_send_progress, zfs_secpolicy_read, DATASET_NAME, B_FALSE,
4957      -            POOL_CHECK_NONE }
4958      -};
     5068 + * innvl: {
     5069 + *     "fd" -> file descriptor to write stream to (int32)
     5070 + *     (optional) "fromsnap" -> full snap name to send an incremental from
     5071 + * }
     5072 + *
     5073 + * outnvl is unused
     5074 + */
     5075 +/* ARGSUSED */
     5076 +static int
     5077 +zfs_ioc_send_new(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
     5078 +{
     5079 +        objset_t *fromsnap = NULL;
     5080 +        objset_t *tosnap;
     5081 +        int error;
     5082 +        offset_t off;
     5083 +        char *fromname;
     5084 +        int fd;
     5085 +
     5086 +        error = nvlist_lookup_int32(innvl, "fd", &fd);
     5087 +        if (error != 0)
     5088 +                return (EINVAL);
     5089 +
     5090 +        error = dmu_objset_hold(snapname, FTAG, &tosnap);
     5091 +        if (error)
     5092 +                return (error);
     5093 +
     5094 +        error = nvlist_lookup_string(innvl, "fromsnap", &fromname);
     5095 +        if (error == 0) {
     5096 +                error = dmu_objset_hold(fromname, FTAG, &fromsnap);
     5097 +                if (error) {
     5098 +                        dmu_objset_rele(tosnap, FTAG);
     5099 +                        return (error);
     5100 +                }
     5101 +        }
     5102 +
     5103 +        file_t *fp = getf(fd);
     5104 +        if (fp == NULL) {
     5105 +                dmu_objset_rele(tosnap, FTAG);
     5106 +                if (fromsnap != NULL)
     5107 +                        dmu_objset_rele(fromsnap, FTAG);
     5108 +                return (EBADF);
     5109 +        }
     5110 +
     5111 +        off = fp->f_offset;
     5112 +        error = dmu_send(tosnap, fromsnap, fd, fp->f_vnode, &off);
     5113 +
     5114 +        if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
     5115 +                fp->f_offset = off;
     5116 +        releasef(fd);
     5117 +        if (fromsnap != NULL)
     5118 +                dmu_objset_rele(fromsnap, FTAG);
     5119 +        dmu_objset_rele(tosnap, FTAG);
     5120 +        return (error);
     5121 +}
     5122 +
     5123 +/*
     5124 + * Determine approximately how large a zfs send stream will be -- the number
     5125 + * of bytes that will be written to the fd supplied to zfs_ioc_send_new().
     5126 + *
     5127 + * innvl: {
     5128 + *     (optional) "fromsnap" -> full snap name to send an incremental from
     5129 + * }
     5130 + *
     5131 + * outnvl: {
     5132 + *     "space" -> bytes of space (uint64)
     5133 + * }
     5134 + */
     5135 +static int
     5136 +zfs_ioc_send_space(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
     5137 +{
     5138 +        objset_t *fromsnap = NULL;
     5139 +        objset_t *tosnap;
     5140 +        int error;
     5141 +        char *fromname;
     5142 +        uint64_t space;
     5143 +
     5144 +        error = dmu_objset_hold(snapname, FTAG, &tosnap);
     5145 +        if (error)
     5146 +                return (error);
     5147 +
     5148 +        error = nvlist_lookup_string(innvl, "fromsnap", &fromname);
     5149 +        if (error == 0) {
     5150 +                error = dmu_objset_hold(fromname, FTAG, &fromsnap);
     5151 +                if (error) {
     5152 +                        dmu_objset_rele(tosnap, FTAG);
     5153 +                        return (error);
     5154 +                }
     5155 +        }
     5156 +
     5157 +        error = dmu_send_estimate(tosnap, fromsnap, &space);
     5158 +        fnvlist_add_uint64(outnvl, "space", space);
     5159 +
     5160 +        if (fromsnap != NULL)
     5161 +                dmu_objset_rele(fromsnap, FTAG);
     5162 +        dmu_objset_rele(tosnap, FTAG);
     5163 +        return (error);
     5164 +}
     5165 +
     5166 +
     5167 +static zfs_ioc_vec_t zfs_ioc_vec[ZFS_IOC_LAST - ZFS_IOC_FIRST];
     5168 +
     5169 +static void
     5170 +zfs_ioctl_register_legacy(zfs_ioc_t ioc, zfs_ioc_legacy_func_t *func,
     5171 +    zfs_secpolicy_func_t *secpolicy, zfs_ioc_namecheck_t namecheck,
     5172 +    boolean_t log_history, zfs_ioc_poolcheck_t pool_check)
     5173 +{
     5174 +        zfs_ioc_vec_t *vec = &zfs_ioc_vec[ioc - ZFS_IOC_FIRST];
     5175 +
     5176 +        ASSERT3U(ioc, >=, ZFS_IOC_FIRST);
     5177 +        ASSERT3U(ioc, <, ZFS_IOC_LAST);
     5178 +        ASSERT3P(vec->zvec_legacy_func, ==, NULL);
     5179 +        ASSERT3P(vec->zvec_func, ==, NULL);
     5180 +
     5181 +        vec->zvec_legacy_func = func;
     5182 +        vec->zvec_secpolicy = secpolicy;
     5183 +        vec->zvec_namecheck = namecheck;
     5184 +        vec->zvec_allow_log = log_history;
     5185 +        vec->zvec_pool_check = pool_check;
     5186 +}
     5187 +
     5188 +/*
     5189 + * See the block comment at the beginning of this file for details on
     5190 + * each argument to this function.
     5191 + */
     5192 +static void
     5193 +zfs_ioctl_register(const char *name, zfs_ioc_t ioc, zfs_ioc_func_t *func,
     5194 +    zfs_secpolicy_func_t *secpolicy, zfs_ioc_namecheck_t namecheck,
     5195 +    zfs_ioc_poolcheck_t pool_check, boolean_t smush_outnvlist,
     5196 +    boolean_t allow_log)
     5197 +{
     5198 +        zfs_ioc_vec_t *vec = &zfs_ioc_vec[ioc - ZFS_IOC_FIRST];
     5199 +
     5200 +        ASSERT3U(ioc, >=, ZFS_IOC_FIRST);
     5201 +        ASSERT3U(ioc, <, ZFS_IOC_LAST);
     5202 +        ASSERT3P(vec->zvec_legacy_func, ==, NULL);
     5203 +        ASSERT3P(vec->zvec_func, ==, NULL);
     5204 +
     5205 +        /* if we are logging, the name must be valid */
     5206 +        ASSERT(!allow_log || namecheck != NO_NAME);
     5207 +
     5208 +        vec->zvec_name = name;
     5209 +        vec->zvec_func = func;
     5210 +        vec->zvec_secpolicy = secpolicy;
     5211 +        vec->zvec_namecheck = namecheck;
     5212 +        vec->zvec_pool_check = pool_check;
     5213 +        vec->zvec_smush_outnvlist = smush_outnvlist;
     5214 +        vec->zvec_allow_log = allow_log;
     5215 +}
     5216 +
     5217 +static void
     5218 +zfs_ioctl_register_pool(zfs_ioc_t ioc, zfs_ioc_legacy_func_t *func,
     5219 +    zfs_secpolicy_func_t *secpolicy, boolean_t log_history,
     5220 +    zfs_ioc_poolcheck_t pool_check)
     5221 +{
     5222 +        zfs_ioctl_register_legacy(ioc, func, secpolicy,
     5223 +            POOL_NAME, log_history, pool_check);
     5224 +}
     5225 +
     5226 +static void
     5227 +zfs_ioctl_register_dataset_nolog(zfs_ioc_t ioc, zfs_ioc_legacy_func_t *func,
     5228 +    zfs_secpolicy_func_t *secpolicy, zfs_ioc_poolcheck_t pool_check)
     5229 +{
     5230 +        zfs_ioctl_register_legacy(ioc, func, secpolicy,
     5231 +            DATASET_NAME, B_FALSE, pool_check);
     5232 +}
     5233 +
     5234 +static void
     5235 +zfs_ioctl_register_pool_modify(zfs_ioc_t ioc, zfs_ioc_legacy_func_t *func)
     5236 +{
     5237 +        zfs_ioctl_register_legacy(ioc, func, zfs_secpolicy_config,
     5238 +            POOL_NAME, B_TRUE, POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY);
     5239 +}
     5240 +
     5241 +static void
     5242 +zfs_ioctl_register_pool_meta(zfs_ioc_t ioc, zfs_ioc_legacy_func_t *func,
     5243 +    zfs_secpolicy_func_t *secpolicy)
     5244 +{
     5245 +        zfs_ioctl_register_legacy(ioc, func, secpolicy,
     5246 +            NO_NAME, B_FALSE, POOL_CHECK_NONE);
     5247 +}
     5248 +
     5249 +static void
     5250 +zfs_ioctl_register_dataset_read_secpolicy(zfs_ioc_t ioc,
     5251 +    zfs_ioc_legacy_func_t *func, zfs_secpolicy_func_t *secpolicy)
     5252 +{
     5253 +        zfs_ioctl_register_legacy(ioc, func, secpolicy,
     5254 +            DATASET_NAME, B_FALSE, POOL_CHECK_SUSPENDED);
     5255 +}
     5256 +
     5257 +static void
     5258 +zfs_ioctl_register_dataset_read(zfs_ioc_t ioc, zfs_ioc_legacy_func_t *func)
     5259 +{
     5260 +        zfs_ioctl_register_dataset_read_secpolicy(ioc, func,
     5261 +            zfs_secpolicy_read);
     5262 +}
     5263 +
     5264 +static void
     5265 +zfs_ioctl_register_dataset_modify(zfs_ioc_t ioc, zfs_ioc_legacy_func_t *func,
     5266 +        zfs_secpolicy_func_t *secpolicy)
     5267 +{
     5268 +        zfs_ioctl_register_legacy(ioc, func, secpolicy,
     5269 +            DATASET_NAME, B_TRUE, POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY);
     5270 +}
     5271 +
     5272 +static void
     5273 +zfs_ioctl_init(void)
     5274 +{
     5275 +        zfs_ioctl_register("snapshot", ZFS_IOC_SNAPSHOT,
     5276 +            zfs_ioc_snapshot, zfs_secpolicy_snapshot, POOL_NAME,
     5277 +            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
     5278 +
     5279 +        zfs_ioctl_register("log_history", ZFS_IOC_LOG_HISTORY,
     5280 +            zfs_ioc_log_history, zfs_secpolicy_log_history, NO_NAME,
     5281 +            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_FALSE, B_FALSE);
     5282 +
     5283 +        zfs_ioctl_register("space_snaps", ZFS_IOC_SPACE_SNAPS,
     5284 +            zfs_ioc_space_snaps, zfs_secpolicy_read, DATASET_NAME,
     5285 +            POOL_CHECK_SUSPENDED, B_FALSE, B_FALSE);
     5286 +
     5287 +        zfs_ioctl_register("send", ZFS_IOC_SEND_NEW,
     5288 +            zfs_ioc_send_new, zfs_secpolicy_send_new, DATASET_NAME,
     5289 +            POOL_CHECK_SUSPENDED, B_FALSE, B_FALSE);
     5290 +
     5291 +        zfs_ioctl_register("send_space", ZFS_IOC_SEND_SPACE,
     5292 +            zfs_ioc_send_space, zfs_secpolicy_read, DATASET_NAME,
     5293 +            POOL_CHECK_SUSPENDED, B_FALSE, B_FALSE);
     5294 +
     5295 +        zfs_ioctl_register("create", ZFS_IOC_CREATE,
     5296 +            zfs_ioc_create, zfs_secpolicy_create_clone, DATASET_NAME,
     5297 +            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
     5298 +
     5299 +        zfs_ioctl_register("clone", ZFS_IOC_CLONE,
     5300 +            zfs_ioc_clone, zfs_secpolicy_create_clone, DATASET_NAME,
     5301 +            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
     5302 +
     5303 +        zfs_ioctl_register("destroy_snaps", ZFS_IOC_DESTROY_SNAPS,
     5304 +            zfs_ioc_destroy_snaps, zfs_secpolicy_destroy_snaps, POOL_NAME,
     5305 +            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
     5306 +
     5307 +        /* IOCTLS that use the legacy function signature */
     5308 +
     5309 +        zfs_ioctl_register_legacy(ZFS_IOC_POOL_FREEZE, zfs_ioc_pool_freeze,
     5310 +            zfs_secpolicy_config, NO_NAME, B_FALSE, POOL_CHECK_READONLY);
     5311 +
     5312 +        zfs_ioctl_register_pool(ZFS_IOC_POOL_CREATE, zfs_ioc_pool_create,
     5313 +            zfs_secpolicy_config, B_TRUE, POOL_CHECK_NONE);
     5314 +        zfs_ioctl_register_pool_modify(ZFS_IOC_POOL_SCAN,
     5315 +            zfs_ioc_pool_scan);
     5316 +        zfs_ioctl_register_pool_modify(ZFS_IOC_POOL_UPGRADE,
     5317 +            zfs_ioc_pool_upgrade);
     5318 +        zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_ADD,
     5319 +            zfs_ioc_vdev_add);
     5320 +        zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_REMOVE,
     5321 +            zfs_ioc_vdev_remove);
     5322 +        zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_SET_STATE,
     5323 +            zfs_ioc_vdev_set_state);
     5324 +        zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_ATTACH,
     5325 +            zfs_ioc_vdev_attach);
     5326 +        zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_DETACH,
     5327 +            zfs_ioc_vdev_detach);
     5328 +        zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_SETPATH,
     5329 +            zfs_ioc_vdev_setpath);
     5330 +        zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_SETFRU,
     5331 +            zfs_ioc_vdev_setfru);
     5332 +        zfs_ioctl_register_pool_modify(ZFS_IOC_POOL_SET_PROPS,
     5333 +            zfs_ioc_pool_set_props);
     5334 +        zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_SPLIT,
     5335 +            zfs_ioc_vdev_split);
     5336 +        zfs_ioctl_register_pool_modify(ZFS_IOC_POOL_REGUID,
     5337 +            zfs_ioc_pool_reguid);
     5338 +
     5339 +        zfs_ioctl_register_pool_meta(ZFS_IOC_POOL_CONFIGS,
     5340 +            zfs_ioc_pool_configs, zfs_secpolicy_none);
     5341 +        zfs_ioctl_register_pool_meta(ZFS_IOC_POOL_TRYIMPORT,
     5342 +            zfs_ioc_pool_tryimport, zfs_secpolicy_config);
     5343 +        zfs_ioctl_register_pool_meta(ZFS_IOC_INJECT_FAULT,
     5344 +            zfs_ioc_inject_fault, zfs_secpolicy_inject);
     5345 +        zfs_ioctl_register_pool_meta(ZFS_IOC_CLEAR_FAULT,
     5346 +            zfs_ioc_clear_fault, zfs_secpolicy_inject);
     5347 +        zfs_ioctl_register_pool_meta(ZFS_IOC_INJECT_LIST_NEXT,
     5348 +            zfs_ioc_inject_list_next, zfs_secpolicy_inject);
     5349 +
     5350 +        /*
     5351 +         * pool destroy, and export don't log the history as part of
     5352 +         * zfsdev_ioctl, but rather zfs_ioc_pool_export
     5353 +         * does the logging of those commands.
     5354 +         */
     5355 +        zfs_ioctl_register_pool(ZFS_IOC_POOL_DESTROY, zfs_ioc_pool_destroy,
     5356 +            zfs_secpolicy_config, B_FALSE, POOL_CHECK_NONE);
     5357 +        zfs_ioctl_register_pool(ZFS_IOC_POOL_EXPORT, zfs_ioc_pool_export,
     5358 +            zfs_secpolicy_config, B_FALSE, POOL_CHECK_NONE);
     5359 +
     5360 +        zfs_ioctl_register_pool(ZFS_IOC_POOL_STATS, zfs_ioc_pool_stats,
     5361 +            zfs_secpolicy_read, B_FALSE, POOL_CHECK_NONE);
     5362 +        zfs_ioctl_register_pool(ZFS_IOC_POOL_GET_PROPS, zfs_ioc_pool_get_props,
     5363 +            zfs_secpolicy_read, B_FALSE, POOL_CHECK_NONE);
     5364 +
     5365 +        zfs_ioctl_register_pool(ZFS_IOC_ERROR_LOG, zfs_ioc_error_log,
     5366 +            zfs_secpolicy_inject, B_FALSE, POOL_CHECK_SUSPENDED);
     5367 +        zfs_ioctl_register_pool(ZFS_IOC_DSOBJ_TO_DSNAME,
     5368 +            zfs_ioc_dsobj_to_dsname,
     5369 +            zfs_secpolicy_diff, B_FALSE, POOL_CHECK_SUSPENDED);
     5370 +        zfs_ioctl_register_pool(ZFS_IOC_POOL_GET_HISTORY,
     5371 +            zfs_ioc_pool_get_history,
     5372 +            zfs_secpolicy_config, B_FALSE, POOL_CHECK_SUSPENDED);
     5373 +
     5374 +        zfs_ioctl_register_pool(ZFS_IOC_POOL_IMPORT, zfs_ioc_pool_import,
     5375 +            zfs_secpolicy_config, B_TRUE, POOL_CHECK_NONE);
     5376 +
     5377 +        zfs_ioctl_register_pool(ZFS_IOC_CLEAR, zfs_ioc_clear,
     5378 +            zfs_secpolicy_config, B_TRUE, POOL_CHECK_SUSPENDED);
     5379 +        zfs_ioctl_register_pool(ZFS_IOC_POOL_REOPEN, zfs_ioc_pool_reopen,
     5380 +            zfs_secpolicy_config, B_TRUE, POOL_CHECK_SUSPENDED);
     5381 +
     5382 +        zfs_ioctl_register_dataset_read(ZFS_IOC_SPACE_WRITTEN,
     5383 +            zfs_ioc_space_written);
     5384 +        zfs_ioctl_register_dataset_read(ZFS_IOC_GET_HOLDS,
     5385 +            zfs_ioc_get_holds);
     5386 +        zfs_ioctl_register_dataset_read(ZFS_IOC_OBJSET_RECVD_PROPS,
     5387 +            zfs_ioc_objset_recvd_props);
     5388 +        zfs_ioctl_register_dataset_read(ZFS_IOC_NEXT_OBJ,
     5389 +            zfs_ioc_next_obj);
     5390 +        zfs_ioctl_register_dataset_read(ZFS_IOC_GET_FSACL,
     5391 +            zfs_ioc_get_fsacl);
     5392 +        zfs_ioctl_register_dataset_read(ZFS_IOC_OBJSET_STATS,
     5393 +            zfs_ioc_objset_stats);
     5394 +        zfs_ioctl_register_dataset_read(ZFS_IOC_OBJSET_ZPLPROPS,
     5395 +            zfs_ioc_objset_zplprops);
     5396 +        zfs_ioctl_register_dataset_read(ZFS_IOC_DATASET_LIST_NEXT,
     5397 +            zfs_ioc_dataset_list_next);
     5398 +        zfs_ioctl_register_dataset_read(ZFS_IOC_SNAPSHOT_LIST_NEXT,
     5399 +            zfs_ioc_snapshot_list_next);
     5400 +        zfs_ioctl_register_dataset_read(ZFS_IOC_SEND_PROGRESS,
     5401 +            zfs_ioc_send_progress);
     5402 +
     5403 +        zfs_ioctl_register_dataset_read_secpolicy(ZFS_IOC_DIFF,
     5404 +            zfs_ioc_diff, zfs_secpolicy_diff);
     5405 +        zfs_ioctl_register_dataset_read_secpolicy(ZFS_IOC_OBJ_TO_STATS,
     5406 +            zfs_ioc_obj_to_stats, zfs_secpolicy_diff);
     5407 +        zfs_ioctl_register_dataset_read_secpolicy(ZFS_IOC_OBJ_TO_PATH,
     5408 +            zfs_ioc_obj_to_path, zfs_secpolicy_diff);
     5409 +        zfs_ioctl_register_dataset_read_secpolicy(ZFS_IOC_USERSPACE_ONE,
     5410 +            zfs_ioc_userspace_one, zfs_secpolicy_userspace_one);
     5411 +        zfs_ioctl_register_dataset_read_secpolicy(ZFS_IOC_USERSPACE_MANY,
     5412 +            zfs_ioc_userspace_many, zfs_secpolicy_userspace_many);
     5413 +        zfs_ioctl_register_dataset_read_secpolicy(ZFS_IOC_SEND,
     5414 +            zfs_ioc_send, zfs_secpolicy_send);
     5415 +
     5416 +        zfs_ioctl_register_dataset_modify(ZFS_IOC_SET_PROP, zfs_ioc_set_prop,
     5417 +            zfs_secpolicy_none);
     5418 +        zfs_ioctl_register_dataset_modify(ZFS_IOC_DESTROY, zfs_ioc_destroy,
     5419 +            zfs_secpolicy_destroy);
     5420 +        zfs_ioctl_register_dataset_modify(ZFS_IOC_ROLLBACK, zfs_ioc_rollback,
     5421 +            zfs_secpolicy_rollback);
     5422 +        zfs_ioctl_register_dataset_modify(ZFS_IOC_RENAME, zfs_ioc_rename,
     5423 +            zfs_secpolicy_rename);
     5424 +        zfs_ioctl_register_dataset_modify(ZFS_IOC_RECV, zfs_ioc_recv,
     5425 +            zfs_secpolicy_recv);
     5426 +        zfs_ioctl_register_dataset_modify(ZFS_IOC_PROMOTE, zfs_ioc_promote,
     5427 +            zfs_secpolicy_promote);
     5428 +        zfs_ioctl_register_dataset_modify(ZFS_IOC_HOLD, zfs_ioc_hold,
     5429 +            zfs_secpolicy_hold);
     5430 +        zfs_ioctl_register_dataset_modify(ZFS_IOC_RELEASE, zfs_ioc_release,
     5431 +            zfs_secpolicy_release);
     5432 +        zfs_ioctl_register_dataset_modify(ZFS_IOC_INHERIT_PROP,
     5433 +            zfs_ioc_inherit_prop, zfs_secpolicy_inherit_prop);
     5434 +        zfs_ioctl_register_dataset_modify(ZFS_IOC_SET_FSACL, zfs_ioc_set_fsacl,
     5435 +            zfs_secpolicy_set_fsacl);
     5436 +
     5437 +        zfs_ioctl_register_dataset_nolog(ZFS_IOC_SHARE, zfs_ioc_share,
     5438 +            zfs_secpolicy_share, POOL_CHECK_NONE);
     5439 +        zfs_ioctl_register_dataset_nolog(ZFS_IOC_SMB_ACL, zfs_ioc_smb_acl,
     5440 +            zfs_secpolicy_smb_acl, POOL_CHECK_NONE);
     5441 +        zfs_ioctl_register_dataset_nolog(ZFS_IOC_USERSPACE_UPGRADE,
     5442 +            zfs_ioc_userspace_upgrade, zfs_secpolicy_userspace_upgrade,
     5443 +            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY);
     5444 +        zfs_ioctl_register_dataset_nolog(ZFS_IOC_TMP_SNAPSHOT,
     5445 +            zfs_ioc_tmp_snapshot, zfs_secpolicy_tmp_snapshot,
     5446 +            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY);
     5447 +}
4959 5448  
4960 5449  int
4961 5450  pool_status_check(const char *name, zfs_ioc_namecheck_t type,
4962 5451      zfs_ioc_poolcheck_t check)
4963 5452  {
4964 5453          spa_t *spa;
4965 5454          int error;
4966 5455  
4967 5456          ASSERT(type == POOL_NAME || type == DATASET_NAME);
4968 5457  
↓ open down ↓ 116 lines elided ↑ open up ↑
5085 5574          zfs_ctldev_destroy(zo, minor);
5086 5575          mutex_exit(&zfsdev_state_lock);
5087 5576  
5088 5577          return (0);
5089 5578  }
5090 5579  
5091 5580  static int
5092 5581  zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
5093 5582  {
5094 5583          zfs_cmd_t *zc;
5095      -        uint_t vec;
5096      -        int error, rc;
     5584 +        uint_t vecnum;
     5585 +        int error, rc, len;
5097 5586          minor_t minor = getminor(dev);
     5587 +        const zfs_ioc_vec_t *vec;
     5588 +        char *saved_poolname = NULL;
     5589 +        nvlist_t *innvl = NULL;
5098 5590  
5099 5591          if (minor != 0 &&
5100 5592              zfsdev_get_soft_state(minor, ZSST_CTLDEV) == NULL)
5101 5593                  return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp));
5102 5594  
5103      -        vec = cmd - ZFS_IOC;
     5595 +        vecnum = cmd - ZFS_IOC_FIRST;
5104 5596          ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip));
5105 5597  
5106      -        if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0]))
     5598 +        if (vecnum >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0]))
5107 5599                  return (EINVAL);
     5600 +        vec = &zfs_ioc_vec[vecnum];
5108 5601  
5109 5602          zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
5110 5603  
5111 5604          error = ddi_copyin((void *)arg, zc, sizeof (zfs_cmd_t), flag);
5112      -        if (error != 0)
     5605 +        if (error != 0) {
5113 5606                  error = EFAULT;
     5607 +                goto out;
     5608 +        }
5114 5609  
5115      -        if ((error == 0) && !(flag & FKIOCTL))
5116      -                error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr);
     5610 +        zc->zc_iflags = flag & FKIOCTL;
     5611 +        if (zc->zc_nvlist_src_size != 0) {
     5612 +                error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
     5613 +                    zc->zc_iflags, &innvl);
     5614 +                if (error != 0)
     5615 +                        goto out;
     5616 +        }
5117 5617  
5118 5618          /*
5119 5619           * Ensure that all pool/dataset names are valid before we pass down to
5120 5620           * the lower layers.
5121 5621           */
5122      -        if (error == 0) {
5123      -                zc->zc_name[sizeof (zc->zc_name) - 1] = '\0';
5124      -                zc->zc_iflags = flag & FKIOCTL;
5125      -                switch (zfs_ioc_vec[vec].zvec_namecheck) {
5126      -                case POOL_NAME:
5127      -                        if (pool_namecheck(zc->zc_name, NULL, NULL) != 0)
5128      -                                error = EINVAL;
     5622 +        zc->zc_name[sizeof (zc->zc_name) - 1] = '\0';
     5623 +        switch (vec->zvec_namecheck) {
     5624 +        case POOL_NAME:
     5625 +                if (pool_namecheck(zc->zc_name, NULL, NULL) != 0)
     5626 +                        error = EINVAL;
     5627 +                else
5129 5628                          error = pool_status_check(zc->zc_name,
5130      -                            zfs_ioc_vec[vec].zvec_namecheck,
5131      -                            zfs_ioc_vec[vec].zvec_pool_check);
5132      -                        break;
     5629 +                            vec->zvec_namecheck, vec->zvec_pool_check);
     5630 +                break;
5133 5631  
5134      -                case DATASET_NAME:
5135      -                        if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0)
5136      -                                error = EINVAL;
     5632 +        case DATASET_NAME:
     5633 +                if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0)
     5634 +                        error = EINVAL;
     5635 +                else
5137 5636                          error = pool_status_check(zc->zc_name,
5138      -                            zfs_ioc_vec[vec].zvec_namecheck,
5139      -                            zfs_ioc_vec[vec].zvec_pool_check);
5140      -                        break;
     5637 +                            vec->zvec_namecheck, vec->zvec_pool_check);
     5638 +                break;
5141 5639  
5142      -                case NO_NAME:
5143      -                        break;
5144      -                }
     5640 +        case NO_NAME:
     5641 +                break;
5145 5642          }
5146 5643  
5147      -        if (error == 0)
5148      -                error = zfs_ioc_vec[vec].zvec_func(zc);
5149 5644  
     5645 +        if (error == 0 && !(flag & FKIOCTL))
     5646 +                error = vec->zvec_secpolicy(zc, innvl, cr);
     5647 +
     5648 +        if (error != 0)
     5649 +                goto out;
     5650 +
     5651 +        /* legacy ioctls can modify zc_name */
     5652 +        len = strcspn(zc->zc_name, "/@") + 1;
     5653 +        saved_poolname = kmem_alloc(len, KM_SLEEP);
     5654 +        (void) strlcpy(saved_poolname, zc->zc_name, len);
     5655 +
     5656 +        if (vec->zvec_func != NULL) {
     5657 +                nvlist_t *outnvl;
     5658 +                int puterror = 0;
     5659 +                spa_t *spa;
     5660 +                nvlist_t *lognv = NULL;
     5661 +
     5662 +                ASSERT(vec->zvec_legacy_func == NULL);
     5663 +
     5664 +                /*
     5665 +                 * Add the innvl to the lognv before calling the func,
     5666 +                 * in case the func changes the innvl.
     5667 +                 */
     5668 +                if (vec->zvec_allow_log) {
     5669 +                        lognv = fnvlist_alloc();
     5670 +                        fnvlist_add_string(lognv, ZPOOL_HIST_IOCTL,
     5671 +                            vec->zvec_name);
     5672 +                        if (!nvlist_empty(innvl)) {
     5673 +                                fnvlist_add_nvlist(lognv, ZPOOL_HIST_INPUT_NVL,
     5674 +                                    innvl);
     5675 +                        }
     5676 +                }
     5677 +
     5678 +                outnvl = fnvlist_alloc();
     5679 +                error = vec->zvec_func(zc->zc_name, innvl, outnvl);
     5680 +
     5681 +                if (error == 0 && vec->zvec_allow_log &&
     5682 +                    spa_open(zc->zc_name, &spa, FTAG) == 0) {
     5683 +                        if (!nvlist_empty(outnvl)) {
     5684 +                                fnvlist_add_nvlist(lognv, ZPOOL_HIST_OUTPUT_NVL,
     5685 +                                    outnvl);
     5686 +                        }
     5687 +                        (void) spa_history_log_nvl(spa, lognv);
     5688 +                        spa_close(spa, FTAG);
     5689 +                }
     5690 +                fnvlist_free(lognv);
     5691 +
     5692 +                if (!nvlist_empty(outnvl) || zc->zc_nvlist_dst_size != 0) {
     5693 +                        int smusherror = 0;
     5694 +                        if (vec->zvec_smush_outnvlist) {
     5695 +                                smusherror = nvlist_smush(outnvl,
     5696 +                                    zc->zc_nvlist_dst_size);
     5697 +                        }
     5698 +                        if (smusherror == 0)
     5699 +                                puterror = put_nvlist(zc, outnvl);
     5700 +                }
     5701 +
     5702 +                if (puterror != 0)
     5703 +                        error = puterror;
     5704 +
     5705 +                nvlist_free(outnvl);
     5706 +        } else {
     5707 +                error = vec->zvec_legacy_func(zc);
     5708 +        }
     5709 +
     5710 +out:
     5711 +        nvlist_free(innvl);
5150 5712          rc = ddi_copyout(zc, (void *)arg, sizeof (zfs_cmd_t), flag);
5151      -        if (error == 0) {
5152      -                if (rc != 0)
5153      -                        error = EFAULT;
5154      -                if (zfs_ioc_vec[vec].zvec_his_log)
5155      -                        zfs_log_history(zc);
     5713 +        if (error == 0 && rc != 0)
     5714 +                error = EFAULT;
     5715 +        if (error == 0 && vec->zvec_allow_log) {
     5716 +                char *s = tsd_get(zfs_allow_log_key);
     5717 +                if (s != NULL)
     5718 +                        strfree(s);
     5719 +                (void) tsd_set(zfs_allow_log_key, saved_poolname);
     5720 +        } else {
     5721 +                if (saved_poolname != NULL)
     5722 +                        strfree(saved_poolname);
5156 5723          }
5157 5724  
5158 5725          kmem_free(zc, sizeof (zfs_cmd_t));
5159 5726          return (error);
5160 5727  }
5161 5728  
5162 5729  static int
5163 5730  zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
5164 5731  {
5165 5732          if (cmd != DDI_ATTACH)
↓ open down ↓ 95 lines elided ↑ open up ↑
5261 5828          &zfs_dev_ops
5262 5829  };
5263 5830  
5264 5831  static struct modlinkage modlinkage = {
5265 5832          MODREV_1,
5266 5833          (void *)&zfs_modlfs,
5267 5834          (void *)&zfs_modldrv,
5268 5835          NULL
5269 5836  };
5270 5837  
5271      -
5272      -uint_t zfs_fsyncer_key;
5273      -extern uint_t rrw_tsd_key;
     5838 +static void
     5839 +zfs_allow_log_destroy(void *arg)
     5840 +{
     5841 +        char *poolname = arg;
     5842 +        strfree(poolname);
     5843 +}
5274 5844  
5275 5845  int
5276 5846  _init(void)
5277 5847  {
5278 5848          int error;
5279 5849  
5280 5850          spa_init(FREAD | FWRITE);
5281 5851          zfs_init();
5282 5852          zvol_init();
     5853 +        zfs_ioctl_init();
5283 5854  
5284 5855          if ((error = mod_install(&modlinkage)) != 0) {
5285 5856                  zvol_fini();
5286 5857                  zfs_fini();
5287 5858                  spa_fini();
5288 5859                  return (error);
5289 5860          }
5290 5861  
5291 5862          tsd_create(&zfs_fsyncer_key, NULL);
5292      -        tsd_create(&rrw_tsd_key, NULL);
     5863 +        tsd_create(&rrw_tsd_key, rrw_tsd_destroy);
     5864 +        tsd_create(&zfs_allow_log_key, zfs_allow_log_destroy);
5293 5865  
5294 5866          error = ldi_ident_from_mod(&modlinkage, &zfs_li);
5295 5867          ASSERT(error == 0);
5296 5868          mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL);
5297 5869  
5298 5870          return (0);
5299 5871  }
5300 5872  
5301 5873  int
5302 5874  _fini(void)
↓ open down ↓ 32 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX