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 6024849Sahrens if (prop == ZFS_PROP_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 6182676Seschrock get_nvlist(zfs_cmd_t *zc, nvlist_t **nvp) 619789Sahrens { 620789Sahrens char *packed; 621789Sahrens size_t size; 622789Sahrens int error; 623789Sahrens nvlist_t *config = NULL; 624789Sahrens 625789Sahrens /* 6262676Seschrock * Read in and unpack the user-supplied nvlist. 627789Sahrens */ 6282676Seschrock if ((size = zc->zc_nvlist_src_size) == 0) 629789Sahrens return (EINVAL); 630789Sahrens 631789Sahrens packed = kmem_alloc(size, KM_SLEEP); 632789Sahrens 6332676Seschrock if ((error = xcopyin((void *)(uintptr_t)zc->zc_nvlist_src, packed, 634789Sahrens size)) != 0) { 635789Sahrens kmem_free(packed, size); 636789Sahrens return (error); 637789Sahrens } 638789Sahrens 639789Sahrens if ((error = nvlist_unpack(packed, size, &config, 0)) != 0) { 640789Sahrens kmem_free(packed, size); 641789Sahrens return (error); 642789Sahrens } 643789Sahrens 644789Sahrens kmem_free(packed, size); 645789Sahrens 646789Sahrens *nvp = config; 647789Sahrens return (0); 648789Sahrens } 649789Sahrens 650789Sahrens static int 6512676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 6522676Seschrock { 6532676Seschrock char *packed = NULL; 6542676Seschrock size_t size; 6552676Seschrock int error; 6562676Seschrock 6572676Seschrock VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 6582676Seschrock 6592676Seschrock if (size > zc->zc_nvlist_dst_size) { 6602676Seschrock error = ENOMEM; 6612676Seschrock } else { 6624611Smarks packed = kmem_alloc(size, KM_SLEEP); 6632676Seschrock VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 6642676Seschrock KM_SLEEP) == 0); 6652676Seschrock error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 6662676Seschrock size); 6672676Seschrock kmem_free(packed, size); 6682676Seschrock } 6692676Seschrock 6702676Seschrock zc->zc_nvlist_dst_size = size; 6712676Seschrock return (error); 6722676Seschrock } 6732676Seschrock 6742676Seschrock static int 675789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc) 676789Sahrens { 677789Sahrens int error; 678789Sahrens nvlist_t *config; 6794715Sek110237 char *buf; 680789Sahrens 681*4988Sek110237 if ((error = get_nvlist(zc, &config)) != 0) 682*4988Sek110237 return (error); 6834715Sek110237 684*4988Sek110237 buf = history_str_get(zc); 685789Sahrens 6862676Seschrock error = spa_create(zc->zc_name, config, zc->zc_value[0] == '\0' ? 6874715Sek110237 NULL : zc->zc_value, buf); 688789Sahrens 689*4988Sek110237 if (buf != NULL) 690*4988Sek110237 history_str_free(buf); 691789Sahrens nvlist_free(config); 692789Sahrens 693789Sahrens return (error); 694789Sahrens } 695789Sahrens 696789Sahrens static int 697789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc) 698789Sahrens { 6994543Smarks int error; 7004543Smarks zfs_log_history(zc); 7014543Smarks error = spa_destroy(zc->zc_name); 7024543Smarks return (error); 703789Sahrens } 704789Sahrens 705789Sahrens static int 706789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc) 707789Sahrens { 708789Sahrens int error; 709789Sahrens nvlist_t *config; 710789Sahrens uint64_t guid; 711789Sahrens 7122676Seschrock if ((error = get_nvlist(zc, &config)) != 0) 713789Sahrens return (error); 714789Sahrens 715789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 7161544Seschrock guid != zc->zc_guid) 717789Sahrens error = EINVAL; 718789Sahrens else 719789Sahrens error = spa_import(zc->zc_name, config, 7202676Seschrock zc->zc_value[0] == '\0' ? NULL : zc->zc_value); 721789Sahrens 722789Sahrens nvlist_free(config); 723789Sahrens 724789Sahrens return (error); 725789Sahrens } 726789Sahrens 727789Sahrens static int 728789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc) 729789Sahrens { 7304543Smarks int error; 7314543Smarks zfs_log_history(zc); 7324543Smarks error = spa_export(zc->zc_name, NULL); 7334543Smarks return (error); 734789Sahrens } 735789Sahrens 736789Sahrens static int 737789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc) 738789Sahrens { 739789Sahrens nvlist_t *configs; 740789Sahrens int error; 741789Sahrens 742789Sahrens if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 743789Sahrens return (EEXIST); 744789Sahrens 7452676Seschrock error = put_nvlist(zc, configs); 746789Sahrens 747789Sahrens nvlist_free(configs); 748789Sahrens 749789Sahrens return (error); 750789Sahrens } 751789Sahrens 752789Sahrens static int 753789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc) 754789Sahrens { 755789Sahrens nvlist_t *config; 756789Sahrens int error; 7571544Seschrock int ret = 0; 758789Sahrens 7592676Seschrock error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 7602676Seschrock sizeof (zc->zc_value)); 761789Sahrens 762789Sahrens if (config != NULL) { 7632676Seschrock ret = put_nvlist(zc, config); 764789Sahrens nvlist_free(config); 7651544Seschrock 7661544Seschrock /* 7671544Seschrock * The config may be present even if 'error' is non-zero. 7681544Seschrock * In this case we return success, and preserve the real errno 7691544Seschrock * in 'zc_cookie'. 7701544Seschrock */ 7711544Seschrock zc->zc_cookie = error; 772789Sahrens } else { 7731544Seschrock ret = error; 774789Sahrens } 775789Sahrens 7761544Seschrock return (ret); 777789Sahrens } 778789Sahrens 779789Sahrens /* 780789Sahrens * Try to import the given pool, returning pool stats as appropriate so that 781789Sahrens * user land knows which devices are available and overall pool health. 782789Sahrens */ 783789Sahrens static int 784789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 785789Sahrens { 786789Sahrens nvlist_t *tryconfig, *config; 787789Sahrens int error; 788789Sahrens 7892676Seschrock if ((error = get_nvlist(zc, &tryconfig)) != 0) 790789Sahrens return (error); 791789Sahrens 792789Sahrens config = spa_tryimport(tryconfig); 793789Sahrens 794789Sahrens nvlist_free(tryconfig); 795789Sahrens 796789Sahrens if (config == NULL) 797789Sahrens return (EINVAL); 798789Sahrens 7992676Seschrock error = put_nvlist(zc, config); 800789Sahrens nvlist_free(config); 801789Sahrens 802789Sahrens return (error); 803789Sahrens } 804789Sahrens 805789Sahrens static int 806789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc) 807789Sahrens { 808789Sahrens spa_t *spa; 809789Sahrens int error; 810789Sahrens 8112926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8122926Sek110237 return (error); 8132926Sek110237 8144808Sek110237 mutex_enter(&spa_namespace_lock); 8152926Sek110237 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); 8164808Sek110237 mutex_exit(&spa_namespace_lock); 8172926Sek110237 8182926Sek110237 spa_close(spa, FTAG); 8192926Sek110237 820789Sahrens return (error); 821789Sahrens } 822789Sahrens 823789Sahrens static int 824789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 825789Sahrens { 826789Sahrens spa_t *spa; 827789Sahrens int error; 828789Sahrens 829789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 830789Sahrens if (error == 0) { 831789Sahrens spa_freeze(spa); 832789Sahrens spa_close(spa, FTAG); 833789Sahrens } 834789Sahrens return (error); 835789Sahrens } 836789Sahrens 837789Sahrens static int 8381760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 8391760Seschrock { 8401760Seschrock spa_t *spa; 8411760Seschrock int error; 8421760Seschrock 8432926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8442926Sek110237 return (error); 8452926Sek110237 8462926Sek110237 spa_upgrade(spa); 8472926Sek110237 spa_close(spa, FTAG); 8482926Sek110237 8492926Sek110237 return (error); 8502926Sek110237 } 8512926Sek110237 8522926Sek110237 static int 8532926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 8542926Sek110237 { 8552926Sek110237 spa_t *spa; 8562926Sek110237 char *hist_buf; 8572926Sek110237 uint64_t size; 8582926Sek110237 int error; 8592926Sek110237 8602926Sek110237 if ((size = zc->zc_history_len) == 0) 8612926Sek110237 return (EINVAL); 8622926Sek110237 8632926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8642926Sek110237 return (error); 8652926Sek110237 8664577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 8673863Sek110237 spa_close(spa, FTAG); 8683863Sek110237 return (ENOTSUP); 8693863Sek110237 } 8703863Sek110237 8712926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 8722926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 8732926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 8744543Smarks error = xcopyout(hist_buf, 8754543Smarks (char *)(uintptr_t)zc->zc_history, 8762926Sek110237 zc->zc_history_len); 8772926Sek110237 } 8782926Sek110237 8792926Sek110237 spa_close(spa, FTAG); 8802926Sek110237 kmem_free(hist_buf, size); 8812926Sek110237 return (error); 8822926Sek110237 } 8832926Sek110237 8842926Sek110237 static int 8853444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 8863444Sek110237 { 8873444Sek110237 int error; 8883444Sek110237 8893912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 8903444Sek110237 return (error); 8913444Sek110237 8923444Sek110237 return (0); 8933444Sek110237 } 8943444Sek110237 8953444Sek110237 static int 8963444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 8973444Sek110237 { 8983444Sek110237 objset_t *osp; 8993444Sek110237 int error; 9003444Sek110237 9013444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 9023444Sek110237 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) 9033444Sek110237 return (error); 9043444Sek110237 9053444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 9063444Sek110237 sizeof (zc->zc_value)); 9073444Sek110237 dmu_objset_close(osp); 9083444Sek110237 9093444Sek110237 return (error); 9103444Sek110237 } 9113444Sek110237 9123444Sek110237 static int 913789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 914789Sahrens { 915789Sahrens spa_t *spa; 916789Sahrens int error; 917789Sahrens nvlist_t *config; 918789Sahrens 919789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 920789Sahrens if (error != 0) 921789Sahrens return (error); 922789Sahrens 9233912Slling /* 9243912Slling * A root pool with concatenated devices is not supported. 9253912Slling * Thus, can not add a device to a root pool with one device. 9263912Slling */ 9273912Slling if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0) { 9283912Slling spa_close(spa, FTAG); 9293912Slling return (EDOM); 9303912Slling } 9313912Slling 9322676Seschrock if ((error = get_nvlist(zc, &config)) == 0) { 933789Sahrens error = spa_vdev_add(spa, config); 934789Sahrens nvlist_free(config); 935789Sahrens } 936789Sahrens spa_close(spa, FTAG); 937789Sahrens return (error); 938789Sahrens } 939789Sahrens 940789Sahrens static int 941789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 942789Sahrens { 9432082Seschrock spa_t *spa; 9442082Seschrock int error; 9452082Seschrock 9462082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 9472082Seschrock if (error != 0) 9482082Seschrock return (error); 9492082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 9502082Seschrock spa_close(spa, FTAG); 9512082Seschrock return (error); 952789Sahrens } 953789Sahrens 954789Sahrens static int 9554451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 956789Sahrens { 957789Sahrens spa_t *spa; 958789Sahrens int error; 9594451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 960789Sahrens 9612926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 962789Sahrens return (error); 9634451Seschrock switch (zc->zc_cookie) { 9644451Seschrock case VDEV_STATE_ONLINE: 9654451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 9664451Seschrock break; 9674451Seschrock 9684451Seschrock case VDEV_STATE_OFFLINE: 9694451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 9704451Seschrock break; 971789Sahrens 9724451Seschrock case VDEV_STATE_FAULTED: 9734451Seschrock error = vdev_fault(spa, zc->zc_guid); 9744451Seschrock break; 975789Sahrens 9764451Seschrock case VDEV_STATE_DEGRADED: 9774451Seschrock error = vdev_degrade(spa, zc->zc_guid); 9784451Seschrock break; 9794451Seschrock 9804451Seschrock default: 9814451Seschrock error = EINVAL; 9824451Seschrock } 9834451Seschrock zc->zc_cookie = newstate; 984789Sahrens spa_close(spa, FTAG); 985789Sahrens return (error); 986789Sahrens } 987789Sahrens 988789Sahrens static int 989789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 990789Sahrens { 991789Sahrens spa_t *spa; 992789Sahrens int replacing = zc->zc_cookie; 993789Sahrens nvlist_t *config; 994789Sahrens int error; 995789Sahrens 9962926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 997789Sahrens return (error); 998789Sahrens 9992676Seschrock if ((error = get_nvlist(zc, &config)) == 0) { 10001544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 1001789Sahrens nvlist_free(config); 1002789Sahrens } 1003789Sahrens 1004789Sahrens spa_close(spa, FTAG); 1005789Sahrens return (error); 1006789Sahrens } 1007789Sahrens 1008789Sahrens static int 1009789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 1010789Sahrens { 1011789Sahrens spa_t *spa; 1012789Sahrens int error; 1013789Sahrens 10142926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1015789Sahrens return (error); 1016789Sahrens 10171544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1018789Sahrens 1019789Sahrens spa_close(spa, FTAG); 1020789Sahrens return (error); 1021789Sahrens } 1022789Sahrens 1023789Sahrens static int 10241354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 10251354Seschrock { 10261354Seschrock spa_t *spa; 10272676Seschrock char *path = zc->zc_value; 10281544Seschrock uint64_t guid = zc->zc_guid; 10291354Seschrock int error; 10301354Seschrock 10311354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10321354Seschrock if (error != 0) 10331354Seschrock return (error); 10341354Seschrock 10351354Seschrock error = spa_vdev_setpath(spa, guid, path); 10361354Seschrock spa_close(spa, FTAG); 10371354Seschrock return (error); 10381354Seschrock } 10391354Seschrock 10401354Seschrock static int 1041789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1042789Sahrens { 1043789Sahrens objset_t *os = NULL; 1044789Sahrens int error; 10451356Seschrock nvlist_t *nv; 1046789Sahrens 1047789Sahrens retry: 1048789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1049789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1050789Sahrens if (error != 0) { 1051789Sahrens /* 1052789Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1053789Sahrens * the objset is held exclusively. Fortunately this hold is 1054789Sahrens * only for a short while, so we retry here. 1055789Sahrens * This avoids user code having to handle EBUSY, 1056789Sahrens * for example for a "zfs list". 1057789Sahrens */ 1058789Sahrens if (error == EBUSY) { 1059789Sahrens delay(1); 1060789Sahrens goto retry; 1061789Sahrens } 1062789Sahrens return (error); 1063789Sahrens } 1064789Sahrens 10652885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1066789Sahrens 10672856Snd150628 if (zc->zc_nvlist_dst != 0 && 10681356Seschrock (error = dsl_prop_get_all(os, &nv)) == 0) { 10692885Sahrens dmu_objset_stats(os, nv); 10703087Sahrens /* 10714577Sahrens * NB: {zpl,zvol}_get_stats() will read the objset contents, 10723087Sahrens * which we aren't supposed to do with a 10733087Sahrens * DS_MODE_STANDARD open, because it could be 10743087Sahrens * inconsistent. So this is a bit of a workaround... 10753087Sahrens */ 10764577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 10774577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 10784577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 10794577Sahrens else if (dmu_objset_type(os) == DMU_OST_ZFS) 10804577Sahrens (void) zfs_get_stats(os, nv); 10814577Sahrens } 10822676Seschrock error = put_nvlist(zc, nv); 10831356Seschrock nvlist_free(nv); 10841356Seschrock } 1085789Sahrens 10862676Seschrock spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value)); 10871544Seschrock 1088789Sahrens dmu_objset_close(os); 1089789Sahrens return (error); 1090789Sahrens } 1091789Sahrens 1092789Sahrens static int 1093789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1094789Sahrens { 1095885Sahrens objset_t *os; 1096789Sahrens int error; 1097789Sahrens char *p; 1098789Sahrens 1099885Sahrens retry: 1100885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1101885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1102885Sahrens if (error != 0) { 1103885Sahrens /* 1104885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1105885Sahrens * the objset is held exclusively. Fortunately this hold is 1106885Sahrens * only for a short while, so we retry here. 1107885Sahrens * This avoids user code having to handle EBUSY, 1108885Sahrens * for example for a "zfs list". 1109885Sahrens */ 1110885Sahrens if (error == EBUSY) { 1111885Sahrens delay(1); 1112885Sahrens goto retry; 1113885Sahrens } 1114885Sahrens if (error == ENOENT) 1115885Sahrens error = ESRCH; 1116885Sahrens return (error); 1117789Sahrens } 1118789Sahrens 1119789Sahrens p = strrchr(zc->zc_name, '/'); 1120789Sahrens if (p == NULL || p[1] != '\0') 1121789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1122789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1123789Sahrens 1124789Sahrens do { 1125885Sahrens error = dmu_dir_list_next(os, 1126885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1127885Sahrens NULL, &zc->zc_cookie); 1128789Sahrens if (error == ENOENT) 1129789Sahrens error = ESRCH; 1130885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1131789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 1132789Sahrens 1133885Sahrens /* 1134885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1135885Sahrens * try to get stats for it. Userland will skip over it. 1136885Sahrens */ 1137885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1138885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1139789Sahrens 1140885Sahrens dmu_objset_close(os); 1141789Sahrens return (error); 1142789Sahrens } 1143789Sahrens 1144789Sahrens static int 1145789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1146789Sahrens { 1147885Sahrens objset_t *os; 1148789Sahrens int error; 1149789Sahrens 1150789Sahrens retry: 1151885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1152885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1153885Sahrens if (error != 0) { 1154789Sahrens /* 1155885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1156789Sahrens * the objset is held exclusively. Fortunately this hold is 1157789Sahrens * only for a short while, so we retry here. 1158789Sahrens * This avoids user code having to handle EBUSY, 1159885Sahrens * for example for a "zfs list". 1160789Sahrens */ 1161789Sahrens if (error == EBUSY) { 1162789Sahrens delay(1); 1163789Sahrens goto retry; 1164789Sahrens } 1165789Sahrens if (error == ENOENT) 1166885Sahrens error = ESRCH; 1167789Sahrens return (error); 1168789Sahrens } 1169789Sahrens 11701003Slling /* 11711003Slling * A dataset name of maximum length cannot have any snapshots, 11721003Slling * so exit immediately. 11731003Slling */ 11741003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1175885Sahrens dmu_objset_close(os); 11761003Slling return (ESRCH); 1177789Sahrens } 1178789Sahrens 1179885Sahrens error = dmu_snapshot_list_next(os, 1180885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 1181885Sahrens zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie); 1182789Sahrens if (error == ENOENT) 1183789Sahrens error = ESRCH; 1184789Sahrens 1185885Sahrens if (error == 0) 1186885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1187789Sahrens 1188885Sahrens dmu_objset_close(os); 1189789Sahrens return (error); 1190789Sahrens } 1191789Sahrens 1192789Sahrens static int 11934787Sahrens zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) 1194789Sahrens { 11952676Seschrock nvpair_t *elem; 11962676Seschrock int error; 11972676Seschrock uint64_t intval; 11982676Seschrock char *strval; 11992676Seschrock 12004543Smarks /* 12014543Smarks * First validate permission to set all of the properties 12024543Smarks */ 12032676Seschrock elem = NULL; 12042676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 12054670Sahrens const char *propname = nvpair_name(elem); 12064670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 12072676Seschrock 12084670Sahrens if (prop == ZFS_PROP_INVAL) { 12092676Seschrock /* 12102676Seschrock * If this is a user-defined property, it must be a 12112676Seschrock * string, and there is no further validation to do. 12122676Seschrock */ 12132676Seschrock if (!zfs_prop_user(propname) || 12142676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 12152676Seschrock return (EINVAL); 12162676Seschrock 12174543Smarks error = zfs_secpolicy_write_perms(name, 12184787Sahrens ZFS_DELEG_PERM_USERPROP, CRED()); 12194670Sahrens if (error) 12204670Sahrens return (error); 12214543Smarks continue; 12222676Seschrock } 12232676Seschrock 12244787Sahrens if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 12254670Sahrens return (error); 12262676Seschrock 12274670Sahrens /* 12284670Sahrens * Check that this value is valid for this pool version 12294670Sahrens */ 12304670Sahrens switch (prop) { 12313886Sahl case ZFS_PROP_COMPRESSION: 12323886Sahl /* 12333886Sahl * If the user specified gzip compression, make sure 12343886Sahl * the SPA supports it. We ignore any errors here since 12353886Sahl * we'll catch them later. 12363886Sahl */ 12373886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 12383886Sahl nvpair_value_uint64(elem, &intval) == 0 && 12393886Sahl intval >= ZIO_COMPRESS_GZIP_1 && 12403886Sahl intval <= ZIO_COMPRESS_GZIP_9) { 12414543Smarks spa_t *spa; 12424543Smarks 12434603Sahrens if (spa_open(name, &spa, FTAG) == 0) { 12443886Sahl if (spa_version(spa) < 12454577Sahrens SPA_VERSION_GZIP_COMPRESSION) { 12463886Sahl spa_close(spa, FTAG); 12473886Sahl return (ENOTSUP); 12483886Sahl } 12493886Sahl 12503886Sahl spa_close(spa, FTAG); 12513886Sahl } 12523886Sahl } 12533886Sahl break; 12544603Sahrens 12554603Sahrens case ZFS_PROP_COPIES: 12564603Sahrens { 12574603Sahrens spa_t *spa; 12584603Sahrens 12594603Sahrens if (spa_open(name, &spa, FTAG) == 0) { 12604603Sahrens if (spa_version(spa) < 12614603Sahrens SPA_VERSION_DITTO_BLOCKS) { 12624603Sahrens spa_close(spa, FTAG); 12634603Sahrens return (ENOTSUP); 12644603Sahrens } 12654603Sahrens spa_close(spa, FTAG); 12664603Sahrens } 12674603Sahrens break; 12684603Sahrens } 12692676Seschrock } 12704543Smarks } 12714543Smarks 12724543Smarks elem = NULL; 12734543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 12744670Sahrens const char *propname = nvpair_name(elem); 12754670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 12764543Smarks 12774670Sahrens if (prop == ZFS_PROP_INVAL) { 12784543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 12794543Smarks error = dsl_prop_set(name, propname, 1, 12804543Smarks strlen(strval) + 1, strval); 12814543Smarks if (error == 0) 12824543Smarks continue; 12834543Smarks else 12844543Smarks return (error); 12854543Smarks } 12862676Seschrock 12872676Seschrock switch (prop) { 12882676Seschrock case ZFS_PROP_QUOTA: 12892676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 12904577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 12912676Seschrock return (error); 12922676Seschrock break; 12932676Seschrock 12942676Seschrock case ZFS_PROP_RESERVATION: 12952676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 12962676Seschrock (error = dsl_dir_set_reservation(name, 12972676Seschrock intval)) != 0) 12982676Seschrock return (error); 12992676Seschrock break; 1300789Sahrens 13012676Seschrock case ZFS_PROP_VOLSIZE: 13022676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13034787Sahrens (error = zvol_set_volsize(name, 13044787Sahrens ddi_driver_major(zfs_dip), intval)) != 0) 13052676Seschrock return (error); 13062676Seschrock break; 13072676Seschrock 13082676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 13092676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13104577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 13114577Sahrens return (error); 13124577Sahrens break; 13134577Sahrens 13144577Sahrens case ZFS_PROP_VERSION: 13154577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13164577Sahrens (error = zfs_set_version(name, intval)) != 0) 13172676Seschrock return (error); 13182676Seschrock break; 13192676Seschrock 13202676Seschrock default: 13212676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 13222676Seschrock if (zfs_prop_get_type(prop) != 13234787Sahrens PROP_TYPE_STRING) 13242676Seschrock return (EINVAL); 13252717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 13262717Seschrock if ((error = dsl_prop_set(name, 13272676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 13282717Seschrock strval)) != 0) 13292717Seschrock return (error); 13302676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 13312885Sahrens const char *unused; 13322885Sahrens 13332717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 13342676Seschrock 13352676Seschrock switch (zfs_prop_get_type(prop)) { 13364787Sahrens case PROP_TYPE_NUMBER: 13372676Seschrock break; 13384787Sahrens case PROP_TYPE_STRING: 13392717Seschrock return (EINVAL); 13404787Sahrens case PROP_TYPE_INDEX: 13412717Seschrock if (zfs_prop_index_to_string(prop, 13422717Seschrock intval, &unused) != 0) 13432717Seschrock return (EINVAL); 13442676Seschrock break; 13452676Seschrock default: 13464577Sahrens cmn_err(CE_PANIC, 13474577Sahrens "unknown property type"); 13482676Seschrock break; 13492676Seschrock } 13502676Seschrock 13512717Seschrock if ((error = dsl_prop_set(name, propname, 13522717Seschrock 8, 1, &intval)) != 0) 13532717Seschrock return (error); 13542676Seschrock } else { 13552676Seschrock return (EINVAL); 13562676Seschrock } 13572676Seschrock break; 13582676Seschrock } 13592676Seschrock } 13602676Seschrock 13612676Seschrock return (0); 1362789Sahrens } 1363789Sahrens 1364789Sahrens static int 13652676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1366789Sahrens { 13672676Seschrock nvlist_t *nvl; 13682676Seschrock int error; 1369789Sahrens 13702676Seschrock if ((error = get_nvlist(zc, &nvl)) != 0) 13712676Seschrock return (error); 13722676Seschrock 13734787Sahrens error = zfs_set_prop_nvlist(zc->zc_name, nvl); 13744543Smarks 13752676Seschrock nvlist_free(nvl); 13762676Seschrock return (error); 1377789Sahrens } 1378789Sahrens 1379789Sahrens static int 13804849Sahrens zfs_ioc_inherit_prop(zfs_cmd_t *zc) 13814849Sahrens { 13824849Sahrens /* the property name has been validated by zfs_secpolicy_inherit() */ 13834849Sahrens return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 13844849Sahrens } 13854849Sahrens 13864849Sahrens static int 13874098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 13883912Slling { 13893912Slling nvlist_t *nvl; 13903912Slling int error, reset_bootfs = 0; 13913912Slling uint64_t objnum; 13924543Smarks uint64_t intval; 13933912Slling zpool_prop_t prop; 13943912Slling nvpair_t *elem; 13953912Slling char *propname, *strval; 13963912Slling spa_t *spa; 13973912Slling vdev_t *rvdev; 13983912Slling char *vdev_type; 13993912Slling objset_t *os; 14003912Slling 14013912Slling if ((error = get_nvlist(zc, &nvl)) != 0) 14023912Slling return (error); 14033912Slling 14043912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 14053912Slling nvlist_free(nvl); 14063912Slling return (error); 14073912Slling } 14083912Slling 14094577Sahrens if (spa_version(spa) < SPA_VERSION_BOOTFS) { 14103912Slling nvlist_free(nvl); 14113912Slling spa_close(spa, FTAG); 14123912Slling return (ENOTSUP); 14133912Slling } 14143912Slling 14153912Slling elem = NULL; 14163912Slling while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 14173912Slling 14183912Slling propname = nvpair_name(elem); 14193912Slling 14203912Slling if ((prop = zpool_name_to_prop(propname)) == 14213912Slling ZFS_PROP_INVAL) { 14223912Slling nvlist_free(nvl); 14233912Slling spa_close(spa, FTAG); 14243912Slling return (EINVAL); 14253912Slling } 14263912Slling 14273912Slling switch (prop) { 14284543Smarks case ZPOOL_PROP_DELEGATION: 14294543Smarks VERIFY(nvpair_value_uint64(elem, &intval) == 0); 14304543Smarks if (intval > 1) 14314543Smarks error = EINVAL; 14324543Smarks break; 14334451Seschrock case ZPOOL_PROP_BOOTFS: 14343912Slling /* 14353912Slling * A bootable filesystem can not be on a RAIDZ pool 14363912Slling * nor a striped pool with more than 1 device. 14373912Slling */ 14383912Slling rvdev = spa->spa_root_vdev; 14393912Slling vdev_type = 14403912Slling rvdev->vdev_child[0]->vdev_ops->vdev_op_type; 14413912Slling if (strcmp(vdev_type, VDEV_TYPE_RAIDZ) == 0 || 14423912Slling (strcmp(vdev_type, VDEV_TYPE_MIRROR) != 0 && 14433912Slling rvdev->vdev_children > 1)) { 14443912Slling error = ENOTSUP; 14453912Slling break; 14463912Slling } 14473912Slling 14483912Slling reset_bootfs = 1; 14493912Slling 14503912Slling VERIFY(nvpair_value_string(elem, &strval) == 0); 14513912Slling if (strval == NULL || strval[0] == '\0') { 14524451Seschrock objnum = zpool_prop_default_numeric( 14534451Seschrock ZPOOL_PROP_BOOTFS); 14543912Slling break; 14553912Slling } 14563912Slling 14573912Slling if (error = dmu_objset_open(strval, DMU_OST_ZFS, 14583912Slling DS_MODE_STANDARD | DS_MODE_READONLY, &os)) 14593912Slling break; 14603912Slling objnum = dmu_objset_id(os); 14613912Slling dmu_objset_close(os); 14623912Slling break; 14633912Slling } 14643912Slling 14653912Slling if (error) 14663912Slling break; 14673912Slling } 14683912Slling if (error == 0) { 14693912Slling if (reset_bootfs) { 14703912Slling VERIFY(nvlist_remove(nvl, 14714451Seschrock zpool_prop_to_name(ZPOOL_PROP_BOOTFS), 14723912Slling DATA_TYPE_STRING) == 0); 14733912Slling VERIFY(nvlist_add_uint64(nvl, 14744451Seschrock zpool_prop_to_name(ZPOOL_PROP_BOOTFS), 14754451Seschrock objnum) == 0); 14763912Slling } 14773912Slling error = spa_set_props(spa, nvl); 14783912Slling } 14793912Slling 14803912Slling nvlist_free(nvl); 14813912Slling spa_close(spa, FTAG); 14823912Slling 14833912Slling return (error); 14843912Slling } 14853912Slling 14863912Slling static int 14874098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 14883912Slling { 14893912Slling spa_t *spa; 14903912Slling int error; 14913912Slling nvlist_t *nvp = NULL; 14923912Slling 14933912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 14943912Slling return (error); 14953912Slling 14963912Slling error = spa_get_props(spa, &nvp); 14973912Slling 14983912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 14993912Slling error = put_nvlist(zc, nvp); 15003912Slling else 15013912Slling error = EFAULT; 15023912Slling 15033912Slling spa_close(spa, FTAG); 15043912Slling 15053912Slling if (nvp) 15063912Slling nvlist_free(nvp); 15073912Slling return (error); 15083912Slling } 15093912Slling 15103912Slling static int 15114543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 15124543Smarks { 15134543Smarks nvlist_t *nvp; 15144543Smarks int error; 15154543Smarks uint32_t uid; 15164543Smarks uint32_t gid; 15174543Smarks uint32_t *groups; 15184543Smarks uint_t group_cnt; 15194543Smarks cred_t *usercred; 15204543Smarks 15214543Smarks if ((error = get_nvlist(zc, &nvp)) != 0) { 15224543Smarks return (error); 15234543Smarks } 15244543Smarks 15254543Smarks if ((error = nvlist_lookup_uint32(nvp, 15264543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 15274543Smarks nvlist_free(nvp); 15284543Smarks return (EPERM); 15294543Smarks } 15304543Smarks 15314543Smarks if ((error = nvlist_lookup_uint32(nvp, 15324543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 15334543Smarks nvlist_free(nvp); 15344543Smarks return (EPERM); 15354543Smarks } 15364543Smarks 15374543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 15384543Smarks &groups, &group_cnt)) != 0) { 15394543Smarks nvlist_free(nvp); 15404543Smarks return (EPERM); 15414543Smarks } 15424543Smarks usercred = cralloc(); 15434543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 15444543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 15454543Smarks nvlist_free(nvp); 15464543Smarks crfree(usercred); 15474543Smarks return (EPERM); 15484543Smarks } 15494543Smarks nvlist_free(nvp); 15504543Smarks error = dsl_deleg_access(zc->zc_name, 15514787Sahrens zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); 15524543Smarks crfree(usercred); 15534543Smarks return (error); 15544543Smarks } 15554543Smarks 15564543Smarks static int 15574543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 15584543Smarks { 15594543Smarks int error; 15604543Smarks nvlist_t *fsaclnv = NULL; 15614543Smarks 15624543Smarks if ((error = get_nvlist(zc, &fsaclnv)) != 0) 15634543Smarks return (error); 15644543Smarks 15654543Smarks /* 15664543Smarks * Verify nvlist is constructed correctly 15674543Smarks */ 15684543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 15694543Smarks nvlist_free(fsaclnv); 15704543Smarks return (EINVAL); 15714543Smarks } 15724543Smarks 15734543Smarks /* 15744543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 15754543Smarks * that user is allowed to hand out each permission in 15764543Smarks * the nvlist(s) 15774543Smarks */ 15784543Smarks 15794787Sahrens error = secpolicy_zfs(CRED()); 15804543Smarks if (error) { 15814787Sahrens if (zc->zc_perm_action == B_FALSE) { 15824787Sahrens error = dsl_deleg_can_allow(zc->zc_name, 15834787Sahrens fsaclnv, CRED()); 15844787Sahrens } else { 15854787Sahrens error = dsl_deleg_can_unallow(zc->zc_name, 15864787Sahrens fsaclnv, CRED()); 15874787Sahrens } 15884543Smarks } 15894543Smarks 15904543Smarks if (error == 0) 15914543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 15924543Smarks 15934543Smarks nvlist_free(fsaclnv); 15944543Smarks return (error); 15954543Smarks } 15964543Smarks 15974543Smarks static int 15984543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 15994543Smarks { 16004543Smarks nvlist_t *nvp; 16014543Smarks int error; 16024543Smarks 16034543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 16044543Smarks error = put_nvlist(zc, nvp); 16054543Smarks nvlist_free(nvp); 16064543Smarks } 16074543Smarks 16084543Smarks return (error); 16094543Smarks } 16104543Smarks 16114543Smarks static int 1612789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1613789Sahrens { 16144787Sahrens return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); 1615789Sahrens } 1616789Sahrens 1617789Sahrens static int 1618789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1619789Sahrens { 16202676Seschrock return (zvol_remove_minor(zc->zc_name)); 1621789Sahrens } 1622789Sahrens 1623789Sahrens /* 1624789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1625789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1626789Sahrens * is responsible for releasing the returned vfs pointer. 1627789Sahrens */ 1628789Sahrens static vfs_t * 1629789Sahrens zfs_get_vfs(const char *resource) 1630789Sahrens { 1631789Sahrens struct vfs *vfsp; 1632789Sahrens struct vfs *vfs_found = NULL; 1633789Sahrens 1634789Sahrens vfs_list_read_lock(); 1635789Sahrens vfsp = rootvfs; 1636789Sahrens do { 1637789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1638789Sahrens VFS_HOLD(vfsp); 1639789Sahrens vfs_found = vfsp; 1640789Sahrens break; 1641789Sahrens } 1642789Sahrens vfsp = vfsp->vfs_next; 1643789Sahrens } while (vfsp != rootvfs); 1644789Sahrens vfs_list_unlock(); 1645789Sahrens return (vfs_found); 1646789Sahrens } 1647789Sahrens 16484543Smarks /* ARGSUSED */ 1649789Sahrens static void 16504543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1651789Sahrens { 16524577Sahrens nvlist_t *nvprops = arg; 16534577Sahrens uint64_t version = ZPL_VERSION; 16544577Sahrens 16554577Sahrens (void) nvlist_lookup_uint64(nvprops, 16564577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version); 16574577Sahrens 16584577Sahrens zfs_create_fs(os, cr, version, tx); 1659789Sahrens } 1660789Sahrens 1661789Sahrens static int 1662789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1663789Sahrens { 1664789Sahrens objset_t *clone; 1665789Sahrens int error = 0; 16664543Smarks nvlist_t *nvprops = NULL; 16674543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1668789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1669789Sahrens 1670789Sahrens switch (type) { 1671789Sahrens 1672789Sahrens case DMU_OST_ZFS: 1673789Sahrens cbfunc = zfs_create_cb; 1674789Sahrens break; 1675789Sahrens 1676789Sahrens case DMU_OST_ZVOL: 1677789Sahrens cbfunc = zvol_create_cb; 1678789Sahrens break; 1679789Sahrens 1680789Sahrens default: 16812199Sahrens cbfunc = NULL; 16822199Sahrens } 16832199Sahrens if (strchr(zc->zc_name, '@')) 1684789Sahrens return (EINVAL); 1685789Sahrens 16862676Seschrock if (zc->zc_nvlist_src != NULL && 16874543Smarks (error = get_nvlist(zc, &nvprops)) != 0) 16882676Seschrock return (error); 16892676Seschrock 16902676Seschrock if (zc->zc_value[0] != '\0') { 1691789Sahrens /* 1692789Sahrens * We're creating a clone of an existing snapshot. 1693789Sahrens */ 16942676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 16952676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 16964543Smarks nvlist_free(nvprops); 1697789Sahrens return (EINVAL); 16982676Seschrock } 1699789Sahrens 17002676Seschrock error = dmu_objset_open(zc->zc_value, type, 1701789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 17022676Seschrock if (error) { 17034543Smarks nvlist_free(nvprops); 1704789Sahrens return (error); 17052676Seschrock } 1706789Sahrens error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); 1707789Sahrens dmu_objset_close(clone); 1708789Sahrens } else { 17092676Seschrock if (cbfunc == NULL) { 17104543Smarks nvlist_free(nvprops); 17112199Sahrens return (EINVAL); 17122676Seschrock } 17132676Seschrock 1714789Sahrens if (type == DMU_OST_ZVOL) { 17152676Seschrock uint64_t volsize, volblocksize; 17162676Seschrock 17174543Smarks if (nvprops == NULL || 17184543Smarks nvlist_lookup_uint64(nvprops, 17192676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 17202676Seschrock &volsize) != 0) { 17214543Smarks nvlist_free(nvprops); 17222676Seschrock return (EINVAL); 17232676Seschrock } 17242676Seschrock 17254543Smarks if ((error = nvlist_lookup_uint64(nvprops, 17262676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 17272676Seschrock &volblocksize)) != 0 && error != ENOENT) { 17284543Smarks nvlist_free(nvprops); 17292676Seschrock return (EINVAL); 17302676Seschrock } 17311133Seschrock 17322676Seschrock if (error != 0) 17332676Seschrock volblocksize = zfs_prop_default_numeric( 17342676Seschrock ZFS_PROP_VOLBLOCKSIZE); 17352676Seschrock 17362676Seschrock if ((error = zvol_check_volblocksize( 17372676Seschrock volblocksize)) != 0 || 17382676Seschrock (error = zvol_check_volsize(volsize, 17392676Seschrock volblocksize)) != 0) { 17404543Smarks nvlist_free(nvprops); 1741789Sahrens return (error); 17422676Seschrock } 17434577Sahrens } else if (type == DMU_OST_ZFS) { 17444577Sahrens uint64_t version; 17454577Sahrens 17464577Sahrens if (0 == nvlist_lookup_uint64(nvprops, 17474577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version) && 17484577Sahrens (version < ZPL_VERSION_INITIAL || 17494577Sahrens version > ZPL_VERSION)) { 17504577Sahrens nvlist_free(nvprops); 17514577Sahrens return (EINVAL); 17524577Sahrens } 17532676Seschrock } 17541133Seschrock 17552676Seschrock error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, 17564543Smarks nvprops); 1757789Sahrens } 17582676Seschrock 17592676Seschrock /* 17602676Seschrock * It would be nice to do this atomically. 17612676Seschrock */ 17622676Seschrock if (error == 0) { 17634787Sahrens if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) 17642676Seschrock (void) dmu_objset_destroy(zc->zc_name); 17652676Seschrock } 17662676Seschrock 17674543Smarks nvlist_free(nvprops); 1768789Sahrens return (error); 1769789Sahrens } 1770789Sahrens 1771789Sahrens static int 17722199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 17732199Sahrens { 17742676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 17752199Sahrens return (EINVAL); 17762199Sahrens return (dmu_objset_snapshot(zc->zc_name, 17772676Seschrock zc->zc_value, zc->zc_cookie)); 17782199Sahrens } 17792199Sahrens 17804007Smmusante int 17812199Sahrens zfs_unmount_snap(char *name, void *arg) 1782789Sahrens { 17832199Sahrens char *snapname = arg; 17842199Sahrens char *cp; 17852417Sahrens vfs_t *vfsp = NULL; 17862199Sahrens 17872199Sahrens /* 17882199Sahrens * Snapshots (which are under .zfs control) must be unmounted 17892199Sahrens * before they can be destroyed. 17902199Sahrens */ 17912199Sahrens 17922199Sahrens if (snapname) { 17932199Sahrens (void) strcat(name, "@"); 17942199Sahrens (void) strcat(name, snapname); 17952199Sahrens vfsp = zfs_get_vfs(name); 17962199Sahrens cp = strchr(name, '@'); 17972199Sahrens *cp = '\0'; 17982417Sahrens } else if (strchr(name, '@')) { 17992199Sahrens vfsp = zfs_get_vfs(name); 18002199Sahrens } 18012199Sahrens 18022199Sahrens if (vfsp) { 18032199Sahrens /* 18042199Sahrens * Always force the unmount for snapshots. 18052199Sahrens */ 18062199Sahrens int flag = MS_FORCE; 1807789Sahrens int err; 1808789Sahrens 18092199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 18102199Sahrens VFS_RELE(vfsp); 18112199Sahrens return (err); 18122199Sahrens } 18132199Sahrens VFS_RELE(vfsp); 18142199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 18152199Sahrens return (err); 18162199Sahrens } 18172199Sahrens return (0); 18182199Sahrens } 18192199Sahrens 18202199Sahrens static int 18212199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 18222199Sahrens { 18232199Sahrens int err; 1824789Sahrens 18252676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 18262199Sahrens return (EINVAL); 18272199Sahrens err = dmu_objset_find(zc->zc_name, 18282676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 18292199Sahrens if (err) 18302199Sahrens return (err); 18312676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 18322199Sahrens } 18332199Sahrens 18342199Sahrens static int 18352199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 18362199Sahrens { 18372199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 18382199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18392199Sahrens if (err) 18402199Sahrens return (err); 1841789Sahrens } 1842789Sahrens 1843789Sahrens return (dmu_objset_destroy(zc->zc_name)); 1844789Sahrens } 1845789Sahrens 1846789Sahrens static int 1847789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 1848789Sahrens { 1849789Sahrens return (dmu_objset_rollback(zc->zc_name)); 1850789Sahrens } 1851789Sahrens 1852789Sahrens static int 1853789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 1854789Sahrens { 18554490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 18564007Smmusante 18572676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 18582676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) 1859789Sahrens return (EINVAL); 1860789Sahrens 18614007Smmusante /* 18624007Smmusante * Unmount snapshot unless we're doing a recursive rename, 18634007Smmusante * in which case the dataset code figures out which snapshots 18644007Smmusante * to unmount. 18654007Smmusante */ 18664007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 1867789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 18682199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18692199Sahrens if (err) 18702199Sahrens return (err); 1871789Sahrens } 1872789Sahrens 18734007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 1874789Sahrens } 1875789Sahrens 1876789Sahrens static int 1877789Sahrens zfs_ioc_recvbackup(zfs_cmd_t *zc) 1878789Sahrens { 1879789Sahrens file_t *fp; 1880789Sahrens int error, fd; 18812885Sahrens offset_t new_off; 1882789Sahrens 18833265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 18843265Sahrens strchr(zc->zc_value, '@') == NULL) 18853265Sahrens return (EINVAL); 18863265Sahrens 1887789Sahrens fd = zc->zc_cookie; 1888789Sahrens fp = getf(fd); 1889789Sahrens if (fp == NULL) 1890789Sahrens return (EBADF); 18912676Seschrock error = dmu_recvbackup(zc->zc_value, &zc->zc_begin_record, 18922676Seschrock &zc->zc_cookie, (boolean_t)zc->zc_guid, fp->f_vnode, 18932665Snd150628 fp->f_offset); 18942885Sahrens 18952885Sahrens new_off = fp->f_offset + zc->zc_cookie; 18962885Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &new_off) == 0) 18972885Sahrens fp->f_offset = new_off; 18982885Sahrens 1899789Sahrens releasef(fd); 1900789Sahrens return (error); 1901789Sahrens } 1902789Sahrens 1903789Sahrens static int 1904789Sahrens zfs_ioc_sendbackup(zfs_cmd_t *zc) 1905789Sahrens { 1906789Sahrens objset_t *fromsnap = NULL; 1907789Sahrens objset_t *tosnap; 1908789Sahrens file_t *fp; 1909789Sahrens int error; 1910789Sahrens 1911789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1912789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); 1913789Sahrens if (error) 1914789Sahrens return (error); 1915789Sahrens 19162676Seschrock if (zc->zc_value[0] != '\0') { 19172885Sahrens char buf[MAXPATHLEN]; 19182885Sahrens char *cp; 19192885Sahrens 19202885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 19212885Sahrens cp = strchr(buf, '@'); 19222885Sahrens if (cp) 19232885Sahrens *(cp+1) = 0; 19242885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 19252885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 1926789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); 1927789Sahrens if (error) { 1928789Sahrens dmu_objset_close(tosnap); 1929789Sahrens return (error); 1930789Sahrens } 1931789Sahrens } 1932789Sahrens 1933789Sahrens fp = getf(zc->zc_cookie); 1934789Sahrens if (fp == NULL) { 1935789Sahrens dmu_objset_close(tosnap); 1936789Sahrens if (fromsnap) 1937789Sahrens dmu_objset_close(fromsnap); 1938789Sahrens return (EBADF); 1939789Sahrens } 1940789Sahrens 1941789Sahrens error = dmu_sendbackup(tosnap, fromsnap, fp->f_vnode); 1942789Sahrens 1943789Sahrens releasef(zc->zc_cookie); 1944789Sahrens if (fromsnap) 1945789Sahrens dmu_objset_close(fromsnap); 1946789Sahrens dmu_objset_close(tosnap); 1947789Sahrens return (error); 1948789Sahrens } 1949789Sahrens 19501544Seschrock static int 19511544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 19521544Seschrock { 19531544Seschrock int id, error; 19541544Seschrock 19551544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 19561544Seschrock &zc->zc_inject_record); 19571544Seschrock 19581544Seschrock if (error == 0) 19591544Seschrock zc->zc_guid = (uint64_t)id; 19601544Seschrock 19611544Seschrock return (error); 19621544Seschrock } 19631544Seschrock 19641544Seschrock static int 19651544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 19661544Seschrock { 19671544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 19681544Seschrock } 19691544Seschrock 19701544Seschrock static int 19711544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 19721544Seschrock { 19731544Seschrock int id = (int)zc->zc_guid; 19741544Seschrock int error; 19751544Seschrock 19761544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 19771544Seschrock &zc->zc_inject_record); 19781544Seschrock 19791544Seschrock zc->zc_guid = id; 19801544Seschrock 19811544Seschrock return (error); 19821544Seschrock } 19831544Seschrock 19841544Seschrock static int 19851544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 19861544Seschrock { 19871544Seschrock spa_t *spa; 19881544Seschrock int error; 19892676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 19901544Seschrock 19911544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 19921544Seschrock return (error); 19931544Seschrock 19942676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 19951544Seschrock &count); 19961544Seschrock if (error == 0) 19972676Seschrock zc->zc_nvlist_dst_size = count; 19981544Seschrock else 19992676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 20001544Seschrock 20011544Seschrock spa_close(spa, FTAG); 20021544Seschrock 20031544Seschrock return (error); 20041544Seschrock } 20051544Seschrock 20061544Seschrock static int 20071544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 20081544Seschrock { 20091544Seschrock spa_t *spa; 20101544Seschrock vdev_t *vd; 20114808Sek110237 uint64_t txg; 20121544Seschrock int error; 20131544Seschrock 20141544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 20151544Seschrock return (error); 20161544Seschrock 20174451Seschrock txg = spa_vdev_enter(spa); 20181544Seschrock 20192676Seschrock if (zc->zc_guid == 0) { 20201544Seschrock vd = NULL; 20212676Seschrock } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { 20224451Seschrock (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 20231544Seschrock spa_close(spa, FTAG); 20241544Seschrock return (ENODEV); 20251544Seschrock } 20261544Seschrock 20271544Seschrock vdev_clear(spa, vd); 20281544Seschrock 20294451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 20301544Seschrock 20311544Seschrock spa_close(spa, FTAG); 20321544Seschrock 20331544Seschrock return (0); 20341544Seschrock } 20351544Seschrock 20361544Seschrock static int 20372082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 20382082Seschrock { 20392417Sahrens char *cp; 20402417Sahrens 20412417Sahrens /* 20422417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 20432417Sahrens * it's easier. 20442417Sahrens */ 20452676Seschrock cp = strchr(zc->zc_value, '@'); 20462417Sahrens if (cp) 20472417Sahrens *cp = '\0'; 20482676Seschrock (void) dmu_objset_find(zc->zc_value, 20492417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 20502082Seschrock return (dsl_dataset_promote(zc->zc_name)); 20512082Seschrock } 20522082Seschrock 20534543Smarks /* 20544543Smarks * We don't want to have a hard dependency 20554543Smarks * against some special symbols in sharefs 20564543Smarks * and nfs. Determine them if needed when 20574543Smarks * the first file system is shared. 20584543Smarks * Neither sharefs or nfs are unloadable modules. 20594543Smarks */ 20604543Smarks int (*zexport_fs)(void *arg); 20614543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 20624543Smarks 20634543Smarks int zfs_share_inited; 20644543Smarks ddi_modhandle_t nfs_mod; 20654543Smarks ddi_modhandle_t sharefs_mod; 20664543Smarks kmutex_t zfs_share_lock; 20674543Smarks 20684543Smarks static int 20694543Smarks zfs_ioc_share(zfs_cmd_t *zc) 20704543Smarks { 20714543Smarks int error; 20724543Smarks int opcode; 20734543Smarks 20744543Smarks if (zfs_share_inited == 0) { 20754543Smarks mutex_enter(&zfs_share_lock); 20764543Smarks nfs_mod = ddi_modopen("fs/nfs", KRTLD_MODE_FIRST, &error); 20774543Smarks sharefs_mod = ddi_modopen("fs/sharefs", 20784543Smarks KRTLD_MODE_FIRST, &error); 20794543Smarks if (nfs_mod == NULL || sharefs_mod == NULL) { 20804543Smarks mutex_exit(&zfs_share_lock); 20814543Smarks return (ENOSYS); 20824543Smarks } 20834543Smarks if (zexport_fs == NULL && ((zexport_fs = (int (*)(void *)) 20844543Smarks ddi_modsym(nfs_mod, "nfs_export", &error)) == NULL)) { 20854543Smarks mutex_exit(&zfs_share_lock); 20864543Smarks return (ENOSYS); 20874543Smarks } 20884543Smarks 20894543Smarks if (zshare_fs == NULL && ((zshare_fs = 20904543Smarks (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 20914543Smarks ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 20924543Smarks mutex_exit(&zfs_share_lock); 20934543Smarks return (ENOSYS); 20944543Smarks } 20954543Smarks zfs_share_inited = 1; 20964543Smarks mutex_exit(&zfs_share_lock); 20974543Smarks } 20984543Smarks 20994543Smarks if (error = zexport_fs((void *)(uintptr_t)zc->zc_share.z_exportdata)) 21004543Smarks return (error); 21014543Smarks 21024543Smarks opcode = (zc->zc_share.z_sharetype == B_TRUE) ? 21034543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 21044543Smarks 21054543Smarks error = zshare_fs(opcode, 21064543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 21074543Smarks zc->zc_share.z_sharemax); 21084543Smarks 21094543Smarks return (error); 21104543Smarks 21114543Smarks } 21124543Smarks 21134543Smarks /* 2114*4988Sek110237 * pool create, destroy, and export don't log the history as part of 2115*4988Sek110237 * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export 2116*4988Sek110237 * do the logging of those commands. 21174543Smarks */ 2118789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 21194715Sek110237 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21204577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21214577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21224577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21234577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 21244577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 21254577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21264577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21274577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21284577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21294577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21304577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21314577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21324577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21334577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21344577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21354577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21364577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 21374543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 21384577Sahrens DATASET_NAME, B_FALSE }, 21394543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 21404577Sahrens DATASET_NAME, B_FALSE }, 21414577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 21424577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 21434577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 21444577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 21454577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 21464577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 21474577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 21484577Sahrens { zfs_ioc_recvbackup, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 21494577Sahrens { zfs_ioc_sendbackup, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 21504577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21514577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21524577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21534577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 21544577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21554577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 21564577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 21574577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 21584577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21594577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21604577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21614577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 21624577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 21634577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 21644543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 21654577Sahrens DATASET_NAME, B_FALSE }, 21664849Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }, 21674849Sahrens { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE }, 2168789Sahrens }; 2169789Sahrens 2170789Sahrens static int 2171789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2172789Sahrens { 2173789Sahrens zfs_cmd_t *zc; 2174789Sahrens uint_t vec; 21752199Sahrens int error, rc; 2176789Sahrens 2177789Sahrens if (getminor(dev) != 0) 2178789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2179789Sahrens 2180789Sahrens vec = cmd - ZFS_IOC; 21814787Sahrens ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); 2182789Sahrens 2183789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2184789Sahrens return (EINVAL); 2185789Sahrens 2186789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2187789Sahrens 2188789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2189789Sahrens 21904787Sahrens if (error == 0) 21914543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2192789Sahrens 2193789Sahrens /* 2194789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2195789Sahrens * the lower layers. 2196789Sahrens */ 2197789Sahrens if (error == 0) { 2198789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2199789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 22004577Sahrens case POOL_NAME: 2201789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2202789Sahrens error = EINVAL; 2203789Sahrens break; 2204789Sahrens 22054577Sahrens case DATASET_NAME: 2206789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2207789Sahrens error = EINVAL; 2208789Sahrens break; 22092856Snd150628 22104577Sahrens case NO_NAME: 22112856Snd150628 break; 2212789Sahrens } 2213789Sahrens } 2214789Sahrens 2215789Sahrens if (error == 0) 2216789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2217789Sahrens 22182199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 22194543Smarks if (error == 0) { 22202199Sahrens error = rc; 22214543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 22224543Smarks zfs_log_history(zc); 22234543Smarks } 2224789Sahrens 2225789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2226789Sahrens return (error); 2227789Sahrens } 2228789Sahrens 2229789Sahrens static int 2230789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2231789Sahrens { 2232789Sahrens if (cmd != DDI_ATTACH) 2233789Sahrens return (DDI_FAILURE); 2234789Sahrens 2235789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2236789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2237789Sahrens return (DDI_FAILURE); 2238789Sahrens 2239789Sahrens zfs_dip = dip; 2240789Sahrens 2241789Sahrens ddi_report_dev(dip); 2242789Sahrens 2243789Sahrens return (DDI_SUCCESS); 2244789Sahrens } 2245789Sahrens 2246789Sahrens static int 2247789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2248789Sahrens { 2249789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2250789Sahrens return (DDI_FAILURE); 2251789Sahrens 2252789Sahrens if (cmd != DDI_DETACH) 2253789Sahrens return (DDI_FAILURE); 2254789Sahrens 2255789Sahrens zfs_dip = NULL; 2256789Sahrens 2257789Sahrens ddi_prop_remove_all(dip); 2258789Sahrens ddi_remove_minor_node(dip, NULL); 2259789Sahrens 2260789Sahrens return (DDI_SUCCESS); 2261789Sahrens } 2262789Sahrens 2263789Sahrens /*ARGSUSED*/ 2264789Sahrens static int 2265789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2266789Sahrens { 2267789Sahrens switch (infocmd) { 2268789Sahrens case DDI_INFO_DEVT2DEVINFO: 2269789Sahrens *result = zfs_dip; 2270789Sahrens return (DDI_SUCCESS); 2271789Sahrens 2272789Sahrens case DDI_INFO_DEVT2INSTANCE: 2273849Sbonwick *result = (void *)0; 2274789Sahrens return (DDI_SUCCESS); 2275789Sahrens } 2276789Sahrens 2277789Sahrens return (DDI_FAILURE); 2278789Sahrens } 2279789Sahrens 2280789Sahrens /* 2281789Sahrens * OK, so this is a little weird. 2282789Sahrens * 2283789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2284789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2285789Sahrens * 2286789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2287789Sahrens * so most of the standard driver entry points are in zvol.c. 2288789Sahrens */ 2289789Sahrens static struct cb_ops zfs_cb_ops = { 2290789Sahrens zvol_open, /* open */ 2291789Sahrens zvol_close, /* close */ 2292789Sahrens zvol_strategy, /* strategy */ 2293789Sahrens nodev, /* print */ 2294789Sahrens nodev, /* dump */ 2295789Sahrens zvol_read, /* read */ 2296789Sahrens zvol_write, /* write */ 2297789Sahrens zfsdev_ioctl, /* ioctl */ 2298789Sahrens nodev, /* devmap */ 2299789Sahrens nodev, /* mmap */ 2300789Sahrens nodev, /* segmap */ 2301789Sahrens nochpoll, /* poll */ 2302789Sahrens ddi_prop_op, /* prop_op */ 2303789Sahrens NULL, /* streamtab */ 2304789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2305789Sahrens CB_REV, /* version */ 23063638Sbillm nodev, /* async read */ 23073638Sbillm nodev, /* async write */ 2308789Sahrens }; 2309789Sahrens 2310789Sahrens static struct dev_ops zfs_dev_ops = { 2311789Sahrens DEVO_REV, /* version */ 2312789Sahrens 0, /* refcnt */ 2313789Sahrens zfs_info, /* info */ 2314789Sahrens nulldev, /* identify */ 2315789Sahrens nulldev, /* probe */ 2316789Sahrens zfs_attach, /* attach */ 2317789Sahrens zfs_detach, /* detach */ 2318789Sahrens nodev, /* reset */ 2319789Sahrens &zfs_cb_ops, /* driver operations */ 2320789Sahrens NULL /* no bus operations */ 2321789Sahrens }; 2322789Sahrens 2323789Sahrens static struct modldrv zfs_modldrv = { 23244577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 23252676Seschrock &zfs_dev_ops 2326789Sahrens }; 2327789Sahrens 2328789Sahrens static struct modlinkage modlinkage = { 2329789Sahrens MODREV_1, 2330789Sahrens (void *)&zfs_modlfs, 2331789Sahrens (void *)&zfs_modldrv, 2332789Sahrens NULL 2333789Sahrens }; 2334789Sahrens 23354720Sfr157268 23364720Sfr157268 uint_t zfs_fsyncer_key; 23374720Sfr157268 2338789Sahrens int 2339789Sahrens _init(void) 2340789Sahrens { 2341789Sahrens int error; 2342789Sahrens 2343849Sbonwick spa_init(FREAD | FWRITE); 2344849Sbonwick zfs_init(); 2345849Sbonwick zvol_init(); 2346849Sbonwick 2347849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 2348849Sbonwick zvol_fini(); 2349849Sbonwick zfs_fini(); 2350849Sbonwick spa_fini(); 2351789Sahrens return (error); 2352849Sbonwick } 2353789Sahrens 23544720Sfr157268 tsd_create(&zfs_fsyncer_key, NULL); 23554720Sfr157268 2356789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 2357789Sahrens ASSERT(error == 0); 23584543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 2359789Sahrens 2360789Sahrens return (0); 2361789Sahrens } 2362789Sahrens 2363789Sahrens int 2364789Sahrens _fini(void) 2365789Sahrens { 2366789Sahrens int error; 2367789Sahrens 23681544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 2369789Sahrens return (EBUSY); 2370789Sahrens 2371789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 2372789Sahrens return (error); 2373789Sahrens 2374789Sahrens zvol_fini(); 2375789Sahrens zfs_fini(); 2376789Sahrens spa_fini(); 23774543Smarks if (zfs_share_inited) { 23784543Smarks (void) ddi_modclose(nfs_mod); 23794543Smarks (void) ddi_modclose(sharefs_mod); 23804543Smarks } 2381789Sahrens 23824720Sfr157268 tsd_destroy(&zfs_fsyncer_key); 2383789Sahrens ldi_ident_release(zfs_li); 2384789Sahrens zfs_li = NULL; 23854543Smarks mutex_destroy(&zfs_share_lock); 2386789Sahrens 2387789Sahrens return (error); 2388789Sahrens } 2389789Sahrens 2390789Sahrens int 2391789Sahrens _info(struct modinfo *modinfop) 2392789Sahrens { 2393789Sahrens return (mod_info(&modlinkage, modinfop)); 2394789Sahrens } 2395