Print this page
8520 lzc_rollback_to should support rolling back to origin
7198 libzfs should gracefully handle EINVAL from lzc_rollback
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Approved by: Dan McDonald <danmcd@joyent.com>
NEX-16623 Ability to set properties for multiple datasets/snapshots during single sync-round
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-16502 libshare needs to support SMB in a zone
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-15279 support NFS server in zone
NEX-15520 online NFS shares cause zoneadm halt to hang in nfs_export_zone_fini
Portions contributed by: Dan Kruchinin dan.kruchinin@nexenta.com
Portions contributed by: Stepan Zastupov stepan.zastupov@gmail.com
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-8600 Destroying a KRRP session takes too long
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-5736 implement autoreplace matching based on FRU slot number
NEX-6200 hot spares are not reactivated after reinserting into enclosure
NEX-9403 need to update FRU for spare and l2cache devices
NEX-9404 remove lofi autoreplace support from syseventd
NEX-9409 hotsparing doesn't work for vdevs without FRU
NEX-9424 zfs`vdev_online() needs better notification about state changes
Portions contributed by: Alek Pinchuk <alek@nexenta.com>
Portions contributed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-7822 40Gb Intel XL710 NIC performance data
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-8827 AUTOSNAP: can't register recursive zone when there is a child under autosnappool/volumegrou
Reviewed by: Alex Deiter <alex.deiter@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-8106 async ZFS event notifications don't need to announce publish failure
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-6490 Unable to destroy filesystem with receive_resume_token
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
NEX-6213 KRRP: System panics if recv-stream does not have snap-properties
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Alexey Komarov <alexey.komarov@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
NEX-5553 ZFS auto-trim, manual-trim and scrub can race and deadlock
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-5795 Rename 'wrc' as 'wbc' in the source and in the tech docs
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-5272 KRRP: replicate snapshot properties
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Alexey Komarov <alexey.komarov@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
NEX-5268 WBC: add sysevent migration-done
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-5060 WBC: Writecache and deduplication should not be used together
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
NEX-4830 writecache=off leaks data on special vdev (the data will never migrate)
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
NEX-4608 WRC: Possible deadlock during the disabling of WRC for a dataset
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
4986 receiving replication stream fails if any snapshot exceeds refquota
Reviewed by: John Kennedy <john.kennedy@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Approved by: Gordon Ross <gordon.ross@nexenta.com>
6388 Failure of userland copy should return EFAULT
Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Dan Kimmel <dan.kimmel@delphix.com>
Approved by: Robert Mustacchi <rm@joyent.com>
6328 Fix cstyle errors in zfs codebase (fix studio)
6328 Fix cstyle errors in zfs codebase
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Alex Reece <alex@delphix.com>
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Jorgen Lundman <lundman@lundman.net>
Approved by: Robert Mustacchi <rm@joyent.com>
2605 want to resume interrupted zfs send
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Paul Dagnelie <pcd@delphix.com>
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Xin Li <delphij@freebsd.org>
Reviewed by: Arne Jansen <sensille@gmx.net>
Approved by: Dan McDonald <danmcd@omniti.com>
6286 ZFS internal error when set large block on bootfs
Reviewed by: Paul Dagnelie <pcd@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Andriy Gapon <avg@FreeBSD.org>
Approved by: Robert Mustacchi <rm@joyent.com>
4185 add new cryptographic checksums to ZFS: SHA-512, Skein, Edon-R (fix studio build)
4185 add new cryptographic checksums to ZFS: SHA-512, Skein, Edon-R
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Approved by: Garrett D'Amore <garrett@damore.org>
6096 ZFS_SMB_ACL_RENAME needs to cleanup better
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Gordon Ross <gordon.w.ross@gmail.com>
Reviewed by: George Wilson <gwilson@zfsmail.com>
Approved by: Robert Mustacchi <rm@joyent.com>
5946 zfs_ioc_space_snaps must check that firstsnap and lastsnap refer to snapshots
5945 zfs_ioc_send_space must ensure that fromsnap refers to a snapshot
Reviewed by: Steven Hartland <killing@multiplay.co.uk>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Approved by: Gordon Ross <gordon.ross@nexenta.com>
5515 dataset user hold doesn't reject empty tags
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Approved by: Matthew Ahrens <mahrens@delphix.com>
5765 add support for estimating send stream size with lzc_send_space when source is a bookmark
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Reviewed by: Steven Hartland <killing@multiplay.co.uk>
Reviewed by: Bayard Bell <buffer.g.overflow@gmail.com>
Approved by: Albert Lee <trisk@nexenta.com>
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Revert "NEX-4476 WRC: Allow to use write back cache per tree of datasets"
This reverts commit fe97b74444278a6f36fec93179133641296312da.
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
NEX-4194 WRC does not migrate data when idle
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
NEX-4206 Event 'recv' should contain information that received ds is new
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alexey Komarov <alexey.komarov@nexenta.com>
NEX-4044 remove sha1crc32 in preparation with upstream merge of edon-r and skien
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Alek Pinchuk <alek@nexenta.com>
Conflicts:
        usr/src/uts/common/fs/zfs/sys/zio_checksum.h
NEX-3984 On-demand TRIM
Reviewed by: Alek Pinchuk <alek@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Conflicts:
        usr/src/common/zfs/zpool_prop.c
        usr/src/uts/common/sys/fs/zfs.h
NEX-3964 It should not be allowed to rename a snapshot that its new name is matched to the prefix of in-kernel autosnapshots
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-3878 Bogus address kernel panic in nvlist_copy_pairs from snmpd whilst exporting a zpool
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-3921 Memory leaks in ZFS_IOC_OBJSET_STATS_NVL implementation
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-3010 e1000g use after free on start failure
Reviewed by: Marcel Telka <marcel.telka@nexenta.com>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-3731 fixed incorrect behavior of zpool export/destroy for faulted pool that is caused by krrp-check (lint)
NEX-3731 fixed incorrect behavior of zpool export/destroy for faulted pool that is caused by krrp-check
 Reviewed by: Alek Pinchuk <alek@nexenta.com>
 Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
NEX-3723 Want ZFS dataset bulk listing support
Reviewed by: Josef Sipek <josef.sipek@nexenta.com>
NEX-2195 zfs panic assertion failed: strcmp(zn->zn_key_orig, mze->mze_name) != 0
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
NEX-3726 CBC decrypt returns encrypted data
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-3709 Fixed KRRP/WRC code style and KRRP related warnings that are showed by 'git nits'
Reviewed by: Alek Pinchuk <alek@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-3558 KRRP Integration
NEX-3165 need some dedup improvements
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
NEX-3070 Panic in zpool_create_features_002_pos test
NEX-2935 want async notification for certain ZFS changes (fix)
NEX-2935 want async notification for certain ZFS changes (lint)
NEX-2935 want async notification for certain ZFS changes
OS-103 handle CoS descriptor persistent references across vdev operations
OS-102 add man page info and tests for vdev/CoS properties and ZFS meta features
OS-80 support for vdev and CoS properties for the new I/O scheduler
OS-95 lint warning introduced by OS-61
Remaining fixes for the illumos merge
Moved closed ZFS files to open repo, changed Makefiles accordingly
Removed unneeded weak symbols
Issue #34: Add feature flag for the compount checksum - sha1crc32
           Contributors: Boris Protopopov
Fixup merge results
OS-15 ensure that truss continues to work
OS-15 revert changes to put_nvlist
re #13850 Refactor ZFS config discovery IOCs to libzfs_core patterns
re 13748 added zpool export -c option
zpool export -c command exports specified pool while keeping its latest
configuration in the cache file for subsequent zpool import -c.
re #12619 rb4429 More dp->dp_config_rwlock holds
re #13204 rb4280 zfs receive/rollback deadlock
re #12585 rb4049 ZFS++ work port - refactoring to improve separation of open/closed code, bug fixes, performance improvements - open code
Bug 11205: add missing libzfs_closed_stubs.c to fix opensource-only build.
ZFS plus work: special vdevs, cos, cos/vdev properties
Bug 10481 - Dry run option in 'zfs send' isn't the same as in NexentaStor 3.1
re #7550 rb2134 lint-clean nza-kernel
re #6815 rb1758 need WORM in nza-kernel (4.0)

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 ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  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 + */
       25 +
       26 +/*
  24   27   * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
  25   28   * Portions Copyright 2011 Martin Matuska
  26   29   * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
  27      - * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  28   30   * Copyright (c) 2014, 2016 Joyent, Inc. All rights reserved.
  29   31   * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
  30   32   * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
  31   33   * Copyright (c) 2013 Steven Hartland. All rights reserved.
  32   34   * Copyright (c) 2014 Integros [integros.com]
       35 + * Copyright 2018 Nexenta Systems, Inc.
  33   36   * Copyright 2016 Toomas Soome <tsoome@me.com>
  34   37   * Copyright 2017 RackTop Systems.
  35   38   * Copyright (c) 2017 Datto Inc.
  36   39   */
  37   40  
  38   41  /*
  39   42   * ZFS ioctls.
  40   43   *
  41   44   * This file handles the ioctls to /dev/zfs, used for configuring ZFS storage
  42   45   * pools and filesystems, e.g. with /sbin/zfs and /sbin/zpool.
↓ open down ↓ 106 lines elided ↑ open up ↑
 149  152  #include <sys/cmn_err.h>
 150  153  #include <sys/stat.h>
 151  154  #include <sys/zfs_ioctl.h>
 152  155  #include <sys/zfs_vfsops.h>
 153  156  #include <sys/zfs_znode.h>
 154  157  #include <sys/zap.h>
 155  158  #include <sys/spa.h>
 156  159  #include <sys/spa_impl.h>
 157  160  #include <sys/vdev.h>
 158  161  #include <sys/priv_impl.h>
      162 +#include <sys/autosnap.h>
 159  163  #include <sys/dmu.h>
 160  164  #include <sys/dsl_dir.h>
 161  165  #include <sys/dsl_dataset.h>
 162  166  #include <sys/dsl_prop.h>
 163  167  #include <sys/dsl_deleg.h>
      168 +#include <sys/dsl_synctask.h>
 164  169  #include <sys/dmu_objset.h>
 165  170  #include <sys/dmu_impl.h>
 166  171  #include <sys/dmu_tx.h>
 167  172  #include <sys/ddi.h>
 168  173  #include <sys/sunddi.h>
 169  174  #include <sys/sunldi.h>
 170  175  #include <sys/policy.h>
 171  176  #include <sys/zone.h>
 172  177  #include <sys/nvpair.h>
 173  178  #include <sys/pathname.h>
↓ open down ↓ 5 lines elided ↑ open up ↑
 179  184  #include <sys/zfs_onexit.h>
 180  185  #include <sys/zvol.h>
 181  186  #include <sys/dsl_scan.h>
 182  187  #include <sharefs/share.h>
 183  188  #include <sys/dmu_objset.h>
 184  189  #include <sys/dmu_send.h>
 185  190  #include <sys/dsl_destroy.h>
 186  191  #include <sys/dsl_bookmark.h>
 187  192  #include <sys/dsl_userhold.h>
 188  193  #include <sys/zfeature.h>
      194 +#include <sys/cos.h>
      195 +#include <sys/cos_impl.h>
      196 +#include <sys/zfeature.h>
      197 +#include <sys/sysevent.h>
      198 +#include <sys/sysevent_impl.h>
 189  199  #include <sys/zcp.h>
 190  200  #include <sys/zio_checksum.h>
 191      -#include <sys/vdev_removal.h>
 192  201  
 193  202  #include "zfs_namecheck.h"
 194  203  #include "zfs_prop.h"
 195  204  #include "zfs_deleg.h"
 196  205  #include "zfs_comutil.h"
      206 +#include "zfs_errno.h"
 197  207  
 198  208  #include "lua.h"
 199  209  #include "lauxlib.h"
 200  210  
 201  211  extern struct modlfs zfs_modlfs;
 202  212  
 203  213  extern void zfs_init(void);
 204  214  extern void zfs_fini(void);
 205  215  
 206  216  ldi_ident_t zfs_li = NULL;
↓ open down ↓ 43 lines elided ↑ open up ↑
 250  260      cred_t *cr);
 251  261  static int zfs_check_clearable(char *dataset, nvlist_t *props,
 252  262      nvlist_t **errors);
 253  263  static int zfs_fill_zplprops_root(uint64_t, nvlist_t *, nvlist_t *,
 254  264      boolean_t *);
 255  265  int zfs_set_prop_nvlist(const char *, zprop_source_t, nvlist_t *, nvlist_t *);
 256  266  static int get_nvlist(uint64_t nvl, uint64_t size, int iflag, nvlist_t **nvp);
 257  267  
 258  268  static int zfs_prop_activate_feature(spa_t *spa, spa_feature_t feature);
 259  269  
      270 +static int
      271 +zfs_is_wormed_ds(dsl_dataset_t *ds)
      272 +{
      273 +        char worminfo[13] = {0};
      274 +
      275 +        if (dsl_prop_get_ds(ds, "nms:worm", 1, 12, &worminfo, NULL) == 0 &&
      276 +            worminfo[0] && strcmp(worminfo, "0") != 0 &&
      277 +            strcmp(worminfo, "off") != 0 && strcmp(worminfo, "-") != 0) {
      278 +                return (1);
      279 +        }
      280 +        return (0);
      281 +}
      282 +
      283 +static int
      284 +zfs_is_wormed(const char *name)
      285 +{
      286 +        char worminfo[13] = {0};
      287 +        char cname[MAXNAMELEN];
      288 +        char *end;
      289 +
      290 +        (void) strlcpy(cname, name, MAXNAMELEN);
      291 +        end = strchr(cname, '@');
      292 +        if (end)
      293 +                *end = 0;
      294 +
      295 +        if (dsl_prop_get(cname, "nms:worm", 1, 12, &worminfo, NULL) == 0 &&
      296 +            worminfo[0] && strcmp(worminfo, "0") != 0 &&
      297 +            strcmp(worminfo, "off") != 0 && strcmp(worminfo, "-") != 0) {
      298 +                return (1);
      299 +        }
      300 +        return (0);
      301 +}
      302 +
 260  303  /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */
 261  304  void
 262  305  __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
 263  306  {
 264  307          const char *newfile;
 265  308          char buf[512];
 266  309          va_list adx;
 267  310  
 268  311          /*
 269  312           * Get rid of annoying "../common/" prefix to filename.
↓ open down ↓ 495 lines elided ↑ open up ↑
 765  808          }
 766  809  
 767  810          VN_RELE(vp);
 768  811          return (dsl_deleg_access(zc->zc_name,
 769  812              ZFS_DELEG_PERM_SHARE, cr));
 770  813  }
 771  814  
 772  815  int
 773  816  zfs_secpolicy_share(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 774  817  {
 775      -        if (!INGLOBALZONE(curproc))
 776      -                return (SET_ERROR(EPERM));
 777      -
 778  818          if (secpolicy_nfs(cr) == 0) {
 779  819                  return (0);
 780  820          } else {
 781  821                  return (zfs_secpolicy_deleg_share(zc, innvl, cr));
 782  822          }
 783  823  }
 784  824  
 785  825  int
 786  826  zfs_secpolicy_smb_acl(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
 787  827  {
 788      -        if (!INGLOBALZONE(curproc))
 789      -                return (SET_ERROR(EPERM));
 790      -
 791  828          if (secpolicy_smb(cr) == 0) {
 792  829                  return (0);
 793  830          } else {
 794  831                  return (zfs_secpolicy_deleg_share(zc, innvl, cr));
 795  832          }
 796  833  }
 797  834  
 798  835  static int
 799  836  zfs_get_parent(const char *datasetname, char *parent, int parentsize)
 800  837  {
↓ open down ↓ 235 lines elided ↑ open up ↑
1036 1073                      ZFS_DELEG_PERM_BOOKMARK, cr);
1037 1074                  *hashp = '#';
1038 1075                  if (error != 0)
1039 1076                          break;
1040 1077          }
1041 1078          return (error);
1042 1079  }
1043 1080  
1044 1081  /* ARGSUSED */
1045 1082  static int
1046      -zfs_secpolicy_remap(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
1047      -{
1048      -        return (zfs_secpolicy_write_perms(zc->zc_name,
1049      -            ZFS_DELEG_PERM_REMAP, cr));
1050      -}
1051      -
1052      -/* ARGSUSED */
1053      -static int
1054 1083  zfs_secpolicy_destroy_bookmarks(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
1055 1084  {
1056 1085          nvpair_t *pair, *nextpair;
1057 1086          int error = 0;
1058 1087  
1059 1088          for (pair = nvlist_next_nvpair(innvl, NULL); pair != NULL;
1060 1089              pair = nextpair) {
1061 1090                  char *name = nvpair_name(pair);
1062 1091                  char *hashp = strchr(name, '#');
1063 1092                  nextpair = nvlist_next_nvpair(innvl, pair);
↓ open down ↓ 312 lines elided ↑ open up ↑
1376 1405                  } while (size > max);
1377 1406  
1378 1407                  fnvlist_remove_nvpair(errors, more_errors);
1379 1408                  fnvlist_add_int32(errors, ZPROP_N_MORE_ERRORS, n);
1380 1409                  ASSERT3U(fnvlist_size(errors), <=, max);
1381 1410          }
1382 1411  
1383 1412          return (0);
1384 1413  }
1385 1414  
     1415 +/*
     1416 + * Callers will know whether there's anything to unpack based on ret non-0/errno
     1417 + * set to ENOMEM, but observers (e.g truss) need the message properly marked to
     1418 + * know if it should be unpacked and displayed. Don't marked as filled unless
     1419 + * completely successful. If there's a non-empty nvlist, set size to its nvl
     1420 + * size as resize hint.
     1421 + */
1386 1422  static int
1387 1423  put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl)
1388 1424  {
1389 1425          char *packed = NULL;
1390 1426          int error = 0;
1391 1427          size_t size;
1392 1428  
1393 1429          size = fnvlist_size(nvl);
1394 1430  
     1431 +        zc->zc_nvlist_dst_filled = B_FALSE;
1395 1432          if (size > zc->zc_nvlist_dst_size) {
1396 1433                  error = SET_ERROR(ENOMEM);
1397 1434          } else {
1398 1435                  packed = fnvlist_pack(nvl, &size);
1399 1436                  if (ddi_copyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst,
1400 1437                      size, zc->zc_iflags) != 0)
1401 1438                          error = SET_ERROR(EFAULT);
     1439 +                else
     1440 +                        zc->zc_nvlist_dst_filled = B_TRUE;
1402 1441                  fnvlist_pack_free(packed, size);
1403 1442          }
1404 1443  
1405 1444          zc->zc_nvlist_dst_size = size;
1406      -        zc->zc_nvlist_dst_filled = B_TRUE;
1407 1445          return (error);
1408 1446  }
1409 1447  
     1448 +static int
     1449 +getzfsvfs_from_ds(dsl_dataset_t *ds, zfsvfs_t **zfvp)
     1450 +{
     1451 +        objset_t *os;
     1452 +        int error;
     1453 +        dsl_pool_t *dp;
     1454 +
     1455 +        dp = ds->ds_dir->dd_pool;
     1456 +        dsl_pool_config_enter(dp, FTAG);
     1457 +
     1458 +        /*
     1459 +         * IU:  we probably need to hold dataset here.
     1460 +         *      For now let's assume we do.
     1461 +         *      May need revision later.
     1462 +         */
     1463 +        dsl_dataset_long_hold(ds, FTAG);
     1464 +        error = dmu_objset_from_ds(ds, &os);
     1465 +        if (dmu_objset_type(os) != DMU_OST_ZFS) {
     1466 +                dsl_dataset_long_rele(ds, FTAG);
     1467 +                dsl_pool_config_exit(dp, FTAG);
     1468 +                return (EINVAL);
     1469 +        }
     1470 +
     1471 +        mutex_enter(&os->os_user_ptr_lock);
     1472 +        *zfvp = dmu_objset_get_user(os);
     1473 +        if (*zfvp) {
     1474 +                VFS_HOLD((*zfvp)->z_vfs);
     1475 +        } else {
     1476 +                error = ESRCH;
     1477 +        }
     1478 +        mutex_exit(&os->os_user_ptr_lock);
     1479 +        dsl_dataset_long_rele(ds, FTAG);
     1480 +        dsl_pool_config_exit(dp, FTAG);
     1481 +        return (error);
     1482 +}
     1483 +
1410 1484  int
1411 1485  getzfsvfs_impl(objset_t *os, zfsvfs_t **zfvp)
1412 1486  {
1413 1487          int error = 0;
1414 1488          if (dmu_objset_type(os) != DMU_OST_ZFS) {
1415 1489                  return (SET_ERROR(EINVAL));
1416 1490          }
1417 1491  
1418 1492          mutex_enter(&os->os_user_ptr_lock);
1419 1493          *zfvp = dmu_objset_get_user(os);
↓ open down ↓ 56 lines elided ↑ open up ↑
1476 1550          rrm_exit(&zfsvfs->z_teardown_lock, tag);
1477 1551  
1478 1552          if (zfsvfs->z_vfs) {
1479 1553                  VFS_RELE(zfsvfs->z_vfs);
1480 1554          } else {
1481 1555                  dmu_objset_disown(zfsvfs->z_os, zfsvfs);
1482 1556                  zfsvfs_free(zfsvfs);
1483 1557          }
1484 1558  }
1485 1559  
     1560 +
     1561 +/*
     1562 + * Publish events using GPEC subsystem
     1563 + */
     1564 +
     1565 +static evchan_t *zfs_channel = NULL;
     1566 +
     1567 +void
     1568 +zfs_event_post(const char *subclass, const char *operation, nvlist_t *ev_data)
     1569 +{
     1570 +
     1571 +        if (zfs_channel == NULL)
     1572 +                goto out;
     1573 +
     1574 +        fnvlist_add_string(ev_data, "operation", operation);
     1575 +
     1576 +        (void) sysevent_evc_publish(zfs_channel, subclass, operation,
     1577 +            "com.nexenta", "zfs-kernel", ev_data, EVCH_NOSLEEP);
     1578 +
     1579 +out:
     1580 +        fnvlist_free(ev_data);
     1581 +}
     1582 +
1486 1583  static int
1487 1584  zfs_ioc_pool_create(zfs_cmd_t *zc)
1488 1585  {
1489 1586          int error;
1490 1587          nvlist_t *config, *props = NULL;
1491 1588          nvlist_t *rootprops = NULL;
1492 1589          nvlist_t *zplprops = NULL;
     1590 +        nvlist_t *event;
1493 1591  
1494 1592          if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
1495 1593              zc->zc_iflags, &config))
1496 1594                  return (error);
1497 1595  
1498 1596          if (zc->zc_nvlist_src_size != 0 && (error =
1499 1597              get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
1500 1598              zc->zc_iflags, &props))) {
1501 1599                  nvlist_free(config);
1502 1600                  return (error);
↓ open down ↓ 28 lines elided ↑ open up ↑
1531 1629  
1532 1630          error = spa_create(zc->zc_name, config, props, zplprops);
1533 1631  
1534 1632          /*
1535 1633           * Set the remaining root properties
1536 1634           */
1537 1635          if (!error && (error = zfs_set_prop_nvlist(zc->zc_name,
1538 1636              ZPROP_SRC_LOCAL, rootprops, NULL)) != 0)
1539 1637                  (void) spa_destroy(zc->zc_name);
1540 1638  
     1639 +        if (error == 0) {
     1640 +                event = fnvlist_alloc();
     1641 +                fnvlist_add_string(event, "name", zc->zc_name);
     1642 +                fnvlist_add_nvlist(event, "config", config);
     1643 +                if (props != NULL)
     1644 +                        fnvlist_add_nvlist(event, "props", props);
     1645 +                zfs_event_post(ZPOOL_EC_STATUS, "create", event);
     1646 +        }
     1647 +
1541 1648  pool_props_bad:
1542 1649          nvlist_free(rootprops);
1543 1650          nvlist_free(zplprops);
1544 1651          nvlist_free(config);
1545 1652          nvlist_free(props);
1546 1653  
1547 1654          return (error);
1548 1655  }
1549 1656  
1550 1657  static int
1551 1658  zfs_ioc_pool_destroy(zfs_cmd_t *zc)
1552 1659  {
1553 1660          int error;
     1661 +        nvlist_t *event;
1554 1662          zfs_log_history(zc);
1555 1663          error = spa_destroy(zc->zc_name);
1556      -        if (error == 0)
     1664 +        if (error == 0) {
1557 1665                  zvol_remove_minors(zc->zc_name);
     1666 +                event = fnvlist_alloc();
     1667 +                fnvlist_add_string(event, "pool", zc->zc_name);
     1668 +                zfs_event_post(ZPOOL_EC_STATUS, "destroy", event);
     1669 +        }
1558 1670          return (error);
1559 1671  }
1560 1672  
1561 1673  static int
1562 1674  zfs_ioc_pool_import(zfs_cmd_t *zc)
1563 1675  {
1564 1676          nvlist_t *config, *props = NULL;
1565 1677          uint64_t guid;
1566 1678          int error;
     1679 +        nvlist_t *event;
1567 1680  
1568 1681          if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
1569 1682              zc->zc_iflags, &config)) != 0)
1570 1683                  return (error);
1571 1684  
1572 1685          if (zc->zc_nvlist_src_size != 0 && (error =
1573 1686              get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
1574 1687              zc->zc_iflags, &props))) {
1575 1688                  nvlist_free(config);
1576 1689                  return (error);
1577 1690          }
1578 1691  
1579 1692          if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 ||
1580 1693              guid != zc->zc_guid)
1581 1694                  error = SET_ERROR(EINVAL);
1582 1695          else
1583 1696                  error = spa_import(zc->zc_name, config, props, zc->zc_cookie);
1584 1697  
     1698 +        if (error == 0) {
     1699 +                event = fnvlist_alloc();
     1700 +                fnvlist_add_string(event, "pool", zc->zc_name);
     1701 +                fnvlist_add_uint64(event, "guid", zc->zc_guid);
     1702 +                fnvlist_add_nvlist(event, "config", config);
     1703 +                if (props != NULL)
     1704 +                        fnvlist_add_nvlist(event, "props", props);
     1705 +                zfs_event_post(ZPOOL_EC_STATUS, "import", event);
     1706 +        }
     1707 +
1585 1708          if (zc->zc_nvlist_dst != 0) {
1586 1709                  int err;
1587 1710  
1588 1711                  if ((err = put_nvlist(zc, config)) != 0)
1589 1712                          error = err;
1590 1713          }
1591 1714  
1592 1715          nvlist_free(config);
1593 1716  
1594 1717          nvlist_free(props);
1595 1718  
1596 1719          return (error);
1597 1720  }
1598 1721  
1599 1722  static int
1600 1723  zfs_ioc_pool_export(zfs_cmd_t *zc)
1601 1724  {
1602 1725          int error;
1603 1726          boolean_t force = (boolean_t)zc->zc_cookie;
1604 1727          boolean_t hardforce = (boolean_t)zc->zc_guid;
     1728 +        boolean_t saveconfig = (boolean_t)zc->zc_obj;
     1729 +        nvlist_t *event;
1605 1730  
1606 1731          zfs_log_history(zc);
1607      -        error = spa_export(zc->zc_name, NULL, force, hardforce);
1608      -        if (error == 0)
     1732 +        error = spa_export(zc->zc_name, NULL, force, hardforce, saveconfig);
     1733 +        if (error == 0) {
1609 1734                  zvol_remove_minors(zc->zc_name);
     1735 +                event = fnvlist_alloc();
     1736 +                fnvlist_add_string(event, "pool", zc->zc_name);
     1737 +                zfs_event_post(ZPOOL_EC_STATUS, "export", event);
     1738 +        }
1610 1739          return (error);
1611 1740  }
1612 1741  
1613 1742  static int
1614 1743  zfs_ioc_pool_configs(zfs_cmd_t *zc)
1615 1744  {
1616 1745          nvlist_t *configs;
1617 1746          int error;
1618 1747  
1619 1748          if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL)
↓ open down ↓ 92 lines elided ↑ open up ↑
1712 1841          else if (zc->zc_cookie == POOL_SCAN_NONE)
1713 1842                  error = spa_scan_stop(spa);
1714 1843          else
1715 1844                  error = spa_scan(spa, zc->zc_cookie);
1716 1845  
1717 1846          spa_close(spa, FTAG);
1718 1847  
1719 1848          return (error);
1720 1849  }
1721 1850  
     1851 +/*
     1852 + * inputs:
     1853 + * zc_name              name of the pool
     1854 + * zc_cookie            trim_cmd_info_t
     1855 + */
1722 1856  static int
     1857 +zfs_ioc_pool_trim(zfs_cmd_t *zc)
     1858 +{
     1859 +        spa_t *spa;
     1860 +        int error;
     1861 +        trim_cmd_info_t tci;
     1862 +
     1863 +        if (ddi_copyin((void *)(uintptr_t)zc->zc_cookie, &tci,
     1864 +            sizeof (tci), 0) == -1)
     1865 +                return (EFAULT);
     1866 +
     1867 +        if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
     1868 +                return (error);
     1869 +
     1870 +        if (tci.tci_start) {
     1871 +                spa_man_trim(spa, tci.tci_rate);
     1872 +        } else {
     1873 +                spa_man_trim_stop(spa);
     1874 +        }
     1875 +
     1876 +        spa_close(spa, FTAG);
     1877 +
     1878 +        return (error);
     1879 +}
     1880 +
     1881 +static int
1723 1882  zfs_ioc_pool_freeze(zfs_cmd_t *zc)
1724 1883  {
1725 1884          spa_t *spa;
1726 1885          int error;
1727 1886  
1728 1887          error = spa_open(zc->zc_name, &spa, FTAG);
1729 1888          if (error == 0) {
1730 1889                  spa_freeze(spa);
1731 1890                  spa_close(spa, FTAG);
1732 1891          }
↓ open down ↓ 130 lines elided ↑ open up ↑
1863 2022          return (error);
1864 2023  }
1865 2024  
1866 2025  static int
1867 2026  zfs_ioc_vdev_add(zfs_cmd_t *zc)
1868 2027  {
1869 2028          spa_t *spa;
1870 2029          int error;
1871 2030          nvlist_t *config, **l2cache, **spares;
1872 2031          uint_t nl2cache = 0, nspares = 0;
     2032 +        nvlist_t *event;
1873 2033  
1874 2034          error = spa_open(zc->zc_name, &spa, FTAG);
1875 2035          if (error != 0)
1876 2036                  return (error);
1877 2037  
1878 2038          error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
1879 2039              zc->zc_iflags, &config);
1880 2040          (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_L2CACHE,
1881 2041              &l2cache, &nl2cache);
1882 2042  
↓ open down ↓ 11 lines elided ↑ open up ↑
1894 2054           * l2cache and spare devices are ok to be added to a rootpool.
1895 2055           */
1896 2056          if (spa_bootfs(spa) != 0 && nl2cache == 0 && nspares == 0) {
1897 2057                  nvlist_free(config);
1898 2058                  spa_close(spa, FTAG);
1899 2059                  return (SET_ERROR(EDOM));
1900 2060          }
1901 2061  
1902 2062          if (error == 0) {
1903 2063                  error = spa_vdev_add(spa, config);
     2064 +                if (error == 0) {
     2065 +                        event = fnvlist_alloc();
     2066 +                        fnvlist_add_string(event, "pool", zc->zc_name);
     2067 +                        fnvlist_add_nvlist(event, "config", config);
     2068 +                        zfs_event_post(ZPOOL_EC_STATUS, "add", event);
     2069 +
     2070 +                }
1904 2071                  nvlist_free(config);
1905 2072          }
1906 2073          spa_close(spa, FTAG);
1907 2074          return (error);
1908 2075  }
1909 2076  
1910 2077  /*
1911 2078   * inputs:
1912 2079   * zc_name              name of the pool
1913      - * zc_guid              guid of vdev to remove
1914      - * zc_cookie            cancel removal
     2080 + * zc_nvlist_conf       nvlist of devices to remove
     2081 + * zc_cookie            to stop the remove?
1915 2082   */
1916 2083  static int
1917 2084  zfs_ioc_vdev_remove(zfs_cmd_t *zc)
1918 2085  {
1919 2086          spa_t *spa;
1920 2087          int error;
     2088 +        nvlist_t *event;
1921 2089  
1922 2090          error = spa_open(zc->zc_name, &spa, FTAG);
1923 2091          if (error != 0)
1924 2092                  return (error);
1925      -        if (zc->zc_cookie != 0) {
1926      -                error = spa_vdev_remove_cancel(spa);
1927      -        } else {
1928      -                error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE);
     2093 +        error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE);
     2094 +        if (error == 0) {
     2095 +                event = fnvlist_alloc();
     2096 +                fnvlist_add_string(event, "pool", zc->zc_name);
     2097 +                fnvlist_add_uint64(event, "guid", zc->zc_guid);
     2098 +                zfs_event_post(ZPOOL_EC_STATUS, "remove", event);
1929 2099          }
     2100 +
1930 2101          spa_close(spa, FTAG);
1931 2102          return (error);
1932 2103  }
1933 2104  
1934 2105  static int
1935 2106  zfs_ioc_vdev_set_state(zfs_cmd_t *zc)
1936 2107  {
1937 2108          spa_t *spa;
1938 2109          int error;
1939 2110          vdev_state_t newstate = VDEV_STATE_UNKNOWN;
↓ open down ↓ 4 lines elided ↑ open up ↑
1944 2115          case VDEV_STATE_ONLINE:
1945 2116                  error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate);
1946 2117                  break;
1947 2118  
1948 2119          case VDEV_STATE_OFFLINE:
1949 2120                  error = vdev_offline(spa, zc->zc_guid, zc->zc_obj);
1950 2121                  break;
1951 2122  
1952 2123          case VDEV_STATE_FAULTED:
1953 2124                  if (zc->zc_obj != VDEV_AUX_ERR_EXCEEDED &&
1954      -                    zc->zc_obj != VDEV_AUX_EXTERNAL)
     2125 +                    zc->zc_obj != VDEV_AUX_EXTERNAL &&
     2126 +                    zc->zc_obj != VDEV_AUX_OPEN_FAILED)
1955 2127                          zc->zc_obj = VDEV_AUX_ERR_EXCEEDED;
1956 2128  
1957 2129                  error = vdev_fault(spa, zc->zc_guid, zc->zc_obj);
1958 2130                  break;
1959 2131  
1960 2132          case VDEV_STATE_DEGRADED:
1961 2133                  if (zc->zc_obj != VDEV_AUX_ERR_EXCEEDED &&
1962 2134                      zc->zc_obj != VDEV_AUX_EXTERNAL)
1963 2135                          zc->zc_obj = VDEV_AUX_ERR_EXCEEDED;
1964 2136  
↓ open down ↓ 7 lines elided ↑ open up ↑
1972 2144          spa_close(spa, FTAG);
1973 2145          return (error);
1974 2146  }
1975 2147  
1976 2148  static int
1977 2149  zfs_ioc_vdev_attach(zfs_cmd_t *zc)
1978 2150  {
1979 2151          spa_t *spa;
1980 2152          int replacing = zc->zc_cookie;
1981 2153          nvlist_t *config;
     2154 +        nvlist_t *event;
1982 2155          int error;
1983 2156  
1984 2157          if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
1985 2158                  return (error);
1986 2159  
1987 2160          if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
1988 2161              zc->zc_iflags, &config)) == 0) {
1989 2162                  error = spa_vdev_attach(spa, zc->zc_guid, config, replacing);
     2163 +                if (error == 0) {
     2164 +                        event = fnvlist_alloc();
     2165 +                        fnvlist_add_string(event, "pool", zc->zc_name);
     2166 +                        fnvlist_add_nvlist(event, "config", config);
     2167 +                        fnvlist_add_int32(event, "replacing", replacing);
     2168 +                        zfs_event_post(ZPOOL_EC_STATUS, "attach", event);
     2169 +                }
1990 2170                  nvlist_free(config);
1991 2171          }
1992 2172  
1993 2173          spa_close(spa, FTAG);
1994 2174          return (error);
1995 2175  }
1996 2176  
1997 2177  static int
1998 2178  zfs_ioc_vdev_detach(zfs_cmd_t *zc)
1999 2179  {
2000 2180          spa_t *spa;
2001 2181          int error;
     2182 +        nvlist_t *event;
2002 2183  
2003 2184          if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
2004 2185                  return (error);
2005 2186  
2006 2187          error = spa_vdev_detach(spa, zc->zc_guid, 0, B_FALSE);
2007      -
     2188 +        if (error == 0) {
     2189 +                event = fnvlist_alloc();
     2190 +                fnvlist_add_string(event, "pool", zc->zc_name);
     2191 +                fnvlist_add_uint64(event, "guid", zc->zc_guid);
     2192 +                zfs_event_post(ZPOOL_EC_STATUS, "detach", event);
     2193 +        }
2008 2194          spa_close(spa, FTAG);
2009 2195          return (error);
2010 2196  }
2011 2197  
2012 2198  static int
2013 2199  zfs_ioc_vdev_split(zfs_cmd_t *zc)
2014 2200  {
2015 2201          spa_t *spa;
2016 2202          nvlist_t *config, *props = NULL;
2017 2203          int error;
↓ open down ↓ 20 lines elided ↑ open up ↑
2038 2224  
2039 2225          spa_close(spa, FTAG);
2040 2226  
2041 2227          nvlist_free(config);
2042 2228          nvlist_free(props);
2043 2229  
2044 2230          return (error);
2045 2231  }
2046 2232  
2047 2233  static int
     2234 +zfs_ioc_vdev_setl2adddt(zfs_cmd_t *zc)
     2235 +{
     2236 +        spa_t *spa;
     2237 +        int error;
     2238 +        uint64_t guid = zc->zc_guid;
     2239 +        char *l2ad_ddt = zc->zc_value;
     2240 +
     2241 +        error = spa_open(zc->zc_name, &spa, FTAG);
     2242 +        if (error != 0)
     2243 +                return (error);
     2244 +
     2245 +        error = spa_vdev_setl2adddt(spa, guid, l2ad_ddt);
     2246 +        spa_close(spa, FTAG);
     2247 +        return (error);
     2248 +}
     2249 +
     2250 +
     2251 +static int
2048 2252  zfs_ioc_vdev_setpath(zfs_cmd_t *zc)
2049 2253  {
2050 2254          spa_t *spa;
2051 2255          char *path = zc->zc_value;
2052 2256          uint64_t guid = zc->zc_guid;
2053 2257          int error;
2054 2258  
2055 2259          error = spa_open(zc->zc_name, &spa, FTAG);
2056 2260          if (error != 0)
2057 2261                  return (error);
↓ open down ↓ 58 lines elided ↑ open up ↑
2116 2320   * zc_nvlist_dst_size   size of buffer for property nvlist
2117 2321   *
2118 2322   * outputs:
2119 2323   * zc_objset_stats      stats
2120 2324   * zc_nvlist_dst        property nvlist
2121 2325   * zc_nvlist_dst_size   size of property nvlist
2122 2326   */
2123 2327  static int
2124 2328  zfs_ioc_objset_stats(zfs_cmd_t *zc)
2125 2329  {
2126      -        objset_t *os;
     2330 +        objset_t *os = NULL;
2127 2331          int error;
2128 2332  
2129 2333          error = dmu_objset_hold(zc->zc_name, FTAG, &os);
2130 2334          if (error == 0) {
2131 2335                  error = zfs_ioc_objset_stats_impl(zc, os);
2132 2336                  dmu_objset_rele(os, FTAG);
2133 2337          }
2134 2338  
2135 2339          return (error);
2136 2340  }
↓ open down ↓ 88 lines elided ↑ open up ↑
2225 2429                      (err = nvl_add_zplprop(os, nv, ZFS_PROP_CASE)) == 0)
2226 2430                          err = put_nvlist(zc, nv);
2227 2431                  nvlist_free(nv);
2228 2432          } else {
2229 2433                  err = SET_ERROR(ENOENT);
2230 2434          }
2231 2435          dmu_objset_rele(os, FTAG);
2232 2436          return (err);
2233 2437  }
2234 2438  
2235      -static boolean_t
2236      -dataset_name_hidden(const char *name)
2237      -{
2238      -        /*
2239      -         * Skip over datasets that are not visible in this zone,
2240      -         * internal datasets (which have a $ in their name), and
2241      -         * temporary datasets (which have a % in their name).
2242      -         */
2243      -        if (strchr(name, '$') != NULL)
2244      -                return (B_TRUE);
2245      -        if (strchr(name, '%') != NULL)
2246      -                return (B_TRUE);
2247      -        if (!INGLOBALZONE(curproc) && !zone_dataset_visible(name, NULL))
2248      -                return (B_TRUE);
2249      -        return (B_FALSE);
2250      -}
2251      -
2252 2439  /*
2253 2440   * inputs:
2254 2441   * zc_name              name of filesystem
2255 2442   * zc_cookie            zap cursor
2256 2443   * zc_nvlist_dst_size   size of buffer for property nvlist
2257 2444   *
2258 2445   * outputs:
2259 2446   * zc_name              name of next filesystem
2260 2447   * zc_cookie            zap cursor
2261 2448   * zc_objset_stats      stats
↓ open down ↓ 252 lines elided ↑ open up ↑
2514 2701   * with the list of names of all the properties that failed along with the
2515 2702   * corresponding error numbers.
2516 2703   *
2517 2704   * If every property is set successfully, zero is returned and errlist is not
2518 2705   * modified.
2519 2706   */
2520 2707  int
2521 2708  zfs_set_prop_nvlist(const char *dsname, zprop_source_t source, nvlist_t *nvl,
2522 2709      nvlist_t *errlist)
2523 2710  {
     2711 +        spa_t *spa = NULL;
2524 2712          nvpair_t *pair;
2525 2713          nvpair_t *propval;
2526 2714          int rv = 0;
2527 2715          uint64_t intval;
2528 2716          char *strval;
2529 2717          nvlist_t *genericnvl = fnvlist_alloc();
2530 2718          nvlist_t *retrynvl = fnvlist_alloc();
     2719 +        zfsvfs_t *zfsvfs;
     2720 +        boolean_t set_worm = B_FALSE;
     2721 +        boolean_t set_wbc_mode = B_FALSE;
     2722 +        boolean_t wbc_walk_locked = B_FALSE;
     2723 +        boolean_t set_dedup = B_FALSE;
2531 2724  
     2725 +        if ((rv = spa_open(dsname, &spa, FTAG)) != 0)
     2726 +                return (rv);
     2727 +
2532 2728  retry:
2533 2729          pair = NULL;
2534 2730          while ((pair = nvlist_next_nvpair(nvl, pair)) != NULL) {
2535 2731                  const char *propname = nvpair_name(pair);
2536 2732                  zfs_prop_t prop = zfs_name_to_prop(propname);
2537 2733                  int err = 0;
2538 2734  
     2735 +                if (!set_worm && (strcmp(propname, "nms:worm") == 0)) {
     2736 +                        set_worm = B_TRUE;
     2737 +                }
     2738 +
     2739 +                /*
     2740 +                 * If 'wbc_mode' is going to be changed, then we need to
     2741 +                 * do some actions before 'set'
     2742 +                 */
     2743 +                if (prop == ZFS_PROP_WBC_MODE)
     2744 +                        set_wbc_mode = B_TRUE;
     2745 +
     2746 +                /*
     2747 +                 *
     2748 +                 */
     2749 +                if (prop == ZFS_PROP_DEDUP)
     2750 +                        set_dedup = B_TRUE;
     2751 +
2539 2752                  /* decode the property value */
2540 2753                  propval = pair;
2541 2754                  if (nvpair_type(pair) == DATA_TYPE_NVLIST) {
2542 2755                          nvlist_t *attrs;
2543 2756                          attrs = fnvpair_value_nvlist(pair);
2544 2757                          if (nvlist_lookup_nvpair(attrs, ZPROP_VALUE,
2545 2758                              &propval) != 0)
2546 2759                                  err = SET_ERROR(EINVAL);
2547 2760                  }
2548 2761  
↓ open down ↓ 65 lines elided ↑ open up ↑
2614 2827                                  fnvlist_add_int32(errlist, propname, err);
2615 2828                          rv = err;
2616 2829                  }
2617 2830          }
2618 2831  
2619 2832          if (nvl != retrynvl && !nvlist_empty(retrynvl)) {
2620 2833                  nvl = retrynvl;
2621 2834                  goto retry;
2622 2835          }
2623 2836  
     2837 +        /*
     2838 +         * Deduplication and WBC cannot be used together
     2839 +         * This code returns error also for case when
     2840 +         * WBC is ON, DEDUP is off and a user tries
     2841 +         * to do DEDUP=off, because in this case the code
     2842 +         * will be more complex, but benefit is too small
     2843 +         */
     2844 +        if (set_wbc_mode && set_dedup) {
     2845 +                nvlist_free(genericnvl);
     2846 +                nvlist_free(retrynvl);
     2847 +                spa_close(spa, FTAG);
     2848 +
     2849 +                return (SET_ERROR(EKZFS_WBCCONFLICT));
     2850 +        }
     2851 +
     2852 +        /*
     2853 +         * Additional actions before set wbc_mode:
     2854 +         * - first need to try to lock WBC-walking, to stop migration and
     2855 +         *   avoid the openning of new migration window
     2856 +         * - second step (from sync-context): if migration window
     2857 +         *   is active it will be purged, to correctly add/remove WBC-instance
     2858 +         */
     2859 +        if (set_wbc_mode && wbc_walk_lock(spa) == 0)
     2860 +                wbc_walk_locked = B_TRUE;
     2861 +
2624 2862          if (!nvlist_empty(genericnvl) &&
2625 2863              dsl_props_set(dsname, source, genericnvl) != 0) {
2626 2864                  /*
2627 2865                   * If this fails, we still want to set as many properties as we
2628 2866                   * can, so try setting them individually.
2629 2867                   */
2630 2868                  pair = NULL;
2631 2869                  while ((pair = nvlist_next_nvpair(genericnvl, pair)) != NULL) {
2632 2870                          const char *propname = nvpair_name(pair);
2633 2871                          int err = 0;
↓ open down ↓ 21 lines elided ↑ open up ↑
2655 2893                                          fnvlist_add_int32(errlist, propname,
2656 2894                                              err);
2657 2895                                  }
2658 2896                                  rv = err;
2659 2897                          }
2660 2898                  }
2661 2899          }
2662 2900          nvlist_free(genericnvl);
2663 2901          nvlist_free(retrynvl);
2664 2902  
     2903 +        if (wbc_walk_locked)
     2904 +                wbc_walk_unlock(spa);
     2905 +
     2906 +        if (set_worm && getzfsvfs(dsname, &zfsvfs) == 0) {
     2907 +                if (zfs_is_wormed(dsname)) {
     2908 +                        zfsvfs->z_isworm = B_TRUE;
     2909 +                } else {
     2910 +                        zfsvfs->z_isworm = B_FALSE;
     2911 +                }
     2912 +                VFS_RELE(zfsvfs->z_vfs);
     2913 +        }
     2914 +
     2915 +        if (rv == 0)
     2916 +                autosnap_force_snap_by_name(dsname, NULL, B_FALSE);
     2917 +
     2918 +        spa_close(spa, FTAG);
     2919 +
2665 2920          return (rv);
2666 2921  }
2667 2922  
2668 2923  /*
2669 2924   * Check that all the properties are valid user properties.
2670 2925   */
2671 2926  static int
2672 2927  zfs_check_userprops(const char *fsname, nvlist_t *nvl)
2673 2928  {
2674 2929          nvpair_t *pair = NULL;
↓ open down ↓ 7 lines elided ↑ open up ↑
2682 2937                          return (SET_ERROR(EINVAL));
2683 2938  
2684 2939                  if (error = zfs_secpolicy_write_perms(fsname,
2685 2940                      ZFS_DELEG_PERM_USERPROP, CRED()))
2686 2941                          return (error);
2687 2942  
2688 2943                  if (strlen(propname) >= ZAP_MAXNAMELEN)
2689 2944                          return (SET_ERROR(ENAMETOOLONG));
2690 2945  
2691 2946                  if (strlen(fnvpair_value_string(pair)) >= ZAP_MAXVALUELEN)
2692      -                        return (E2BIG);
     2947 +                        return (SET_ERROR(E2BIG));
2693 2948          }
2694 2949          return (0);
2695 2950  }
2696 2951  
2697 2952  static void
2698 2953  props_skip(nvlist_t *props, nvlist_t *skipped, nvlist_t **newprops)
2699 2954  {
2700 2955          nvpair_t *pair;
2701 2956  
2702 2957          VERIFY(nvlist_alloc(newprops, NV_UNIQUE_NAME, KM_SLEEP) == 0);
↓ open down ↓ 20 lines elided ↑ open up ↑
2723 2978                   * properties at least once on or after SPA_VERSION_RECVD_PROPS.
2724 2979                   */
2725 2980                  zprop_source_t flags = (ZPROP_SRC_NONE |
2726 2981                      (dsl_prop_get_hasrecvd(dsname) ? ZPROP_SRC_RECEIVED : 0));
2727 2982                  err = zfs_set_prop_nvlist(dsname, flags, cleared_props, NULL);
2728 2983          }
2729 2984          nvlist_free(cleared_props);
2730 2985          return (err);
2731 2986  }
2732 2987  
     2988 +int
     2989 +zfs_ioc_set_prop_impl(char *name, nvlist_t *props,
     2990 +    boolean_t received, nvlist_t **out_errors)
     2991 +{
     2992 +        int error = 0;
     2993 +        nvlist_t *errors, *event;
     2994 +        zprop_source_t source = (received ? ZPROP_SRC_RECEIVED :
     2995 +            ZPROP_SRC_LOCAL);
     2996 +
     2997 +        ASSERT(props != NULL);
     2998 +
     2999 +        if (received) {
     3000 +                nvlist_t *origprops;
     3001 +
     3002 +                if (dsl_prop_get_received(name, &origprops) == 0) {
     3003 +                        (void) clear_received_props(name, origprops, props);
     3004 +                        nvlist_free(origprops);
     3005 +                }
     3006 +
     3007 +                error = dsl_prop_set_hasrecvd(name);
     3008 +        }
     3009 +
     3010 +        errors = fnvlist_alloc();
     3011 +        if (error == 0)
     3012 +                error = zfs_set_prop_nvlist(name, source, props, errors);
     3013 +
     3014 +        event = fnvlist_alloc();
     3015 +        fnvlist_add_string(event, "fsname", name);
     3016 +        fnvlist_add_nvlist(event, "properties", props);
     3017 +        fnvlist_add_nvlist(event, "errors", errors);
     3018 +        zfs_event_post(ZFS_EC_STATUS, "set", event);
     3019 +
     3020 +        if (out_errors != NULL)
     3021 +                *out_errors = fnvlist_dup(errors);
     3022 +
     3023 +        fnvlist_free(errors);
     3024 +
     3025 +        return (error);
     3026 +}
     3027 +
2733 3028  /*
     3029 + * XXX This functionality will be removed after integration of
     3030 + * functionality, that does the same via zfs-channel programm.
     3031 + * The zfs-channel programm implementation is being developed
     3032 + * by Delphix.
     3033 + *
     3034 + * This functions sets provided props for provided datasets
     3035 + * in one sync-round. There are some requirements:
     3036 + *  - all datasets should belong to the same pool
     3037 + *  - only user-properties
     3038 + *
     3039 + * This function does all or nothing.
     3040 + *
2734 3041   * inputs:
     3042 + * zc_nvlist_src{_size} nvlist of datasets and properties to apply
     3043 + *
     3044 + * outputs:
     3045 + * zc_nvlist_dst{_size} error for each unapplied property
     3046 + */
     3047 +/* ARGSUSED */
     3048 +static int
     3049 +zfs_ioc_set_prop_mds(const char *pool_name, nvlist_t *dss_props,
     3050 +    nvlist_t *outnvl)
     3051 +{
     3052 +        int error = 0;
     3053 +        spa_t *spa = NULL;
     3054 +        nvpair_t *pair = NULL;
     3055 +        size_t pool_name_len;
     3056 +        size_t total_num_props = 0;
     3057 +
     3058 +        ASSERT(dss_props != NULL);
     3059 +
     3060 +        if (nvlist_empty(dss_props))
     3061 +                return (SET_ERROR(ENODATA));
     3062 +
     3063 +        pool_name_len = strlen(pool_name);
     3064 +        while ((pair = nvlist_next_nvpair(dss_props, pair)) != NULL) {
     3065 +                nvlist_t *props;
     3066 +                nvpair_t *prop_nvp = NULL;
     3067 +                const char *ds_name;
     3068 +
     3069 +                ds_name = nvpair_name(pair);
     3070 +                if (strncmp(pool_name, ds_name, pool_name_len) == 0) {
     3071 +                        char c = ds_name[pool_name_len];
     3072 +                        if (c != '\0' && c != '/' && c != '@')
     3073 +                                return (SET_ERROR(EXDEV));
     3074 +                }
     3075 +
     3076 +                if (nvpair_type(pair) != DATA_TYPE_NVLIST)
     3077 +                        return (SET_ERROR(EINVAL));
     3078 +
     3079 +                props = fnvpair_value_nvlist(pair);
     3080 +                while ((prop_nvp = nvlist_next_nvpair(props,
     3081 +                    prop_nvp)) != NULL) {
     3082 +                        const char *propname = nvpair_name(prop_nvp);
     3083 +                        /* Only user-props */
     3084 +                        if (!zfs_prop_user(propname) ||
     3085 +                            nvpair_type(prop_nvp) != DATA_TYPE_STRING)
     3086 +                                return (SET_ERROR(EINVAL));
     3087 +
     3088 +                        /*
     3089 +                         * We count the number to use it
     3090 +                         * later to check for ENOSPC
     3091 +                         */
     3092 +                        total_num_props++;
     3093 +                }
     3094 +        }
     3095 +
     3096 +        if ((error = spa_open(pool_name, &spa, FTAG)) != 0)
     3097 +                return (error);
     3098 +
     3099 +        error = dsl_props_set_mds(pool_name, dss_props, total_num_props);
     3100 +        spa_close(spa, FTAG);
     3101 +        if (error == 0) {
     3102 +                nvlist_t *event = fnvlist_alloc();
     3103 +                fnvlist_add_nvlist(event, "properties", dss_props);
     3104 +                zfs_event_post(ZFS_EC_STATUS, "set-mds", event);
     3105 +        }
     3106 +
     3107 +        return (error);
     3108 +}
     3109 +
     3110 +/*
     3111 + * inputs:
2735 3112   * zc_name              name of filesystem
2736 3113   * zc_value             name of property to set
2737 3114   * zc_nvlist_src{_size} nvlist of properties to apply
2738 3115   * zc_cookie            received properties flag
2739 3116   *
2740 3117   * outputs:
2741 3118   * zc_nvlist_dst{_size} error for each unapplied received property
2742 3119   */
2743 3120  static int
2744 3121  zfs_ioc_set_prop(zfs_cmd_t *zc)
2745 3122  {
2746 3123          nvlist_t *nvl;
2747 3124          boolean_t received = zc->zc_cookie;
2748      -        zprop_source_t source = (received ? ZPROP_SRC_RECEIVED :
2749      -            ZPROP_SRC_LOCAL);
2750      -        nvlist_t *errors;
     3125 +        nvlist_t *errors = NULL;
2751 3126          int error;
2752 3127  
2753 3128          if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
2754 3129              zc->zc_iflags, &nvl)) != 0)
2755 3130                  return (error);
2756 3131  
2757      -        if (received) {
2758      -                nvlist_t *origprops;
     3132 +        error = zfs_ioc_set_prop_impl(zc->zc_name, nvl, received, &errors);
2759 3133  
2760      -                if (dsl_prop_get_received(zc->zc_name, &origprops) == 0) {
2761      -                        (void) clear_received_props(zc->zc_name,
2762      -                            origprops, nvl);
2763      -                        nvlist_free(origprops);
2764      -                }
2765      -
2766      -                error = dsl_prop_set_hasrecvd(zc->zc_name);
2767      -        }
2768      -
2769      -        errors = fnvlist_alloc();
2770      -        if (error == 0)
2771      -                error = zfs_set_prop_nvlist(zc->zc_name, source, nvl, errors);
2772      -
2773 3134          if (zc->zc_nvlist_dst != NULL && errors != NULL) {
2774 3135                  (void) put_nvlist(zc, errors);
2775 3136          }
2776 3137  
2777 3138          nvlist_free(errors);
2778 3139          nvlist_free(nvl);
2779 3140          return (error);
2780 3141  }
2781 3142  
2782 3143  /*
↓ open down ↓ 71 lines elided ↑ open up ↑
2854 3215          return (dsl_prop_inherit(zc->zc_name, zc->zc_value, source));
2855 3216  }
2856 3217  
2857 3218  static int
2858 3219  zfs_ioc_pool_set_props(zfs_cmd_t *zc)
2859 3220  {
2860 3221          nvlist_t *props;
2861 3222          spa_t *spa;
2862 3223          int error;
2863 3224          nvpair_t *pair;
2864      -
     3225 +        nvlist_t *event;
2865 3226          if (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
2866 3227              zc->zc_iflags, &props))
2867 3228                  return (error);
2868 3229  
2869 3230          /*
2870 3231           * If the only property is the configfile, then just do a spa_lookup()
2871 3232           * to handle the faulted case.
2872 3233           */
2873 3234          pair = nvlist_next_nvpair(props, NULL);
2874 3235          if (pair != NULL && strcmp(nvpair_name(pair),
2875 3236              zpool_prop_to_name(ZPOOL_PROP_CACHEFILE)) == 0 &&
2876 3237              nvlist_next_nvpair(props, pair) == NULL) {
2877 3238                  mutex_enter(&spa_namespace_lock);
2878 3239                  if ((spa = spa_lookup(zc->zc_name)) != NULL) {
2879 3240                          spa_configfile_set(spa, props, B_FALSE);
2880      -                        spa_write_cachefile(spa, B_FALSE, B_TRUE);
     3241 +                        spa_config_sync(spa, B_FALSE, B_TRUE);
2881 3242                  }
2882 3243                  mutex_exit(&spa_namespace_lock);
2883 3244                  if (spa != NULL) {
2884 3245                          nvlist_free(props);
2885 3246                          return (0);
2886 3247                  }
2887 3248          }
2888 3249  
2889 3250          if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) {
2890 3251                  nvlist_free(props);
2891 3252                  return (error);
2892 3253          }
2893 3254  
2894 3255          error = spa_prop_set(spa, props);
2895 3256  
     3257 +        if (error == 0) {
     3258 +                event = fnvlist_alloc();
     3259 +                fnvlist_add_string(event, "pool", zc->zc_name);
     3260 +                fnvlist_add_nvlist(event, "props", props);
     3261 +                zfs_event_post(ZPOOL_EC_STATUS, "set", event);
     3262 +        }
     3263 +
2896 3264          nvlist_free(props);
2897 3265          spa_close(spa, FTAG);
2898 3266  
2899 3267          return (error);
2900 3268  }
2901 3269  
2902 3270  static int
2903 3271  zfs_ioc_pool_get_props(zfs_cmd_t *zc)
2904 3272  {
2905 3273          spa_t *spa;
↓ open down ↓ 101 lines elided ↑ open up ↑
3007 3375  {
3008 3376          zfs_creat_t *zct = arg;
3009 3377  
3010 3378          zfs_create_fs(os, cr, zct->zct_zplprops, tx);
3011 3379  }
3012 3380  
3013 3381  #define ZFS_PROP_UNDEFINED      ((uint64_t)-1)
3014 3382  
3015 3383  /*
3016 3384   * inputs:
     3385 + * createprops          list of properties requested by creator
     3386 + * default_zplver       zpl version to use if unspecified in createprops
     3387 + * fuids_ok             fuids allowed in this version of the spa?
3017 3388   * os                   parent objset pointer (NULL if root fs)
3018 3389   * fuids_ok             fuids allowed in this version of the spa?
3019 3390   * sa_ok                SAs allowed in this version of the spa?
3020 3391   * createprops          list of properties requested by creator
3021 3392   *
3022 3393   * outputs:
3023 3394   * zplprops     values for the zplprops we attach to the master node object
3024 3395   * is_ci        true if requested file system will be purely case-insensitive
3025 3396   *
3026 3397   * Determine the settings for utf8only, normalization and
↓ open down ↓ 57 lines elided ↑ open up ↑
3084 3455           * Put the version in the zplprops
3085 3456           */
3086 3457          VERIFY(nvlist_add_uint64(zplprops,
3087 3458              zfs_prop_to_name(ZFS_PROP_VERSION), zplver) == 0);
3088 3459  
3089 3460          if (norm == ZFS_PROP_UNDEFINED)
3090 3461                  VERIFY(zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &norm) == 0);
3091 3462          VERIFY(nvlist_add_uint64(zplprops,
3092 3463              zfs_prop_to_name(ZFS_PROP_NORMALIZE), norm) == 0);
3093 3464  
     3465 +        if (os) {
     3466 +                if (zfs_is_wormed_ds(dmu_objset_ds(os)))
     3467 +                        return (SET_ERROR(EPERM));
     3468 +        }
     3469 +
3094 3470          /*
3095 3471           * If we're normalizing, names must always be valid UTF-8 strings.
3096 3472           */
3097 3473          if (norm)
3098 3474                  u8 = 1;
3099 3475          if (u8 == ZFS_PROP_UNDEFINED)
3100 3476                  VERIFY(zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &u8) == 0);
3101 3477          VERIFY(nvlist_add_uint64(zplprops,
3102 3478              zfs_prop_to_name(ZFS_PROP_UTF8ONLY), u8) == 0);
3103 3479  
↓ open down ↓ 77 lines elided ↑ open up ↑
3181 3557  static int
3182 3558  zfs_ioc_create(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
3183 3559  {
3184 3560          int error = 0;
3185 3561          zfs_creat_t zct = { 0 };
3186 3562          nvlist_t *nvprops = NULL;
3187 3563          void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx);
3188 3564          int32_t type32;
3189 3565          dmu_objset_type_t type;
3190 3566          boolean_t is_insensitive = B_FALSE;
     3567 +        char parent[MAXNAMELEN];
     3568 +        nvlist_t *event;
3191 3569  
3192 3570          if (nvlist_lookup_int32(innvl, "type", &type32) != 0)
3193 3571                  return (SET_ERROR(EINVAL));
3194 3572          type = type32;
3195 3573          (void) nvlist_lookup_nvlist(innvl, "props", &nvprops);
3196 3574  
3197 3575          switch (type) {
3198 3576          case DMU_OST_ZFS:
3199 3577                  cbfunc = zfs_create_cb;
3200 3578                  break;
↓ open down ↓ 8 lines elided ↑ open up ↑
3209 3587          }
3210 3588          if (strchr(fsname, '@') ||
3211 3589              strchr(fsname, '%'))
3212 3590                  return (SET_ERROR(EINVAL));
3213 3591  
3214 3592          zct.zct_props = nvprops;
3215 3593  
3216 3594          if (cbfunc == NULL)
3217 3595                  return (SET_ERROR(EINVAL));
3218 3596  
     3597 +        if (zfs_get_parent(fsname, parent, MAXNAMELEN) == 0 &&
     3598 +            zfs_is_wormed(parent)) {
     3599 +                return (SET_ERROR(EPERM));
     3600 +        }
     3601 +
3219 3602          if (type == DMU_OST_ZVOL) {
3220 3603                  uint64_t volsize, volblocksize;
3221 3604  
3222 3605                  if (nvprops == NULL)
3223 3606                          return (SET_ERROR(EINVAL));
3224 3607                  if (nvlist_lookup_uint64(nvprops,
3225 3608                      zfs_prop_to_name(ZFS_PROP_VOLSIZE), &volsize) != 0)
3226 3609                          return (SET_ERROR(EINVAL));
3227 3610  
3228 3611                  if ((error = nvlist_lookup_uint64(nvprops,
↓ open down ↓ 4 lines elided ↑ open up ↑
3233 3616                  if (error != 0)
3234 3617                          volblocksize = zfs_prop_default_numeric(
3235 3618                              ZFS_PROP_VOLBLOCKSIZE);
3236 3619  
3237 3620                  if ((error = zvol_check_volblocksize(
3238 3621                      volblocksize)) != 0 ||
3239 3622                      (error = zvol_check_volsize(volsize,
3240 3623                      volblocksize)) != 0)
3241 3624                          return (error);
3242 3625          } else if (type == DMU_OST_ZFS) {
3243      -                int error;
3244      -
3245 3626                  /*
3246 3627                   * We have to have normalization and
3247 3628                   * case-folding flags correct when we do the
3248 3629                   * file system creation, so go figure them out
3249 3630                   * now.
3250 3631                   */
3251 3632                  VERIFY(nvlist_alloc(&zct.zct_zplprops,
3252 3633                      NV_UNIQUE_NAME, KM_SLEEP) == 0);
3253 3634                  error = zfs_fill_zplprops(fsname, nvprops,
3254 3635                      zct.zct_zplprops, &is_insensitive);
↓ open down ↓ 9 lines elided ↑ open up ↑
3264 3645  
3265 3646          /*
3266 3647           * It would be nice to do this atomically.
3267 3648           */
3268 3649          if (error == 0) {
3269 3650                  error = zfs_set_prop_nvlist(fsname, ZPROP_SRC_LOCAL,
3270 3651                      nvprops, outnvl);
3271 3652                  if (error != 0)
3272 3653                          (void) dsl_destroy_head(fsname);
3273 3654          }
     3655 +
     3656 +        if (error == 0) {
     3657 +                event = fnvlist_alloc();
     3658 +                fnvlist_add_string(event, "fsname", fsname);
     3659 +                fnvlist_add_int32(event, "type", type);
     3660 +                if (nvprops != NULL)
     3661 +                        fnvlist_add_nvlist(event, "properties", nvprops);
     3662 +                zfs_event_post(ZFS_EC_STATUS, "create", event);
     3663 +        }
     3664 +
3274 3665          return (error);
3275 3666  }
3276 3667  
3277 3668  /*
3278 3669   * innvl: {
3279 3670   *     "origin" -> name of origin snapshot
3280 3671   *     (optional) "props" -> { prop -> value }
3281 3672   * }
3282 3673   *
3283 3674   * outnvl: propname -> error code (int32)
3284 3675   */
3285 3676  static int
3286 3677  zfs_ioc_clone(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
3287 3678  {
3288 3679          int error = 0;
3289 3680          nvlist_t *nvprops = NULL;
3290      -        char *origin_name;
     3681 +        char *origin_name, *origin_snap;
     3682 +        nvlist_t *event;
3291 3683  
3292 3684          if (nvlist_lookup_string(innvl, "origin", &origin_name) != 0)
3293 3685                  return (SET_ERROR(EINVAL));
     3686 +
     3687 +        origin_snap = strchr(origin_name, '@');
     3688 +        if (!origin_snap)
     3689 +                return (SET_ERROR(EINVAL));
     3690 +
     3691 +        if (autosnap_check_name(origin_snap))
     3692 +                return (SET_ERROR(EPERM));
     3693 +
3294 3694          (void) nvlist_lookup_nvlist(innvl, "props", &nvprops);
3295 3695  
3296 3696          if (strchr(fsname, '@') ||
3297 3697              strchr(fsname, '%'))
3298 3698                  return (SET_ERROR(EINVAL));
3299 3699  
3300 3700          if (dataset_namecheck(origin_name, NULL, NULL) != 0)
3301 3701                  return (SET_ERROR(EINVAL));
     3702 +
3302 3703          error = dmu_objset_clone(fsname, origin_name);
3303 3704          if (error != 0)
3304 3705                  return (error);
3305 3706  
3306 3707          /*
3307 3708           * It would be nice to do this atomically.
3308 3709           */
3309 3710          if (error == 0) {
3310 3711                  error = zfs_set_prop_nvlist(fsname, ZPROP_SRC_LOCAL,
3311 3712                      nvprops, outnvl);
3312 3713                  if (error != 0)
3313 3714                          (void) dsl_destroy_head(fsname);
3314 3715          }
3315      -        return (error);
3316      -}
3317 3716  
3318      -/* ARGSUSED */
3319      -static int
3320      -zfs_ioc_remap(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
3321      -{
3322      -        if (strchr(fsname, '@') ||
3323      -            strchr(fsname, '%'))
3324      -                return (SET_ERROR(EINVAL));
     3717 +        if (error == 0) {
     3718 +                event = fnvlist_alloc();
     3719 +                fnvlist_add_string(event, "origin", origin_name);
     3720 +                fnvlist_add_string(event, "fsname", fsname);
     3721 +                if (nvprops != NULL)
     3722 +                        fnvlist_add_nvlist(event, "properties", nvprops);
     3723 +                zfs_event_post(ZFS_EC_STATUS, "clone", event);
     3724 +        }
3325 3725  
3326      -        return (dmu_objset_remap_indirects(fsname));
     3726 +        return (error);
3327 3727  }
3328 3728  
3329 3729  /*
3330 3730   * innvl: {
3331 3731   *     "snaps" -> { snapshot1, snapshot2 }
3332 3732   *     (optional) "props" -> { prop -> value (string) }
3333 3733   * }
3334 3734   *
3335 3735   * outnvl: snapshot -> error code (int32)
3336 3736   */
3337 3737  static int
3338 3738  zfs_ioc_snapshot(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
3339 3739  {
3340 3740          nvlist_t *snaps;
3341 3741          nvlist_t *props = NULL;
3342 3742          int error, poollen;
3343 3743          nvpair_t *pair;
     3744 +        nvlist_t *event;
3344 3745  
3345 3746          (void) nvlist_lookup_nvlist(innvl, "props", &props);
3346 3747          if ((error = zfs_check_userprops(poolname, props)) != 0)
3347 3748                  return (error);
3348 3749  
3349 3750          if (!nvlist_empty(props) &&
3350 3751              zfs_earlier_version(poolname, SPA_VERSION_SNAP_PROPS))
3351 3752                  return (SET_ERROR(ENOTSUP));
3352 3753  
3353 3754          if (nvlist_lookup_nvlist(innvl, "snaps", &snaps) != 0)
↓ open down ↓ 5 lines elided ↑ open up ↑
3359 3760                  const char *cp = strchr(name, '@');
3360 3761  
3361 3762                  /*
3362 3763                   * The snap name must contain an @, and the part after it must
3363 3764                   * contain only valid characters.
3364 3765                   */
3365 3766                  if (cp == NULL ||
3366 3767                      zfs_component_namecheck(cp + 1, NULL, NULL) != 0)
3367 3768                          return (SET_ERROR(EINVAL));
3368 3769  
     3770 +                if (autosnap_check_name(cp))
     3771 +                        return (EINVAL);
     3772 +
3369 3773                  /*
3370 3774                   * The snap must be in the specified pool.
3371 3775                   */
3372 3776                  if (strncmp(name, poolname, poollen) != 0 ||
3373 3777                      (name[poollen] != '/' && name[poollen] != '@'))
3374 3778                          return (SET_ERROR(EXDEV));
3375 3779  
3376 3780                  /* This must be the only snap of this fs. */
3377 3781                  for (nvpair_t *pair2 = nvlist_next_nvpair(snaps, pair);
3378 3782                      pair2 != NULL; pair2 = nvlist_next_nvpair(snaps, pair2)) {
3379 3783                          if (strncmp(name, nvpair_name(pair2), cp - name + 1)
3380 3784                              == 0) {
3381 3785                                  return (SET_ERROR(EXDEV));
3382 3786                          }
3383 3787                  }
3384 3788          }
3385 3789  
3386 3790          error = dsl_dataset_snapshot(snaps, props, outnvl);
     3791 +
     3792 +        event = fnvlist_alloc();
     3793 +        fnvlist_add_nvlist(event, "snaps", snaps);
     3794 +        fnvlist_add_nvlist(event, "errors", outnvl);
     3795 +        fnvlist_add_string(event, "pool", poolname);
     3796 +        zfs_event_post(ZFS_EC_STATUS, "snapshot", event);
     3797 +
3387 3798          return (error);
3388 3799  }
3389 3800  
3390 3801  /*
3391 3802   * innvl: "message" -> string
3392 3803   */
3393 3804  /* ARGSUSED */
3394 3805  static int
3395 3806  zfs_ioc_log_history(const char *unused, nvlist_t *innvl, nvlist_t *outnvl)
3396 3807  {
↓ open down ↓ 97 lines elided ↑ open up ↑
3494 3905          if (dsl_dir_is_clone(ds->ds_dir) && DS_IS_DEFER_DESTROY(ds->ds_prev)) {
3495 3906                  char originname[ZFS_MAX_DATASET_NAME_LEN];
3496 3907                  dsl_dataset_name(ds->ds_prev, originname);
3497 3908                  dmu_objset_rele(os, FTAG);
3498 3909                  zfs_unmount_snap(originname);
3499 3910          } else {
3500 3911                  dmu_objset_rele(os, FTAG);
3501 3912          }
3502 3913  }
3503 3914  
     3915 +static int
     3916 +zfs_destroy_check_autosnap(spa_t *spa, const char *name)
     3917 +{
     3918 +        const char *snap = strchr(name, '@');
     3919 +
     3920 +        if (snap == NULL)
     3921 +                return (EINVAL);
     3922 +
     3923 +        if (autosnap_check_name(snap)) {
     3924 +                int err = autosnap_check_for_destroy(
     3925 +                    spa_get_autosnap(spa), name);
     3926 +
     3927 +                if (err != 0)
     3928 +                        return (EBUSY);
     3929 +        }
     3930 +
     3931 +        return (0);
     3932 +}
     3933 +
3504 3934  /*
3505 3935   * innvl: {
3506 3936   *     "snaps" -> { snapshot1, snapshot2 }
3507 3937   *     (optional boolean) "defer"
3508 3938   * }
3509 3939   *
3510 3940   * outnvl: snapshot -> error code (int32)
3511 3941   *
3512 3942   */
3513 3943  /* ARGSUSED */
3514 3944  static int
3515 3945  zfs_ioc_destroy_snaps(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
3516 3946  {
3517 3947          nvlist_t *snaps;
3518 3948          nvpair_t *pair;
3519 3949          boolean_t defer;
     3950 +        int error = 0;
     3951 +        nvlist_t *event;
     3952 +        spa_t *spa;
3520 3953  
     3954 +        if (zfs_is_wormed(poolname))
     3955 +                return (SET_ERROR(EPERM));
     3956 +
3521 3957          if (nvlist_lookup_nvlist(innvl, "snaps", &snaps) != 0)
3522 3958                  return (SET_ERROR(EINVAL));
3523 3959          defer = nvlist_exists(innvl, "defer");
3524 3960  
     3961 +        error = spa_open(poolname, &spa, FTAG);
     3962 +        if (spa == NULL)
     3963 +                return (error);
     3964 +
     3965 +        for (pair = nvlist_next_nvpair(snaps, NULL);
     3966 +            pair != NULL; pair = nvlist_next_nvpair(snaps, pair)) {
     3967 +                error = zfs_destroy_check_autosnap(spa, nvpair_name(pair));
     3968 +                if (error)
     3969 +                        fnvlist_add_int32(outnvl, nvpair_name(pair), error);
     3970 +        }
     3971 +
     3972 +        spa_close(spa, FTAG);
     3973 +
     3974 +        if (error)
     3975 +                return (error);
     3976 +
3525 3977          for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
3526 3978              pair = nvlist_next_nvpair(snaps, pair)) {
3527 3979                  zfs_unmount_snap(nvpair_name(pair));
3528 3980          }
3529 3981  
3530      -        return (dsl_destroy_snapshots_nvl(snaps, defer, outnvl));
     3982 +        error = dsl_destroy_snapshots_nvl(snaps, defer, outnvl);
     3983 +
     3984 +        if (error == 0) {
     3985 +                event = fnvlist_alloc();
     3986 +                fnvlist_add_nvlist(event, "snaps", snaps);
     3987 +                fnvlist_add_nvlist(event, "errors", outnvl);
     3988 +                zfs_event_post(ZFS_EC_STATUS, "destroy_snaps", event);
     3989 +        }
     3990 +
     3991 +        return (error);
3531 3992  }
3532 3993  
3533 3994  /*
3534 3995   * Create bookmarks.  Bookmark names are of the form <fs>#<bmark>.
3535 3996   * All bookmarks must be in the same pool.
3536 3997   *
3537 3998   * innvl: {
3538 3999   *     bookmark1 -> snapshot1, bookmark2 -> snapshot2
3539 4000   * }
3540 4001   *
↓ open down ↓ 115 lines elided ↑ open up ↑
3656 4117  
3657 4118          return (zcp_eval(poolname, program, sync_flag, instrlimit, memlimit,
3658 4119              nvarg, outnvl));
3659 4120  }
3660 4121  
3661 4122  /*
3662 4123   * inputs:
3663 4124   * zc_name              name of dataset to destroy
3664 4125   * zc_objset_type       type of objset
3665 4126   * zc_defer_destroy     mark for deferred destroy
     4127 + * zc_guid              if set, do atomical recursive destroy
3666 4128   *
3667 4129   * outputs:             none
3668 4130   */
3669 4131  static int
3670 4132  zfs_ioc_destroy(zfs_cmd_t *zc)
3671 4133  {
3672 4134          int err;
     4135 +        nvlist_t *event;
3673 4136  
     4137 +        if (zfs_is_wormed(zc->zc_name))
     4138 +                return (SET_ERROR(EPERM));
     4139 +
3674 4140          if (zc->zc_objset_type == DMU_OST_ZFS)
3675 4141                  zfs_unmount_snap(zc->zc_name);
3676 4142  
3677      -        if (strchr(zc->zc_name, '@'))
3678      -                err = dsl_destroy_snapshot(zc->zc_name, zc->zc_defer_destroy);
3679      -        else
3680      -                err = dsl_destroy_head(zc->zc_name);
     4143 +        if (zc->zc_guid) {
     4144 +                spa_t *spa;
     4145 +
     4146 +                if ((err = spa_open(zc->zc_name, &spa, FTAG)) != 0)
     4147 +                        return (err);
     4148 +
     4149 +                err = autosnap_lock(spa, RW_WRITER);
     4150 +                if (err == 0) {
     4151 +                        err = wbc_walk_lock(spa);
     4152 +                        if (err != 0)
     4153 +                                autosnap_unlock(spa);
     4154 +                }
     4155 +
     4156 +                if (err == 0) {
     4157 +                        err = dsl_destroy_atomically(zc->zc_name,
     4158 +                            zc->zc_defer_destroy);
     4159 +                        wbc_walk_unlock(spa);
     4160 +                        autosnap_unlock(spa);
     4161 +                }
     4162 +
     4163 +                spa_close(spa, FTAG);
     4164 +        } else {
     4165 +                if (strchr(zc->zc_name, '@')) {
     4166 +                        spa_t *spa = NULL;
     4167 +
     4168 +                        err = spa_open(zc->zc_name, &spa, FTAG);
     4169 +                        if (err != 0)
     4170 +                                return (err);
     4171 +
     4172 +                        err = zfs_destroy_check_autosnap(spa, zc->zc_name);
     4173 +                        if (err == 0) {
     4174 +                                err = dsl_destroy_snapshot(zc->zc_name,
     4175 +                                    zc->zc_defer_destroy);
     4176 +                        }
     4177 +
     4178 +                        spa_close(spa, FTAG);
     4179 +                } else {
     4180 +                        err = dsl_destroy_head(zc->zc_name);
     4181 +                        if (err == EEXIST) {
     4182 +                                /*
     4183 +                                 * It is possible that the given DS may have
     4184 +                                 * hidden child (%recv) datasets - "leftovers"
     4185 +                                 * resulting from the previously interrupted
     4186 +                                 * 'zfs receive'.
     4187 +                                 */
     4188 +                                char namebuf[ZFS_MAX_DATASET_NAME_LEN];
     4189 +
     4190 +                                if (snprintf(namebuf, sizeof (namebuf),
     4191 +                                    "%s/%%recv", zc->zc_name) >=
     4192 +                                    sizeof (namebuf))
     4193 +                                        return (err);
     4194 +
     4195 +                                /* Try to remove the hidden child (%recv) */
     4196 +                                err = dsl_destroy_head(namebuf);
     4197 +                                if (err == 0) {
     4198 +                                        /*
     4199 +                                         * Now the given DS should not have
     4200 +                                         * children, so we can try to remove
     4201 +                                         * it again
     4202 +                                         */
     4203 +                                        err = dsl_destroy_head(zc->zc_name);
     4204 +                                } else if (err == ENOENT) {
     4205 +                                        /*
     4206 +                                         * The hidden child (%recv) does not
     4207 +                                         * exist, so need to restore original
     4208 +                                         * error
     4209 +                                         */
     4210 +                                        err = EEXIST;
     4211 +                                }
     4212 +
     4213 +                        }
     4214 +                }
     4215 +        }
3681 4216          if (zc->zc_objset_type == DMU_OST_ZVOL && err == 0)
3682 4217                  (void) zvol_remove_minor(zc->zc_name);
     4218 +
     4219 +        if (err == 0) {
     4220 +                event = fnvlist_alloc();
     4221 +                fnvlist_add_string(event, "fsname", zc->zc_name);
     4222 +                fnvlist_add_int32(event, "type", zc->zc_objset_type);
     4223 +                zfs_event_post(ZFS_EC_STATUS, "destroy", event);
     4224 +        }
     4225 +
3683 4226          return (err);
3684 4227  }
3685 4228  
3686 4229  /*
3687 4230   * fsname is name of dataset to rollback (to most recent snapshot)
3688 4231   *
3689 4232   * innvl may contain name of expected target snapshot
3690 4233   *
3691 4234   * outnvl: "target" -> name of most recent snapshot
3692 4235   * }
3693 4236   */
3694 4237  /* ARGSUSED */
3695 4238  static int
3696 4239  zfs_ioc_rollback(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
3697 4240  {
3698 4241          zfsvfs_t *zfsvfs;
3699 4242          char *target = NULL;
3700 4243          int error;
     4244 +        nvlist_t *event;
     4245 +        int resume_err = 0;
3701 4246  
     4247 +        if (zfs_is_wormed(fsname))
     4248 +                return (SET_ERROR(EPERM));
     4249 +
3702 4250          (void) nvlist_lookup_string(innvl, "target", &target);
3703 4251          if (target != NULL) {
3704 4252                  const char *cp = strchr(target, '@');
3705 4253  
3706 4254                  /*
3707 4255                   * The snap name must contain an @, and the part after it must
3708 4256                   * contain only valid characters.
3709 4257                   */
3710 4258                  if (cp == NULL ||
3711 4259                      zfs_component_namecheck(cp + 1, NULL, NULL) != 0)
3712 4260                          return (SET_ERROR(EINVAL));
3713 4261          }
3714 4262  
3715 4263          if (getzfsvfs(fsname, &zfsvfs) == 0) {
3716 4264                  dsl_dataset_t *ds;
3717 4265  
3718 4266                  ds = dmu_objset_ds(zfsvfs->z_os);
3719 4267                  error = zfs_suspend_fs(zfsvfs);
3720 4268                  if (error == 0) {
3721      -                        int resume_err;
3722      -
3723 4269                          error = dsl_dataset_rollback(fsname, target, zfsvfs,
3724 4270                              outnvl);
3725 4271                          resume_err = zfs_resume_fs(zfsvfs, ds);
3726      -                        error = error ? error : resume_err;
3727 4272                  }
3728 4273                  VFS_RELE(zfsvfs->z_vfs);
3729 4274          } else {
3730 4275                  error = dsl_dataset_rollback(fsname, target, NULL, outnvl);
3731 4276          }
     4277 +
     4278 +        if (error == 0) {
     4279 +                event = fnvlist_alloc();
     4280 +                fnvlist_add_string(event, "target", (target != NULL) ? target : "");
     4281 +                fnvlist_add_string(event, "fsname", fsname);
     4282 +                fnvlist_add_int32(event, "resume_err", resume_err);
     4283 +                zfs_event_post(ZFS_EC_STATUS, "rollback", event);
     4284 +        }
     4285 +
     4286 +        error = (error != 0) ? error : resume_err;
3732 4287          return (error);
3733 4288  }
3734 4289  
3735 4290  static int
3736 4291  recursive_unmount(const char *fsname, void *arg)
3737 4292  {
3738 4293          const char *snapname = arg;
3739 4294          char fullname[ZFS_MAX_DATASET_NAME_LEN];
3740 4295  
3741 4296          (void) snprintf(fullname, sizeof (fullname), "%s@%s", fsname, snapname);
↓ open down ↓ 8 lines elided ↑ open up ↑
3750 4305   * zc_value     new name of dataset
3751 4306   * zc_cookie    recursive flag (only valid for snapshots)
3752 4307   *
3753 4308   * outputs:     none
3754 4309   */
3755 4310  static int
3756 4311  zfs_ioc_rename(zfs_cmd_t *zc)
3757 4312  {
3758 4313          boolean_t recursive = zc->zc_cookie & 1;
3759 4314          char *at;
     4315 +        nvlist_t *event;
     4316 +        int error;
3760 4317  
3761      -        /* "zfs rename" from and to ...%recv datasets should both fail */
3762      -        zc->zc_name[sizeof (zc->zc_name) - 1] = '\0';
     4318 +        if (zfs_is_wormed(zc->zc_name))
     4319 +                return (SET_ERROR(EPERM));
     4320 +
3763 4321          zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
3764      -        if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0 ||
3765      -            dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
3766      -            strchr(zc->zc_name, '%') || strchr(zc->zc_value, '%'))
     4322 +        if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
     4323 +            strchr(zc->zc_value, '%'))
3767 4324                  return (SET_ERROR(EINVAL));
3768 4325  
3769 4326          at = strchr(zc->zc_name, '@');
3770 4327          if (at != NULL) {
3771 4328                  /* snaps must be in same fs */
3772      -                int error;
3773 4329  
3774 4330                  if (strncmp(zc->zc_name, zc->zc_value, at - zc->zc_name + 1))
3775 4331                          return (SET_ERROR(EXDEV));
3776 4332                  *at = '\0';
3777 4333                  if (zc->zc_objset_type == DMU_OST_ZFS) {
3778 4334                          error = dmu_objset_find(zc->zc_name,
3779 4335                              recursive_unmount, at + 1,
3780 4336                              recursive ? DS_FIND_CHILDREN : 0);
3781 4337                          if (error != 0) {
3782 4338                                  *at = '@';
3783 4339                                  return (error);
3784 4340                          }
3785 4341                  }
3786 4342                  error = dsl_dataset_rename_snapshot(zc->zc_name,
3787 4343                      at + 1, strchr(zc->zc_value, '@') + 1, recursive);
3788 4344                  *at = '@';
3789 4345  
3790      -                return (error);
3791 4346          } else {
3792 4347                  if (zc->zc_objset_type == DMU_OST_ZVOL)
3793 4348                          (void) zvol_remove_minor(zc->zc_name);
3794      -                return (dsl_dir_rename(zc->zc_name, zc->zc_value));
     4349 +                error = dsl_dir_rename(zc->zc_name, zc->zc_value);
3795 4350          }
     4351 +
     4352 +        if (error == 0) {
     4353 +                event = fnvlist_alloc();
     4354 +                fnvlist_add_string(event, "origin", zc->zc_name);
     4355 +                fnvlist_add_string(event, "fsname", zc->zc_value);
     4356 +                fnvlist_add_int32(event, "type", zc->zc_objset_type);
     4357 +                zfs_event_post(ZFS_EC_STATUS, "rename", event);
     4358 +        }
     4359 +
     4360 +        return (error);
3796 4361  }
3797 4362  
3798 4363  static int
3799 4364  zfs_check_settable(const char *dsname, nvpair_t *pair, cred_t *cr)
3800 4365  {
3801 4366          const char *propname = nvpair_name(pair);
3802 4367          boolean_t issnap = (strchr(dsname, '@') != NULL);
3803 4368          zfs_prop_t prop = zfs_name_to_prop(propname);
3804 4369          uint64_t intval;
3805 4370          int err;
↓ open down ↓ 136 lines elided ↑ open up ↑
3942 4507          case ZFS_PROP_ACLINHERIT:
3943 4508                  if (nvpair_type(pair) == DATA_TYPE_UINT64 &&
3944 4509                      nvpair_value_uint64(pair, &intval) == 0) {
3945 4510                          if (intval == ZFS_ACL_PASSTHROUGH_X &&
3946 4511                              zfs_earlier_version(dsname,
3947 4512                              SPA_VERSION_PASSTHROUGH_X))
3948 4513                                  return (SET_ERROR(ENOTSUP));
3949 4514                  }
3950 4515                  break;
3951 4516  
     4517 +        case ZFS_PROP_WBC_MODE:
     4518 +                {
     4519 +                        spa_t *spa;
     4520 +                        boolean_t wbc_feature_enabled;
     4521 +
     4522 +                        if ((err = spa_open(dsname, &spa, FTAG)) != 0)
     4523 +                                return (err);
     4524 +
     4525 +                        wbc_feature_enabled =
     4526 +                            spa_feature_is_enabled(spa, SPA_FEATURE_WBC);
     4527 +                        spa_close(spa, FTAG);
     4528 +
     4529 +                        /* WBC cannot be used without special-vdev */
     4530 +                        if (!wbc_feature_enabled || !spa_has_special(spa))
     4531 +                                return (SET_ERROR(EKZFS_WBCNOTSUP));
     4532 +
     4533 +                        /*
     4534 +                         * We do not want to have races, because on
     4535 +                         * import or after reboot WBC does registration
     4536 +                         * asynchronously.
     4537 +                         */
     4538 +                        if (!spa->spa_wbc.wbc_ready_to_use)
     4539 +                                return (SET_ERROR(EBUSY));
     4540 +                }
     4541 +                break;
     4542 +
3952 4543          case ZFS_PROP_CHECKSUM:
3953 4544          case ZFS_PROP_DEDUP:
3954 4545          {
3955 4546                  spa_feature_t feature;
3956 4547                  spa_t *spa;
3957 4548  
3958 4549                  /* dedup feature version checks */
3959 4550                  if (prop == ZFS_PROP_DEDUP &&
3960 4551                      zfs_earlier_version(dsname, SPA_VERSION_DEDUP))
3961 4552                          return (SET_ERROR(ENOTSUP));
↓ open down ↓ 255 lines elided ↑ open up ↑
4217 4808                  nvlist_free(delayprops);
4218 4809                  delayprops = NULL;
4219 4810          }
4220 4811          return (delayprops);
4221 4812  }
4222 4813  
4223 4814  #ifdef  DEBUG
4224 4815  static boolean_t zfs_ioc_recv_inject_err;
4225 4816  #endif
4226 4817  
4227      -/*
4228      - * inputs:
4229      - * zc_name              name of containing filesystem
4230      - * zc_nvlist_src{_size} nvlist of properties to apply
4231      - * zc_value             name of snapshot to create
4232      - * zc_string            name of clone origin (if DRR_FLAG_CLONE)
4233      - * zc_cookie            file descriptor to recv from
4234      - * zc_begin_record      the BEGIN record of the stream (not byteswapped)
4235      - * zc_guid              force flag
4236      - * zc_cleanup_fd        cleanup-on-exit file descriptor
4237      - * zc_action_handle     handle for this guid/ds mapping (or zero on first call)
4238      - * zc_resumable         if data is incomplete assume sender will resume
4239      - *
4240      - * outputs:
4241      - * zc_cookie            number of bytes read
4242      - * zc_nvlist_dst{_size} error for each unapplied received property
4243      - * zc_obj               zprop_errflags_t
4244      - * zc_action_handle     handle for this guid/ds mapping
4245      - */
4246      -static int
4247      -zfs_ioc_recv(zfs_cmd_t *zc)
     4818 +int
     4819 +dmu_recv_impl(int fd, char *tofs, char *tosnap, char *origin,
     4820 +    dmu_replay_record_t *drr_begin, boolean_t is_resumable, nvlist_t *props,
     4821 +    nvlist_t *errors, uint64_t *errf, int cfd, uint64_t *ahdl, uint64_t *sz,
     4822 +    boolean_t force, dmu_krrp_task_t *krrp_task)
4248 4823  {
4249      -        file_t *fp;
     4824 +        file_t *fp = getf(fd);
4250 4825          dmu_recv_cookie_t drc;
4251      -        boolean_t force = (boolean_t)zc->zc_guid;
4252      -        int fd;
4253 4826          int error = 0;
4254 4827          int props_error = 0;
4255      -        nvlist_t *errors;
4256 4828          offset_t off;
4257      -        nvlist_t *props = NULL; /* sent properties */
4258 4829          nvlist_t *origprops = NULL; /* existing properties */
4259 4830          nvlist_t *delayprops = NULL; /* sent properties applied post-receive */
4260      -        char *origin = NULL;
4261      -        char *tosnap;
4262      -        char tofs[ZFS_MAX_DATASET_NAME_LEN];
4263 4831          boolean_t first_recvd_props = B_FALSE;
     4832 +        nvlist_t *event;
     4833 +        boolean_t force_cksum =
     4834 +            !krrp_task || krrp_task->buffer_args.force_cksum;
4264 4835  
4265      -        if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
4266      -            strchr(zc->zc_value, '@') == NULL ||
4267      -            strchr(zc->zc_value, '%'))
4268      -                return (SET_ERROR(EINVAL));
     4836 +        ASSERT(fp || krrp_task);
4269 4837  
4270      -        (void) strcpy(tofs, zc->zc_value);
4271      -        tosnap = strchr(tofs, '@');
4272      -        *tosnap++ = '\0';
4273      -
4274      -        if (zc->zc_nvlist_src != NULL &&
4275      -            (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
4276      -            zc->zc_iflags, &props)) != 0)
4277      -                return (error);
4278      -
4279      -        fd = zc->zc_cookie;
4280      -        fp = getf(fd);
4281      -        if (fp == NULL) {
4282      -                nvlist_free(props);
4283      -                return (SET_ERROR(EBADF));
4284      -        }
4285      -
4286      -        errors = fnvlist_alloc();
4287      -
4288      -        if (zc->zc_string[0])
4289      -                origin = zc->zc_string;
4290      -
4291 4838          error = dmu_recv_begin(tofs, tosnap,
4292      -            &zc->zc_begin_record, force, zc->zc_resumable, origin, &drc);
     4839 +            drr_begin, force, is_resumable, force_cksum, origin, &drc);
     4840 +
4293 4841          if (error != 0)
4294 4842                  goto out;
4295 4843  
     4844 +        drc.drc_krrp_task = krrp_task;
4296 4845          /*
4297 4846           * Set properties before we receive the stream so that they are applied
4298 4847           * to the new data. Note that we must call dmu_recv_stream() if
4299 4848           * dmu_recv_begin() succeeds.
4300 4849           */
4301 4850          if (props != NULL && !drc.drc_newfs) {
4302 4851                  if (spa_version(dsl_dataset_get_spa(drc.drc_ds)) >=
4303 4852                      SPA_VERSION_RECVD_PROPS &&
4304 4853                      !dsl_prop_get_hasrecvd(tofs))
4305 4854                          first_recvd_props = B_TRUE;
↓ open down ↓ 14 lines elided ↑ open up ↑
4320 4869                           * regardless.
4321 4870                           */
4322 4871                          if (!first_recvd_props)
4323 4872                                  props_reduce(props, origprops);
4324 4873                          if (zfs_check_clearable(tofs, origprops, &errlist) != 0)
4325 4874                                  (void) nvlist_merge(errors, errlist, 0);
4326 4875                          nvlist_free(errlist);
4327 4876  
4328 4877                          if (clear_received_props(tofs, origprops,
4329 4878                              first_recvd_props ? NULL : props) != 0)
4330      -                                zc->zc_obj |= ZPROP_ERR_NOCLEAR;
     4879 +                                *errf |= ZPROP_ERR_NOCLEAR;
4331 4880                  } else {
4332      -                        zc->zc_obj |= ZPROP_ERR_NOCLEAR;
     4881 +                        *errf |= ZPROP_ERR_NOCLEAR;
4333 4882                  }
4334 4883          }
4335 4884  
4336 4885          if (props != NULL) {
4337 4886                  props_error = dsl_prop_set_hasrecvd(tofs);
4338 4887  
4339 4888                  if (props_error == 0) {
4340 4889                          delayprops = extract_delay_props(props);
4341 4890                          (void) zfs_set_prop_nvlist(tofs, ZPROP_SRC_RECEIVED,
4342 4891                              props, errors);
4343 4892                  }
4344 4893          }
4345 4894  
4346      -        off = fp->f_offset;
4347      -        error = dmu_recv_stream(&drc, fp->f_vnode, &off, zc->zc_cleanup_fd,
4348      -            &zc->zc_action_handle);
     4895 +        if (fp) {
     4896 +                off = fp->f_offset;
     4897 +        } else {
     4898 +                off = 0;
     4899 +        }
     4900 +        error = dmu_recv_stream(&drc, fp ? fp->f_vnode : NULL,
     4901 +            &off, cfd, ahdl, krrp_task);
4349 4902  
4350 4903          if (error == 0) {
4351 4904                  zfsvfs_t *zfsvfs = NULL;
4352 4905  
4353      -                if (getzfsvfs(tofs, &zfsvfs) == 0) {
     4906 +                error = getzfsvfs(tofs, &zfsvfs);
     4907 +                if (error == 0) {
4354 4908                          /* online recv */
4355 4909                          dsl_dataset_t *ds;
4356 4910                          int end_err;
4357 4911  
4358 4912                          ds = dmu_objset_ds(zfsvfs->z_os);
4359 4913                          error = zfs_suspend_fs(zfsvfs);
4360 4914                          /*
4361 4915                           * If the suspend fails, then the recv_end will
4362 4916                           * likely also fail, and clean up after itself.
4363 4917                           */
↓ open down ↓ 20 lines elided ↑ open up ↑
4384 4938                   * we have to make sure clear_received_props() includes
4385 4939                   * the delayed properties).
4386 4940                   *
4387 4941                   * Since zfs_ioc_recv_inject_err is only in DEBUG kernels,
4388 4942                   * using ASSERT() will be just like a VERIFY.
4389 4943                   */
4390 4944                  ASSERT(nvlist_merge(props, delayprops, 0) == 0);
4391 4945                  nvlist_free(delayprops);
4392 4946          }
4393 4947  
4394      -        /*
4395      -         * Now that all props, initial and delayed, are set, report the prop
4396      -         * errors to the caller.
4397      -         */
4398      -        if (zc->zc_nvlist_dst_size != 0 &&
4399      -            (nvlist_smush(errors, zc->zc_nvlist_dst_size) != 0 ||
4400      -            put_nvlist(zc, errors) != 0)) {
4401      -                /*
4402      -                 * Caller made zc->zc_nvlist_dst less than the minimum expected
4403      -                 * size or supplied an invalid address.
4404      -                 */
4405      -                props_error = SET_ERROR(EINVAL);
     4948 +        if (fp) {
     4949 +                *sz = off - fp->f_offset;
     4950 +                if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
     4951 +                        fp->f_offset = off;
     4952 +        } else {
     4953 +                *sz = off;
4406 4954          }
     4955 +        if (error == 0) {
     4956 +                char val[MAXNAMELEN];
4407 4957  
4408      -        zc->zc_cookie = off - fp->f_offset;
4409      -        if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
4410      -                fp->f_offset = off;
     4958 +                (void) strcpy(val, tofs);
     4959 +                (void) strcat(val, "@");
     4960 +                (void) strcat(val, tosnap);
4411 4961  
     4962 +                event = fnvlist_alloc();
     4963 +                if (props != NULL)
     4964 +                        fnvlist_add_nvlist(event, "props", props);
     4965 +                fnvlist_add_string(event, "origin", tofs);
     4966 +                fnvlist_add_string(event, "tosnap", val);
     4967 +                fnvlist_add_uint64(event, "bytes", *sz);
     4968 +                fnvlist_add_boolean_value(event, "newds", drc.drc_newfs);
     4969 +                zfs_event_post(ZFS_EC_STATUS, "recv", event);
     4970 +        }
     4971 +
4412 4972  #ifdef  DEBUG
4413 4973          if (zfs_ioc_recv_inject_err) {
4414 4974                  zfs_ioc_recv_inject_err = B_FALSE;
4415 4975                  error = 1;
4416 4976          }
4417 4977  #endif
4418 4978          /*
4419 4979           * On error, restore the original props.
4420 4980           */
4421 4981          if (error != 0 && props != NULL && !drc.drc_newfs) {
4422 4982                  if (clear_received_props(tofs, props, NULL) != 0) {
4423 4983                          /*
4424 4984                           * We failed to clear the received properties.
4425 4985                           * Since we may have left a $recvd value on the
4426 4986                           * system, we can't clear the $hasrecvd flag.
4427 4987                           */
4428      -                        zc->zc_obj |= ZPROP_ERR_NORESTORE;
     4988 +                        *errf |= ZPROP_ERR_NORESTORE;
4429 4989                  } else if (first_recvd_props) {
4430 4990                          dsl_prop_unset_hasrecvd(tofs);
4431 4991                  }
4432 4992  
4433 4993                  if (origprops == NULL && !drc.drc_newfs) {
4434 4994                          /* We failed to stash the original properties. */
4435      -                        zc->zc_obj |= ZPROP_ERR_NORESTORE;
     4995 +                        *errf |= ZPROP_ERR_NORESTORE;
4436 4996                  }
4437 4997  
4438 4998                  /*
4439 4999                   * dsl_props_set() will not convert RECEIVED to LOCAL on or
4440 5000                   * after SPA_VERSION_RECVD_PROPS, so we need to specify LOCAL
4441 5001                   * explictly if we're restoring local properties cleared in the
4442 5002                   * first new-style receive.
4443 5003                   */
4444 5004                  if (origprops != NULL &&
4445 5005                      zfs_set_prop_nvlist(tofs, (first_recvd_props ?
4446 5006                      ZPROP_SRC_LOCAL : ZPROP_SRC_RECEIVED),
4447 5007                      origprops, NULL) != 0) {
4448 5008                          /*
4449 5009                           * We stashed the original properties but failed to
4450 5010                           * restore them.
4451 5011                           */
4452      -                        zc->zc_obj |= ZPROP_ERR_NORESTORE;
     5012 +                        *errf |= ZPROP_ERR_NORESTORE;
4453 5013                  }
4454 5014          }
4455 5015  out:
4456      -        nvlist_free(props);
4457 5016          nvlist_free(origprops);
4458      -        nvlist_free(errors);
4459      -        releasef(fd);
     5017 +        if (fp)
     5018 +                releasef(fd);
4460 5019  
4461 5020          if (error == 0)
4462 5021                  error = props_error;
4463 5022  
4464 5023          return (error);
4465 5024  }
4466 5025  
4467 5026  /*
4468 5027   * inputs:
     5028 + * zc_name              name of containing filesystem
     5029 + * zc_nvlist_src{_size} nvlist of properties to apply
     5030 + * zc_value             name of snapshot to create
     5031 + * zc_string            name of clone origin (if DRR_FLAG_CLONE)
     5032 + * zc_cookie            file descriptor to recv from
     5033 + * zc_begin_record      the BEGIN record of the stream (not byteswapped)
     5034 + * zc_guid              force flag
     5035 + * zc_cleanup_fd        cleanup-on-exit file descriptor
     5036 + * zc_action_handle     handle for this guid/ds mapping (or zero on first call)
     5037 + * zc_resumable         if data is incomplete assume sender will resume
     5038 + *
     5039 + * outputs:
     5040 + * zc_cookie            number of bytes read
     5041 + * zc_nvlist_dst{_size} error for each unapplied received property
     5042 + * zc_obj               zprop_errflags_t
     5043 + * zc_action_handle     handle for this guid/ds mapping
     5044 + */
     5045 +static int
     5046 +zfs_ioc_recv(zfs_cmd_t *zc)
     5047 +{
     5048 +        int fd = zc->zc_cookie;
     5049 +        char tofs[ZFS_MAX_DATASET_NAME_LEN];
     5050 +        char *tosnap;
     5051 +        char *origin = NULL;
     5052 +        nvlist_t *errors;
     5053 +        nvlist_t *props = NULL; /* sent properties */
     5054 +        boolean_t force = (boolean_t)zc->zc_guid;
     5055 +        int err;
     5056 +
     5057 +        if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
     5058 +            strchr(zc->zc_value, '@') == NULL ||
     5059 +            strchr(zc->zc_value, '%'))
     5060 +                return (SET_ERROR(EINVAL));
     5061 +
     5062 +        (void) strcpy(tofs, zc->zc_value);
     5063 +        tosnap = strchr(tofs, '@');
     5064 +        *tosnap++ = '\0';
     5065 +
     5066 +        if (zc->zc_string[0])
     5067 +                origin = zc->zc_string;
     5068 +
     5069 +        if (zc->zc_nvlist_src != NULL &&
     5070 +            (err = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
     5071 +            zc->zc_iflags, &props)) != 0)
     5072 +                return (err);
     5073 +
     5074 +        errors = fnvlist_alloc();
     5075 +
     5076 +        err = dmu_recv_impl(fd, tofs, tosnap, origin,
     5077 +            &zc->zc_begin_record, zc->zc_resumable, props, errors, &zc->zc_obj,
     5078 +            zc->zc_cleanup_fd, &zc->zc_action_handle, &zc->zc_cookie,
     5079 +            force, NULL);
     5080 +
     5081 +        /*
     5082 +         * Now that all props, initial and delayed, are set, report the prop
     5083 +         * errors to the caller.
     5084 +         */
     5085 +        if (zc->zc_nvlist_dst_size != 0 &&
     5086 +            (nvlist_smush(errors, zc->zc_nvlist_dst_size) != 0 ||
     5087 +            put_nvlist(zc, errors) != 0)) {
     5088 +                /*
     5089 +                 * Caller made zc->zc_nvlist_dst less than the minimum expected
     5090 +                 * size or supplied an invalid address.
     5091 +                 */
     5092 +                err = SET_ERROR(EINVAL);
     5093 +        }
     5094 +
     5095 +        nvlist_free(errors);
     5096 +        nvlist_free(props);
     5097 +        return (err);
     5098 +
     5099 +}
     5100 +
     5101 +/*
     5102 + * inputs:
4469 5103   * zc_name      name of snapshot to send
4470 5104   * zc_cookie    file descriptor to send stream to
4471 5105   * zc_obj       fromorigin flag (mutually exclusive with zc_fromobj)
4472 5106   * zc_sendobj   objsetid of snapshot to send
4473 5107   * zc_fromobj   objsetid of incremental fromsnap (may be zero)
4474 5108   * zc_guid      if set, estimate size of stream only.  zc_cookie is ignored.
4475 5109   *              output size in zc_objset_type.
4476 5110   * zc_flags     lzc_send_flags
4477 5111   *
4478 5112   * outputs:
↓ open down ↓ 56 lines elided ↑ open up ↑
4535 5169                  }
4536 5170  
4537 5171                  error = dmu_send_estimate(tosnap, fromsnap, compressok,
4538 5172                      &zc->zc_objset_type);
4539 5173  
4540 5174                  if (fromsnap != NULL)
4541 5175                          dsl_dataset_rele(fromsnap, FTAG);
4542 5176                  dsl_dataset_rele(tosnap, FTAG);
4543 5177                  dsl_pool_rele(dp, FTAG);
4544 5178          } else {
     5179 +                offset_t off_starting;
4545 5180                  file_t *fp = getf(zc->zc_cookie);
4546 5181                  if (fp == NULL)
4547 5182                          return (SET_ERROR(EBADF));
4548 5183  
4549      -                off = fp->f_offset;
     5184 +                off_starting = off = fp->f_offset;
4550 5185                  error = dmu_send_obj(zc->zc_name, zc->zc_sendobj,
4551 5186                      zc->zc_fromobj, embedok, large_block_ok, compressok,
4552      -                    zc->zc_cookie, fp->f_vnode, &off);
     5187 +                    zc->zc_cookie, fp->f_vnode, &off, zc->zc_sendsize);
4553 5188  
     5189 +                zc->zc_sendcounter = off - off_starting;
4554 5190                  if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
4555 5191                          fp->f_offset = off;
4556 5192                  releasef(zc->zc_cookie);
4557 5193          }
4558 5194          return (error);
4559 5195  }
4560 5196  
4561 5197  /*
4562 5198   * inputs:
4563 5199   * zc_name      name of snapshot on which to report progress
↓ open down ↓ 214 lines elided ↑ open up ↑
4778 5414   * zc_string    name of conflicting snapshot, if there is one
4779 5415   */
4780 5416  static int
4781 5417  zfs_ioc_promote(zfs_cmd_t *zc)
4782 5418  {
4783 5419          dsl_pool_t *dp;
4784 5420          dsl_dataset_t *ds, *ods;
4785 5421          char origin[ZFS_MAX_DATASET_NAME_LEN];
4786 5422          char *cp;
4787 5423          int error;
     5424 +        nvlist_t *event;
4788 5425  
4789      -        zc->zc_name[sizeof (zc->zc_name) - 1] = '\0';
4790      -        if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0 ||
4791      -            strchr(zc->zc_name, '%'))
4792      -                return (SET_ERROR(EINVAL));
4793      -
4794 5426          error = dsl_pool_hold(zc->zc_name, FTAG, &dp);
4795 5427          if (error != 0)
4796 5428                  return (error);
4797 5429  
4798 5430          error = dsl_dataset_hold(dp, zc->zc_name, FTAG, &ds);
4799 5431          if (error != 0) {
4800 5432                  dsl_pool_rele(dp, FTAG);
4801 5433                  return (error);
4802 5434          }
4803 5435  
↓ open down ↓ 18 lines elided ↑ open up ↑
4822 5454  
4823 5455          /*
4824 5456           * We don't need to unmount *all* the origin fs's snapshots, but
4825 5457           * it's easier.
4826 5458           */
4827 5459          cp = strchr(origin, '@');
4828 5460          if (cp)
4829 5461                  *cp = '\0';
4830 5462          (void) dmu_objset_find(origin,
4831 5463              zfs_unmount_snap_cb, NULL, DS_FIND_SNAPSHOTS);
4832      -        return (dsl_dataset_promote(zc->zc_name, zc->zc_string));
     5464 +        error = dsl_dataset_promote(zc->zc_name, zc->zc_string);
     5465 +
     5466 +        if (error == 0) {
     5467 +                event = fnvlist_alloc();
     5468 +                fnvlist_add_string(event, "fsname", zc->zc_name);
     5469 +                fnvlist_add_string(event, "origin", zc->zc_value);
     5470 +                zfs_event_post(ZFS_EC_STATUS, "promote", event);
     5471 +        }
     5472 +
     5473 +        return (error);
4833 5474  }
4834 5475  
4835 5476  /*
4836 5477   * Retrieve a single {user|group}{used|quota}@... property.
4837 5478   *
4838 5479   * inputs:
4839 5480   * zc_name      name of filesystem
4840 5481   * zc_objset_type zfs_userquota_prop_t
4841 5482   * zc_value     domain name (eg. "S-1-234-567-89")
4842 5483   * zc_guid      RID/UID/GID
↓ open down ↓ 660 lines elided ↑ open up ↑
5503 6144          error = dsl_dataset_space_wouldfree(old, new, &used, &comp, &uncomp);
5504 6145          dsl_dataset_rele(old, FTAG);
5505 6146          dsl_dataset_rele(new, FTAG);
5506 6147          dsl_pool_rele(dp, FTAG);
5507 6148          fnvlist_add_uint64(outnvl, "used", used);
5508 6149          fnvlist_add_uint64(outnvl, "compressed", comp);
5509 6150          fnvlist_add_uint64(outnvl, "uncompressed", uncomp);
5510 6151          return (error);
5511 6152  }
5512 6153  
     6154 +static int
     6155 +zfs_ioc_vdev_set_props(zfs_cmd_t *zc)
     6156 +{
     6157 +        nvlist_t *props;
     6158 +        spa_t *spa;
     6159 +        int error;
     6160 +        uint64_t vdev_guid = zc->zc_guid;
     6161 +
     6162 +        if (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
     6163 +            zc->zc_iflags, &props))
     6164 +                return (error);
     6165 +
     6166 +        if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) {
     6167 +                nvlist_free(props);
     6168 +                return (error);
     6169 +        }
     6170 +
     6171 +        error = spa_vdev_prop_set(spa, vdev_guid, props);
     6172 +
     6173 +        nvlist_free(props);
     6174 +        spa_close(spa, FTAG);
     6175 +
     6176 +        return (error);
     6177 +}
     6178 +
     6179 +static int
     6180 +zfs_ioc_vdev_get_props(zfs_cmd_t *zc)
     6181 +{
     6182 +        spa_t *spa;
     6183 +        uint64_t vdev_guid = zc->zc_guid;
     6184 +        nvlist_t *nvp = NULL;
     6185 +        int error;
     6186 +
     6187 +        if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) {
     6188 +                /*
     6189 +                 * If the pool is faulted, there may be properties we can still
     6190 +                 * get (such as altroot and cachefile), so attempt to get them
     6191 +                 * anyway.
     6192 +                 */
     6193 +                mutex_enter(&spa_namespace_lock);
     6194 +                if ((spa = spa_lookup(zc->zc_name)) != NULL)
     6195 +                        error = spa_vdev_prop_get(spa, vdev_guid, &nvp);
     6196 +                mutex_exit(&spa_namespace_lock);
     6197 +        } else {
     6198 +                error = spa_vdev_prop_get(spa, vdev_guid, &nvp);
     6199 +                spa_close(spa, FTAG);
     6200 +        }
     6201 +
     6202 +        if (error == 0 && zc->zc_nvlist_dst != NULL)
     6203 +                error = put_nvlist(zc, nvp);
     6204 +        else
     6205 +                error = EFAULT;
     6206 +
     6207 +        nvlist_free(nvp);
     6208 +        return (error);
     6209 +}
     6210 +
     6211 +static int
     6212 +zfs_ioc_cos_alloc(zfs_cmd_t *zc)
     6213 +{
     6214 +        nvlist_t *props;
     6215 +        spa_t *spa;
     6216 +        int error;
     6217 +
     6218 +        if (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
     6219 +            zc->zc_iflags, &props))
     6220 +                return (error);
     6221 +
     6222 +        if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) {
     6223 +                nvlist_free(props);
     6224 +                return (error);
     6225 +        }
     6226 +
     6227 +        error = spa_alloc_cos(spa, zc->zc_string, 0);
     6228 +        if (!error)
     6229 +                error = spa_cos_prop_set(spa, zc->zc_string, props);
     6230 +
     6231 +        spa_close(spa, FTAG);
     6232 +        nvlist_free(props);
     6233 +
     6234 +        return (error);
     6235 +}
     6236 +
     6237 +static int
     6238 +zfs_ioc_cos_free(zfs_cmd_t *zc)
     6239 +{
     6240 +        spa_t *spa;
     6241 +        int error = 0;
     6242 +
     6243 +        if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
     6244 +                return (error);
     6245 +
     6246 +        error = spa_free_cos(spa, zc->zc_string, zc->zc_cookie);
     6247 +
     6248 +        spa_close(spa, FTAG);
     6249 +
     6250 +        return (error);
     6251 +}
     6252 +
     6253 +static int
     6254 +zfs_ioc_cos_list(zfs_cmd_t *zc)
     6255 +{
     6256 +        spa_t *spa;
     6257 +        nvlist_t *nvl;
     6258 +        int error = 0;
     6259 +
     6260 +        VERIFY(nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) == 0);
     6261 +
     6262 +        if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) {
     6263 +                nvlist_free(nvl);
     6264 +                return (error);
     6265 +        }
     6266 +
     6267 +        error = spa_list_cos(spa, nvl);
     6268 +
     6269 +        if (error == 0 && zc->zc_nvlist_dst != NULL)
     6270 +                error = put_nvlist(zc, nvl);
     6271 +
     6272 +        spa_close(spa, FTAG);
     6273 +        nvlist_free(nvl);
     6274 +
     6275 +        return (error);
     6276 +}
     6277 +
     6278 +static int
     6279 +zfs_ioc_cos_set_props(zfs_cmd_t *zc)
     6280 +{
     6281 +        nvlist_t *props;
     6282 +        spa_t *spa;
     6283 +        cos_t *cos;
     6284 +        const char *cosname = NULL;
     6285 +        int error = 0;
     6286 +
     6287 +        if ((zc->zc_string == NULL || zc->zc_string[0] == '\0') &&
     6288 +            zc->zc_guid == 0)
     6289 +                return (SET_ERROR(EINVAL));
     6290 +
     6291 +        if (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
     6292 +            zc->zc_iflags, &props))
     6293 +                return (error);
     6294 +
     6295 +        if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) {
     6296 +                nvlist_free(props);
     6297 +                return (error);
     6298 +        }
     6299 +
     6300 +        if (zc->zc_guid == 0) {
     6301 +                cosname = zc->zc_string;
     6302 +        } else {
     6303 +                spa_cos_enter(spa);
     6304 +                cos = spa_lookup_cos_by_guid(spa, zc->zc_guid);
     6305 +                if (cos != NULL)
     6306 +                        cosname = cos->cos_name;
     6307 +                else
     6308 +                        error = SET_ERROR(ENOENT);
     6309 +                spa_cos_exit(spa);
     6310 +        }
     6311 +
     6312 +        if (error == 0)
     6313 +                error = spa_cos_prop_set(spa, cosname, props);
     6314 +
     6315 +        spa_close(spa, FTAG);
     6316 +        nvlist_free(props);
     6317 +
     6318 +        return (error);
     6319 +}
     6320 +
     6321 +static int
     6322 +zfs_ioc_cos_get_props(zfs_cmd_t *zc)
     6323 +{
     6324 +        spa_t *spa;
     6325 +        cos_t *cos;
     6326 +        nvlist_t *nvp = NULL;
     6327 +        const char *cosname = NULL;
     6328 +        int error = 0;
     6329 +
     6330 +        if ((zc->zc_string == NULL || zc->zc_string[0] == '\0') &&
     6331 +            zc->zc_guid == 0)
     6332 +                return (SET_ERROR(EINVAL));
     6333 +
     6334 +        if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
     6335 +                return (error);
     6336 +
     6337 +        if (zc->zc_guid == 0) {
     6338 +                cosname = zc->zc_string;
     6339 +        } else {
     6340 +                spa_cos_enter(spa);
     6341 +                cos = spa_lookup_cos_by_guid(spa, zc->zc_guid);
     6342 +                if (cos != NULL)
     6343 +                        cosname = cos->cos_name;
     6344 +                spa_cos_exit(spa);
     6345 +        }
     6346 +
     6347 +        if (error == 0)
     6348 +                error = spa_cos_prop_get(spa, cosname, &nvp);
     6349 +
     6350 +        spa_close(spa, FTAG);
     6351 +
     6352 +        if (error == 0 && zc->zc_nvlist_dst != NULL)
     6353 +                error = put_nvlist(zc, nvp);
     6354 +        else
     6355 +                error = EFAULT;
     6356 +
     6357 +        nvlist_free(nvp);
     6358 +        return (error);
     6359 +}
     6360 +
5513 6361  /*
5514 6362   * innvl: {
5515 6363   *     "fd" -> file descriptor to write stream to (int32)
5516 6364   *     (optional) "fromsnap" -> full snap name to send an incremental from
5517 6365   *     (optional) "largeblockok" -> (value ignored)
5518 6366   *         indicates that blocks > 128KB are permitted
5519 6367   *     (optional) "embedok" -> (value ignored)
5520 6368   *         presence indicates DRR_WRITE_EMBEDDED records are permitted
5521 6369   *     (optional) "compressok" -> (value ignored)
5522 6370   *         presence indicates compressed DRR_WRITE records are permitted
↓ open down ↓ 130 lines elided ↑ open up ↑
5653 6501          }
5654 6502  
5655 6503          fnvlist_add_uint64(outnvl, "space", space);
5656 6504  
5657 6505  out:
5658 6506          dsl_dataset_rele(tosnap, FTAG);
5659 6507          dsl_pool_rele(dp, FTAG);
5660 6508          return (error);
5661 6509  }
5662 6510  
     6511 +typedef struct dp_cursor_cb_arg {
     6512 +        nvlist_t *outnvl;
     6513 +        uint64_t offset;
     6514 +        uint32_t count;
     6515 +        uint32_t skip;
     6516 +        boolean_t verbose;
     6517 +        boolean_t snaps;
     6518 +} dp_cursor_cb_arg_t;
     6519 +
     6520 +/* ARGSUSED */
     6521 +int
     6522 +ds_cursor_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg)
     6523 +{
     6524 +        int error;
     6525 +        char dsname[MAXNAMELEN];
     6526 +        objset_t *osp;
     6527 +
     6528 +        dp_cursor_cb_arg_t *cb = (dp_cursor_cb_arg_t *)arg;
     6529 +
     6530 +        dsl_dataset_name(ds, dsname);
     6531 +        nvlist_t *nv = fnvlist_alloc();
     6532 +
     6533 +        fnvlist_add_uint64(nv, zfs_prop_to_name(ZFS_PROP_GUID),
     6534 +            dsl_dataset_phys(ds)->ds_guid);
     6535 +
     6536 +        if (cb->verbose) {
     6537 +                uint64_t refd, avail, uobjs, aobjs;
     6538 +                dsl_dataset_space(ds, &refd, &avail, &uobjs, &aobjs);
     6539 +
     6540 +                fnvlist_add_uint64(nv, zfs_prop_to_name(ZFS_PROP_AVAILABLE),
     6541 +                    avail);
     6542 +                fnvlist_add_uint64(nv, zfs_prop_to_name(ZFS_PROP_REFERENCED),
     6543 +                    refd);
     6544 +                fnvlist_add_uint64(nv, zfs_prop_to_name(ZFS_PROP_USED),
     6545 +                    dsl_dir_phys(ds->ds_dir)->dd_used_bytes);
     6546 +        }
     6547 +
     6548 +        error = dmu_objset_from_ds(ds, &osp);
     6549 +
     6550 +        if (error == 0)
     6551 +                fnvlist_add_uint64(nv, zfs_prop_to_name(ZFS_PROP_TYPE),
     6552 +                    dmu_objset_type(osp));
     6553 +
     6554 +        fnvlist_add_nvlist(cb->outnvl, dsname, nv);
     6555 +        nvlist_free(nv);
     6556 +        return (error);
     6557 +}
     6558 +
     6559 +int
     6560 +dmu_objset_find_dp_cursor(dsl_pool_t *dp, uint64_t ddobj,
     6561 +    int func(dsl_pool_t *, dsl_dataset_t *, void *), void *arg)
     6562 +{
     6563 +        dsl_dir_t *dd;
     6564 +        dsl_dataset_t *ds;
     6565 +        zap_cursor_t zc;
     6566 +        zap_attribute_t *attr;
     6567 +        uint64_t thisobj;
     6568 +        int error, i;
     6569 +
     6570 +        dp_cursor_cb_arg_t *cb = (dp_cursor_cb_arg_t *)arg;
     6571 +
     6572 +        ASSERT(dsl_pool_config_held(dp));
     6573 +        error = dsl_dir_hold_obj(dp, ddobj, NULL, FTAG, &dd);
     6574 +        thisobj = dsl_dir_phys(dd)->dd_head_dataset_obj;
     6575 +
     6576 +        if (error != 0)
     6577 +                return (error);
     6578 +
     6579 +        attr = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP);
     6580 +
     6581 +        /* we are interrestd in filesytems and volumes */
     6582 +        if (!cb->snaps) {
     6583 +
     6584 +                /* init the cursor at given offset */
     6585 +                zap_cursor_init_serialized(&zc, dp->dp_meta_objset,
     6586 +                    dsl_dir_phys(dd)->dd_child_dir_zapobj, cb->offset);
     6587 +
     6588 +
     6589 +                for (i = 0; i < cb->skip; i++) {
     6590 +                        zap_cursor_advance(&zc);
     6591 +                        if ((zap_cursor_retrieve(&zc, attr) != 0)) {
     6592 +                                error = ENOENT;
     6593 +                                goto out;
     6594 +                        }
     6595 +                }
     6596 +
     6597 +                for (i = 0; i < cb->count; i++) {
     6598 +                        zap_cursor_advance(&zc);
     6599 +                        if ((zap_cursor_retrieve(&zc, attr) != 0)) {
     6600 +                                error = ENOENT;
     6601 +                                goto out;
     6602 +                        }
     6603 +
     6604 +                        ASSERT3U(attr->za_integer_length, ==,
     6605 +                            sizeof (uint64_t));
     6606 +                        ASSERT3U(attr->za_num_integers, ==, 1);
     6607 +                        /* recursivly walk objects skipping $MOS and $ORIGIN */
     6608 +                        error = dmu_objset_find_dp(dp, attr->za_first_integer,
     6609 +                            func, arg, 0);
     6610 +                        if (error != 0)
     6611 +                                break;
     6612 +                }
     6613 +        } else {
     6614 +
     6615 +                dsl_dataset_t *ds;
     6616 +
     6617 +                error = dsl_dataset_hold_obj(dp, thisobj, FTAG, &ds);
     6618 +
     6619 +                if (error == 0) {
     6620 +
     6621 +                        dsl_dataset_rele(ds, FTAG);
     6622 +                        zap_cursor_init_serialized(&zc, dp->dp_meta_objset,
     6623 +                            dsl_dataset_phys(ds)->ds_snapnames_zapobj,
     6624 +                            cb->offset);
     6625 +
     6626 +                        for (i = 0; i < cb->skip; i++) {
     6627 +                                zap_cursor_advance(&zc);
     6628 +                                        if ((zap_cursor_retrieve(&zc,
     6629 +                                            attr) != 0)) {
     6630 +                                        error = ENOENT;
     6631 +                                        goto out;
     6632 +                                }
     6633 +                        }
     6634 +
     6635 +                        for (i = 0; i < cb->count; i++) {
     6636 +                                zap_cursor_advance(&zc);
     6637 +                                if ((zap_cursor_retrieve(&zc, attr) != 0)) {
     6638 +                                        error = ENOENT;
     6639 +                                        goto out;
     6640 +
     6641 +                                }
     6642 +
     6643 +                                ASSERT3U(attr->za_integer_length, ==,
     6644 +                                    sizeof (uint64_t));
     6645 +                                ASSERT3U(attr->za_num_integers, ==, 1);
     6646 +
     6647 +                                error = dsl_dataset_hold_obj(dp,
     6648 +                                    attr->za_first_integer, FTAG, &ds);
     6649 +                                if (error != 0)
     6650 +                                        break;
     6651 +                                error = func(dp, ds, arg);
     6652 +                                dsl_dataset_rele(ds, FTAG);
     6653 +                                if (error != 0)
     6654 +                                        break;
     6655 +                        }
     6656 +                }
     6657 +        }
     6658 +out:
     6659 +        cb->offset = zap_cursor_serialize(&zc);
     6660 +        zap_cursor_fini(&zc);
     6661 +        dsl_dir_rele(dd, FTAG);
     6662 +        kmem_free(attr, sizeof (zap_attribute_t));
     6663 +
     6664 +        /* return self as the last dataset */
     6665 +        if (error == ENOENT) {
     6666 +                if ((error = dsl_dataset_hold_obj(dp, thisobj, FTAG, &ds)) != 0)
     6667 +                        return (error);
     6668 +                error = func(dp, ds, arg);
     6669 +                dsl_dataset_rele(ds, FTAG);
     6670 +                if (error)
     6671 +                        return (error);
     6672 +                error = ENOENT;
     6673 +        }
     6674 +
     6675 +        return (error);
     6676 +}
     6677 +
     6678 +
     6679 +/*
     6680 + * We want to list all dataset under the given name. Optionally, we advance the
     6681 + * ZAP cursor "skip" times and retrieve "count" datasets. We return the offset
     6682 + * so the user can start the next invocation where he left off.
     6683 + */
     6684 +
     6685 +static int
     6686 +zfs_ioc_list_from_cursor(const char *name, nvlist_t *innvl, nvlist_t *outnvl)
     6687 +{
     6688 +
     6689 +        dsl_pool_t *dp;
     6690 +        dsl_dataset_t *ds;
     6691 +
     6692 +        int error;
     6693 +
     6694 +        dp_cursor_cb_arg_t cb_args;
     6695 +
     6696 +        if ((strchr(name, '@') != NULL))
     6697 +                return (EINVAL);
     6698 +
     6699 +        if ((error = dsl_pool_hold(name, FTAG, &dp)) != 0)
     6700 +                return (error);
     6701 +
     6702 +        if ((error = dsl_dataset_hold(dp, name, FTAG, &ds)) != 0) {
     6703 +                dsl_pool_rele(dp, FTAG);
     6704 +                return (error);
     6705 +        }
     6706 +
     6707 +        (void) nvlist_lookup_uint32(innvl, "count", &cb_args.count);
     6708 +        (void) nvlist_lookup_uint32(innvl, "skip", &cb_args.skip);
     6709 +        (void) nvlist_lookup_uint64(innvl, "offset", &cb_args.offset);
     6710 +        (void) nvlist_lookup_boolean_value(innvl, "verbose", &cb_args.verbose);
     6711 +        (void) nvlist_lookup_boolean_value(innvl, "snaps", &cb_args.snaps);
     6712 +
     6713 +        cb_args.outnvl = outnvl;
     6714 +        error = dmu_objset_find_dp_cursor(dp, ds->ds_dir->dd_object,
     6715 +            &ds_cursor_cb, &cb_args);
     6716 +
     6717 +        fnvlist_add_uint64(outnvl, "offset", cb_args.offset);
     6718 +        dsl_dataset_rele(ds, FTAG);
     6719 +        dsl_pool_rele(dp, FTAG);
     6720 +
     6721 +        return (error);
     6722 +}
     6723 +
     6724 +
5663 6725  static zfs_ioc_vec_t zfs_ioc_vec[ZFS_IOC_LAST - ZFS_IOC_FIRST];
5664 6726  
5665 6727  static void
5666 6728  zfs_ioctl_register_legacy(zfs_ioc_t ioc, zfs_ioc_legacy_func_t *func,
5667 6729      zfs_secpolicy_func_t *secpolicy, zfs_ioc_namecheck_t namecheck,
5668 6730      boolean_t log_history, zfs_ioc_poolcheck_t pool_check)
5669 6731  {
5670 6732          zfs_ioc_vec_t *vec = &zfs_ioc_vec[ioc - ZFS_IOC_FIRST];
5671 6733  
5672 6734          ASSERT3U(ioc, >=, ZFS_IOC_FIRST);
↓ open down ↓ 85 lines elided ↑ open up ↑
5758 6820  }
5759 6821  
5760 6822  static void
5761 6823  zfs_ioctl_register_dataset_modify(zfs_ioc_t ioc, zfs_ioc_legacy_func_t *func,
5762 6824      zfs_secpolicy_func_t *secpolicy)
5763 6825  {
5764 6826          zfs_ioctl_register_legacy(ioc, func, secpolicy,
5765 6827              DATASET_NAME, B_TRUE, POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY);
5766 6828  }
5767 6829  
     6830 +/*
     6831 + * Appearing to take poolname as a parameter is a concession to the ioctl
     6832 + * handler. Leading underbar for generation idea nvpair exists only on output to
     6833 + * avoid pool name conflict.
     6834 + */
     6835 +/* ARGSUSED */
     6836 +static int
     6837 +zfs_ioc_pool_configs_nvl(const char *poolname, nvlist_t *innvl,
     6838 +    nvlist_t *outnvl)
     6839 +{
     6840 +        nvlist_t *configs;
     6841 +        uint64_t generation;
     6842 +
     6843 +        if (nvlist_lookup_uint64(innvl, "generation", &generation) != 0)
     6844 +                return (SET_ERROR(EINVAL));
     6845 +
     6846 +        if ((configs = spa_all_configs(&generation)) == NULL)
     6847 +                return (SET_ERROR(EEXIST));
     6848 +
     6849 +        fnvlist_merge(outnvl, configs);
     6850 +        nvlist_free(configs);
     6851 +        fnvlist_add_uint64(outnvl, "_generation", generation);
     6852 +
     6853 +        return (0);
     6854 +}
     6855 +
     6856 +/*
     6857 + * Ask spa for pool statistics. If we get a non-NULL config but a non-zero
     6858 + * return from spa, we return EAGAIN to hint to callers that we've retrieved
     6859 + * a config for a faulted pool. We take no arguments but declare otherwise to
     6860 + * suit the ioctl handler's pattern. Similar considerations apply to outnvl as a
     6861 + * single pointer that has to be merged with config allocated or nulled by spa.
     6862 + */
     6863 +static int
     6864 +zfs_ioc_pool_stats_nvl(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
     6865 +{
     6866 +        nvlist_t *config;
     6867 +        int error;
     6868 +        int ret = 0;
     6869 +
     6870 +        ASSERT3P(innvl, ==, NULL);
     6871 +        error = spa_get_stats(poolname, &config, NULL, 0);
     6872 +        ASSERT3U(error, !=, EAGAIN);
     6873 +
     6874 +        if (config != NULL) {
     6875 +                fnvlist_merge(outnvl, config);
     6876 +                nvlist_free(config);
     6877 +                if (error)
     6878 +                        ret = SET_ERROR(EAGAIN);
     6879 +        } else {
     6880 +                ret = error;
     6881 +        }
     6882 +
     6883 +        return (ret);
     6884 +}
     6885 +
     6886 +static nvlist_t *
     6887 +objset_stats2nv(dmu_objset_stats_t *stat)
     6888 +{
     6889 +        nvlist_t *statlist  = fnvlist_alloc();
     6890 +
     6891 +        fnvlist_add_uint64(statlist, "dds_num_clones", stat->dds_num_clones);
     6892 +        fnvlist_add_uint64(statlist, "dds_creation_txg",
     6893 +            stat->dds_creation_txg);
     6894 +        fnvlist_add_uint64(statlist, "dds_guid", stat->dds_guid);
     6895 +        fnvlist_add_uint8(statlist, "dds_type", (uint8_t)stat->dds_type);
     6896 +        fnvlist_add_uint8(statlist, "dds_is_snapshot", stat->dds_is_snapshot);
     6897 +        fnvlist_add_uint8(statlist, "dds_inconsistent",
     6898 +            stat->dds_inconsistent);
     6899 +        fnvlist_add_string(statlist, "dds_origin", stat->dds_origin);
     6900 +
     6901 +        return (statlist);
     6902 +}
     6903 +
     6904 +/* Given an objset, retrieve stats and props by adding them to the output nvl */
     6905 +static int
     6906 +objset_render(objset_t *os, nvlist_t *outnvl)
     6907 +{
     6908 +        int error = 0;
     6909 +        nvlist_t *props = NULL, *statlist = NULL;
     6910 +        dmu_objset_stats_t stats;
     6911 +
     6912 +        dmu_objset_fast_stat(os, &stats);
     6913 +
     6914 +        if ((error = dsl_prop_get_all(os, &props)) == 0) {
     6915 +                dmu_objset_stats(os, props);
     6916 +                /*
     6917 +                 * NB: zvol_get_stats() will read the objset contents,
     6918 +                 * which we aren't supposed to do with a
     6919 +                 * DS_MODE_USER hold, because it could be
     6920 +                 * inconsistent.  So this is a bit of a workaround...
     6921 +                 * XXX reading with out owning
     6922 +                 */
     6923 +                if (!stats.dds_inconsistent &&
     6924 +                    dmu_objset_type(os) == DMU_OST_ZVOL) {
     6925 +                        error = zvol_get_stats(os, props);
     6926 +                        if (error == EIO)
     6927 +                                goto out;
     6928 +                        VERIFY0(error);
     6929 +                }
     6930 +                fnvlist_add_nvlist(outnvl, "props", props);
     6931 +                statlist = objset_stats2nv(&stats);
     6932 +                fnvlist_add_nvlist(outnvl, "stats", statlist);
     6933 +                nvlist_free(statlist);
     6934 +        }
     6935 +
     6936 +out:
     6937 +        nvlist_free(props);
     6938 +        return (error);
     6939 +}
     6940 +
     6941 +/*
     6942 + * Note: this IOC can be called internally by other IOCs as an existence
     6943 + * check against race conditions. Given a dataset name, return its stats
     6944 + * and props. Optionally we can verify type, which simplifies things for
     6945 + * callers that may not want to parse stats for themselves (and may discard
     6946 + * the outnvl in handlers).
     6947 + */
     6948 +static int
     6949 +zfs_ioc_objset_stats_nvl(const char *data, nvlist_t *innvl, nvlist_t *outnvl)
     6950 +{
     6951 +        objset_t *os;
     6952 +        int error;
     6953 +        dmu_objset_type_t checktype = DMU_OST_ANY;
     6954 +        boolean_t gettype = B_FALSE;
     6955 +
     6956 +        if (innvl != NULL) {
     6957 +                if (nvlist_lookup_uint8(innvl, "type", (uint8_t *)&checktype)
     6958 +                    == 0)
     6959 +                        gettype = B_TRUE;
     6960 +        }
     6961 +        if ((error = dmu_objset_hold(data, FTAG, &os)) == 0) {
     6962 +                error = objset_render(os, outnvl);
     6963 +                dmu_objset_rele(os, FTAG);
     6964 +
     6965 +                if (error == 0) {
     6966 +                        nvlist_t *statlist;
     6967 +                        dmu_objset_type_t type;
     6968 +                        statlist = fnvlist_lookup_nvlist(outnvl, "stats");
     6969 +                        type = fnvlist_lookup_uint8_t(statlist, "dds_type");
     6970 +                        if (checktype != DMU_OST_ANY && type != checktype) {
     6971 +                                error = EEXIST;
     6972 +                                fnvlist_remove(outnvl, "stats");
     6973 +                                fnvlist_remove(outnvl, "props");
     6974 +                        }
     6975 +                        if (gettype)
     6976 +                                fnvlist_add_uint8(outnvl, "type", type);
     6977 +                }
     6978 +        }
     6979 +
     6980 +        return (error);
     6981 +}
     6982 +
     6983 +/*
     6984 + * Given a dataset name and an innvl containing a DMU cursor offset, find the
     6985 + * next child dataset, and return its name, stats, and props and an updated
     6986 + * cursor.
     6987 + */
     6988 +static int
     6989 +zfs_ioc_dataset_list_next_nvl(const char *data, nvlist_t *innvl,
     6990 +    nvlist_t *outnvl)
     6991 +{
     6992 +        objset_t *os;
     6993 +        int error;
     6994 +        uint64_t off;
     6995 +        char *p, *nextds;
     6996 +        char name[MAXNAMELEN];
     6997 +        size_t len;
     6998 +        size_t orig_len = strlen(data);
     6999 +
     7000 +        if (innvl == NULL ||
     7001 +            nvlist_lookup_uint64(innvl, "offset", &off) != 0)
     7002 +                return (SET_ERROR(EINVAL));
     7003 +
     7004 +        (void) strlcpy(name, data, sizeof (name));
     7005 +top:
     7006 +        if (error = dmu_objset_hold(name, FTAG, &os)) {
     7007 +                if (error == ENOENT)
     7008 +                        error = SET_ERROR(ESRCH);
     7009 +                return (error);
     7010 +        }
     7011 +
     7012 +        p = strrchr(name, '/');
     7013 +        if (p == NULL || p[1] != '\0') {
     7014 +                if ((len = strlcat(name, "/", sizeof (name))) >= MAXNAMELEN) {
     7015 +                        dmu_objset_rele(os, FTAG);
     7016 +                        return (SET_ERROR(ESRCH));
     7017 +                }
     7018 +        } else {
     7019 +                len = orig_len;
     7020 +        }
     7021 +        p = name + len;
     7022 +
     7023 +        do {
     7024 +                error = dmu_dir_list_next(os, sizeof (name) - len, p, NULL,
     7025 +                    &off);
     7026 +                if (error == ENOENT)
     7027 +                        error = ESRCH;
     7028 +        } while (error == 0 && dataset_name_hidden(name));
     7029 +        dmu_objset_rele(os, FTAG);
     7030 +
     7031 +        /*
     7032 +         * If it's an internal dataset (ie. with a '$' in its name),
     7033 +         * don't try to get stats for it, otherwise we'll return ENOENT.
     7034 +         */
     7035 +        if (error == 0 && strchr(name, '$') == NULL) {
     7036 +                error = zfs_ioc_objset_stats_nvl(name, NULL, outnvl);
     7037 +                if (error == ENOENT) {
     7038 +                        /* We lost a race with destroy, get the next one. */
     7039 +                        name[orig_len] = '\0';
     7040 +                        goto top;
     7041 +                }
     7042 +                len = strlen(name) + 1;
     7043 +                nextds = kmem_alloc(len, KM_SLEEP);
     7044 +                (void) strlcpy(nextds, name, len);
     7045 +                fnvlist_add_string(outnvl, "nextds", (const char *)nextds);
     7046 +                fnvlist_add_uint64(outnvl, "offset", off);
     7047 +        }
     7048 +
     7049 +        return (error);
     7050 +}
     7051 +
     7052 +/*
     7053 + * Given a dataset name and a DMU cursor offset, find its next snapshot, and
     7054 + * return its name, props, and stats and an updated cursor offset.
     7055 + */
     7056 +static int
     7057 +zfs_ioc_snapshot_list_next_nvl(const char *data, nvlist_t *innvl,
     7058 +    nvlist_t *outnvl)
     7059 +{
     7060 +        objset_t *os;
     7061 +        int error;
     7062 +        uint64_t off, obj;
     7063 +        char name[MAXNAMELEN], *nextsnap;
     7064 +        size_t len;
     7065 +
     7066 +        if (innvl == NULL ||
     7067 +            nvlist_lookup_uint64(innvl, "offset", &off) != 0)
     7068 +                return (SET_ERROR(EINVAL));
     7069 +
     7070 +        error = dmu_objset_hold(data, FTAG, &os);
     7071 +        if (error != 0) {
     7072 +                return (error == ENOENT ? ESRCH : error);
     7073 +        }
     7074 +
     7075 +        /*
     7076 +         * A dataset name of maximum length cannot have any snapshots,
     7077 +         * so exit immediately.
     7078 +         */
     7079 +        (void) strlcpy(name, data, sizeof (name));
     7080 +        if ((len = strlcat(name, "@", sizeof (name))) >= MAXNAMELEN) {
     7081 +                dmu_objset_rele(os, FTAG);
     7082 +                return (SET_ERROR(ESRCH));
     7083 +        }
     7084 +
     7085 +        /* Rest of name buffer is passed so snap ID can be appended. */
     7086 +        error = dmu_snapshot_list_next(os, sizeof (name) - len, name + len,
     7087 +            &obj, &off, NULL);
     7088 +
     7089 +        if (error == 0) {
     7090 +                dsl_dataset_t *ds;
     7091 +                dsl_pool_t *dp = os->os_dsl_dataset->ds_dir->dd_pool;
     7092 +
     7093 +                error = dsl_dataset_hold_obj(dp, obj, FTAG, &ds);
     7094 +                if (error == 0) {
     7095 +                        objset_t *ossnap;
     7096 +
     7097 +                        error = dmu_objset_from_ds(ds, &ossnap);
     7098 +                        if (error == 0)
     7099 +                                error = objset_render(ossnap, outnvl);
     7100 +                        dsl_dataset_rele(ds, FTAG);
     7101 +                }
     7102 +        } else if (error == ENOENT) {
     7103 +                error = ESRCH;
     7104 +        }
     7105 +
     7106 +        dmu_objset_rele(os, FTAG);
     7107 +
     7108 +        if (error == 0) {
     7109 +                len = strlen(name) + 1;
     7110 +                nextsnap = kmem_alloc(len, KM_SLEEP);
     7111 +                (void) strlcpy(nextsnap, name, len);
     7112 +                fnvlist_add_string(outnvl, "nextsnap", (const char *)nextsnap);
     7113 +                fnvlist_add_uint64(outnvl, "offset", off);
     7114 +        }
     7115 +        return (error);
     7116 +}
     7117 +
     7118 +static int
     7119 +zfs_ioc_pool_get_props_nvl(const char *poolname, nvlist_t *innvl,
     7120 +    nvlist_t *outnvl)
     7121 +{
     7122 +        spa_t *spa;
     7123 +        int error;
     7124 +        nvlist_t *props = NULL;
     7125 +
     7126 +        ASSERT3P(innvl, ==, NULL);
     7127 +        if ((error = spa_open(poolname, &spa, FTAG)) != 0) {
     7128 +                /*
     7129 +                 * If the pool is faulted, there may be properties we can still
     7130 +                 * get (such as altroot and cachefile), so attempt to get them
     7131 +                 * anyway.
     7132 +                 */
     7133 +                mutex_enter(&spa_namespace_lock);
     7134 +                if ((spa = spa_lookup(poolname)) != NULL)
     7135 +                        error = spa_prop_get(spa, &props);
     7136 +                mutex_exit(&spa_namespace_lock);
     7137 +        } else {
     7138 +                error = spa_prop_get(spa, &props);
     7139 +                spa_close(spa, FTAG);
     7140 +        }
     7141 +
     7142 +        if (props != NULL) {
     7143 +                fnvlist_merge(outnvl, props);
     7144 +                nvlist_free(props);
     7145 +        } else {
     7146 +                ASSERT3S(error, !=, 0);
     7147 +        }
     7148 +
     7149 +        return (error);
     7150 +}
     7151 +
     7152 +/* ARGSUSED */
     7153 +static int
     7154 +zfs_ioc_check_krrp(const char *dataset, nvlist_t *innvl, nvlist_t *outnvl)
     7155 +{
     7156 +        spa_t *spa;
     7157 +        int err;
     7158 +
     7159 +        /*
     7160 +         * Here we use different way to open spa for the given pool,
     7161 +         * because the pool maybe faulted
     7162 +         */
     7163 +
     7164 +        mutex_enter(&spa_namespace_lock);
     7165 +        if ((spa = spa_lookup(dataset)) == NULL) {
     7166 +                mutex_exit(&spa_namespace_lock);
     7167 +                /* From KRRP side everything nice */
     7168 +                return (0);
     7169 +        }
     7170 +
     7171 +        spa_open_ref(spa, FTAG);
     7172 +        mutex_exit(&spa_namespace_lock);
     7173 +
     7174 +        err = autosnap_check_for_destroy(spa_get_autosnap(spa), dataset);
     7175 +        if (err == 0)
     7176 +                err = ENOTSUP;
     7177 +
     7178 +        mutex_enter(&spa_namespace_lock);
     7179 +        spa_close(spa, FTAG);
     7180 +        mutex_exit(&spa_namespace_lock);
     7181 +
     7182 +        return (err != 0 ? SET_ERROR(err) : 0);
     7183 +}
     7184 +
5768 7185  static void
5769 7186  zfs_ioctl_init(void)
5770 7187  {
     7188 +        zfs_ioctl_register("bulk_list", ZFS_IOC_BULK_LIST,
     7189 +            zfs_ioc_list_from_cursor, zfs_secpolicy_read,
     7190 +            DATASET_NAME, POOL_CHECK_SUSPENDED, B_FALSE, B_FALSE);
     7191 +
5771 7192          zfs_ioctl_register("snapshot", ZFS_IOC_SNAPSHOT,
5772 7193              zfs_ioc_snapshot, zfs_secpolicy_snapshot, POOL_NAME,
5773 7194              POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
5774 7195  
5775 7196          zfs_ioctl_register("log_history", ZFS_IOC_LOG_HISTORY,
5776 7197              zfs_ioc_log_history, zfs_secpolicy_log_history, NO_NAME,
5777 7198              POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_FALSE, B_FALSE);
5778 7199  
5779 7200          zfs_ioctl_register("space_snaps", ZFS_IOC_SPACE_SNAPS,
5780 7201              zfs_ioc_space_snaps, zfs_secpolicy_read, DATASET_NAME,
↓ open down ↓ 8 lines elided ↑ open up ↑
5789 7210              POOL_CHECK_SUSPENDED, B_FALSE, B_FALSE);
5790 7211  
5791 7212          zfs_ioctl_register("create", ZFS_IOC_CREATE,
5792 7213              zfs_ioc_create, zfs_secpolicy_create_clone, DATASET_NAME,
5793 7214              POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
5794 7215  
5795 7216          zfs_ioctl_register("clone", ZFS_IOC_CLONE,
5796 7217              zfs_ioc_clone, zfs_secpolicy_create_clone, DATASET_NAME,
5797 7218              POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
5798 7219  
5799      -        zfs_ioctl_register("remap", ZFS_IOC_REMAP,
5800      -            zfs_ioc_remap, zfs_secpolicy_remap, DATASET_NAME,
5801      -            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_FALSE, B_TRUE);
5802      -
5803 7220          zfs_ioctl_register("destroy_snaps", ZFS_IOC_DESTROY_SNAPS,
5804 7221              zfs_ioc_destroy_snaps, zfs_secpolicy_destroy_snaps, POOL_NAME,
5805 7222              POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
5806 7223  
     7224 +        zfs_ioctl_register("check_krrp", ZFS_IOC_CHECK_KRRP,
     7225 +            zfs_ioc_check_krrp, zfs_secpolicy_read, DATASET_NAME,
     7226 +            POOL_CHECK_NONE, B_FALSE, B_FALSE);
     7227 +
     7228 +        zfs_ioctl_register("pool_stats_nvl", ZFS_IOC_POOL_STATS_NVL,
     7229 +            zfs_ioc_pool_stats_nvl, zfs_secpolicy_read, POOL_NAME,
     7230 +            POOL_CHECK_NONE, B_FALSE, B_FALSE);
     7231 +
     7232 +        zfs_ioctl_register("pool_configs_nvl", ZFS_IOC_POOL_CONFIGS_NVL,
     7233 +            zfs_ioc_pool_configs_nvl, zfs_secpolicy_none, NO_NAME,
     7234 +            POOL_CHECK_NONE, B_FALSE, B_FALSE);
     7235 +
     7236 +        zfs_ioctl_register("pool_get_props_nvl", ZFS_IOC_POOL_GET_PROPS_NVL,
     7237 +            zfs_ioc_pool_get_props_nvl, zfs_secpolicy_read, POOL_NAME,
     7238 +            POOL_CHECK_NONE, B_FALSE, B_FALSE);
     7239 +
     7240 +        zfs_ioctl_register("objset_stats_nvl", ZFS_IOC_OBJSET_STATS_NVL,
     7241 +            zfs_ioc_objset_stats_nvl, zfs_secpolicy_read, DATASET_NAME,
     7242 +            POOL_CHECK_SUSPENDED, B_FALSE, B_FALSE);
     7243 +
     7244 +        zfs_ioctl_register("dataset_list_next_nvl",
     7245 +            ZFS_IOC_DATASET_LIST_NEXT_NVL, zfs_ioc_dataset_list_next_nvl,
     7246 +            zfs_secpolicy_read, DATASET_NAME, POOL_CHECK_SUSPENDED, B_FALSE,
     7247 +            B_FALSE);
     7248 +
     7249 +        zfs_ioctl_register("snapshot_list_next_nvl",
     7250 +            ZFS_IOC_SNAPSHOT_LIST_NEXT_NVL, zfs_ioc_snapshot_list_next_nvl,
     7251 +            zfs_secpolicy_read, DATASET_NAME, POOL_CHECK_SUSPENDED, B_FALSE,
     7252 +            B_FALSE);
     7253 +
5807 7254          zfs_ioctl_register("hold", ZFS_IOC_HOLD,
5808 7255              zfs_ioc_hold, zfs_secpolicy_hold, POOL_NAME,
5809 7256              POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
5810 7257          zfs_ioctl_register("release", ZFS_IOC_RELEASE,
5811 7258              zfs_ioc_release, zfs_secpolicy_release, POOL_NAME,
5812 7259              POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
5813 7260  
5814 7261          zfs_ioctl_register("get_holds", ZFS_IOC_GET_HOLDS,
5815 7262              zfs_ioc_get_holds, zfs_secpolicy_read, DATASET_NAME,
5816 7263              POOL_CHECK_SUSPENDED, B_FALSE, B_FALSE);
↓ open down ↓ 13 lines elided ↑ open up ↑
5830 7277          zfs_ioctl_register("destroy_bookmarks", ZFS_IOC_DESTROY_BOOKMARKS,
5831 7278              zfs_ioc_destroy_bookmarks, zfs_secpolicy_destroy_bookmarks,
5832 7279              POOL_NAME,
5833 7280              POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
5834 7281  
5835 7282          zfs_ioctl_register("channel_program", ZFS_IOC_CHANNEL_PROGRAM,
5836 7283              zfs_ioc_channel_program, zfs_secpolicy_config,
5837 7284              POOL_NAME, POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE,
5838 7285              B_TRUE);
5839 7286  
     7287 +        zfs_ioctl_register("set_props_mds", ZFS_IOC_SET_PROPS_MDS,
     7288 +            zfs_ioc_set_prop_mds, zfs_secpolicy_config,
     7289 +            POOL_NAME,
     7290 +            POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
     7291 +
5840 7292          /* IOCTLS that use the legacy function signature */
5841 7293  
5842 7294          zfs_ioctl_register_legacy(ZFS_IOC_POOL_FREEZE, zfs_ioc_pool_freeze,
5843 7295              zfs_secpolicy_config, NO_NAME, B_FALSE, POOL_CHECK_READONLY);
5844 7296  
5845 7297          zfs_ioctl_register_pool(ZFS_IOC_POOL_CREATE, zfs_ioc_pool_create,
5846 7298              zfs_secpolicy_config, B_TRUE, POOL_CHECK_NONE);
5847 7299          zfs_ioctl_register_pool_modify(ZFS_IOC_POOL_SCAN,
5848 7300              zfs_ioc_pool_scan);
     7301 +        zfs_ioctl_register_pool_modify(ZFS_IOC_POOL_TRIM,
     7302 +            zfs_ioc_pool_trim);
5849 7303          zfs_ioctl_register_pool_modify(ZFS_IOC_POOL_UPGRADE,
5850 7304              zfs_ioc_pool_upgrade);
5851 7305          zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_ADD,
5852 7306              zfs_ioc_vdev_add);
5853 7307          zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_REMOVE,
5854 7308              zfs_ioc_vdev_remove);
5855 7309          zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_SET_STATE,
5856 7310              zfs_ioc_vdev_set_state);
5857 7311          zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_ATTACH,
5858 7312              zfs_ioc_vdev_attach);
5859 7313          zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_DETACH,
5860 7314              zfs_ioc_vdev_detach);
     7315 +        zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_SETL2ADDDT,
     7316 +            zfs_ioc_vdev_setl2adddt);
5861 7317          zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_SETPATH,
5862 7318              zfs_ioc_vdev_setpath);
5863 7319          zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_SETFRU,
5864 7320              zfs_ioc_vdev_setfru);
5865 7321          zfs_ioctl_register_pool_modify(ZFS_IOC_POOL_SET_PROPS,
5866 7322              zfs_ioc_pool_set_props);
5867 7323          zfs_ioctl_register_pool_modify(ZFS_IOC_VDEV_SPLIT,
5868 7324              zfs_ioc_vdev_split);
5869 7325          zfs_ioctl_register_pool_modify(ZFS_IOC_POOL_REGUID,
5870 7326              zfs_ioc_pool_reguid);
↓ open down ↓ 30 lines elided ↑ open up ↑
5901 7357              zfs_ioc_dsobj_to_dsname,
5902 7358              zfs_secpolicy_diff, B_FALSE, POOL_CHECK_SUSPENDED);
5903 7359          zfs_ioctl_register_pool(ZFS_IOC_POOL_GET_HISTORY,
5904 7360              zfs_ioc_pool_get_history,
5905 7361              zfs_secpolicy_config, B_FALSE, POOL_CHECK_SUSPENDED);
5906 7362  
5907 7363          zfs_ioctl_register_pool(ZFS_IOC_POOL_IMPORT, zfs_ioc_pool_import,
5908 7364              zfs_secpolicy_config, B_TRUE, POOL_CHECK_NONE);
5909 7365  
5910 7366          zfs_ioctl_register_pool(ZFS_IOC_CLEAR, zfs_ioc_clear,
5911      -            zfs_secpolicy_config, B_TRUE, POOL_CHECK_READONLY);
     7367 +            zfs_secpolicy_config, B_TRUE, POOL_CHECK_NONE);
5912 7368          zfs_ioctl_register_pool(ZFS_IOC_POOL_REOPEN, zfs_ioc_pool_reopen,
5913 7369              zfs_secpolicy_config, B_TRUE, POOL_CHECK_SUSPENDED);
5914      -
     7370 +        zfs_ioctl_register_pool(ZFS_IOC_VDEV_SET_PROPS, zfs_ioc_vdev_set_props,
     7371 +            zfs_secpolicy_config, B_TRUE, POOL_CHECK_SUSPENDED);
     7372 +        zfs_ioctl_register_pool(ZFS_IOC_VDEV_GET_PROPS, zfs_ioc_vdev_get_props,
     7373 +            zfs_secpolicy_config, B_TRUE, POOL_CHECK_SUSPENDED);
     7374 +        zfs_ioctl_register_pool(ZFS_IOC_COS_ALLOC, zfs_ioc_cos_alloc,
     7375 +            zfs_secpolicy_config, B_TRUE, POOL_CHECK_SUSPENDED);
     7376 +        zfs_ioctl_register_pool(ZFS_IOC_COS_FREE, zfs_ioc_cos_free,
     7377 +            zfs_secpolicy_config, B_TRUE, POOL_CHECK_SUSPENDED);
     7378 +        zfs_ioctl_register_pool(ZFS_IOC_COS_LIST, zfs_ioc_cos_list,
     7379 +            zfs_secpolicy_config, B_TRUE, POOL_CHECK_SUSPENDED);
     7380 +        zfs_ioctl_register_pool(ZFS_IOC_COS_SET_PROPS, zfs_ioc_cos_set_props,
     7381 +            zfs_secpolicy_config, B_TRUE, POOL_CHECK_SUSPENDED);
     7382 +        zfs_ioctl_register_pool(ZFS_IOC_COS_GET_PROPS, zfs_ioc_cos_get_props,
     7383 +            zfs_secpolicy_config, B_TRUE, POOL_CHECK_SUSPENDED);
5915 7384          zfs_ioctl_register_dataset_read(ZFS_IOC_SPACE_WRITTEN,
5916 7385              zfs_ioc_space_written);
5917 7386          zfs_ioctl_register_dataset_read(ZFS_IOC_OBJSET_RECVD_PROPS,
5918 7387              zfs_ioc_objset_recvd_props);
5919 7388          zfs_ioctl_register_dataset_read(ZFS_IOC_NEXT_OBJ,
5920 7389              zfs_ioc_next_obj);
5921 7390          zfs_ioctl_register_dataset_read(ZFS_IOC_GET_FSACL,
5922 7391              zfs_ioc_get_fsacl);
5923 7392          zfs_ioctl_register_dataset_read(ZFS_IOC_OBJSET_STATS,
5924 7393              zfs_ioc_objset_stats);
↓ open down ↓ 471 lines elided ↑ open up ↑
6396 7865          }
6397 7866  
6398 7867          tsd_create(&zfs_fsyncer_key, NULL);
6399 7868          tsd_create(&rrw_tsd_key, rrw_tsd_destroy);
6400 7869          tsd_create(&zfs_allow_log_key, zfs_allow_log_destroy);
6401 7870  
6402 7871          error = ldi_ident_from_mod(&modlinkage, &zfs_li);
6403 7872          ASSERT(error == 0);
6404 7873          mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL);
6405 7874  
     7875 +        if (sysevent_evc_bind(ZFS_EVENT_CHANNEL, &zfs_channel,
     7876 +            EVCH_HOLD_PEND | EVCH_CREAT) != 0)
     7877 +                cmn_err(CE_NOTE, "Failed to bind to zfs event channel");
     7878 +
6406 7879          return (0);
6407 7880  }
6408 7881  
6409 7882  int
6410 7883  _fini(void)
6411 7884  {
6412 7885          int error;
6413 7886  
6414 7887          if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled)
6415 7888                  return (SET_ERROR(EBUSY));
↓ open down ↓ 9 lines elided ↑ open up ↑
6425 7898          if (zfs_smbshare_inited)
6426 7899                  (void) ddi_modclose(smbsrv_mod);
6427 7900          if (zfs_nfsshare_inited || zfs_smbshare_inited)
6428 7901                  (void) ddi_modclose(sharefs_mod);
6429 7902  
6430 7903          tsd_destroy(&zfs_fsyncer_key);
6431 7904          ldi_ident_release(zfs_li);
6432 7905          zfs_li = NULL;
6433 7906          mutex_destroy(&zfs_share_lock);
6434 7907  
     7908 +        if (zfs_channel)
     7909 +                (void) sysevent_evc_unbind(zfs_channel);
     7910 +
6435 7911          return (error);
6436 7912  }
6437 7913  
6438 7914  int
6439 7915  _info(struct modinfo *modinfop)
6440 7916  {
6441 7917          return (mod_info(&modlinkage, modinfop));
6442 7918  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX