1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51485Slling * Common Development and Distribution License (the "License"). 61485Slling * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 223444Sek110237 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27789Sahrens 28789Sahrens #include <sys/types.h> 29789Sahrens #include <sys/param.h> 30789Sahrens #include <sys/errno.h> 31789Sahrens #include <sys/uio.h> 32789Sahrens #include <sys/buf.h> 33789Sahrens #include <sys/modctl.h> 34789Sahrens #include <sys/open.h> 35789Sahrens #include <sys/file.h> 36789Sahrens #include <sys/kmem.h> 37789Sahrens #include <sys/conf.h> 38789Sahrens #include <sys/cmn_err.h> 39789Sahrens #include <sys/stat.h> 40789Sahrens #include <sys/zfs_ioctl.h> 41789Sahrens #include <sys/zap.h> 42789Sahrens #include <sys/spa.h> 433912Slling #include <sys/spa_impl.h> 44789Sahrens #include <sys/vdev.h> 453912Slling #include <sys/vdev_impl.h> 46789Sahrens #include <sys/dmu.h> 47789Sahrens #include <sys/dsl_dir.h> 48789Sahrens #include <sys/dsl_dataset.h> 49789Sahrens #include <sys/dsl_prop.h> 504543Smarks #include <sys/dsl_deleg.h> 514543Smarks #include <sys/dmu_objset.h> 52789Sahrens #include <sys/ddi.h> 53789Sahrens #include <sys/sunddi.h> 54789Sahrens #include <sys/sunldi.h> 55789Sahrens #include <sys/policy.h> 56789Sahrens #include <sys/zone.h> 57789Sahrens #include <sys/nvpair.h> 58789Sahrens #include <sys/pathname.h> 59789Sahrens #include <sys/mount.h> 60789Sahrens #include <sys/sdt.h> 61789Sahrens #include <sys/fs/zfs.h> 62789Sahrens #include <sys/zfs_ctldir.h> 632885Sahrens #include <sys/zvol.h> 644543Smarks #include <sharefs/share.h> 654577Sahrens #include <sys/zfs_znode.h> 66789Sahrens 67789Sahrens #include "zfs_namecheck.h" 682676Seschrock #include "zfs_prop.h" 694543Smarks #include "zfs_deleg.h" 70789Sahrens 71789Sahrens extern struct modlfs zfs_modlfs; 72789Sahrens 73789Sahrens extern void zfs_init(void); 74789Sahrens extern void zfs_fini(void); 75789Sahrens 76789Sahrens ldi_ident_t zfs_li = NULL; 77789Sahrens dev_info_t *zfs_dip; 78789Sahrens 79789Sahrens typedef int zfs_ioc_func_t(zfs_cmd_t *); 804543Smarks typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *); 81789Sahrens 82789Sahrens typedef struct zfs_ioc_vec { 83789Sahrens zfs_ioc_func_t *zvec_func; 84789Sahrens zfs_secpolicy_func_t *zvec_secpolicy; 85789Sahrens enum { 864577Sahrens NO_NAME, 874577Sahrens POOL_NAME, 884577Sahrens DATASET_NAME 894543Smarks } zvec_namecheck; 904543Smarks boolean_t zvec_his_log; 91789Sahrens } zfs_ioc_vec_t; 92789Sahrens 93789Sahrens /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */ 94789Sahrens void 95789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 96789Sahrens { 97789Sahrens const char *newfile; 98789Sahrens char buf[256]; 99789Sahrens va_list adx; 100789Sahrens 101789Sahrens /* 102789Sahrens * Get rid of annoying "../common/" prefix to filename. 103789Sahrens */ 104789Sahrens newfile = strrchr(file, '/'); 105789Sahrens if (newfile != NULL) { 106789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 107789Sahrens } else { 108789Sahrens newfile = file; 109789Sahrens } 110789Sahrens 111789Sahrens va_start(adx, fmt); 112789Sahrens (void) vsnprintf(buf, sizeof (buf), fmt, adx); 113789Sahrens va_end(adx); 114789Sahrens 115789Sahrens /* 116789Sahrens * To get this data, use the zfs-dprintf probe as so: 117789Sahrens * dtrace -q -n 'zfs-dprintf \ 118789Sahrens * /stringof(arg0) == "dbuf.c"/ \ 119789Sahrens * {printf("%s: %s", stringof(arg1), stringof(arg3))}' 120789Sahrens * arg0 = file name 121789Sahrens * arg1 = function name 122789Sahrens * arg2 = line number 123789Sahrens * arg3 = message 124789Sahrens */ 125789Sahrens DTRACE_PROBE4(zfs__dprintf, 126789Sahrens char *, newfile, char *, func, int, line, char *, buf); 127789Sahrens } 128789Sahrens 1294543Smarks static void 1304543Smarks zfs_log_history(zfs_cmd_t *zc) 1314543Smarks { 1324543Smarks spa_t *spa; 1334603Sahrens char *buf; 1344543Smarks 1354543Smarks if (zc->zc_history == NULL) 1364543Smarks return; 1374543Smarks 1384577Sahrens if (zc->zc_history_offset != LOG_CMD_POOL_CREATE && 1394577Sahrens zc->zc_history_offset != LOG_CMD_NORMAL) 1404577Sahrens return; 1414577Sahrens 1424543Smarks buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP); 1434543Smarks if (copyinstr((void *)(uintptr_t)zc->zc_history, 1444543Smarks buf, HIS_MAX_RECORD_LEN, NULL) != 0) { 1454543Smarks kmem_free(buf, HIS_MAX_RECORD_LEN); 1464543Smarks return; 1474543Smarks } 1484543Smarks 1494543Smarks buf[HIS_MAX_RECORD_LEN -1] = '\0'; 1504543Smarks 1514603Sahrens if (spa_open(zc->zc_name, &spa, FTAG) != 0) { 1524543Smarks kmem_free(buf, HIS_MAX_RECORD_LEN); 1534543Smarks return; 1544543Smarks } 1554543Smarks 1564577Sahrens if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY) 1574543Smarks (void) spa_history_log(spa, buf, zc->zc_history_offset); 1584543Smarks 1594543Smarks spa_close(spa, FTAG); 1604543Smarks kmem_free(buf, HIS_MAX_RECORD_LEN); 1614543Smarks } 1624543Smarks 163789Sahrens /* 164789Sahrens * Policy for top-level read operations (list pools). Requires no privileges, 165789Sahrens * and can be used in the local zone, as there is no associated dataset. 166789Sahrens */ 167789Sahrens /* ARGSUSED */ 168789Sahrens static int 1694543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) 170789Sahrens { 171789Sahrens return (0); 172789Sahrens } 173789Sahrens 174789Sahrens /* 175789Sahrens * Policy for dataset read operations (list children, get statistics). Requires 176789Sahrens * no privileges, but must be visible in the local zone. 177789Sahrens */ 178789Sahrens /* ARGSUSED */ 179789Sahrens static int 1804543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) 181789Sahrens { 182789Sahrens if (INGLOBALZONE(curproc) || 1834543Smarks zone_dataset_visible(zc->zc_name, NULL)) 184789Sahrens return (0); 185789Sahrens 186789Sahrens return (ENOENT); 187789Sahrens } 188789Sahrens 189789Sahrens static int 190789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr) 191789Sahrens { 192789Sahrens uint64_t zoned; 193789Sahrens int writable = 1; 194789Sahrens 195789Sahrens /* 196789Sahrens * The dataset must be visible by this zone -- check this first 197789Sahrens * so they don't see EPERM on something they shouldn't know about. 198789Sahrens */ 199789Sahrens if (!INGLOBALZONE(curproc) && 200789Sahrens !zone_dataset_visible(dataset, &writable)) 201789Sahrens return (ENOENT); 202789Sahrens 203789Sahrens if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) 204789Sahrens return (ENOENT); 205789Sahrens 206789Sahrens if (INGLOBALZONE(curproc)) { 207789Sahrens /* 208789Sahrens * If the fs is zoned, only root can access it from the 209789Sahrens * global zone. 210789Sahrens */ 211789Sahrens if (secpolicy_zfs(cr) && zoned) 212789Sahrens return (EPERM); 213789Sahrens } else { 214789Sahrens /* 215789Sahrens * If we are in a local zone, the 'zoned' property must be set. 216789Sahrens */ 217789Sahrens if (!zoned) 218789Sahrens return (EPERM); 219789Sahrens 220789Sahrens /* must be writable by this zone */ 221789Sahrens if (!writable) 222789Sahrens return (EPERM); 223789Sahrens } 224789Sahrens return (0); 225789Sahrens } 226789Sahrens 227789Sahrens int 2284543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) 229789Sahrens { 230789Sahrens int error; 231789Sahrens 2324543Smarks error = zfs_dozonecheck(name, cr); 2334543Smarks if (error == 0) { 2344543Smarks error = secpolicy_zfs(cr); 235*4670Sahrens if (error) 2364543Smarks error = dsl_deleg_access(name, perm, cr); 2374543Smarks } 2384543Smarks return (error); 2394543Smarks } 2404543Smarks 2414543Smarks static int 2424543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) 2434543Smarks { 2444543Smarks /* 2454543Smarks * Check permissions for special properties. 2464543Smarks */ 2474543Smarks switch (prop) { 2484543Smarks case ZFS_PROP_ZONED: 2494543Smarks /* 2504543Smarks * Disallow setting of 'zoned' from within a local zone. 2514543Smarks */ 2524543Smarks if (!INGLOBALZONE(curproc)) 2534543Smarks return (EPERM); 2544543Smarks break; 255789Sahrens 2564543Smarks case ZFS_PROP_QUOTA: 2574543Smarks if (!INGLOBALZONE(curproc)) { 2584543Smarks uint64_t zoned; 2594543Smarks char setpoint[MAXNAMELEN]; 2604543Smarks /* 2614543Smarks * Unprivileged users are allowed to modify the 2624543Smarks * quota on things *under* (ie. contained by) 2634543Smarks * the thing they own. 2644543Smarks */ 2654543Smarks if (dsl_prop_get_integer(name, "zoned", &zoned, 2664543Smarks setpoint)) 2674543Smarks return (EPERM); 268*4670Sahrens if (!zoned || strlen(name) <= strlen(setpoint)) 2694543Smarks return (EPERM); 2704543Smarks } 271*4670Sahrens break; 2724543Smarks } 2734543Smarks 274*4670Sahrens return (zfs_secpolicy_write_perms(name, zfs_prop_perm(prop), cr)); 275789Sahrens } 276789Sahrens 2774543Smarks int 2784543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) 2794543Smarks { 2804543Smarks int error; 2814543Smarks 2824543Smarks error = zfs_dozonecheck(zc->zc_name, cr); 2834543Smarks if (error) 2844543Smarks return (error); 2854543Smarks 2864543Smarks /* 2874543Smarks * permission to set permissions will be evaluated later in 2884543Smarks * dsl_deleg_can_allow() 2894543Smarks */ 2904543Smarks return (0); 2914543Smarks } 2924543Smarks 2934543Smarks int 2944543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) 2954543Smarks { 2964543Smarks int error; 2974543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 2984543Smarks ZFS_DELEG_PERM_ROLLBACK, cr); 2994543Smarks if (error == 0) 3004543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3014543Smarks ZFS_DELEG_PERM_MOUNT, cr); 3024543Smarks return (error); 3034543Smarks } 3044543Smarks 3054543Smarks int 3064543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) 3074543Smarks { 3084543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 3094543Smarks ZFS_DELEG_PERM_SEND, cr)); 3104543Smarks } 3114543Smarks 3124543Smarks int 3134543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) 3144543Smarks { 3154543Smarks if (!INGLOBALZONE(curproc)) 3164543Smarks return (EPERM); 3174543Smarks 3184543Smarks if (secpolicy_nfs(CRED()) == 0) { 3194543Smarks return (0); 3204543Smarks } else { 3214543Smarks vnode_t *vp; 3224543Smarks int error; 3234543Smarks 3244543Smarks if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, 3254543Smarks NO_FOLLOW, NULL, &vp)) != 0) 3264543Smarks return (error); 3274543Smarks 3284543Smarks /* Now make sure mntpnt and dataset are ZFS */ 3294543Smarks 3304543Smarks if (vp->v_vfsp->vfs_fstype != zfsfstype || 3314543Smarks (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), 3324543Smarks zc->zc_name) != 0)) { 3334543Smarks VN_RELE(vp); 3344543Smarks return (EPERM); 3354543Smarks } 3364543Smarks 3374543Smarks VN_RELE(vp); 3384543Smarks return (dsl_deleg_access(zc->zc_name, 3394543Smarks ZFS_DELEG_PERM_SHARE, cr)); 3404543Smarks } 3414543Smarks } 3424543Smarks 343789Sahrens static int 3444543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize) 345789Sahrens { 346789Sahrens char *cp; 347789Sahrens 348789Sahrens /* 349789Sahrens * Remove the @bla or /bla from the end of the name to get the parent. 350789Sahrens */ 3514543Smarks (void) strncpy(parent, datasetname, parentsize); 3524543Smarks cp = strrchr(parent, '@'); 353789Sahrens if (cp != NULL) { 354789Sahrens cp[0] = '\0'; 355789Sahrens } else { 3564543Smarks cp = strrchr(parent, '/'); 357789Sahrens if (cp == NULL) 358789Sahrens return (ENOENT); 359789Sahrens cp[0] = '\0'; 360789Sahrens } 361789Sahrens 3624543Smarks return (0); 3634543Smarks } 3644543Smarks 3654543Smarks int 3664543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 3674543Smarks { 3684543Smarks int error; 3694543Smarks 3704543Smarks if ((error = zfs_secpolicy_write_perms(name, 3714543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 3724543Smarks return (error); 3734543Smarks 3744543Smarks return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); 3754543Smarks } 3764543Smarks 3774543Smarks static int 3784543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) 3794543Smarks { 3804543Smarks return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); 3814543Smarks } 3824543Smarks 3834543Smarks /* 3844543Smarks * Must have sys_config privilege to check the iscsi permission 3854543Smarks */ 3864543Smarks /* ARGSUSED */ 3874543Smarks static int 3884543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) 3894543Smarks { 3904543Smarks return (secpolicy_zfs(cr)); 3914543Smarks } 3924543Smarks 3934543Smarks int 3944543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 3954543Smarks { 3964543Smarks char parentname[MAXNAMELEN]; 3974543Smarks int error; 3984543Smarks 3994543Smarks if ((error = zfs_secpolicy_write_perms(from, 4004543Smarks ZFS_DELEG_PERM_RENAME, cr)) != 0) 4014543Smarks return (error); 4024543Smarks 4034543Smarks if ((error = zfs_secpolicy_write_perms(from, 4044543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4054543Smarks return (error); 4064543Smarks 4074543Smarks if ((error = zfs_get_parent(to, parentname, 4084543Smarks sizeof (parentname))) != 0) 4094543Smarks return (error); 4104543Smarks 4114543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4124543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 4134543Smarks return (error); 4144543Smarks 4154543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4164543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4174543Smarks return (error); 4184543Smarks 4194543Smarks return (error); 4204543Smarks } 4214543Smarks 4224543Smarks static int 4234543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) 4244543Smarks { 4254543Smarks return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); 4264543Smarks } 4274543Smarks 4284543Smarks static int 4294543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) 4304543Smarks { 4314543Smarks char parentname[MAXNAMELEN]; 4324543Smarks objset_t *clone; 4334543Smarks int error; 4344543Smarks 4354543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4364543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4374543Smarks if (error) 4384543Smarks return (error); 4394543Smarks 4404543Smarks error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 4414543Smarks DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 4424543Smarks 4434543Smarks if (error == 0) { 4444543Smarks dsl_dataset_t *pclone = NULL; 4454543Smarks dsl_dir_t *dd; 4464543Smarks dd = clone->os->os_dsl_dataset->ds_dir; 4474543Smarks 4484543Smarks rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 4494543Smarks error = dsl_dataset_open_obj(dd->dd_pool, 4504543Smarks dd->dd_phys->dd_clone_parent_obj, NULL, 4514543Smarks DS_MODE_NONE, FTAG, &pclone); 4524543Smarks rw_exit(&dd->dd_pool->dp_config_rwlock); 4534543Smarks if (error) { 4544543Smarks dmu_objset_close(clone); 4554543Smarks return (error); 4564543Smarks } 4574543Smarks 4584543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4594543Smarks ZFS_DELEG_PERM_MOUNT, cr); 4604543Smarks 4614543Smarks dsl_dataset_name(pclone, parentname); 4624543Smarks dmu_objset_close(clone); 4634543Smarks dsl_dataset_close(pclone, DS_MODE_NONE, FTAG); 4644543Smarks if (error == 0) 4654543Smarks error = zfs_secpolicy_write_perms(parentname, 4664543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4674543Smarks } 4684543Smarks return (error); 4694543Smarks } 4704543Smarks 4714543Smarks static int 4724543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) 4734543Smarks { 4744543Smarks int error; 4754543Smarks 4764543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 4774543Smarks ZFS_DELEG_PERM_RECEIVE, cr)) != 0) 4784543Smarks return (error); 4794543Smarks 4804543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 4814543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4824543Smarks return (error); 4834543Smarks 4844543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 4854543Smarks ZFS_DELEG_PERM_CREATE, cr)); 4864543Smarks } 4874543Smarks 4884543Smarks int 4894543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 4904543Smarks { 4914543Smarks int error; 4924543Smarks 4934543Smarks if ((error = zfs_secpolicy_write_perms(name, 4944543Smarks ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) 4954543Smarks return (error); 4964543Smarks 4974543Smarks error = zfs_secpolicy_write_perms(name, 4984543Smarks ZFS_DELEG_PERM_MOUNT, cr); 4994543Smarks 5004543Smarks return (error); 5014543Smarks } 5024543Smarks 5034543Smarks static int 5044543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) 5054543Smarks { 5064543Smarks 5074543Smarks return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); 5084543Smarks } 5094543Smarks 5104543Smarks static int 5114543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) 5124543Smarks { 5134543Smarks char parentname[MAXNAMELEN]; 5144543Smarks int error; 5154543Smarks 5164543Smarks if ((error = zfs_get_parent(zc->zc_name, parentname, 5174543Smarks sizeof (parentname))) != 0) 5184543Smarks return (error); 5194543Smarks 5204543Smarks if (zc->zc_value[0] != '\0') { 5214543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_value, 5224543Smarks ZFS_DELEG_PERM_CLONE, cr)) != 0) 5234543Smarks return (error); 5244543Smarks } 5254543Smarks 5264543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 5274543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 5284543Smarks return (error); 5294543Smarks 5304543Smarks error = zfs_secpolicy_write_perms(parentname, 5314543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5324543Smarks 5334543Smarks return (error); 5344543Smarks } 5354543Smarks 5364543Smarks static int 5374543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) 5384543Smarks { 5394543Smarks int error; 5404543Smarks 5414543Smarks error = secpolicy_fs_unmount(cr, NULL); 5424543Smarks if (error) { 5434543Smarks error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); 5444543Smarks } 5454543Smarks return (error); 546789Sahrens } 547789Sahrens 548789Sahrens /* 549789Sahrens * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires 550789Sahrens * SYS_CONFIG privilege, which is not available in a local zone. 551789Sahrens */ 552789Sahrens /* ARGSUSED */ 553789Sahrens static int 5544543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) 555789Sahrens { 556789Sahrens if (secpolicy_sys_config(cr, B_FALSE) != 0) 557789Sahrens return (EPERM); 558789Sahrens 559789Sahrens return (0); 560789Sahrens } 561789Sahrens 562789Sahrens /* 5634543Smarks * Just like zfs_secpolicy_config, except that we will check for 5644543Smarks * mount permission on the dataset for permission to create/remove 5654543Smarks * the minor nodes. 5664543Smarks */ 5674543Smarks static int 5684543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) 5694543Smarks { 5704543Smarks if (secpolicy_sys_config(cr, B_FALSE) != 0) { 5714543Smarks return (dsl_deleg_access(zc->zc_name, 5724543Smarks ZFS_DELEG_PERM_MOUNT, cr)); 5734543Smarks } 5744543Smarks 5754543Smarks return (0); 5764543Smarks } 5774543Smarks 5784543Smarks /* 5791544Seschrock * Policy for fault injection. Requires all privileges. 5801544Seschrock */ 5811544Seschrock /* ARGSUSED */ 5821544Seschrock static int 5834543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) 5841544Seschrock { 5851544Seschrock return (secpolicy_zinject(cr)); 5861544Seschrock } 5871544Seschrock 5881544Seschrock /* 589789Sahrens * Returns the nvlist as specified by the user in the zfs_cmd_t. 590789Sahrens */ 591789Sahrens static int 5922676Seschrock get_nvlist(zfs_cmd_t *zc, nvlist_t **nvp) 593789Sahrens { 594789Sahrens char *packed; 595789Sahrens size_t size; 596789Sahrens int error; 597789Sahrens nvlist_t *config = NULL; 598789Sahrens 599789Sahrens /* 6002676Seschrock * Read in and unpack the user-supplied nvlist. 601789Sahrens */ 6022676Seschrock if ((size = zc->zc_nvlist_src_size) == 0) 603789Sahrens return (EINVAL); 604789Sahrens 605789Sahrens packed = kmem_alloc(size, KM_SLEEP); 606789Sahrens 6072676Seschrock if ((error = xcopyin((void *)(uintptr_t)zc->zc_nvlist_src, packed, 608789Sahrens size)) != 0) { 609789Sahrens kmem_free(packed, size); 610789Sahrens return (error); 611789Sahrens } 612789Sahrens 613789Sahrens if ((error = nvlist_unpack(packed, size, &config, 0)) != 0) { 614789Sahrens kmem_free(packed, size); 615789Sahrens return (error); 616789Sahrens } 617789Sahrens 618789Sahrens kmem_free(packed, size); 619789Sahrens 620789Sahrens *nvp = config; 621789Sahrens return (0); 622789Sahrens } 623789Sahrens 624789Sahrens static int 6252676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 6262676Seschrock { 6272676Seschrock char *packed = NULL; 6282676Seschrock size_t size; 6292676Seschrock int error; 6302676Seschrock 6312676Seschrock VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 6322676Seschrock 6332676Seschrock if (size > zc->zc_nvlist_dst_size) { 6342676Seschrock error = ENOMEM; 6352676Seschrock } else { 6364611Smarks packed = kmem_alloc(size, KM_SLEEP); 6372676Seschrock VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 6382676Seschrock KM_SLEEP) == 0); 6392676Seschrock error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 6402676Seschrock size); 6412676Seschrock kmem_free(packed, size); 6422676Seschrock } 6432676Seschrock 6442676Seschrock zc->zc_nvlist_dst_size = size; 6452676Seschrock return (error); 6462676Seschrock } 6472676Seschrock 6482676Seschrock static int 649789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc) 650789Sahrens { 651789Sahrens int error; 652789Sahrens nvlist_t *config; 653789Sahrens 6542676Seschrock if ((error = get_nvlist(zc, &config)) != 0) 655789Sahrens return (error); 656789Sahrens 6572676Seschrock error = spa_create(zc->zc_name, config, zc->zc_value[0] == '\0' ? 6582676Seschrock NULL : zc->zc_value); 659789Sahrens 660789Sahrens nvlist_free(config); 661789Sahrens 662789Sahrens return (error); 663789Sahrens } 664789Sahrens 665789Sahrens static int 666789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc) 667789Sahrens { 6684543Smarks int error; 6694543Smarks zfs_log_history(zc); 6704543Smarks error = spa_destroy(zc->zc_name); 6714543Smarks return (error); 672789Sahrens } 673789Sahrens 674789Sahrens static int 675789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc) 676789Sahrens { 677789Sahrens int error; 678789Sahrens nvlist_t *config; 679789Sahrens uint64_t guid; 680789Sahrens 6812676Seschrock if ((error = get_nvlist(zc, &config)) != 0) 682789Sahrens return (error); 683789Sahrens 684789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 6851544Seschrock guid != zc->zc_guid) 686789Sahrens error = EINVAL; 687789Sahrens else 688789Sahrens error = spa_import(zc->zc_name, config, 6892676Seschrock zc->zc_value[0] == '\0' ? NULL : zc->zc_value); 690789Sahrens 691789Sahrens nvlist_free(config); 692789Sahrens 693789Sahrens return (error); 694789Sahrens } 695789Sahrens 696789Sahrens static int 697789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc) 698789Sahrens { 6994543Smarks int error; 7004543Smarks zfs_log_history(zc); 7014543Smarks error = spa_export(zc->zc_name, NULL); 7024543Smarks return (error); 703789Sahrens } 704789Sahrens 705789Sahrens static int 706789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc) 707789Sahrens { 708789Sahrens nvlist_t *configs; 709789Sahrens int error; 710789Sahrens 711789Sahrens if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 712789Sahrens return (EEXIST); 713789Sahrens 7142676Seschrock error = put_nvlist(zc, configs); 715789Sahrens 716789Sahrens nvlist_free(configs); 717789Sahrens 718789Sahrens return (error); 719789Sahrens } 720789Sahrens 721789Sahrens static int 722789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc) 723789Sahrens { 724789Sahrens nvlist_t *config; 725789Sahrens int error; 7261544Seschrock int ret = 0; 727789Sahrens 7282676Seschrock error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 7292676Seschrock sizeof (zc->zc_value)); 730789Sahrens 731789Sahrens if (config != NULL) { 7322676Seschrock ret = put_nvlist(zc, config); 733789Sahrens nvlist_free(config); 7341544Seschrock 7351544Seschrock /* 7361544Seschrock * The config may be present even if 'error' is non-zero. 7371544Seschrock * In this case we return success, and preserve the real errno 7381544Seschrock * in 'zc_cookie'. 7391544Seschrock */ 7401544Seschrock zc->zc_cookie = error; 741789Sahrens } else { 7421544Seschrock ret = error; 743789Sahrens } 744789Sahrens 7451544Seschrock return (ret); 746789Sahrens } 747789Sahrens 748789Sahrens /* 749789Sahrens * Try to import the given pool, returning pool stats as appropriate so that 750789Sahrens * user land knows which devices are available and overall pool health. 751789Sahrens */ 752789Sahrens static int 753789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 754789Sahrens { 755789Sahrens nvlist_t *tryconfig, *config; 756789Sahrens int error; 757789Sahrens 7582676Seschrock if ((error = get_nvlist(zc, &tryconfig)) != 0) 759789Sahrens return (error); 760789Sahrens 761789Sahrens config = spa_tryimport(tryconfig); 762789Sahrens 763789Sahrens nvlist_free(tryconfig); 764789Sahrens 765789Sahrens if (config == NULL) 766789Sahrens return (EINVAL); 767789Sahrens 7682676Seschrock error = put_nvlist(zc, config); 769789Sahrens nvlist_free(config); 770789Sahrens 771789Sahrens return (error); 772789Sahrens } 773789Sahrens 774789Sahrens static int 775789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc) 776789Sahrens { 777789Sahrens spa_t *spa; 778789Sahrens int error; 779789Sahrens 7802926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 7812926Sek110237 return (error); 7822926Sek110237 7834451Seschrock spa_config_enter(spa, RW_READER, FTAG); 7842926Sek110237 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); 7854451Seschrock spa_config_exit(spa, FTAG); 7862926Sek110237 7872926Sek110237 spa_close(spa, FTAG); 7882926Sek110237 789789Sahrens return (error); 790789Sahrens } 791789Sahrens 792789Sahrens static int 793789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 794789Sahrens { 795789Sahrens spa_t *spa; 796789Sahrens int error; 797789Sahrens 798789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 799789Sahrens if (error == 0) { 800789Sahrens spa_freeze(spa); 801789Sahrens spa_close(spa, FTAG); 802789Sahrens } 803789Sahrens return (error); 804789Sahrens } 805789Sahrens 806789Sahrens static int 8071760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 8081760Seschrock { 8091760Seschrock spa_t *spa; 8101760Seschrock int error; 8111760Seschrock 8122926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8132926Sek110237 return (error); 8142926Sek110237 8152926Sek110237 spa_upgrade(spa); 8162926Sek110237 spa_close(spa, FTAG); 8172926Sek110237 8182926Sek110237 return (error); 8192926Sek110237 } 8202926Sek110237 8212926Sek110237 static int 8222926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 8232926Sek110237 { 8242926Sek110237 spa_t *spa; 8252926Sek110237 char *hist_buf; 8262926Sek110237 uint64_t size; 8272926Sek110237 int error; 8282926Sek110237 8292926Sek110237 if ((size = zc->zc_history_len) == 0) 8302926Sek110237 return (EINVAL); 8312926Sek110237 8322926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8332926Sek110237 return (error); 8342926Sek110237 8354577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 8363863Sek110237 spa_close(spa, FTAG); 8373863Sek110237 return (ENOTSUP); 8383863Sek110237 } 8393863Sek110237 8402926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 8412926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 8422926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 8434543Smarks error = xcopyout(hist_buf, 8444543Smarks (char *)(uintptr_t)zc->zc_history, 8452926Sek110237 zc->zc_history_len); 8462926Sek110237 } 8472926Sek110237 8482926Sek110237 spa_close(spa, FTAG); 8492926Sek110237 kmem_free(hist_buf, size); 8502926Sek110237 return (error); 8512926Sek110237 } 8522926Sek110237 8532926Sek110237 static int 8543444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 8553444Sek110237 { 8563444Sek110237 int error; 8573444Sek110237 8583912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 8593444Sek110237 return (error); 8603444Sek110237 8613444Sek110237 return (0); 8623444Sek110237 } 8633444Sek110237 8643444Sek110237 static int 8653444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 8663444Sek110237 { 8673444Sek110237 objset_t *osp; 8683444Sek110237 int error; 8693444Sek110237 8703444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 8713444Sek110237 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) 8723444Sek110237 return (error); 8733444Sek110237 8743444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 8753444Sek110237 sizeof (zc->zc_value)); 8763444Sek110237 dmu_objset_close(osp); 8773444Sek110237 8783444Sek110237 return (error); 8793444Sek110237 } 8803444Sek110237 8813444Sek110237 static int 882789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 883789Sahrens { 884789Sahrens spa_t *spa; 885789Sahrens int error; 886789Sahrens nvlist_t *config; 887789Sahrens 888789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 889789Sahrens if (error != 0) 890789Sahrens return (error); 891789Sahrens 8923912Slling /* 8933912Slling * A root pool with concatenated devices is not supported. 8943912Slling * Thus, can not add a device to a root pool with one device. 8953912Slling */ 8963912Slling if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0) { 8973912Slling spa_close(spa, FTAG); 8983912Slling return (EDOM); 8993912Slling } 9003912Slling 9012676Seschrock if ((error = get_nvlist(zc, &config)) == 0) { 902789Sahrens error = spa_vdev_add(spa, config); 903789Sahrens nvlist_free(config); 904789Sahrens } 905789Sahrens spa_close(spa, FTAG); 906789Sahrens return (error); 907789Sahrens } 908789Sahrens 909789Sahrens static int 910789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 911789Sahrens { 9122082Seschrock spa_t *spa; 9132082Seschrock int error; 9142082Seschrock 9152082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 9162082Seschrock if (error != 0) 9172082Seschrock return (error); 9182082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 9192082Seschrock spa_close(spa, FTAG); 9202082Seschrock return (error); 921789Sahrens } 922789Sahrens 923789Sahrens static int 9244451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 925789Sahrens { 926789Sahrens spa_t *spa; 927789Sahrens int error; 9284451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 929789Sahrens 9302926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 931789Sahrens return (error); 9324451Seschrock switch (zc->zc_cookie) { 9334451Seschrock case VDEV_STATE_ONLINE: 9344451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 9354451Seschrock break; 9364451Seschrock 9374451Seschrock case VDEV_STATE_OFFLINE: 9384451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 9394451Seschrock break; 940789Sahrens 9414451Seschrock case VDEV_STATE_FAULTED: 9424451Seschrock error = vdev_fault(spa, zc->zc_guid); 9434451Seschrock break; 944789Sahrens 9454451Seschrock case VDEV_STATE_DEGRADED: 9464451Seschrock error = vdev_degrade(spa, zc->zc_guid); 9474451Seschrock break; 9484451Seschrock 9494451Seschrock default: 9504451Seschrock error = EINVAL; 9514451Seschrock } 9524451Seschrock zc->zc_cookie = newstate; 953789Sahrens spa_close(spa, FTAG); 954789Sahrens return (error); 955789Sahrens } 956789Sahrens 957789Sahrens static int 958789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 959789Sahrens { 960789Sahrens spa_t *spa; 961789Sahrens int replacing = zc->zc_cookie; 962789Sahrens nvlist_t *config; 963789Sahrens int error; 964789Sahrens 9652926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 966789Sahrens return (error); 967789Sahrens 9682676Seschrock if ((error = get_nvlist(zc, &config)) == 0) { 9691544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 970789Sahrens nvlist_free(config); 971789Sahrens } 972789Sahrens 973789Sahrens spa_close(spa, FTAG); 974789Sahrens return (error); 975789Sahrens } 976789Sahrens 977789Sahrens static int 978789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 979789Sahrens { 980789Sahrens spa_t *spa; 981789Sahrens int error; 982789Sahrens 9832926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 984789Sahrens return (error); 985789Sahrens 9861544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 987789Sahrens 988789Sahrens spa_close(spa, FTAG); 989789Sahrens return (error); 990789Sahrens } 991789Sahrens 992789Sahrens static int 9931354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 9941354Seschrock { 9951354Seschrock spa_t *spa; 9962676Seschrock char *path = zc->zc_value; 9971544Seschrock uint64_t guid = zc->zc_guid; 9981354Seschrock int error; 9991354Seschrock 10001354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10011354Seschrock if (error != 0) 10021354Seschrock return (error); 10031354Seschrock 10041354Seschrock error = spa_vdev_setpath(spa, guid, path); 10051354Seschrock spa_close(spa, FTAG); 10061354Seschrock return (error); 10071354Seschrock } 10081354Seschrock 10091354Seschrock static int 1010789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1011789Sahrens { 1012789Sahrens objset_t *os = NULL; 1013789Sahrens int error; 10141356Seschrock nvlist_t *nv; 1015789Sahrens 1016789Sahrens retry: 1017789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1018789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1019789Sahrens if (error != 0) { 1020789Sahrens /* 1021789Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1022789Sahrens * the objset is held exclusively. Fortunately this hold is 1023789Sahrens * only for a short while, so we retry here. 1024789Sahrens * This avoids user code having to handle EBUSY, 1025789Sahrens * for example for a "zfs list". 1026789Sahrens */ 1027789Sahrens if (error == EBUSY) { 1028789Sahrens delay(1); 1029789Sahrens goto retry; 1030789Sahrens } 1031789Sahrens return (error); 1032789Sahrens } 1033789Sahrens 10342885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1035789Sahrens 10362856Snd150628 if (zc->zc_nvlist_dst != 0 && 10371356Seschrock (error = dsl_prop_get_all(os, &nv)) == 0) { 10382885Sahrens dmu_objset_stats(os, nv); 10393087Sahrens /* 10404577Sahrens * NB: {zpl,zvol}_get_stats() will read the objset contents, 10413087Sahrens * which we aren't supposed to do with a 10423087Sahrens * DS_MODE_STANDARD open, because it could be 10433087Sahrens * inconsistent. So this is a bit of a workaround... 10443087Sahrens */ 10454577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 10464577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 10474577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 10484577Sahrens else if (dmu_objset_type(os) == DMU_OST_ZFS) 10494577Sahrens (void) zfs_get_stats(os, nv); 10504577Sahrens } 10512676Seschrock error = put_nvlist(zc, nv); 10521356Seschrock nvlist_free(nv); 10531356Seschrock } 1054789Sahrens 10552676Seschrock spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value)); 10561544Seschrock 1057789Sahrens dmu_objset_close(os); 1058789Sahrens return (error); 1059789Sahrens } 1060789Sahrens 1061789Sahrens static int 1062789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1063789Sahrens { 1064885Sahrens objset_t *os; 1065789Sahrens int error; 1066789Sahrens char *p; 1067789Sahrens 1068885Sahrens retry: 1069885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1070885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1071885Sahrens if (error != 0) { 1072885Sahrens /* 1073885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1074885Sahrens * the objset is held exclusively. Fortunately this hold is 1075885Sahrens * only for a short while, so we retry here. 1076885Sahrens * This avoids user code having to handle EBUSY, 1077885Sahrens * for example for a "zfs list". 1078885Sahrens */ 1079885Sahrens if (error == EBUSY) { 1080885Sahrens delay(1); 1081885Sahrens goto retry; 1082885Sahrens } 1083885Sahrens if (error == ENOENT) 1084885Sahrens error = ESRCH; 1085885Sahrens return (error); 1086789Sahrens } 1087789Sahrens 1088789Sahrens p = strrchr(zc->zc_name, '/'); 1089789Sahrens if (p == NULL || p[1] != '\0') 1090789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1091789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1092789Sahrens 1093789Sahrens do { 1094885Sahrens error = dmu_dir_list_next(os, 1095885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1096885Sahrens NULL, &zc->zc_cookie); 1097789Sahrens if (error == ENOENT) 1098789Sahrens error = ESRCH; 1099885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1100789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 1101789Sahrens 1102885Sahrens /* 1103885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1104885Sahrens * try to get stats for it. Userland will skip over it. 1105885Sahrens */ 1106885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1107885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1108789Sahrens 1109885Sahrens dmu_objset_close(os); 1110789Sahrens return (error); 1111789Sahrens } 1112789Sahrens 1113789Sahrens static int 1114789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1115789Sahrens { 1116885Sahrens objset_t *os; 1117789Sahrens int error; 1118789Sahrens 1119789Sahrens retry: 1120885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1121885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1122885Sahrens if (error != 0) { 1123789Sahrens /* 1124885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1125789Sahrens * the objset is held exclusively. Fortunately this hold is 1126789Sahrens * only for a short while, so we retry here. 1127789Sahrens * This avoids user code having to handle EBUSY, 1128885Sahrens * for example for a "zfs list". 1129789Sahrens */ 1130789Sahrens if (error == EBUSY) { 1131789Sahrens delay(1); 1132789Sahrens goto retry; 1133789Sahrens } 1134789Sahrens if (error == ENOENT) 1135885Sahrens error = ESRCH; 1136789Sahrens return (error); 1137789Sahrens } 1138789Sahrens 11391003Slling /* 11401003Slling * A dataset name of maximum length cannot have any snapshots, 11411003Slling * so exit immediately. 11421003Slling */ 11431003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1144885Sahrens dmu_objset_close(os); 11451003Slling return (ESRCH); 1146789Sahrens } 1147789Sahrens 1148885Sahrens error = dmu_snapshot_list_next(os, 1149885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 1150885Sahrens zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie); 1151789Sahrens if (error == ENOENT) 1152789Sahrens error = ESRCH; 1153789Sahrens 1154885Sahrens if (error == 0) 1155885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1156789Sahrens 1157885Sahrens dmu_objset_close(os); 1158789Sahrens return (error); 1159789Sahrens } 1160789Sahrens 1161789Sahrens static int 11622676Seschrock zfs_set_prop_nvlist(const char *name, dev_t dev, cred_t *cr, nvlist_t *nvl) 1163789Sahrens { 11642676Seschrock nvpair_t *elem; 11652676Seschrock int error; 11662676Seschrock uint64_t intval; 11672676Seschrock char *strval; 11682676Seschrock 11694543Smarks /* 11704543Smarks * First validate permission to set all of the properties 11714543Smarks */ 11722676Seschrock elem = NULL; 11732676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 1174*4670Sahrens const char *propname = nvpair_name(elem); 1175*4670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 11762676Seschrock 1177*4670Sahrens if (prop == ZFS_PROP_INVAL) { 11782676Seschrock /* 11792676Seschrock * If this is a user-defined property, it must be a 11802676Seschrock * string, and there is no further validation to do. 11812676Seschrock */ 11822676Seschrock if (!zfs_prop_user(propname) || 11832676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 11842676Seschrock return (EINVAL); 11852676Seschrock 11864543Smarks error = zfs_secpolicy_write_perms(name, 11874543Smarks ZFS_DELEG_PERM_USERPROP, cr); 1188*4670Sahrens if (error) 1189*4670Sahrens return (error); 11904543Smarks continue; 11912676Seschrock } 11922676Seschrock 1193*4670Sahrens if ((error = zfs_secpolicy_setprop(name, prop, cr)) != 0) 1194*4670Sahrens return (error); 11952676Seschrock 1196*4670Sahrens /* 1197*4670Sahrens * Check that this value is valid for this pool version 1198*4670Sahrens */ 1199*4670Sahrens switch (prop) { 12003886Sahl case ZFS_PROP_COMPRESSION: 12013886Sahl /* 12023886Sahl * If the user specified gzip compression, make sure 12033886Sahl * the SPA supports it. We ignore any errors here since 12043886Sahl * we'll catch them later. 12053886Sahl */ 12063886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 12073886Sahl nvpair_value_uint64(elem, &intval) == 0 && 12083886Sahl intval >= ZIO_COMPRESS_GZIP_1 && 12093886Sahl intval <= ZIO_COMPRESS_GZIP_9) { 12104543Smarks spa_t *spa; 12114543Smarks 12124603Sahrens if (spa_open(name, &spa, FTAG) == 0) { 12133886Sahl if (spa_version(spa) < 12144577Sahrens SPA_VERSION_GZIP_COMPRESSION) { 12153886Sahl spa_close(spa, FTAG); 12163886Sahl return (ENOTSUP); 12173886Sahl } 12183886Sahl 12193886Sahl spa_close(spa, FTAG); 12203886Sahl } 12213886Sahl } 12223886Sahl break; 12234603Sahrens 12244603Sahrens case ZFS_PROP_COPIES: 12254603Sahrens { 12264603Sahrens spa_t *spa; 12274603Sahrens 12284603Sahrens if (spa_open(name, &spa, FTAG) == 0) { 12294603Sahrens if (spa_version(spa) < 12304603Sahrens SPA_VERSION_DITTO_BLOCKS) { 12314603Sahrens spa_close(spa, FTAG); 12324603Sahrens return (ENOTSUP); 12334603Sahrens } 12344603Sahrens spa_close(spa, FTAG); 12354603Sahrens } 12364603Sahrens break; 12374603Sahrens } 12382676Seschrock } 12394543Smarks } 12404543Smarks 12414543Smarks elem = NULL; 12424543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 1243*4670Sahrens const char *propname = nvpair_name(elem); 1244*4670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 12454543Smarks 1246*4670Sahrens if (prop == ZFS_PROP_INVAL) { 12474543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 12484543Smarks error = dsl_prop_set(name, propname, 1, 12494543Smarks strlen(strval) + 1, strval); 12504543Smarks if (error == 0) 12514543Smarks continue; 12524543Smarks else 12534543Smarks return (error); 12544543Smarks } 12552676Seschrock 12562676Seschrock switch (prop) { 12572676Seschrock case ZFS_PROP_QUOTA: 12582676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 12594577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 12602676Seschrock return (error); 12612676Seschrock break; 12622676Seschrock 12632676Seschrock case ZFS_PROP_RESERVATION: 12642676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 12652676Seschrock (error = dsl_dir_set_reservation(name, 12662676Seschrock intval)) != 0) 12672676Seschrock return (error); 12682676Seschrock break; 1269789Sahrens 12702676Seschrock case ZFS_PROP_VOLSIZE: 12712676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 12724577Sahrens (error = zvol_set_volsize(name, dev, intval)) != 0) 12732676Seschrock return (error); 12742676Seschrock break; 12752676Seschrock 12762676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 12772676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 12784577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 12794577Sahrens return (error); 12804577Sahrens break; 12814577Sahrens 12824577Sahrens case ZFS_PROP_VERSION: 12834577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 12844577Sahrens (error = zfs_set_version(name, intval)) != 0) 12852676Seschrock return (error); 12862676Seschrock break; 12872676Seschrock 12882676Seschrock default: 12892676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 12902676Seschrock if (zfs_prop_get_type(prop) != 12912676Seschrock prop_type_string) 12922676Seschrock return (EINVAL); 12932717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 12942717Seschrock if ((error = dsl_prop_set(name, 12952676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 12962717Seschrock strval)) != 0) 12972717Seschrock return (error); 12982676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 12992885Sahrens const char *unused; 13002885Sahrens 13012717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 13022676Seschrock 13032676Seschrock switch (zfs_prop_get_type(prop)) { 13042676Seschrock case prop_type_number: 13052676Seschrock break; 13062676Seschrock case prop_type_boolean: 13072676Seschrock if (intval > 1) 13082717Seschrock return (EINVAL); 13092676Seschrock break; 13102676Seschrock case prop_type_string: 13112717Seschrock return (EINVAL); 13122676Seschrock case prop_type_index: 13132717Seschrock if (zfs_prop_index_to_string(prop, 13142717Seschrock intval, &unused) != 0) 13152717Seschrock return (EINVAL); 13162676Seschrock break; 13172676Seschrock default: 13184577Sahrens cmn_err(CE_PANIC, 13194577Sahrens "unknown property type"); 13202676Seschrock break; 13212676Seschrock } 13222676Seschrock 13232717Seschrock if ((error = dsl_prop_set(name, propname, 13242717Seschrock 8, 1, &intval)) != 0) 13252717Seschrock return (error); 13262676Seschrock } else { 13272676Seschrock return (EINVAL); 13282676Seschrock } 13292676Seschrock break; 13302676Seschrock } 13312676Seschrock } 13322676Seschrock 13332676Seschrock return (0); 1334789Sahrens } 1335789Sahrens 1336789Sahrens static int 13372676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1338789Sahrens { 13392676Seschrock nvlist_t *nvl; 13402676Seschrock int error; 1341789Sahrens 13422676Seschrock /* 13432676Seschrock * If zc_value is set, then this is an attempt to inherit a value. 13442676Seschrock * Otherwise, zc_nvlist refers to a list of properties to set. 13452676Seschrock */ 13462676Seschrock if (zc->zc_value[0] != '\0') { 1347*4670Sahrens zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); 1348*4670Sahrens 1349*4670Sahrens if (prop == ZFS_PROP_INVAL) { 1350*4670Sahrens if (!zfs_prop_user(zc->zc_value)) 1351*4670Sahrens return (EINVAL); 1352*4670Sahrens error = zfs_secpolicy_write_perms(zc->zc_name, 1353*4670Sahrens ZFS_DELEG_PERM_USERPROP, 1354*4670Sahrens (cred_t *)(uintptr_t)zc->zc_cred); 1355*4670Sahrens } else { 1356*4670Sahrens if (!zfs_prop_inheritable(prop)) 1357*4670Sahrens return (EINVAL); 1358*4670Sahrens error = zfs_secpolicy_setprop(zc->zc_name, 1359*4670Sahrens prop, (cred_t *)(uintptr_t)zc->zc_cred); 1360*4670Sahrens } 1361*4670Sahrens if (error) 1362*4670Sahrens return (error); 13632676Seschrock 13642676Seschrock return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 13652676Seschrock } 13662676Seschrock 13672676Seschrock if ((error = get_nvlist(zc, &nvl)) != 0) 13682676Seschrock return (error); 13692676Seschrock 13702676Seschrock error = zfs_set_prop_nvlist(zc->zc_name, zc->zc_dev, 13712676Seschrock (cred_t *)(uintptr_t)zc->zc_cred, nvl); 13724543Smarks 13732676Seschrock nvlist_free(nvl); 13742676Seschrock return (error); 1375789Sahrens } 1376789Sahrens 1377789Sahrens static int 13784098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 13793912Slling { 13803912Slling nvlist_t *nvl; 13813912Slling int error, reset_bootfs = 0; 13823912Slling uint64_t objnum; 13834543Smarks uint64_t intval; 13843912Slling zpool_prop_t prop; 13853912Slling nvpair_t *elem; 13863912Slling char *propname, *strval; 13873912Slling spa_t *spa; 13883912Slling vdev_t *rvdev; 13893912Slling char *vdev_type; 13903912Slling objset_t *os; 13913912Slling 13923912Slling if ((error = get_nvlist(zc, &nvl)) != 0) 13933912Slling return (error); 13943912Slling 13953912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 13963912Slling nvlist_free(nvl); 13973912Slling return (error); 13983912Slling } 13993912Slling 14004577Sahrens if (spa_version(spa) < SPA_VERSION_BOOTFS) { 14013912Slling nvlist_free(nvl); 14023912Slling spa_close(spa, FTAG); 14033912Slling return (ENOTSUP); 14043912Slling } 14053912Slling 14063912Slling elem = NULL; 14073912Slling while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 14083912Slling 14093912Slling propname = nvpair_name(elem); 14103912Slling 14113912Slling if ((prop = zpool_name_to_prop(propname)) == 14123912Slling ZFS_PROP_INVAL) { 14133912Slling nvlist_free(nvl); 14143912Slling spa_close(spa, FTAG); 14153912Slling return (EINVAL); 14163912Slling } 14173912Slling 14183912Slling switch (prop) { 14194543Smarks case ZPOOL_PROP_DELEGATION: 14204543Smarks VERIFY(nvpair_value_uint64(elem, &intval) == 0); 14214543Smarks if (intval > 1) 14224543Smarks error = EINVAL; 14234543Smarks break; 14244451Seschrock case ZPOOL_PROP_BOOTFS: 14253912Slling /* 14263912Slling * A bootable filesystem can not be on a RAIDZ pool 14273912Slling * nor a striped pool with more than 1 device. 14283912Slling */ 14293912Slling rvdev = spa->spa_root_vdev; 14303912Slling vdev_type = 14313912Slling rvdev->vdev_child[0]->vdev_ops->vdev_op_type; 14323912Slling if (strcmp(vdev_type, VDEV_TYPE_RAIDZ) == 0 || 14333912Slling (strcmp(vdev_type, VDEV_TYPE_MIRROR) != 0 && 14343912Slling rvdev->vdev_children > 1)) { 14353912Slling error = ENOTSUP; 14363912Slling break; 14373912Slling } 14383912Slling 14393912Slling reset_bootfs = 1; 14403912Slling 14413912Slling VERIFY(nvpair_value_string(elem, &strval) == 0); 14423912Slling if (strval == NULL || strval[0] == '\0') { 14434451Seschrock objnum = zpool_prop_default_numeric( 14444451Seschrock ZPOOL_PROP_BOOTFS); 14453912Slling break; 14463912Slling } 14473912Slling 14483912Slling if (error = dmu_objset_open(strval, DMU_OST_ZFS, 14493912Slling DS_MODE_STANDARD | DS_MODE_READONLY, &os)) 14503912Slling break; 14513912Slling objnum = dmu_objset_id(os); 14523912Slling dmu_objset_close(os); 14533912Slling break; 14543912Slling } 14553912Slling 14563912Slling if (error) 14573912Slling break; 14583912Slling } 14593912Slling if (error == 0) { 14603912Slling if (reset_bootfs) { 14613912Slling VERIFY(nvlist_remove(nvl, 14624451Seschrock zpool_prop_to_name(ZPOOL_PROP_BOOTFS), 14633912Slling DATA_TYPE_STRING) == 0); 14643912Slling VERIFY(nvlist_add_uint64(nvl, 14654451Seschrock zpool_prop_to_name(ZPOOL_PROP_BOOTFS), 14664451Seschrock objnum) == 0); 14673912Slling } 14683912Slling error = spa_set_props(spa, nvl); 14693912Slling } 14703912Slling 14713912Slling nvlist_free(nvl); 14723912Slling spa_close(spa, FTAG); 14733912Slling 14743912Slling return (error); 14753912Slling } 14763912Slling 14773912Slling static int 14784098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 14793912Slling { 14803912Slling spa_t *spa; 14813912Slling int error; 14823912Slling nvlist_t *nvp = NULL; 14833912Slling 14843912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 14853912Slling return (error); 14863912Slling 14873912Slling error = spa_get_props(spa, &nvp); 14883912Slling 14893912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 14903912Slling error = put_nvlist(zc, nvp); 14913912Slling else 14923912Slling error = EFAULT; 14933912Slling 14943912Slling spa_close(spa, FTAG); 14953912Slling 14963912Slling if (nvp) 14973912Slling nvlist_free(nvp); 14983912Slling return (error); 14993912Slling } 15003912Slling 15013912Slling static int 15024543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 15034543Smarks { 15044543Smarks nvlist_t *nvp; 15054543Smarks int error; 15064543Smarks uint32_t uid; 15074543Smarks uint32_t gid; 15084543Smarks uint32_t *groups; 15094543Smarks uint_t group_cnt; 15104543Smarks cred_t *usercred; 15114543Smarks 15124543Smarks if ((error = get_nvlist(zc, &nvp)) != 0) { 15134543Smarks return (error); 15144543Smarks } 15154543Smarks 15164543Smarks if ((error = nvlist_lookup_uint32(nvp, 15174543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 15184543Smarks nvlist_free(nvp); 15194543Smarks return (EPERM); 15204543Smarks } 15214543Smarks 15224543Smarks if ((error = nvlist_lookup_uint32(nvp, 15234543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 15244543Smarks nvlist_free(nvp); 15254543Smarks return (EPERM); 15264543Smarks } 15274543Smarks 15284543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 15294543Smarks &groups, &group_cnt)) != 0) { 15304543Smarks nvlist_free(nvp); 15314543Smarks return (EPERM); 15324543Smarks } 15334543Smarks usercred = cralloc(); 15344543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 15354543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 15364543Smarks nvlist_free(nvp); 15374543Smarks crfree(usercred); 15384543Smarks return (EPERM); 15394543Smarks } 15404543Smarks nvlist_free(nvp); 15414543Smarks error = dsl_deleg_access(zc->zc_name, 15424543Smarks ZFS_DELEG_PERM_SHAREISCSI, usercred); 15434543Smarks crfree(usercred); 15444543Smarks return (error); 15454543Smarks } 15464543Smarks 15474543Smarks static int 15484543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 15494543Smarks { 15504543Smarks int error; 15514543Smarks nvlist_t *fsaclnv = NULL; 15524543Smarks cred_t *cr; 15534543Smarks 15544543Smarks if ((error = get_nvlist(zc, &fsaclnv)) != 0) 15554543Smarks return (error); 15564543Smarks 15574543Smarks /* 15584543Smarks * Verify nvlist is constructed correctly 15594543Smarks */ 15604543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 15614543Smarks nvlist_free(fsaclnv); 15624543Smarks return (EINVAL); 15634543Smarks } 15644543Smarks 15654543Smarks /* 15664543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 15674543Smarks * that user is allowed to hand out each permission in 15684543Smarks * the nvlist(s) 15694543Smarks */ 15704543Smarks 15714543Smarks cr = (cred_t *)(uintptr_t)zc->zc_cred; 15724543Smarks error = secpolicy_zfs(cr); 15734543Smarks if (error) { 15744543Smarks if (zc->zc_perm_action == B_FALSE) 15754543Smarks error = dsl_deleg_can_allow(zc->zc_name, fsaclnv, cr); 15764543Smarks else 15774543Smarks error = dsl_deleg_can_unallow(zc->zc_name, fsaclnv, cr); 15784543Smarks } 15794543Smarks 15804543Smarks if (error == 0) 15814543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 15824543Smarks 15834543Smarks nvlist_free(fsaclnv); 15844543Smarks return (error); 15854543Smarks } 15864543Smarks 15874543Smarks static int 15884543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 15894543Smarks { 15904543Smarks nvlist_t *nvp; 15914543Smarks int error; 15924543Smarks 15934543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 15944543Smarks error = put_nvlist(zc, nvp); 15954543Smarks nvlist_free(nvp); 15964543Smarks } 15974543Smarks 15984543Smarks return (error); 15994543Smarks } 16004543Smarks 16014543Smarks static int 1602789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1603789Sahrens { 16042676Seschrock return (zvol_create_minor(zc->zc_name, zc->zc_dev)); 1605789Sahrens } 1606789Sahrens 1607789Sahrens static int 1608789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1609789Sahrens { 16102676Seschrock return (zvol_remove_minor(zc->zc_name)); 1611789Sahrens } 1612789Sahrens 1613789Sahrens /* 1614789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1615789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1616789Sahrens * is responsible for releasing the returned vfs pointer. 1617789Sahrens */ 1618789Sahrens static vfs_t * 1619789Sahrens zfs_get_vfs(const char *resource) 1620789Sahrens { 1621789Sahrens struct vfs *vfsp; 1622789Sahrens struct vfs *vfs_found = NULL; 1623789Sahrens 1624789Sahrens vfs_list_read_lock(); 1625789Sahrens vfsp = rootvfs; 1626789Sahrens do { 1627789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1628789Sahrens VFS_HOLD(vfsp); 1629789Sahrens vfs_found = vfsp; 1630789Sahrens break; 1631789Sahrens } 1632789Sahrens vfsp = vfsp->vfs_next; 1633789Sahrens } while (vfsp != rootvfs); 1634789Sahrens vfs_list_unlock(); 1635789Sahrens return (vfs_found); 1636789Sahrens } 1637789Sahrens 16384543Smarks /* ARGSUSED */ 1639789Sahrens static void 16404543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1641789Sahrens { 16424577Sahrens nvlist_t *nvprops = arg; 16434577Sahrens uint64_t version = ZPL_VERSION; 16444577Sahrens 16454577Sahrens (void) nvlist_lookup_uint64(nvprops, 16464577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version); 16474577Sahrens 16484577Sahrens zfs_create_fs(os, cr, version, tx); 1649789Sahrens } 1650789Sahrens 1651789Sahrens static int 1652789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1653789Sahrens { 1654789Sahrens objset_t *clone; 1655789Sahrens int error = 0; 16564543Smarks nvlist_t *nvprops = NULL; 16574543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1658789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1659789Sahrens 1660789Sahrens switch (type) { 1661789Sahrens 1662789Sahrens case DMU_OST_ZFS: 1663789Sahrens cbfunc = zfs_create_cb; 1664789Sahrens break; 1665789Sahrens 1666789Sahrens case DMU_OST_ZVOL: 1667789Sahrens cbfunc = zvol_create_cb; 1668789Sahrens break; 1669789Sahrens 1670789Sahrens default: 16712199Sahrens cbfunc = NULL; 16722199Sahrens } 16732199Sahrens if (strchr(zc->zc_name, '@')) 1674789Sahrens return (EINVAL); 1675789Sahrens 16762676Seschrock if (zc->zc_nvlist_src != NULL && 16774543Smarks (error = get_nvlist(zc, &nvprops)) != 0) 16782676Seschrock return (error); 16792676Seschrock 16802676Seschrock if (zc->zc_value[0] != '\0') { 1681789Sahrens /* 1682789Sahrens * We're creating a clone of an existing snapshot. 1683789Sahrens */ 16842676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 16852676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 16864543Smarks nvlist_free(nvprops); 1687789Sahrens return (EINVAL); 16882676Seschrock } 1689789Sahrens 16902676Seschrock error = dmu_objset_open(zc->zc_value, type, 1691789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 16922676Seschrock if (error) { 16934543Smarks nvlist_free(nvprops); 1694789Sahrens return (error); 16952676Seschrock } 1696789Sahrens error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); 1697789Sahrens dmu_objset_close(clone); 1698789Sahrens } else { 16992676Seschrock if (cbfunc == NULL) { 17004543Smarks nvlist_free(nvprops); 17012199Sahrens return (EINVAL); 17022676Seschrock } 17032676Seschrock 1704789Sahrens if (type == DMU_OST_ZVOL) { 17052676Seschrock uint64_t volsize, volblocksize; 17062676Seschrock 17074543Smarks if (nvprops == NULL || 17084543Smarks nvlist_lookup_uint64(nvprops, 17092676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 17102676Seschrock &volsize) != 0) { 17114543Smarks nvlist_free(nvprops); 17122676Seschrock return (EINVAL); 17132676Seschrock } 17142676Seschrock 17154543Smarks if ((error = nvlist_lookup_uint64(nvprops, 17162676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 17172676Seschrock &volblocksize)) != 0 && error != ENOENT) { 17184543Smarks nvlist_free(nvprops); 17192676Seschrock return (EINVAL); 17202676Seschrock } 17211133Seschrock 17222676Seschrock if (error != 0) 17232676Seschrock volblocksize = zfs_prop_default_numeric( 17242676Seschrock ZFS_PROP_VOLBLOCKSIZE); 17252676Seschrock 17262676Seschrock if ((error = zvol_check_volblocksize( 17272676Seschrock volblocksize)) != 0 || 17282676Seschrock (error = zvol_check_volsize(volsize, 17292676Seschrock volblocksize)) != 0) { 17304543Smarks nvlist_free(nvprops); 1731789Sahrens return (error); 17322676Seschrock } 17334577Sahrens } else if (type == DMU_OST_ZFS) { 17344577Sahrens uint64_t version; 17354577Sahrens 17364577Sahrens if (0 == nvlist_lookup_uint64(nvprops, 17374577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version) && 17384577Sahrens (version < ZPL_VERSION_INITIAL || 17394577Sahrens version > ZPL_VERSION)) { 17404577Sahrens nvlist_free(nvprops); 17414577Sahrens return (EINVAL); 17424577Sahrens } 17432676Seschrock } 17441133Seschrock 17452676Seschrock error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, 17464543Smarks nvprops); 1747789Sahrens } 17482676Seschrock 17492676Seschrock /* 17502676Seschrock * It would be nice to do this atomically. 17512676Seschrock */ 17522676Seschrock if (error == 0) { 17532676Seschrock if ((error = zfs_set_prop_nvlist(zc->zc_name, 17542676Seschrock zc->zc_dev, (cred_t *)(uintptr_t)zc->zc_cred, 17554543Smarks nvprops)) != 0) 17562676Seschrock (void) dmu_objset_destroy(zc->zc_name); 17572676Seschrock } 17582676Seschrock 17594543Smarks nvlist_free(nvprops); 1760789Sahrens return (error); 1761789Sahrens } 1762789Sahrens 1763789Sahrens static int 17642199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 17652199Sahrens { 17662676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 17672199Sahrens return (EINVAL); 17682199Sahrens return (dmu_objset_snapshot(zc->zc_name, 17692676Seschrock zc->zc_value, zc->zc_cookie)); 17702199Sahrens } 17712199Sahrens 17724007Smmusante int 17732199Sahrens zfs_unmount_snap(char *name, void *arg) 1774789Sahrens { 17752199Sahrens char *snapname = arg; 17762199Sahrens char *cp; 17772417Sahrens vfs_t *vfsp = NULL; 17782199Sahrens 17792199Sahrens /* 17802199Sahrens * Snapshots (which are under .zfs control) must be unmounted 17812199Sahrens * before they can be destroyed. 17822199Sahrens */ 17832199Sahrens 17842199Sahrens if (snapname) { 17852199Sahrens (void) strcat(name, "@"); 17862199Sahrens (void) strcat(name, snapname); 17872199Sahrens vfsp = zfs_get_vfs(name); 17882199Sahrens cp = strchr(name, '@'); 17892199Sahrens *cp = '\0'; 17902417Sahrens } else if (strchr(name, '@')) { 17912199Sahrens vfsp = zfs_get_vfs(name); 17922199Sahrens } 17932199Sahrens 17942199Sahrens if (vfsp) { 17952199Sahrens /* 17962199Sahrens * Always force the unmount for snapshots. 17972199Sahrens */ 17982199Sahrens int flag = MS_FORCE; 1799789Sahrens int err; 1800789Sahrens 18012199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 18022199Sahrens VFS_RELE(vfsp); 18032199Sahrens return (err); 18042199Sahrens } 18052199Sahrens VFS_RELE(vfsp); 18062199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 18072199Sahrens return (err); 18082199Sahrens } 18092199Sahrens return (0); 18102199Sahrens } 18112199Sahrens 18122199Sahrens static int 18132199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 18142199Sahrens { 18152199Sahrens int err; 1816789Sahrens 18172676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 18182199Sahrens return (EINVAL); 18192199Sahrens err = dmu_objset_find(zc->zc_name, 18202676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 18212199Sahrens if (err) 18222199Sahrens return (err); 18232676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 18242199Sahrens } 18252199Sahrens 18262199Sahrens static int 18272199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 18282199Sahrens { 18292199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 18302199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18312199Sahrens if (err) 18322199Sahrens return (err); 1833789Sahrens } 1834789Sahrens 1835789Sahrens return (dmu_objset_destroy(zc->zc_name)); 1836789Sahrens } 1837789Sahrens 1838789Sahrens static int 1839789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 1840789Sahrens { 1841789Sahrens return (dmu_objset_rollback(zc->zc_name)); 1842789Sahrens } 1843789Sahrens 1844789Sahrens static int 1845789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 1846789Sahrens { 18474490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 18484007Smmusante 18492676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 18502676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) 1851789Sahrens return (EINVAL); 1852789Sahrens 18534007Smmusante /* 18544007Smmusante * Unmount snapshot unless we're doing a recursive rename, 18554007Smmusante * in which case the dataset code figures out which snapshots 18564007Smmusante * to unmount. 18574007Smmusante */ 18584007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 1859789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 18602199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18612199Sahrens if (err) 18622199Sahrens return (err); 1863789Sahrens } 1864789Sahrens 18654007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 1866789Sahrens } 1867789Sahrens 1868789Sahrens static int 1869789Sahrens zfs_ioc_recvbackup(zfs_cmd_t *zc) 1870789Sahrens { 1871789Sahrens file_t *fp; 1872789Sahrens int error, fd; 18732885Sahrens offset_t new_off; 1874789Sahrens 18753265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 18763265Sahrens strchr(zc->zc_value, '@') == NULL) 18773265Sahrens return (EINVAL); 18783265Sahrens 1879789Sahrens fd = zc->zc_cookie; 1880789Sahrens fp = getf(fd); 1881789Sahrens if (fp == NULL) 1882789Sahrens return (EBADF); 18832676Seschrock error = dmu_recvbackup(zc->zc_value, &zc->zc_begin_record, 18842676Seschrock &zc->zc_cookie, (boolean_t)zc->zc_guid, fp->f_vnode, 18852665Snd150628 fp->f_offset); 18862885Sahrens 18872885Sahrens new_off = fp->f_offset + zc->zc_cookie; 18882885Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &new_off) == 0) 18892885Sahrens fp->f_offset = new_off; 18902885Sahrens 1891789Sahrens releasef(fd); 1892789Sahrens return (error); 1893789Sahrens } 1894789Sahrens 1895789Sahrens static int 1896789Sahrens zfs_ioc_sendbackup(zfs_cmd_t *zc) 1897789Sahrens { 1898789Sahrens objset_t *fromsnap = NULL; 1899789Sahrens objset_t *tosnap; 1900789Sahrens file_t *fp; 1901789Sahrens int error; 1902789Sahrens 1903789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1904789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); 1905789Sahrens if (error) 1906789Sahrens return (error); 1907789Sahrens 19082676Seschrock if (zc->zc_value[0] != '\0') { 19092885Sahrens char buf[MAXPATHLEN]; 19102885Sahrens char *cp; 19112885Sahrens 19122885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 19132885Sahrens cp = strchr(buf, '@'); 19142885Sahrens if (cp) 19152885Sahrens *(cp+1) = 0; 19162885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 19172885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 1918789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); 1919789Sahrens if (error) { 1920789Sahrens dmu_objset_close(tosnap); 1921789Sahrens return (error); 1922789Sahrens } 1923789Sahrens } 1924789Sahrens 1925789Sahrens fp = getf(zc->zc_cookie); 1926789Sahrens if (fp == NULL) { 1927789Sahrens dmu_objset_close(tosnap); 1928789Sahrens if (fromsnap) 1929789Sahrens dmu_objset_close(fromsnap); 1930789Sahrens return (EBADF); 1931789Sahrens } 1932789Sahrens 1933789Sahrens error = dmu_sendbackup(tosnap, fromsnap, fp->f_vnode); 1934789Sahrens 1935789Sahrens releasef(zc->zc_cookie); 1936789Sahrens if (fromsnap) 1937789Sahrens dmu_objset_close(fromsnap); 1938789Sahrens dmu_objset_close(tosnap); 1939789Sahrens return (error); 1940789Sahrens } 1941789Sahrens 19421544Seschrock static int 19431544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 19441544Seschrock { 19451544Seschrock int id, error; 19461544Seschrock 19471544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 19481544Seschrock &zc->zc_inject_record); 19491544Seschrock 19501544Seschrock if (error == 0) 19511544Seschrock zc->zc_guid = (uint64_t)id; 19521544Seschrock 19531544Seschrock return (error); 19541544Seschrock } 19551544Seschrock 19561544Seschrock static int 19571544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 19581544Seschrock { 19591544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 19601544Seschrock } 19611544Seschrock 19621544Seschrock static int 19631544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 19641544Seschrock { 19651544Seschrock int id = (int)zc->zc_guid; 19661544Seschrock int error; 19671544Seschrock 19681544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 19691544Seschrock &zc->zc_inject_record); 19701544Seschrock 19711544Seschrock zc->zc_guid = id; 19721544Seschrock 19731544Seschrock return (error); 19741544Seschrock } 19751544Seschrock 19761544Seschrock static int 19771544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 19781544Seschrock { 19791544Seschrock spa_t *spa; 19801544Seschrock int error; 19812676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 19821544Seschrock 19831544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 19841544Seschrock return (error); 19851544Seschrock 19862676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 19871544Seschrock &count); 19881544Seschrock if (error == 0) 19892676Seschrock zc->zc_nvlist_dst_size = count; 19901544Seschrock else 19912676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 19921544Seschrock 19931544Seschrock spa_close(spa, FTAG); 19941544Seschrock 19951544Seschrock return (error); 19961544Seschrock } 19971544Seschrock 19981544Seschrock static int 19991544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 20001544Seschrock { 20011544Seschrock spa_t *spa; 20021544Seschrock vdev_t *vd; 20031544Seschrock int error; 20044451Seschrock uint64_t txg; 20051544Seschrock 20061544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 20071544Seschrock return (error); 20081544Seschrock 20094451Seschrock txg = spa_vdev_enter(spa); 20101544Seschrock 20112676Seschrock if (zc->zc_guid == 0) { 20121544Seschrock vd = NULL; 20132676Seschrock } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { 20144451Seschrock (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 20151544Seschrock spa_close(spa, FTAG); 20161544Seschrock return (ENODEV); 20171544Seschrock } 20181544Seschrock 20191544Seschrock vdev_clear(spa, vd); 20201544Seschrock 20214451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 20221544Seschrock 20231544Seschrock spa_close(spa, FTAG); 20241544Seschrock 20251544Seschrock return (0); 20261544Seschrock } 20271544Seschrock 20281544Seschrock static int 20292082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 20302082Seschrock { 20312417Sahrens char *cp; 20322417Sahrens 20332417Sahrens /* 20342417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 20352417Sahrens * it's easier. 20362417Sahrens */ 20372676Seschrock cp = strchr(zc->zc_value, '@'); 20382417Sahrens if (cp) 20392417Sahrens *cp = '\0'; 20402676Seschrock (void) dmu_objset_find(zc->zc_value, 20412417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 20422082Seschrock return (dsl_dataset_promote(zc->zc_name)); 20432082Seschrock } 20442082Seschrock 20454543Smarks /* 20464543Smarks * We don't want to have a hard dependency 20474543Smarks * against some special symbols in sharefs 20484543Smarks * and nfs. Determine them if needed when 20494543Smarks * the first file system is shared. 20504543Smarks * Neither sharefs or nfs are unloadable modules. 20514543Smarks */ 20524543Smarks int (*zexport_fs)(void *arg); 20534543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 20544543Smarks 20554543Smarks int zfs_share_inited; 20564543Smarks ddi_modhandle_t nfs_mod; 20574543Smarks ddi_modhandle_t sharefs_mod; 20584543Smarks kmutex_t zfs_share_lock; 20594543Smarks 20604543Smarks static int 20614543Smarks zfs_ioc_share(zfs_cmd_t *zc) 20624543Smarks { 20634543Smarks int error; 20644543Smarks int opcode; 20654543Smarks 20664543Smarks if (zfs_share_inited == 0) { 20674543Smarks mutex_enter(&zfs_share_lock); 20684543Smarks nfs_mod = ddi_modopen("fs/nfs", KRTLD_MODE_FIRST, &error); 20694543Smarks sharefs_mod = ddi_modopen("fs/sharefs", 20704543Smarks KRTLD_MODE_FIRST, &error); 20714543Smarks if (nfs_mod == NULL || sharefs_mod == NULL) { 20724543Smarks mutex_exit(&zfs_share_lock); 20734543Smarks return (ENOSYS); 20744543Smarks } 20754543Smarks if (zexport_fs == NULL && ((zexport_fs = (int (*)(void *)) 20764543Smarks ddi_modsym(nfs_mod, "nfs_export", &error)) == NULL)) { 20774543Smarks mutex_exit(&zfs_share_lock); 20784543Smarks return (ENOSYS); 20794543Smarks } 20804543Smarks 20814543Smarks if (zshare_fs == NULL && ((zshare_fs = 20824543Smarks (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 20834543Smarks ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 20844543Smarks mutex_exit(&zfs_share_lock); 20854543Smarks return (ENOSYS); 20864543Smarks } 20874543Smarks zfs_share_inited = 1; 20884543Smarks mutex_exit(&zfs_share_lock); 20894543Smarks } 20904543Smarks 20914543Smarks if (error = zexport_fs((void *)(uintptr_t)zc->zc_share.z_exportdata)) 20924543Smarks return (error); 20934543Smarks 20944543Smarks opcode = (zc->zc_share.z_sharetype == B_TRUE) ? 20954543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 20964543Smarks 20974543Smarks error = zshare_fs(opcode, 20984543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 20994543Smarks zc->zc_share.z_sharemax); 21004543Smarks 21014543Smarks return (error); 21024543Smarks 21034543Smarks } 21044543Smarks 21054543Smarks /* 21064543Smarks * pool destroy and pool export don't log the history as part of zfsdev_ioctl, 21074543Smarks * but rather zfs_ioc_pool_create, and zfs_ioc_pool_export do the loggin 21084543Smarks * of those commands. 21094543Smarks */ 2110789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 21114577Sahrens { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21124577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21134577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21144577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21154577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 21164577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 21174577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21184577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21194577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21204577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21214577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21224577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21234577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21244577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21254577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21264577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21274577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21284577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 21294543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 21304577Sahrens DATASET_NAME, B_FALSE }, 21314543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 21324577Sahrens DATASET_NAME, B_FALSE }, 21334577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 21344577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 21354577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 21364577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 21374577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 21384577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 21394577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 21404577Sahrens { zfs_ioc_recvbackup, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 21414577Sahrens { zfs_ioc_sendbackup, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 21424577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21434577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21444577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21454577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 21464577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21474577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 21484577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 21494577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 21504577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21514577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21524577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21534577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 21544577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 21554577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 21564543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 21574577Sahrens DATASET_NAME, B_FALSE }, 21584577Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE } 2159789Sahrens }; 2160789Sahrens 2161789Sahrens static int 2162789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2163789Sahrens { 2164789Sahrens zfs_cmd_t *zc; 2165789Sahrens uint_t vec; 21662199Sahrens int error, rc; 2167789Sahrens 2168789Sahrens if (getminor(dev) != 0) 2169789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2170789Sahrens 2171789Sahrens vec = cmd - ZFS_IOC; 2172789Sahrens 2173789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2174789Sahrens return (EINVAL); 2175789Sahrens 2176789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2177789Sahrens 2178789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2179789Sahrens 2180789Sahrens if (error == 0) { 2181789Sahrens zc->zc_cred = (uintptr_t)cr; 2182789Sahrens zc->zc_dev = dev; 21834543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2184789Sahrens } 2185789Sahrens 2186789Sahrens /* 2187789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2188789Sahrens * the lower layers. 2189789Sahrens */ 2190789Sahrens if (error == 0) { 2191789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2192789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 21934577Sahrens case POOL_NAME: 2194789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2195789Sahrens error = EINVAL; 2196789Sahrens break; 2197789Sahrens 21984577Sahrens case DATASET_NAME: 2199789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2200789Sahrens error = EINVAL; 2201789Sahrens break; 22022856Snd150628 22034577Sahrens case NO_NAME: 22042856Snd150628 break; 2205789Sahrens } 2206789Sahrens } 2207789Sahrens 2208789Sahrens if (error == 0) 2209789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2210789Sahrens 22112199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 22124543Smarks if (error == 0) { 22132199Sahrens error = rc; 22144543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 22154543Smarks zfs_log_history(zc); 22164543Smarks } 2217789Sahrens 2218789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2219789Sahrens return (error); 2220789Sahrens } 2221789Sahrens 2222789Sahrens static int 2223789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2224789Sahrens { 2225789Sahrens if (cmd != DDI_ATTACH) 2226789Sahrens return (DDI_FAILURE); 2227789Sahrens 2228789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2229789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2230789Sahrens return (DDI_FAILURE); 2231789Sahrens 2232789Sahrens zfs_dip = dip; 2233789Sahrens 2234789Sahrens ddi_report_dev(dip); 2235789Sahrens 2236789Sahrens return (DDI_SUCCESS); 2237789Sahrens } 2238789Sahrens 2239789Sahrens static int 2240789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2241789Sahrens { 2242789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2243789Sahrens return (DDI_FAILURE); 2244789Sahrens 2245789Sahrens if (cmd != DDI_DETACH) 2246789Sahrens return (DDI_FAILURE); 2247789Sahrens 2248789Sahrens zfs_dip = NULL; 2249789Sahrens 2250789Sahrens ddi_prop_remove_all(dip); 2251789Sahrens ddi_remove_minor_node(dip, NULL); 2252789Sahrens 2253789Sahrens return (DDI_SUCCESS); 2254789Sahrens } 2255789Sahrens 2256789Sahrens /*ARGSUSED*/ 2257789Sahrens static int 2258789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2259789Sahrens { 2260789Sahrens switch (infocmd) { 2261789Sahrens case DDI_INFO_DEVT2DEVINFO: 2262789Sahrens *result = zfs_dip; 2263789Sahrens return (DDI_SUCCESS); 2264789Sahrens 2265789Sahrens case DDI_INFO_DEVT2INSTANCE: 2266849Sbonwick *result = (void *)0; 2267789Sahrens return (DDI_SUCCESS); 2268789Sahrens } 2269789Sahrens 2270789Sahrens return (DDI_FAILURE); 2271789Sahrens } 2272789Sahrens 2273789Sahrens /* 2274789Sahrens * OK, so this is a little weird. 2275789Sahrens * 2276789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2277789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2278789Sahrens * 2279789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2280789Sahrens * so most of the standard driver entry points are in zvol.c. 2281789Sahrens */ 2282789Sahrens static struct cb_ops zfs_cb_ops = { 2283789Sahrens zvol_open, /* open */ 2284789Sahrens zvol_close, /* close */ 2285789Sahrens zvol_strategy, /* strategy */ 2286789Sahrens nodev, /* print */ 2287789Sahrens nodev, /* dump */ 2288789Sahrens zvol_read, /* read */ 2289789Sahrens zvol_write, /* write */ 2290789Sahrens zfsdev_ioctl, /* ioctl */ 2291789Sahrens nodev, /* devmap */ 2292789Sahrens nodev, /* mmap */ 2293789Sahrens nodev, /* segmap */ 2294789Sahrens nochpoll, /* poll */ 2295789Sahrens ddi_prop_op, /* prop_op */ 2296789Sahrens NULL, /* streamtab */ 2297789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2298789Sahrens CB_REV, /* version */ 22993638Sbillm nodev, /* async read */ 23003638Sbillm nodev, /* async write */ 2301789Sahrens }; 2302789Sahrens 2303789Sahrens static struct dev_ops zfs_dev_ops = { 2304789Sahrens DEVO_REV, /* version */ 2305789Sahrens 0, /* refcnt */ 2306789Sahrens zfs_info, /* info */ 2307789Sahrens nulldev, /* identify */ 2308789Sahrens nulldev, /* probe */ 2309789Sahrens zfs_attach, /* attach */ 2310789Sahrens zfs_detach, /* detach */ 2311789Sahrens nodev, /* reset */ 2312789Sahrens &zfs_cb_ops, /* driver operations */ 2313789Sahrens NULL /* no bus operations */ 2314789Sahrens }; 2315789Sahrens 2316789Sahrens static struct modldrv zfs_modldrv = { 23174577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 23182676Seschrock &zfs_dev_ops 2319789Sahrens }; 2320789Sahrens 2321789Sahrens static struct modlinkage modlinkage = { 2322789Sahrens MODREV_1, 2323789Sahrens (void *)&zfs_modlfs, 2324789Sahrens (void *)&zfs_modldrv, 2325789Sahrens NULL 2326789Sahrens }; 2327789Sahrens 2328789Sahrens int 2329789Sahrens _init(void) 2330789Sahrens { 2331789Sahrens int error; 2332789Sahrens 2333849Sbonwick spa_init(FREAD | FWRITE); 2334849Sbonwick zfs_init(); 2335849Sbonwick zvol_init(); 2336849Sbonwick 2337849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 2338849Sbonwick zvol_fini(); 2339849Sbonwick zfs_fini(); 2340849Sbonwick spa_fini(); 2341789Sahrens return (error); 2342849Sbonwick } 2343789Sahrens 2344789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 2345789Sahrens ASSERT(error == 0); 23464543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 2347789Sahrens 2348789Sahrens return (0); 2349789Sahrens } 2350789Sahrens 2351789Sahrens int 2352789Sahrens _fini(void) 2353789Sahrens { 2354789Sahrens int error; 2355789Sahrens 23561544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 2357789Sahrens return (EBUSY); 2358789Sahrens 2359789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 2360789Sahrens return (error); 2361789Sahrens 2362789Sahrens zvol_fini(); 2363789Sahrens zfs_fini(); 2364789Sahrens spa_fini(); 23654543Smarks if (zfs_share_inited) { 23664543Smarks (void) ddi_modclose(nfs_mod); 23674543Smarks (void) ddi_modclose(sharefs_mod); 23684543Smarks } 2369789Sahrens 2370789Sahrens ldi_ident_release(zfs_li); 2371789Sahrens zfs_li = NULL; 23724543Smarks mutex_destroy(&zfs_share_lock); 2373789Sahrens 2374789Sahrens return (error); 2375789Sahrens } 2376789Sahrens 2377789Sahrens int 2378789Sahrens _info(struct modinfo *modinfop) 2379789Sahrens { 2380789Sahrens return (mod_info(&modlinkage, modinfop)); 2381789Sahrens } 2382