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 1304715Sek110237 history_str_free(char *buf) 1314715Sek110237 { 1324715Sek110237 kmem_free(buf, HIS_MAX_RECORD_LEN); 1334715Sek110237 } 1344715Sek110237 1354715Sek110237 static char * 1364715Sek110237 history_str_get(zfs_cmd_t *zc) 1374715Sek110237 { 1384715Sek110237 char *buf; 1394715Sek110237 1404715Sek110237 if (zc->zc_history == NULL) 1414715Sek110237 return (NULL); 1424715Sek110237 1434715Sek110237 buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP); 1444715Sek110237 if (copyinstr((void *)(uintptr_t)zc->zc_history, 1454715Sek110237 buf, HIS_MAX_RECORD_LEN, NULL) != 0) { 1464715Sek110237 history_str_free(buf); 1474715Sek110237 return (NULL); 1484715Sek110237 } 1494715Sek110237 1504715Sek110237 buf[HIS_MAX_RECORD_LEN -1] = '\0'; 1514715Sek110237 1524715Sek110237 return (buf); 1534715Sek110237 } 1544715Sek110237 1554715Sek110237 static void 1564543Smarks zfs_log_history(zfs_cmd_t *zc) 1574543Smarks { 1584543Smarks spa_t *spa; 1594603Sahrens char *buf; 1604543Smarks 1614715Sek110237 if ((buf = history_str_get(zc)) == NULL) 1624577Sahrens return; 1634577Sahrens 1644715Sek110237 if (spa_open(zc->zc_name, &spa, FTAG) == 0) { 1654715Sek110237 if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY) 1664715Sek110237 (void) spa_history_log(spa, buf, LOG_CMD_NORMAL); 1674715Sek110237 spa_close(spa, FTAG); 1684543Smarks } 1694715Sek110237 history_str_free(buf); 1704543Smarks } 1714543Smarks 172789Sahrens /* 173789Sahrens * Policy for top-level read operations (list pools). Requires no privileges, 174789Sahrens * and can be used in the local zone, as there is no associated dataset. 175789Sahrens */ 176789Sahrens /* ARGSUSED */ 177789Sahrens static int 1784543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) 179789Sahrens { 180789Sahrens return (0); 181789Sahrens } 182789Sahrens 183789Sahrens /* 184789Sahrens * Policy for dataset read operations (list children, get statistics). Requires 185789Sahrens * no privileges, but must be visible in the local zone. 186789Sahrens */ 187789Sahrens /* ARGSUSED */ 188789Sahrens static int 1894543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) 190789Sahrens { 191789Sahrens if (INGLOBALZONE(curproc) || 1924543Smarks zone_dataset_visible(zc->zc_name, NULL)) 193789Sahrens return (0); 194789Sahrens 195789Sahrens return (ENOENT); 196789Sahrens } 197789Sahrens 198789Sahrens static int 199789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr) 200789Sahrens { 201789Sahrens uint64_t zoned; 202789Sahrens int writable = 1; 203789Sahrens 204789Sahrens /* 205789Sahrens * The dataset must be visible by this zone -- check this first 206789Sahrens * so they don't see EPERM on something they shouldn't know about. 207789Sahrens */ 208789Sahrens if (!INGLOBALZONE(curproc) && 209789Sahrens !zone_dataset_visible(dataset, &writable)) 210789Sahrens return (ENOENT); 211789Sahrens 212789Sahrens if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) 213789Sahrens return (ENOENT); 214789Sahrens 215789Sahrens if (INGLOBALZONE(curproc)) { 216789Sahrens /* 217789Sahrens * If the fs is zoned, only root can access it from the 218789Sahrens * global zone. 219789Sahrens */ 220789Sahrens if (secpolicy_zfs(cr) && zoned) 221789Sahrens return (EPERM); 222789Sahrens } else { 223789Sahrens /* 224789Sahrens * If we are in a local zone, the 'zoned' property must be set. 225789Sahrens */ 226789Sahrens if (!zoned) 227789Sahrens return (EPERM); 228789Sahrens 229789Sahrens /* must be writable by this zone */ 230789Sahrens if (!writable) 231789Sahrens return (EPERM); 232789Sahrens } 233789Sahrens return (0); 234789Sahrens } 235789Sahrens 236789Sahrens int 2374543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) 238789Sahrens { 239789Sahrens int error; 240789Sahrens 2414543Smarks error = zfs_dozonecheck(name, cr); 2424543Smarks if (error == 0) { 2434543Smarks error = secpolicy_zfs(cr); 2444670Sahrens if (error) 2454543Smarks error = dsl_deleg_access(name, perm, cr); 2464543Smarks } 2474543Smarks return (error); 2484543Smarks } 2494543Smarks 2504543Smarks static int 2514543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) 2524543Smarks { 2534543Smarks /* 2544543Smarks * Check permissions for special properties. 2554543Smarks */ 2564543Smarks switch (prop) { 2574543Smarks case ZFS_PROP_ZONED: 2584543Smarks /* 2594543Smarks * Disallow setting of 'zoned' from within a local zone. 2604543Smarks */ 2614543Smarks if (!INGLOBALZONE(curproc)) 2624543Smarks return (EPERM); 2634543Smarks break; 264789Sahrens 2654543Smarks case ZFS_PROP_QUOTA: 2664543Smarks if (!INGLOBALZONE(curproc)) { 2674543Smarks uint64_t zoned; 2684543Smarks char setpoint[MAXNAMELEN]; 2694543Smarks /* 2704543Smarks * Unprivileged users are allowed to modify the 2714543Smarks * quota on things *under* (ie. contained by) 2724543Smarks * the thing they own. 2734543Smarks */ 2744543Smarks if (dsl_prop_get_integer(name, "zoned", &zoned, 2754543Smarks setpoint)) 2764543Smarks return (EPERM); 2774670Sahrens if (!zoned || strlen(name) <= strlen(setpoint)) 2784543Smarks return (EPERM); 2794543Smarks } 2804670Sahrens break; 2814543Smarks } 2824543Smarks 2834787Sahrens return (zfs_secpolicy_write_perms(name, zfs_prop_to_name(prop), cr)); 284789Sahrens } 285789Sahrens 2864543Smarks int 2874543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) 2884543Smarks { 2894543Smarks int error; 2904543Smarks 2914543Smarks error = zfs_dozonecheck(zc->zc_name, cr); 2924543Smarks if (error) 2934543Smarks return (error); 2944543Smarks 2954543Smarks /* 2964543Smarks * permission to set permissions will be evaluated later in 2974543Smarks * dsl_deleg_can_allow() 2984543Smarks */ 2994543Smarks return (0); 3004543Smarks } 3014543Smarks 3024543Smarks int 3034543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) 3044543Smarks { 3054543Smarks int error; 3064543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3074543Smarks ZFS_DELEG_PERM_ROLLBACK, cr); 3084543Smarks if (error == 0) 3094543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3104543Smarks ZFS_DELEG_PERM_MOUNT, cr); 3114543Smarks return (error); 3124543Smarks } 3134543Smarks 3144543Smarks int 3154543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) 3164543Smarks { 3174543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 3184543Smarks ZFS_DELEG_PERM_SEND, cr)); 3194543Smarks } 3204543Smarks 3214543Smarks int 3224543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) 3234543Smarks { 3244543Smarks if (!INGLOBALZONE(curproc)) 3254543Smarks return (EPERM); 3264543Smarks 3274543Smarks if (secpolicy_nfs(CRED()) == 0) { 3284543Smarks return (0); 3294543Smarks } else { 3304543Smarks vnode_t *vp; 3314543Smarks int error; 3324543Smarks 3334543Smarks if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, 3344543Smarks NO_FOLLOW, NULL, &vp)) != 0) 3354543Smarks return (error); 3364543Smarks 3374543Smarks /* Now make sure mntpnt and dataset are ZFS */ 3384543Smarks 3394543Smarks if (vp->v_vfsp->vfs_fstype != zfsfstype || 3404543Smarks (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), 3414543Smarks zc->zc_name) != 0)) { 3424543Smarks VN_RELE(vp); 3434543Smarks return (EPERM); 3444543Smarks } 3454543Smarks 3464543Smarks VN_RELE(vp); 3474543Smarks return (dsl_deleg_access(zc->zc_name, 3484543Smarks ZFS_DELEG_PERM_SHARE, cr)); 3494543Smarks } 3504543Smarks } 3514543Smarks 352789Sahrens static int 3534543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize) 354789Sahrens { 355789Sahrens char *cp; 356789Sahrens 357789Sahrens /* 358789Sahrens * Remove the @bla or /bla from the end of the name to get the parent. 359789Sahrens */ 3604543Smarks (void) strncpy(parent, datasetname, parentsize); 3614543Smarks cp = strrchr(parent, '@'); 362789Sahrens if (cp != NULL) { 363789Sahrens cp[0] = '\0'; 364789Sahrens } else { 3654543Smarks cp = strrchr(parent, '/'); 366789Sahrens if (cp == NULL) 367789Sahrens return (ENOENT); 368789Sahrens cp[0] = '\0'; 369789Sahrens } 370789Sahrens 3714543Smarks return (0); 3724543Smarks } 3734543Smarks 3744543Smarks int 3754543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 3764543Smarks { 3774543Smarks int error; 3784543Smarks 3794543Smarks if ((error = zfs_secpolicy_write_perms(name, 3804543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 3814543Smarks return (error); 3824543Smarks 3834543Smarks return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); 3844543Smarks } 3854543Smarks 3864543Smarks static int 3874543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) 3884543Smarks { 3894543Smarks return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); 3904543Smarks } 3914543Smarks 3924543Smarks /* 3934543Smarks * Must have sys_config privilege to check the iscsi permission 3944543Smarks */ 3954543Smarks /* ARGSUSED */ 3964543Smarks static int 3974543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) 3984543Smarks { 3994543Smarks return (secpolicy_zfs(cr)); 4004543Smarks } 4014543Smarks 4024543Smarks int 4034543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 4044543Smarks { 4054543Smarks char parentname[MAXNAMELEN]; 4064543Smarks int error; 4074543Smarks 4084543Smarks if ((error = zfs_secpolicy_write_perms(from, 4094543Smarks ZFS_DELEG_PERM_RENAME, cr)) != 0) 4104543Smarks return (error); 4114543Smarks 4124543Smarks if ((error = zfs_secpolicy_write_perms(from, 4134543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4144543Smarks return (error); 4154543Smarks 4164543Smarks if ((error = zfs_get_parent(to, parentname, 4174543Smarks sizeof (parentname))) != 0) 4184543Smarks return (error); 4194543Smarks 4204543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4214543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 4224543Smarks return (error); 4234543Smarks 4244543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4254543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4264543Smarks return (error); 4274543Smarks 4284543Smarks return (error); 4294543Smarks } 4304543Smarks 4314543Smarks static int 4324543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) 4334543Smarks { 4344543Smarks return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); 4354543Smarks } 4364543Smarks 4374543Smarks static int 4384543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) 4394543Smarks { 4404543Smarks char parentname[MAXNAMELEN]; 4414543Smarks objset_t *clone; 4424543Smarks int error; 4434543Smarks 4444543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4454543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4464543Smarks if (error) 4474543Smarks return (error); 4484543Smarks 4494543Smarks error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 4504543Smarks DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 4514543Smarks 4524543Smarks if (error == 0) { 4534543Smarks dsl_dataset_t *pclone = NULL; 4544543Smarks dsl_dir_t *dd; 4554543Smarks dd = clone->os->os_dsl_dataset->ds_dir; 4564543Smarks 4574543Smarks rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 4584543Smarks error = dsl_dataset_open_obj(dd->dd_pool, 4594543Smarks dd->dd_phys->dd_clone_parent_obj, NULL, 4604543Smarks DS_MODE_NONE, FTAG, &pclone); 4614543Smarks rw_exit(&dd->dd_pool->dp_config_rwlock); 4624543Smarks if (error) { 4634543Smarks dmu_objset_close(clone); 4644543Smarks return (error); 4654543Smarks } 4664543Smarks 4674543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4684543Smarks ZFS_DELEG_PERM_MOUNT, cr); 4694543Smarks 4704543Smarks dsl_dataset_name(pclone, parentname); 4714543Smarks dmu_objset_close(clone); 4724543Smarks dsl_dataset_close(pclone, DS_MODE_NONE, FTAG); 4734543Smarks if (error == 0) 4744543Smarks error = zfs_secpolicy_write_perms(parentname, 4754543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4764543Smarks } 4774543Smarks return (error); 4784543Smarks } 4794543Smarks 4804543Smarks static int 4814543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) 4824543Smarks { 4834543Smarks int error; 4844543Smarks 4854543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 4864543Smarks ZFS_DELEG_PERM_RECEIVE, cr)) != 0) 4874543Smarks return (error); 4884543Smarks 4894543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 4904543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4914543Smarks return (error); 4924543Smarks 4934543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 4944543Smarks ZFS_DELEG_PERM_CREATE, cr)); 4954543Smarks } 4964543Smarks 4974543Smarks int 4984543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 4994543Smarks { 5004543Smarks int error; 5014543Smarks 5024543Smarks if ((error = zfs_secpolicy_write_perms(name, 5034543Smarks ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) 5044543Smarks return (error); 5054543Smarks 5064543Smarks error = zfs_secpolicy_write_perms(name, 5074543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5084543Smarks 5094543Smarks return (error); 5104543Smarks } 5114543Smarks 5124543Smarks static int 5134543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) 5144543Smarks { 5154543Smarks 5164543Smarks return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); 5174543Smarks } 5184543Smarks 5194543Smarks static int 5204543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) 5214543Smarks { 5224543Smarks char parentname[MAXNAMELEN]; 5234543Smarks int error; 5244543Smarks 5254543Smarks if ((error = zfs_get_parent(zc->zc_name, parentname, 5264543Smarks sizeof (parentname))) != 0) 5274543Smarks return (error); 5284543Smarks 5294543Smarks if (zc->zc_value[0] != '\0') { 5304543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_value, 5314543Smarks ZFS_DELEG_PERM_CLONE, cr)) != 0) 5324543Smarks return (error); 5334543Smarks } 5344543Smarks 5354543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 5364543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 5374543Smarks return (error); 5384543Smarks 5394543Smarks error = zfs_secpolicy_write_perms(parentname, 5404543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5414543Smarks 5424543Smarks return (error); 5434543Smarks } 5444543Smarks 5454543Smarks static int 5464543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) 5474543Smarks { 5484543Smarks int error; 5494543Smarks 5504543Smarks error = secpolicy_fs_unmount(cr, NULL); 5514543Smarks if (error) { 5524543Smarks error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); 5534543Smarks } 5544543Smarks return (error); 555789Sahrens } 556789Sahrens 557789Sahrens /* 558789Sahrens * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires 559789Sahrens * SYS_CONFIG privilege, which is not available in a local zone. 560789Sahrens */ 561789Sahrens /* ARGSUSED */ 562789Sahrens static int 5634543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) 564789Sahrens { 565789Sahrens if (secpolicy_sys_config(cr, B_FALSE) != 0) 566789Sahrens return (EPERM); 567789Sahrens 568789Sahrens return (0); 569789Sahrens } 570789Sahrens 571789Sahrens /* 5724543Smarks * Just like zfs_secpolicy_config, except that we will check for 5734543Smarks * mount permission on the dataset for permission to create/remove 5744543Smarks * the minor nodes. 5754543Smarks */ 5764543Smarks static int 5774543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) 5784543Smarks { 5794543Smarks if (secpolicy_sys_config(cr, B_FALSE) != 0) { 5804543Smarks return (dsl_deleg_access(zc->zc_name, 5814543Smarks ZFS_DELEG_PERM_MOUNT, cr)); 5824543Smarks } 5834543Smarks 5844543Smarks return (0); 5854543Smarks } 5864543Smarks 5874543Smarks /* 5881544Seschrock * Policy for fault injection. Requires all privileges. 5891544Seschrock */ 5901544Seschrock /* ARGSUSED */ 5911544Seschrock static int 5924543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) 5931544Seschrock { 5941544Seschrock return (secpolicy_zinject(cr)); 5951544Seschrock } 5961544Seschrock 5974849Sahrens static int 5984849Sahrens zfs_secpolicy_inherit(zfs_cmd_t *zc, cred_t *cr) 5994849Sahrens { 6004849Sahrens zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); 6014849Sahrens 602*5094Slling if (prop == ZPROP_INVAL) { 6034849Sahrens if (!zfs_prop_user(zc->zc_value)) 6044849Sahrens return (EINVAL); 6054849Sahrens return (zfs_secpolicy_write_perms(zc->zc_name, 6064849Sahrens ZFS_DELEG_PERM_USERPROP, cr)); 6074849Sahrens } else { 6084849Sahrens if (!zfs_prop_inheritable(prop)) 6094849Sahrens return (EINVAL); 6104849Sahrens return (zfs_secpolicy_setprop(zc->zc_name, prop, cr)); 6114849Sahrens } 6124849Sahrens } 6134849Sahrens 6141544Seschrock /* 615789Sahrens * Returns the nvlist as specified by the user in the zfs_cmd_t. 616789Sahrens */ 617789Sahrens static int 618*5094Slling get_nvlist(uint64_t nvl, uint64_t size, nvlist_t **nvp) 619789Sahrens { 620789Sahrens char *packed; 621789Sahrens int error; 622*5094Slling nvlist_t *list = NULL; 623789Sahrens 624789Sahrens /* 6252676Seschrock * Read in and unpack the user-supplied nvlist. 626789Sahrens */ 627*5094Slling if (size == 0) 628789Sahrens return (EINVAL); 629789Sahrens 630789Sahrens packed = kmem_alloc(size, KM_SLEEP); 631789Sahrens 632*5094Slling if ((error = xcopyin((void *)(uintptr_t)nvl, packed, size)) != 0) { 633789Sahrens kmem_free(packed, size); 634789Sahrens return (error); 635789Sahrens } 636789Sahrens 637*5094Slling if ((error = nvlist_unpack(packed, size, &list, 0)) != 0) { 638789Sahrens kmem_free(packed, size); 639789Sahrens return (error); 640789Sahrens } 641789Sahrens 642789Sahrens kmem_free(packed, size); 643789Sahrens 644*5094Slling *nvp = list; 645789Sahrens return (0); 646789Sahrens } 647789Sahrens 648789Sahrens static int 6492676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 6502676Seschrock { 6512676Seschrock char *packed = NULL; 6522676Seschrock size_t size; 6532676Seschrock int error; 6542676Seschrock 6552676Seschrock VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 6562676Seschrock 6572676Seschrock if (size > zc->zc_nvlist_dst_size) { 6582676Seschrock error = ENOMEM; 6592676Seschrock } else { 6604611Smarks packed = kmem_alloc(size, KM_SLEEP); 6612676Seschrock VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 6622676Seschrock KM_SLEEP) == 0); 6632676Seschrock error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 6642676Seschrock size); 6652676Seschrock kmem_free(packed, size); 6662676Seschrock } 6672676Seschrock 6682676Seschrock zc->zc_nvlist_dst_size = size; 6692676Seschrock return (error); 6702676Seschrock } 6712676Seschrock 6722676Seschrock static int 673789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc) 674789Sahrens { 675789Sahrens int error; 676*5094Slling nvlist_t *config, *props = NULL; 6774715Sek110237 char *buf; 678789Sahrens 679*5094Slling if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 680*5094Slling &config)) 6814988Sek110237 return (error); 6824715Sek110237 683*5094Slling if (zc->zc_nvlist_src_size != 0 && (error = 684*5094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 685*5094Slling nvlist_free(config); 686*5094Slling return (error); 687*5094Slling } 688*5094Slling 6894988Sek110237 buf = history_str_get(zc); 690789Sahrens 691*5094Slling error = spa_create(zc->zc_name, config, props, buf); 692789Sahrens 6934988Sek110237 if (buf != NULL) 6944988Sek110237 history_str_free(buf); 695*5094Slling 696789Sahrens nvlist_free(config); 697789Sahrens 698*5094Slling if (props) 699*5094Slling nvlist_free(props); 700*5094Slling 701789Sahrens return (error); 702789Sahrens } 703789Sahrens 704789Sahrens static int 705789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc) 706789Sahrens { 7074543Smarks int error; 7084543Smarks zfs_log_history(zc); 7094543Smarks error = spa_destroy(zc->zc_name); 7104543Smarks return (error); 711789Sahrens } 712789Sahrens 713789Sahrens static int 714789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc) 715789Sahrens { 716789Sahrens int error; 717*5094Slling nvlist_t *config, *props = NULL; 718789Sahrens uint64_t guid; 719789Sahrens 720*5094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 721*5094Slling &config)) != 0) 722789Sahrens return (error); 723789Sahrens 724*5094Slling if (zc->zc_nvlist_src_size != 0 && (error = 725*5094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 726*5094Slling nvlist_free(config); 727*5094Slling return (error); 728*5094Slling } 729*5094Slling 730789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 7311544Seschrock guid != zc->zc_guid) 732789Sahrens error = EINVAL; 733789Sahrens else 734*5094Slling error = spa_import(zc->zc_name, config, props); 735789Sahrens 736789Sahrens nvlist_free(config); 737789Sahrens 738*5094Slling if (props) 739*5094Slling nvlist_free(props); 740*5094Slling 741789Sahrens return (error); 742789Sahrens } 743789Sahrens 744789Sahrens static int 745789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc) 746789Sahrens { 7474543Smarks int error; 7484543Smarks zfs_log_history(zc); 7494543Smarks error = spa_export(zc->zc_name, NULL); 7504543Smarks return (error); 751789Sahrens } 752789Sahrens 753789Sahrens static int 754789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc) 755789Sahrens { 756789Sahrens nvlist_t *configs; 757789Sahrens int error; 758789Sahrens 759789Sahrens if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 760789Sahrens return (EEXIST); 761789Sahrens 7622676Seschrock error = put_nvlist(zc, configs); 763789Sahrens 764789Sahrens nvlist_free(configs); 765789Sahrens 766789Sahrens return (error); 767789Sahrens } 768789Sahrens 769789Sahrens static int 770789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc) 771789Sahrens { 772789Sahrens nvlist_t *config; 773789Sahrens int error; 7741544Seschrock int ret = 0; 775789Sahrens 7762676Seschrock error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 7772676Seschrock sizeof (zc->zc_value)); 778789Sahrens 779789Sahrens if (config != NULL) { 7802676Seschrock ret = put_nvlist(zc, config); 781789Sahrens nvlist_free(config); 7821544Seschrock 7831544Seschrock /* 7841544Seschrock * The config may be present even if 'error' is non-zero. 7851544Seschrock * In this case we return success, and preserve the real errno 7861544Seschrock * in 'zc_cookie'. 7871544Seschrock */ 7881544Seschrock zc->zc_cookie = error; 789789Sahrens } else { 7901544Seschrock ret = error; 791789Sahrens } 792789Sahrens 7931544Seschrock return (ret); 794789Sahrens } 795789Sahrens 796789Sahrens /* 797789Sahrens * Try to import the given pool, returning pool stats as appropriate so that 798789Sahrens * user land knows which devices are available and overall pool health. 799789Sahrens */ 800789Sahrens static int 801789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 802789Sahrens { 803789Sahrens nvlist_t *tryconfig, *config; 804789Sahrens int error; 805789Sahrens 806*5094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 807*5094Slling &tryconfig)) != 0) 808789Sahrens return (error); 809789Sahrens 810789Sahrens config = spa_tryimport(tryconfig); 811789Sahrens 812789Sahrens nvlist_free(tryconfig); 813789Sahrens 814789Sahrens if (config == NULL) 815789Sahrens return (EINVAL); 816789Sahrens 8172676Seschrock error = put_nvlist(zc, config); 818789Sahrens nvlist_free(config); 819789Sahrens 820789Sahrens return (error); 821789Sahrens } 822789Sahrens 823789Sahrens static int 824789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc) 825789Sahrens { 826789Sahrens spa_t *spa; 827789Sahrens int error; 828789Sahrens 8292926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8302926Sek110237 return (error); 8312926Sek110237 8324808Sek110237 mutex_enter(&spa_namespace_lock); 8332926Sek110237 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); 8344808Sek110237 mutex_exit(&spa_namespace_lock); 8352926Sek110237 8362926Sek110237 spa_close(spa, FTAG); 8372926Sek110237 838789Sahrens return (error); 839789Sahrens } 840789Sahrens 841789Sahrens static int 842789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 843789Sahrens { 844789Sahrens spa_t *spa; 845789Sahrens int error; 846789Sahrens 847789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 848789Sahrens if (error == 0) { 849789Sahrens spa_freeze(spa); 850789Sahrens spa_close(spa, FTAG); 851789Sahrens } 852789Sahrens return (error); 853789Sahrens } 854789Sahrens 855789Sahrens static int 8561760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 8571760Seschrock { 8581760Seschrock spa_t *spa; 8591760Seschrock int error; 8601760Seschrock 8612926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8622926Sek110237 return (error); 8632926Sek110237 864*5094Slling spa_upgrade(spa, zc->zc_cookie); 8652926Sek110237 spa_close(spa, FTAG); 8662926Sek110237 8672926Sek110237 return (error); 8682926Sek110237 } 8692926Sek110237 8702926Sek110237 static int 8712926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 8722926Sek110237 { 8732926Sek110237 spa_t *spa; 8742926Sek110237 char *hist_buf; 8752926Sek110237 uint64_t size; 8762926Sek110237 int error; 8772926Sek110237 8782926Sek110237 if ((size = zc->zc_history_len) == 0) 8792926Sek110237 return (EINVAL); 8802926Sek110237 8812926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8822926Sek110237 return (error); 8832926Sek110237 8844577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 8853863Sek110237 spa_close(spa, FTAG); 8863863Sek110237 return (ENOTSUP); 8873863Sek110237 } 8883863Sek110237 8892926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 8902926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 8912926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 8924543Smarks error = xcopyout(hist_buf, 8934543Smarks (char *)(uintptr_t)zc->zc_history, 8942926Sek110237 zc->zc_history_len); 8952926Sek110237 } 8962926Sek110237 8972926Sek110237 spa_close(spa, FTAG); 8982926Sek110237 kmem_free(hist_buf, size); 8992926Sek110237 return (error); 9002926Sek110237 } 9012926Sek110237 9022926Sek110237 static int 9033444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 9043444Sek110237 { 9053444Sek110237 int error; 9063444Sek110237 9073912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 9083444Sek110237 return (error); 9093444Sek110237 9103444Sek110237 return (0); 9113444Sek110237 } 9123444Sek110237 9133444Sek110237 static int 9143444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 9153444Sek110237 { 9163444Sek110237 objset_t *osp; 9173444Sek110237 int error; 9183444Sek110237 9193444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 9203444Sek110237 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) 9213444Sek110237 return (error); 9223444Sek110237 9233444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 9243444Sek110237 sizeof (zc->zc_value)); 9253444Sek110237 dmu_objset_close(osp); 9263444Sek110237 9273444Sek110237 return (error); 9283444Sek110237 } 9293444Sek110237 9303444Sek110237 static int 931789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 932789Sahrens { 933789Sahrens spa_t *spa; 934789Sahrens int error; 935789Sahrens nvlist_t *config; 936789Sahrens 937789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 938789Sahrens if (error != 0) 939789Sahrens return (error); 940789Sahrens 9413912Slling /* 9423912Slling * A root pool with concatenated devices is not supported. 9433912Slling * Thus, can not add a device to a root pool with one device. 9443912Slling */ 9453912Slling if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0) { 9463912Slling spa_close(spa, FTAG); 9473912Slling return (EDOM); 9483912Slling } 9493912Slling 950*5094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 951*5094Slling &config)) == 0) { 952789Sahrens error = spa_vdev_add(spa, config); 953789Sahrens nvlist_free(config); 954789Sahrens } 955789Sahrens spa_close(spa, FTAG); 956789Sahrens return (error); 957789Sahrens } 958789Sahrens 959789Sahrens static int 960789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 961789Sahrens { 9622082Seschrock spa_t *spa; 9632082Seschrock int error; 9642082Seschrock 9652082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 9662082Seschrock if (error != 0) 9672082Seschrock return (error); 9682082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 9692082Seschrock spa_close(spa, FTAG); 9702082Seschrock return (error); 971789Sahrens } 972789Sahrens 973789Sahrens static int 9744451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 975789Sahrens { 976789Sahrens spa_t *spa; 977789Sahrens int error; 9784451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 979789Sahrens 9802926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 981789Sahrens return (error); 9824451Seschrock switch (zc->zc_cookie) { 9834451Seschrock case VDEV_STATE_ONLINE: 9844451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 9854451Seschrock break; 9864451Seschrock 9874451Seschrock case VDEV_STATE_OFFLINE: 9884451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 9894451Seschrock break; 990789Sahrens 9914451Seschrock case VDEV_STATE_FAULTED: 9924451Seschrock error = vdev_fault(spa, zc->zc_guid); 9934451Seschrock break; 994789Sahrens 9954451Seschrock case VDEV_STATE_DEGRADED: 9964451Seschrock error = vdev_degrade(spa, zc->zc_guid); 9974451Seschrock break; 9984451Seschrock 9994451Seschrock default: 10004451Seschrock error = EINVAL; 10014451Seschrock } 10024451Seschrock zc->zc_cookie = newstate; 1003789Sahrens spa_close(spa, FTAG); 1004789Sahrens return (error); 1005789Sahrens } 1006789Sahrens 1007789Sahrens static int 1008789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 1009789Sahrens { 1010789Sahrens spa_t *spa; 1011789Sahrens int replacing = zc->zc_cookie; 1012789Sahrens nvlist_t *config; 1013789Sahrens int error; 1014789Sahrens 10152926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1016789Sahrens return (error); 1017789Sahrens 1018*5094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 1019*5094Slling &config)) == 0) { 10201544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 1021789Sahrens nvlist_free(config); 1022789Sahrens } 1023789Sahrens 1024789Sahrens spa_close(spa, FTAG); 1025789Sahrens return (error); 1026789Sahrens } 1027789Sahrens 1028789Sahrens static int 1029789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 1030789Sahrens { 1031789Sahrens spa_t *spa; 1032789Sahrens int error; 1033789Sahrens 10342926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1035789Sahrens return (error); 1036789Sahrens 10371544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1038789Sahrens 1039789Sahrens spa_close(spa, FTAG); 1040789Sahrens return (error); 1041789Sahrens } 1042789Sahrens 1043789Sahrens static int 10441354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 10451354Seschrock { 10461354Seschrock spa_t *spa; 10472676Seschrock char *path = zc->zc_value; 10481544Seschrock uint64_t guid = zc->zc_guid; 10491354Seschrock int error; 10501354Seschrock 10511354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10521354Seschrock if (error != 0) 10531354Seschrock return (error); 10541354Seschrock 10551354Seschrock error = spa_vdev_setpath(spa, guid, path); 10561354Seschrock spa_close(spa, FTAG); 10571354Seschrock return (error); 10581354Seschrock } 10591354Seschrock 10601354Seschrock static int 1061789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1062789Sahrens { 1063789Sahrens objset_t *os = NULL; 1064789Sahrens int error; 10651356Seschrock nvlist_t *nv; 1066789Sahrens 1067789Sahrens retry: 1068789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1069789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1070789Sahrens if (error != 0) { 1071789Sahrens /* 1072789Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1073789Sahrens * the objset is held exclusively. Fortunately this hold is 1074789Sahrens * only for a short while, so we retry here. 1075789Sahrens * This avoids user code having to handle EBUSY, 1076789Sahrens * for example for a "zfs list". 1077789Sahrens */ 1078789Sahrens if (error == EBUSY) { 1079789Sahrens delay(1); 1080789Sahrens goto retry; 1081789Sahrens } 1082789Sahrens return (error); 1083789Sahrens } 1084789Sahrens 10852885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1086789Sahrens 10872856Snd150628 if (zc->zc_nvlist_dst != 0 && 10881356Seschrock (error = dsl_prop_get_all(os, &nv)) == 0) { 10892885Sahrens dmu_objset_stats(os, nv); 10903087Sahrens /* 10914577Sahrens * NB: {zpl,zvol}_get_stats() will read the objset contents, 10923087Sahrens * which we aren't supposed to do with a 10933087Sahrens * DS_MODE_STANDARD open, because it could be 10943087Sahrens * inconsistent. So this is a bit of a workaround... 10953087Sahrens */ 10964577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 10974577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 10984577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 10994577Sahrens else if (dmu_objset_type(os) == DMU_OST_ZFS) 11004577Sahrens (void) zfs_get_stats(os, nv); 11014577Sahrens } 11022676Seschrock error = put_nvlist(zc, nv); 11031356Seschrock nvlist_free(nv); 11041356Seschrock } 1105789Sahrens 11062676Seschrock spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value)); 11071544Seschrock 1108789Sahrens dmu_objset_close(os); 1109789Sahrens return (error); 1110789Sahrens } 1111789Sahrens 1112789Sahrens static int 1113789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1114789Sahrens { 1115885Sahrens objset_t *os; 1116789Sahrens int error; 1117789Sahrens char *p; 1118789Sahrens 1119885Sahrens retry: 1120885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1121885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1122885Sahrens if (error != 0) { 1123885Sahrens /* 1124885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1125885Sahrens * the objset is held exclusively. Fortunately this hold is 1126885Sahrens * only for a short while, so we retry here. 1127885Sahrens * This avoids user code having to handle EBUSY, 1128885Sahrens * for example for a "zfs list". 1129885Sahrens */ 1130885Sahrens if (error == EBUSY) { 1131885Sahrens delay(1); 1132885Sahrens goto retry; 1133885Sahrens } 1134885Sahrens if (error == ENOENT) 1135885Sahrens error = ESRCH; 1136885Sahrens return (error); 1137789Sahrens } 1138789Sahrens 1139789Sahrens p = strrchr(zc->zc_name, '/'); 1140789Sahrens if (p == NULL || p[1] != '\0') 1141789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1142789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1143789Sahrens 1144789Sahrens do { 1145885Sahrens error = dmu_dir_list_next(os, 1146885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1147885Sahrens NULL, &zc->zc_cookie); 1148789Sahrens if (error == ENOENT) 1149789Sahrens error = ESRCH; 1150885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1151789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 1152789Sahrens 1153885Sahrens /* 1154885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1155885Sahrens * try to get stats for it. Userland will skip over it. 1156885Sahrens */ 1157885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1158885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1159789Sahrens 1160885Sahrens dmu_objset_close(os); 1161789Sahrens return (error); 1162789Sahrens } 1163789Sahrens 1164789Sahrens static int 1165789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1166789Sahrens { 1167885Sahrens objset_t *os; 1168789Sahrens int error; 1169789Sahrens 1170789Sahrens retry: 1171885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1172885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1173885Sahrens if (error != 0) { 1174789Sahrens /* 1175885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1176789Sahrens * the objset is held exclusively. Fortunately this hold is 1177789Sahrens * only for a short while, so we retry here. 1178789Sahrens * This avoids user code having to handle EBUSY, 1179885Sahrens * for example for a "zfs list". 1180789Sahrens */ 1181789Sahrens if (error == EBUSY) { 1182789Sahrens delay(1); 1183789Sahrens goto retry; 1184789Sahrens } 1185789Sahrens if (error == ENOENT) 1186885Sahrens error = ESRCH; 1187789Sahrens return (error); 1188789Sahrens } 1189789Sahrens 11901003Slling /* 11911003Slling * A dataset name of maximum length cannot have any snapshots, 11921003Slling * so exit immediately. 11931003Slling */ 11941003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1195885Sahrens dmu_objset_close(os); 11961003Slling return (ESRCH); 1197789Sahrens } 1198789Sahrens 1199885Sahrens error = dmu_snapshot_list_next(os, 1200885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 1201885Sahrens zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie); 1202789Sahrens if (error == ENOENT) 1203789Sahrens error = ESRCH; 1204789Sahrens 1205885Sahrens if (error == 0) 1206885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1207789Sahrens 1208885Sahrens dmu_objset_close(os); 1209789Sahrens return (error); 1210789Sahrens } 1211789Sahrens 1212789Sahrens static int 12134787Sahrens zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) 1214789Sahrens { 12152676Seschrock nvpair_t *elem; 12162676Seschrock int error; 12172676Seschrock uint64_t intval; 12182676Seschrock char *strval; 12192676Seschrock 12204543Smarks /* 12214543Smarks * First validate permission to set all of the properties 12224543Smarks */ 12232676Seschrock elem = NULL; 12242676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 12254670Sahrens const char *propname = nvpair_name(elem); 12264670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 12272676Seschrock 1228*5094Slling if (prop == ZPROP_INVAL) { 12292676Seschrock /* 12302676Seschrock * If this is a user-defined property, it must be a 12312676Seschrock * string, and there is no further validation to do. 12322676Seschrock */ 12332676Seschrock if (!zfs_prop_user(propname) || 12342676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 12352676Seschrock return (EINVAL); 12362676Seschrock 12374543Smarks error = zfs_secpolicy_write_perms(name, 12384787Sahrens ZFS_DELEG_PERM_USERPROP, CRED()); 12394670Sahrens if (error) 12404670Sahrens return (error); 12414543Smarks continue; 12422676Seschrock } 12432676Seschrock 12444787Sahrens if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 12454670Sahrens return (error); 12462676Seschrock 12474670Sahrens /* 12484670Sahrens * Check that this value is valid for this pool version 12494670Sahrens */ 12504670Sahrens switch (prop) { 12513886Sahl case ZFS_PROP_COMPRESSION: 12523886Sahl /* 12533886Sahl * If the user specified gzip compression, make sure 12543886Sahl * the SPA supports it. We ignore any errors here since 12553886Sahl * we'll catch them later. 12563886Sahl */ 12573886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 12583886Sahl nvpair_value_uint64(elem, &intval) == 0 && 12593886Sahl intval >= ZIO_COMPRESS_GZIP_1 && 12603886Sahl intval <= ZIO_COMPRESS_GZIP_9) { 12614543Smarks spa_t *spa; 12624543Smarks 12634603Sahrens if (spa_open(name, &spa, FTAG) == 0) { 12643886Sahl if (spa_version(spa) < 12654577Sahrens SPA_VERSION_GZIP_COMPRESSION) { 12663886Sahl spa_close(spa, FTAG); 12673886Sahl return (ENOTSUP); 12683886Sahl } 12693886Sahl 12703886Sahl spa_close(spa, FTAG); 12713886Sahl } 12723886Sahl } 12733886Sahl break; 12744603Sahrens 12754603Sahrens case ZFS_PROP_COPIES: 12764603Sahrens { 12774603Sahrens spa_t *spa; 12784603Sahrens 12794603Sahrens if (spa_open(name, &spa, FTAG) == 0) { 12804603Sahrens if (spa_version(spa) < 12814603Sahrens SPA_VERSION_DITTO_BLOCKS) { 12824603Sahrens spa_close(spa, FTAG); 12834603Sahrens return (ENOTSUP); 12844603Sahrens } 12854603Sahrens spa_close(spa, FTAG); 12864603Sahrens } 12874603Sahrens break; 12884603Sahrens } 12892676Seschrock } 12904543Smarks } 12914543Smarks 12924543Smarks elem = NULL; 12934543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 12944670Sahrens const char *propname = nvpair_name(elem); 12954670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 12964543Smarks 1297*5094Slling if (prop == ZPROP_INVAL) { 12984543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 12994543Smarks error = dsl_prop_set(name, propname, 1, 13004543Smarks strlen(strval) + 1, strval); 13014543Smarks if (error == 0) 13024543Smarks continue; 13034543Smarks else 13044543Smarks return (error); 13054543Smarks } 13062676Seschrock 13072676Seschrock switch (prop) { 13082676Seschrock case ZFS_PROP_QUOTA: 13092676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13104577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 13112676Seschrock return (error); 13122676Seschrock break; 13132676Seschrock 13142676Seschrock case ZFS_PROP_RESERVATION: 13152676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13162676Seschrock (error = dsl_dir_set_reservation(name, 13172676Seschrock intval)) != 0) 13182676Seschrock return (error); 13192676Seschrock break; 1320789Sahrens 13212676Seschrock case ZFS_PROP_VOLSIZE: 13222676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13234787Sahrens (error = zvol_set_volsize(name, 13244787Sahrens ddi_driver_major(zfs_dip), intval)) != 0) 13252676Seschrock return (error); 13262676Seschrock break; 13272676Seschrock 13282676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 13292676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13304577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 13314577Sahrens return (error); 13324577Sahrens break; 13334577Sahrens 13344577Sahrens case ZFS_PROP_VERSION: 13354577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13364577Sahrens (error = zfs_set_version(name, intval)) != 0) 13372676Seschrock return (error); 13382676Seschrock break; 13392676Seschrock 13402676Seschrock default: 13412676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 13422676Seschrock if (zfs_prop_get_type(prop) != 13434787Sahrens PROP_TYPE_STRING) 13442676Seschrock return (EINVAL); 13452717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 13462717Seschrock if ((error = dsl_prop_set(name, 13472676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 13482717Seschrock strval)) != 0) 13492717Seschrock return (error); 13502676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 13512885Sahrens const char *unused; 13522885Sahrens 13532717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 13542676Seschrock 13552676Seschrock switch (zfs_prop_get_type(prop)) { 13564787Sahrens case PROP_TYPE_NUMBER: 13572676Seschrock break; 13584787Sahrens case PROP_TYPE_STRING: 13592717Seschrock return (EINVAL); 13604787Sahrens case PROP_TYPE_INDEX: 13612717Seschrock if (zfs_prop_index_to_string(prop, 13622717Seschrock intval, &unused) != 0) 13632717Seschrock return (EINVAL); 13642676Seschrock break; 13652676Seschrock default: 13664577Sahrens cmn_err(CE_PANIC, 13674577Sahrens "unknown property type"); 13682676Seschrock break; 13692676Seschrock } 13702676Seschrock 13712717Seschrock if ((error = dsl_prop_set(name, propname, 13722717Seschrock 8, 1, &intval)) != 0) 13732717Seschrock return (error); 13742676Seschrock } else { 13752676Seschrock return (EINVAL); 13762676Seschrock } 13772676Seschrock break; 13782676Seschrock } 13792676Seschrock } 13802676Seschrock 13812676Seschrock return (0); 1382789Sahrens } 1383789Sahrens 1384789Sahrens static int 13852676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1386789Sahrens { 13872676Seschrock nvlist_t *nvl; 13882676Seschrock int error; 1389789Sahrens 1390*5094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 1391*5094Slling &nvl)) != 0) 13922676Seschrock return (error); 13932676Seschrock 13944787Sahrens error = zfs_set_prop_nvlist(zc->zc_name, nvl); 13954543Smarks 13962676Seschrock nvlist_free(nvl); 13972676Seschrock return (error); 1398789Sahrens } 1399789Sahrens 1400789Sahrens static int 14014849Sahrens zfs_ioc_inherit_prop(zfs_cmd_t *zc) 14024849Sahrens { 14034849Sahrens /* the property name has been validated by zfs_secpolicy_inherit() */ 14044849Sahrens return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 14054849Sahrens } 14064849Sahrens 14074849Sahrens static int 14084098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 14093912Slling { 1410*5094Slling nvlist_t *props; 14113912Slling spa_t *spa; 1412*5094Slling int error; 14133912Slling 1414*5094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 1415*5094Slling &props))) 14163912Slling return (error); 14173912Slling 14183912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 1419*5094Slling nvlist_free(props); 14203912Slling return (error); 14213912Slling } 14223912Slling 1423*5094Slling error = spa_prop_set(spa, props); 14243912Slling 1425*5094Slling nvlist_free(props); 14263912Slling spa_close(spa, FTAG); 14273912Slling 14283912Slling return (error); 14293912Slling } 14303912Slling 14313912Slling static int 14324098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 14333912Slling { 14343912Slling spa_t *spa; 14353912Slling int error; 14363912Slling nvlist_t *nvp = NULL; 14373912Slling 14383912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 14393912Slling return (error); 14403912Slling 1441*5094Slling error = spa_prop_get(spa, &nvp); 14423912Slling 14433912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 14443912Slling error = put_nvlist(zc, nvp); 14453912Slling else 14463912Slling error = EFAULT; 14473912Slling 14483912Slling spa_close(spa, FTAG); 14493912Slling 14503912Slling if (nvp) 14513912Slling nvlist_free(nvp); 14523912Slling return (error); 14533912Slling } 14543912Slling 14553912Slling static int 14564543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 14574543Smarks { 14584543Smarks nvlist_t *nvp; 14594543Smarks int error; 14604543Smarks uint32_t uid; 14614543Smarks uint32_t gid; 14624543Smarks uint32_t *groups; 14634543Smarks uint_t group_cnt; 14644543Smarks cred_t *usercred; 14654543Smarks 1466*5094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 1467*5094Slling &nvp)) != 0) { 14684543Smarks return (error); 14694543Smarks } 14704543Smarks 14714543Smarks if ((error = nvlist_lookup_uint32(nvp, 14724543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 14734543Smarks nvlist_free(nvp); 14744543Smarks return (EPERM); 14754543Smarks } 14764543Smarks 14774543Smarks if ((error = nvlist_lookup_uint32(nvp, 14784543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 14794543Smarks nvlist_free(nvp); 14804543Smarks return (EPERM); 14814543Smarks } 14824543Smarks 14834543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 14844543Smarks &groups, &group_cnt)) != 0) { 14854543Smarks nvlist_free(nvp); 14864543Smarks return (EPERM); 14874543Smarks } 14884543Smarks usercred = cralloc(); 14894543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 14904543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 14914543Smarks nvlist_free(nvp); 14924543Smarks crfree(usercred); 14934543Smarks return (EPERM); 14944543Smarks } 14954543Smarks nvlist_free(nvp); 14964543Smarks error = dsl_deleg_access(zc->zc_name, 14974787Sahrens zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); 14984543Smarks crfree(usercred); 14994543Smarks return (error); 15004543Smarks } 15014543Smarks 15024543Smarks static int 15034543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 15044543Smarks { 15054543Smarks int error; 15064543Smarks nvlist_t *fsaclnv = NULL; 15074543Smarks 1508*5094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 1509*5094Slling &fsaclnv)) != 0) 15104543Smarks return (error); 15114543Smarks 15124543Smarks /* 15134543Smarks * Verify nvlist is constructed correctly 15144543Smarks */ 15154543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 15164543Smarks nvlist_free(fsaclnv); 15174543Smarks return (EINVAL); 15184543Smarks } 15194543Smarks 15204543Smarks /* 15214543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 15224543Smarks * that user is allowed to hand out each permission in 15234543Smarks * the nvlist(s) 15244543Smarks */ 15254543Smarks 15264787Sahrens error = secpolicy_zfs(CRED()); 15274543Smarks if (error) { 15284787Sahrens if (zc->zc_perm_action == B_FALSE) { 15294787Sahrens error = dsl_deleg_can_allow(zc->zc_name, 15304787Sahrens fsaclnv, CRED()); 15314787Sahrens } else { 15324787Sahrens error = dsl_deleg_can_unallow(zc->zc_name, 15334787Sahrens fsaclnv, CRED()); 15344787Sahrens } 15354543Smarks } 15364543Smarks 15374543Smarks if (error == 0) 15384543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 15394543Smarks 15404543Smarks nvlist_free(fsaclnv); 15414543Smarks return (error); 15424543Smarks } 15434543Smarks 15444543Smarks static int 15454543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 15464543Smarks { 15474543Smarks nvlist_t *nvp; 15484543Smarks int error; 15494543Smarks 15504543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 15514543Smarks error = put_nvlist(zc, nvp); 15524543Smarks nvlist_free(nvp); 15534543Smarks } 15544543Smarks 15554543Smarks return (error); 15564543Smarks } 15574543Smarks 15584543Smarks static int 1559789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1560789Sahrens { 15614787Sahrens return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); 1562789Sahrens } 1563789Sahrens 1564789Sahrens static int 1565789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1566789Sahrens { 15672676Seschrock return (zvol_remove_minor(zc->zc_name)); 1568789Sahrens } 1569789Sahrens 1570789Sahrens /* 1571789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1572789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1573789Sahrens * is responsible for releasing the returned vfs pointer. 1574789Sahrens */ 1575789Sahrens static vfs_t * 1576789Sahrens zfs_get_vfs(const char *resource) 1577789Sahrens { 1578789Sahrens struct vfs *vfsp; 1579789Sahrens struct vfs *vfs_found = NULL; 1580789Sahrens 1581789Sahrens vfs_list_read_lock(); 1582789Sahrens vfsp = rootvfs; 1583789Sahrens do { 1584789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1585789Sahrens VFS_HOLD(vfsp); 1586789Sahrens vfs_found = vfsp; 1587789Sahrens break; 1588789Sahrens } 1589789Sahrens vfsp = vfsp->vfs_next; 1590789Sahrens } while (vfsp != rootvfs); 1591789Sahrens vfs_list_unlock(); 1592789Sahrens return (vfs_found); 1593789Sahrens } 1594789Sahrens 15954543Smarks /* ARGSUSED */ 1596789Sahrens static void 15974543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1598789Sahrens { 15994577Sahrens nvlist_t *nvprops = arg; 16004577Sahrens uint64_t version = ZPL_VERSION; 16014577Sahrens 16024577Sahrens (void) nvlist_lookup_uint64(nvprops, 16034577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version); 16044577Sahrens 16054577Sahrens zfs_create_fs(os, cr, version, tx); 1606789Sahrens } 1607789Sahrens 1608789Sahrens static int 1609789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1610789Sahrens { 1611789Sahrens objset_t *clone; 1612789Sahrens int error = 0; 16134543Smarks nvlist_t *nvprops = NULL; 16144543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1615789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1616789Sahrens 1617789Sahrens switch (type) { 1618789Sahrens 1619789Sahrens case DMU_OST_ZFS: 1620789Sahrens cbfunc = zfs_create_cb; 1621789Sahrens break; 1622789Sahrens 1623789Sahrens case DMU_OST_ZVOL: 1624789Sahrens cbfunc = zvol_create_cb; 1625789Sahrens break; 1626789Sahrens 1627789Sahrens default: 16282199Sahrens cbfunc = NULL; 16292199Sahrens } 16302199Sahrens if (strchr(zc->zc_name, '@')) 1631789Sahrens return (EINVAL); 1632789Sahrens 16332676Seschrock if (zc->zc_nvlist_src != NULL && 1634*5094Slling (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 1635*5094Slling &nvprops)) != 0) 16362676Seschrock return (error); 16372676Seschrock 16382676Seschrock if (zc->zc_value[0] != '\0') { 1639789Sahrens /* 1640789Sahrens * We're creating a clone of an existing snapshot. 1641789Sahrens */ 16422676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 16432676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 16444543Smarks nvlist_free(nvprops); 1645789Sahrens return (EINVAL); 16462676Seschrock } 1647789Sahrens 16482676Seschrock error = dmu_objset_open(zc->zc_value, type, 1649789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 16502676Seschrock if (error) { 16514543Smarks nvlist_free(nvprops); 1652789Sahrens return (error); 16532676Seschrock } 1654789Sahrens error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); 1655789Sahrens dmu_objset_close(clone); 1656789Sahrens } else { 16572676Seschrock if (cbfunc == NULL) { 16584543Smarks nvlist_free(nvprops); 16592199Sahrens return (EINVAL); 16602676Seschrock } 16612676Seschrock 1662789Sahrens if (type == DMU_OST_ZVOL) { 16632676Seschrock uint64_t volsize, volblocksize; 16642676Seschrock 16654543Smarks if (nvprops == NULL || 16664543Smarks nvlist_lookup_uint64(nvprops, 16672676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 16682676Seschrock &volsize) != 0) { 16694543Smarks nvlist_free(nvprops); 16702676Seschrock return (EINVAL); 16712676Seschrock } 16722676Seschrock 16734543Smarks if ((error = nvlist_lookup_uint64(nvprops, 16742676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 16752676Seschrock &volblocksize)) != 0 && error != ENOENT) { 16764543Smarks nvlist_free(nvprops); 16772676Seschrock return (EINVAL); 16782676Seschrock } 16791133Seschrock 16802676Seschrock if (error != 0) 16812676Seschrock volblocksize = zfs_prop_default_numeric( 16822676Seschrock ZFS_PROP_VOLBLOCKSIZE); 16832676Seschrock 16842676Seschrock if ((error = zvol_check_volblocksize( 16852676Seschrock volblocksize)) != 0 || 16862676Seschrock (error = zvol_check_volsize(volsize, 16872676Seschrock volblocksize)) != 0) { 16884543Smarks nvlist_free(nvprops); 1689789Sahrens return (error); 16902676Seschrock } 16914577Sahrens } else if (type == DMU_OST_ZFS) { 16924577Sahrens uint64_t version; 16934577Sahrens 16944577Sahrens if (0 == nvlist_lookup_uint64(nvprops, 16954577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version) && 16964577Sahrens (version < ZPL_VERSION_INITIAL || 16974577Sahrens version > ZPL_VERSION)) { 16984577Sahrens nvlist_free(nvprops); 16994577Sahrens return (EINVAL); 17004577Sahrens } 17012676Seschrock } 17021133Seschrock 17032676Seschrock error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, 17044543Smarks nvprops); 1705789Sahrens } 17062676Seschrock 17072676Seschrock /* 17082676Seschrock * It would be nice to do this atomically. 17092676Seschrock */ 17102676Seschrock if (error == 0) { 17114787Sahrens if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) 17122676Seschrock (void) dmu_objset_destroy(zc->zc_name); 17132676Seschrock } 17142676Seschrock 17154543Smarks nvlist_free(nvprops); 1716789Sahrens return (error); 1717789Sahrens } 1718789Sahrens 1719789Sahrens static int 17202199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 17212199Sahrens { 17222676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 17232199Sahrens return (EINVAL); 17242199Sahrens return (dmu_objset_snapshot(zc->zc_name, 17252676Seschrock zc->zc_value, zc->zc_cookie)); 17262199Sahrens } 17272199Sahrens 17284007Smmusante int 17292199Sahrens zfs_unmount_snap(char *name, void *arg) 1730789Sahrens { 17312199Sahrens char *snapname = arg; 17322199Sahrens char *cp; 17332417Sahrens vfs_t *vfsp = NULL; 17342199Sahrens 17352199Sahrens /* 17362199Sahrens * Snapshots (which are under .zfs control) must be unmounted 17372199Sahrens * before they can be destroyed. 17382199Sahrens */ 17392199Sahrens 17402199Sahrens if (snapname) { 17412199Sahrens (void) strcat(name, "@"); 17422199Sahrens (void) strcat(name, snapname); 17432199Sahrens vfsp = zfs_get_vfs(name); 17442199Sahrens cp = strchr(name, '@'); 17452199Sahrens *cp = '\0'; 17462417Sahrens } else if (strchr(name, '@')) { 17472199Sahrens vfsp = zfs_get_vfs(name); 17482199Sahrens } 17492199Sahrens 17502199Sahrens if (vfsp) { 17512199Sahrens /* 17522199Sahrens * Always force the unmount for snapshots. 17532199Sahrens */ 17542199Sahrens int flag = MS_FORCE; 1755789Sahrens int err; 1756789Sahrens 17572199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 17582199Sahrens VFS_RELE(vfsp); 17592199Sahrens return (err); 17602199Sahrens } 17612199Sahrens VFS_RELE(vfsp); 17622199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 17632199Sahrens return (err); 17642199Sahrens } 17652199Sahrens return (0); 17662199Sahrens } 17672199Sahrens 17682199Sahrens static int 17692199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 17702199Sahrens { 17712199Sahrens int err; 1772789Sahrens 17732676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 17742199Sahrens return (EINVAL); 17752199Sahrens err = dmu_objset_find(zc->zc_name, 17762676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 17772199Sahrens if (err) 17782199Sahrens return (err); 17792676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 17802199Sahrens } 17812199Sahrens 17822199Sahrens static int 17832199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 17842199Sahrens { 17852199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 17862199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 17872199Sahrens if (err) 17882199Sahrens return (err); 1789789Sahrens } 1790789Sahrens 1791789Sahrens return (dmu_objset_destroy(zc->zc_name)); 1792789Sahrens } 1793789Sahrens 1794789Sahrens static int 1795789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 1796789Sahrens { 1797789Sahrens return (dmu_objset_rollback(zc->zc_name)); 1798789Sahrens } 1799789Sahrens 1800789Sahrens static int 1801789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 1802789Sahrens { 18034490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 18044007Smmusante 18052676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 18062676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) 1807789Sahrens return (EINVAL); 1808789Sahrens 18094007Smmusante /* 18104007Smmusante * Unmount snapshot unless we're doing a recursive rename, 18114007Smmusante * in which case the dataset code figures out which snapshots 18124007Smmusante * to unmount. 18134007Smmusante */ 18144007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 1815789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 18162199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18172199Sahrens if (err) 18182199Sahrens return (err); 1819789Sahrens } 1820789Sahrens 18214007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 1822789Sahrens } 1823789Sahrens 1824789Sahrens static int 1825789Sahrens zfs_ioc_recvbackup(zfs_cmd_t *zc) 1826789Sahrens { 1827789Sahrens file_t *fp; 1828789Sahrens int error, fd; 18292885Sahrens offset_t new_off; 1830789Sahrens 18313265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 18323265Sahrens strchr(zc->zc_value, '@') == NULL) 18333265Sahrens return (EINVAL); 18343265Sahrens 1835789Sahrens fd = zc->zc_cookie; 1836789Sahrens fp = getf(fd); 1837789Sahrens if (fp == NULL) 1838789Sahrens return (EBADF); 18392676Seschrock error = dmu_recvbackup(zc->zc_value, &zc->zc_begin_record, 18402676Seschrock &zc->zc_cookie, (boolean_t)zc->zc_guid, fp->f_vnode, 18412665Snd150628 fp->f_offset); 18422885Sahrens 18432885Sahrens new_off = fp->f_offset + zc->zc_cookie; 18442885Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &new_off) == 0) 18452885Sahrens fp->f_offset = new_off; 18462885Sahrens 1847789Sahrens releasef(fd); 1848789Sahrens return (error); 1849789Sahrens } 1850789Sahrens 1851789Sahrens static int 1852789Sahrens zfs_ioc_sendbackup(zfs_cmd_t *zc) 1853789Sahrens { 1854789Sahrens objset_t *fromsnap = NULL; 1855789Sahrens objset_t *tosnap; 1856789Sahrens file_t *fp; 1857789Sahrens int error; 1858789Sahrens 1859789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1860789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); 1861789Sahrens if (error) 1862789Sahrens return (error); 1863789Sahrens 18642676Seschrock if (zc->zc_value[0] != '\0') { 18652885Sahrens char buf[MAXPATHLEN]; 18662885Sahrens char *cp; 18672885Sahrens 18682885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 18692885Sahrens cp = strchr(buf, '@'); 18702885Sahrens if (cp) 18712885Sahrens *(cp+1) = 0; 18722885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 18732885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 1874789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); 1875789Sahrens if (error) { 1876789Sahrens dmu_objset_close(tosnap); 1877789Sahrens return (error); 1878789Sahrens } 1879789Sahrens } 1880789Sahrens 1881789Sahrens fp = getf(zc->zc_cookie); 1882789Sahrens if (fp == NULL) { 1883789Sahrens dmu_objset_close(tosnap); 1884789Sahrens if (fromsnap) 1885789Sahrens dmu_objset_close(fromsnap); 1886789Sahrens return (EBADF); 1887789Sahrens } 1888789Sahrens 1889789Sahrens error = dmu_sendbackup(tosnap, fromsnap, fp->f_vnode); 1890789Sahrens 1891789Sahrens releasef(zc->zc_cookie); 1892789Sahrens if (fromsnap) 1893789Sahrens dmu_objset_close(fromsnap); 1894789Sahrens dmu_objset_close(tosnap); 1895789Sahrens return (error); 1896789Sahrens } 1897789Sahrens 18981544Seschrock static int 18991544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 19001544Seschrock { 19011544Seschrock int id, error; 19021544Seschrock 19031544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 19041544Seschrock &zc->zc_inject_record); 19051544Seschrock 19061544Seschrock if (error == 0) 19071544Seschrock zc->zc_guid = (uint64_t)id; 19081544Seschrock 19091544Seschrock return (error); 19101544Seschrock } 19111544Seschrock 19121544Seschrock static int 19131544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 19141544Seschrock { 19151544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 19161544Seschrock } 19171544Seschrock 19181544Seschrock static int 19191544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 19201544Seschrock { 19211544Seschrock int id = (int)zc->zc_guid; 19221544Seschrock int error; 19231544Seschrock 19241544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 19251544Seschrock &zc->zc_inject_record); 19261544Seschrock 19271544Seschrock zc->zc_guid = id; 19281544Seschrock 19291544Seschrock return (error); 19301544Seschrock } 19311544Seschrock 19321544Seschrock static int 19331544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 19341544Seschrock { 19351544Seschrock spa_t *spa; 19361544Seschrock int error; 19372676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 19381544Seschrock 19391544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 19401544Seschrock return (error); 19411544Seschrock 19422676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 19431544Seschrock &count); 19441544Seschrock if (error == 0) 19452676Seschrock zc->zc_nvlist_dst_size = count; 19461544Seschrock else 19472676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 19481544Seschrock 19491544Seschrock spa_close(spa, FTAG); 19501544Seschrock 19511544Seschrock return (error); 19521544Seschrock } 19531544Seschrock 19541544Seschrock static int 19551544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 19561544Seschrock { 19571544Seschrock spa_t *spa; 19581544Seschrock vdev_t *vd; 19594808Sek110237 uint64_t txg; 19601544Seschrock int error; 19611544Seschrock 19621544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 19631544Seschrock return (error); 19641544Seschrock 19654451Seschrock txg = spa_vdev_enter(spa); 19661544Seschrock 19672676Seschrock if (zc->zc_guid == 0) { 19681544Seschrock vd = NULL; 19692676Seschrock } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { 19704451Seschrock (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 19711544Seschrock spa_close(spa, FTAG); 19721544Seschrock return (ENODEV); 19731544Seschrock } 19741544Seschrock 19751544Seschrock vdev_clear(spa, vd); 19761544Seschrock 19774451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 19781544Seschrock 19791544Seschrock spa_close(spa, FTAG); 19801544Seschrock 19811544Seschrock return (0); 19821544Seschrock } 19831544Seschrock 19841544Seschrock static int 19852082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 19862082Seschrock { 19872417Sahrens char *cp; 19882417Sahrens 19892417Sahrens /* 19902417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 19912417Sahrens * it's easier. 19922417Sahrens */ 19932676Seschrock cp = strchr(zc->zc_value, '@'); 19942417Sahrens if (cp) 19952417Sahrens *cp = '\0'; 19962676Seschrock (void) dmu_objset_find(zc->zc_value, 19972417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 19982082Seschrock return (dsl_dataset_promote(zc->zc_name)); 19992082Seschrock } 20002082Seschrock 20014543Smarks /* 20024543Smarks * We don't want to have a hard dependency 20034543Smarks * against some special symbols in sharefs 20044543Smarks * and nfs. Determine them if needed when 20054543Smarks * the first file system is shared. 20064543Smarks * Neither sharefs or nfs are unloadable modules. 20074543Smarks */ 20084543Smarks int (*zexport_fs)(void *arg); 20094543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 20104543Smarks 20114543Smarks int zfs_share_inited; 20124543Smarks ddi_modhandle_t nfs_mod; 20134543Smarks ddi_modhandle_t sharefs_mod; 20144543Smarks kmutex_t zfs_share_lock; 20154543Smarks 20164543Smarks static int 20174543Smarks zfs_ioc_share(zfs_cmd_t *zc) 20184543Smarks { 20194543Smarks int error; 20204543Smarks int opcode; 20214543Smarks 20224543Smarks if (zfs_share_inited == 0) { 20234543Smarks mutex_enter(&zfs_share_lock); 20244543Smarks nfs_mod = ddi_modopen("fs/nfs", KRTLD_MODE_FIRST, &error); 20254543Smarks sharefs_mod = ddi_modopen("fs/sharefs", 20264543Smarks KRTLD_MODE_FIRST, &error); 20274543Smarks if (nfs_mod == NULL || sharefs_mod == NULL) { 20284543Smarks mutex_exit(&zfs_share_lock); 20294543Smarks return (ENOSYS); 20304543Smarks } 20314543Smarks if (zexport_fs == NULL && ((zexport_fs = (int (*)(void *)) 20324543Smarks ddi_modsym(nfs_mod, "nfs_export", &error)) == NULL)) { 20334543Smarks mutex_exit(&zfs_share_lock); 20344543Smarks return (ENOSYS); 20354543Smarks } 20364543Smarks 20374543Smarks if (zshare_fs == NULL && ((zshare_fs = 20384543Smarks (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 20394543Smarks ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 20404543Smarks mutex_exit(&zfs_share_lock); 20414543Smarks return (ENOSYS); 20424543Smarks } 20434543Smarks zfs_share_inited = 1; 20444543Smarks mutex_exit(&zfs_share_lock); 20454543Smarks } 20464543Smarks 20474543Smarks if (error = zexport_fs((void *)(uintptr_t)zc->zc_share.z_exportdata)) 20484543Smarks return (error); 20494543Smarks 20504543Smarks opcode = (zc->zc_share.z_sharetype == B_TRUE) ? 20514543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 20524543Smarks 20534543Smarks error = zshare_fs(opcode, 20544543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 20554543Smarks zc->zc_share.z_sharemax); 20564543Smarks 20574543Smarks return (error); 20584543Smarks 20594543Smarks } 20604543Smarks 20614543Smarks /* 20624988Sek110237 * pool create, destroy, and export don't log the history as part of 20634988Sek110237 * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export 20644988Sek110237 * do the logging of those commands. 20654543Smarks */ 2066789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 20674715Sek110237 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 20684577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 20694577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20704577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 20714577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 20724577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 20734577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 20744577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20754577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 20764577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20774577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 20784577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20794577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20804577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20814577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20824577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20834577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 20844577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 20854543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 20864577Sahrens DATASET_NAME, B_FALSE }, 20874543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 20884577Sahrens DATASET_NAME, B_FALSE }, 20894577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 20904577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 20914577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 20924577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 20934577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 20944577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 20954577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 20964577Sahrens { zfs_ioc_recvbackup, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 20974577Sahrens { zfs_ioc_sendbackup, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 20984577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 20994577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21004577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21014577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 21024577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21034577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 21044577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 21054577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 21064577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21074577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21084577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21094577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 21104577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 21114577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 21124543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 21134577Sahrens DATASET_NAME, B_FALSE }, 21144849Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }, 21154849Sahrens { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE }, 2116789Sahrens }; 2117789Sahrens 2118789Sahrens static int 2119789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2120789Sahrens { 2121789Sahrens zfs_cmd_t *zc; 2122789Sahrens uint_t vec; 21232199Sahrens int error, rc; 2124789Sahrens 2125789Sahrens if (getminor(dev) != 0) 2126789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2127789Sahrens 2128789Sahrens vec = cmd - ZFS_IOC; 21294787Sahrens ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); 2130789Sahrens 2131789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2132789Sahrens return (EINVAL); 2133789Sahrens 2134789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2135789Sahrens 2136789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2137789Sahrens 21384787Sahrens if (error == 0) 21394543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2140789Sahrens 2141789Sahrens /* 2142789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2143789Sahrens * the lower layers. 2144789Sahrens */ 2145789Sahrens if (error == 0) { 2146789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2147789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 21484577Sahrens case POOL_NAME: 2149789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2150789Sahrens error = EINVAL; 2151789Sahrens break; 2152789Sahrens 21534577Sahrens case DATASET_NAME: 2154789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2155789Sahrens error = EINVAL; 2156789Sahrens break; 21572856Snd150628 21584577Sahrens case NO_NAME: 21592856Snd150628 break; 2160789Sahrens } 2161789Sahrens } 2162789Sahrens 2163789Sahrens if (error == 0) 2164789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2165789Sahrens 21662199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 21674543Smarks if (error == 0) { 21682199Sahrens error = rc; 21694543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 21704543Smarks zfs_log_history(zc); 21714543Smarks } 2172789Sahrens 2173789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2174789Sahrens return (error); 2175789Sahrens } 2176789Sahrens 2177789Sahrens static int 2178789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2179789Sahrens { 2180789Sahrens if (cmd != DDI_ATTACH) 2181789Sahrens return (DDI_FAILURE); 2182789Sahrens 2183789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2184789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2185789Sahrens return (DDI_FAILURE); 2186789Sahrens 2187789Sahrens zfs_dip = dip; 2188789Sahrens 2189789Sahrens ddi_report_dev(dip); 2190789Sahrens 2191789Sahrens return (DDI_SUCCESS); 2192789Sahrens } 2193789Sahrens 2194789Sahrens static int 2195789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2196789Sahrens { 2197789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2198789Sahrens return (DDI_FAILURE); 2199789Sahrens 2200789Sahrens if (cmd != DDI_DETACH) 2201789Sahrens return (DDI_FAILURE); 2202789Sahrens 2203789Sahrens zfs_dip = NULL; 2204789Sahrens 2205789Sahrens ddi_prop_remove_all(dip); 2206789Sahrens ddi_remove_minor_node(dip, NULL); 2207789Sahrens 2208789Sahrens return (DDI_SUCCESS); 2209789Sahrens } 2210789Sahrens 2211789Sahrens /*ARGSUSED*/ 2212789Sahrens static int 2213789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2214789Sahrens { 2215789Sahrens switch (infocmd) { 2216789Sahrens case DDI_INFO_DEVT2DEVINFO: 2217789Sahrens *result = zfs_dip; 2218789Sahrens return (DDI_SUCCESS); 2219789Sahrens 2220789Sahrens case DDI_INFO_DEVT2INSTANCE: 2221849Sbonwick *result = (void *)0; 2222789Sahrens return (DDI_SUCCESS); 2223789Sahrens } 2224789Sahrens 2225789Sahrens return (DDI_FAILURE); 2226789Sahrens } 2227789Sahrens 2228789Sahrens /* 2229789Sahrens * OK, so this is a little weird. 2230789Sahrens * 2231789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2232789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2233789Sahrens * 2234789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2235789Sahrens * so most of the standard driver entry points are in zvol.c. 2236789Sahrens */ 2237789Sahrens static struct cb_ops zfs_cb_ops = { 2238789Sahrens zvol_open, /* open */ 2239789Sahrens zvol_close, /* close */ 2240789Sahrens zvol_strategy, /* strategy */ 2241789Sahrens nodev, /* print */ 2242789Sahrens nodev, /* dump */ 2243789Sahrens zvol_read, /* read */ 2244789Sahrens zvol_write, /* write */ 2245789Sahrens zfsdev_ioctl, /* ioctl */ 2246789Sahrens nodev, /* devmap */ 2247789Sahrens nodev, /* mmap */ 2248789Sahrens nodev, /* segmap */ 2249789Sahrens nochpoll, /* poll */ 2250789Sahrens ddi_prop_op, /* prop_op */ 2251789Sahrens NULL, /* streamtab */ 2252789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2253789Sahrens CB_REV, /* version */ 22543638Sbillm nodev, /* async read */ 22553638Sbillm nodev, /* async write */ 2256789Sahrens }; 2257789Sahrens 2258789Sahrens static struct dev_ops zfs_dev_ops = { 2259789Sahrens DEVO_REV, /* version */ 2260789Sahrens 0, /* refcnt */ 2261789Sahrens zfs_info, /* info */ 2262789Sahrens nulldev, /* identify */ 2263789Sahrens nulldev, /* probe */ 2264789Sahrens zfs_attach, /* attach */ 2265789Sahrens zfs_detach, /* detach */ 2266789Sahrens nodev, /* reset */ 2267789Sahrens &zfs_cb_ops, /* driver operations */ 2268789Sahrens NULL /* no bus operations */ 2269789Sahrens }; 2270789Sahrens 2271789Sahrens static struct modldrv zfs_modldrv = { 22724577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 22732676Seschrock &zfs_dev_ops 2274789Sahrens }; 2275789Sahrens 2276789Sahrens static struct modlinkage modlinkage = { 2277789Sahrens MODREV_1, 2278789Sahrens (void *)&zfs_modlfs, 2279789Sahrens (void *)&zfs_modldrv, 2280789Sahrens NULL 2281789Sahrens }; 2282789Sahrens 22834720Sfr157268 22844720Sfr157268 uint_t zfs_fsyncer_key; 22854720Sfr157268 2286789Sahrens int 2287789Sahrens _init(void) 2288789Sahrens { 2289789Sahrens int error; 2290789Sahrens 2291849Sbonwick spa_init(FREAD | FWRITE); 2292849Sbonwick zfs_init(); 2293849Sbonwick zvol_init(); 2294849Sbonwick 2295849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 2296849Sbonwick zvol_fini(); 2297849Sbonwick zfs_fini(); 2298849Sbonwick spa_fini(); 2299789Sahrens return (error); 2300849Sbonwick } 2301789Sahrens 23024720Sfr157268 tsd_create(&zfs_fsyncer_key, NULL); 23034720Sfr157268 2304789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 2305789Sahrens ASSERT(error == 0); 23064543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 2307789Sahrens 2308789Sahrens return (0); 2309789Sahrens } 2310789Sahrens 2311789Sahrens int 2312789Sahrens _fini(void) 2313789Sahrens { 2314789Sahrens int error; 2315789Sahrens 23161544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 2317789Sahrens return (EBUSY); 2318789Sahrens 2319789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 2320789Sahrens return (error); 2321789Sahrens 2322789Sahrens zvol_fini(); 2323789Sahrens zfs_fini(); 2324789Sahrens spa_fini(); 23254543Smarks if (zfs_share_inited) { 23264543Smarks (void) ddi_modclose(nfs_mod); 23274543Smarks (void) ddi_modclose(sharefs_mod); 23284543Smarks } 2329789Sahrens 23304720Sfr157268 tsd_destroy(&zfs_fsyncer_key); 2331789Sahrens ldi_ident_release(zfs_li); 2332789Sahrens zfs_li = NULL; 23334543Smarks mutex_destroy(&zfs_share_lock); 2334789Sahrens 2335789Sahrens return (error); 2336789Sahrens } 2337789Sahrens 2338789Sahrens int 2339789Sahrens _info(struct modinfo *modinfop) 2340789Sahrens { 2341789Sahrens return (mod_info(&modlinkage, modinfop)); 2342789Sahrens } 2343