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 6025094Slling 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 6185094Slling get_nvlist(uint64_t nvl, uint64_t size, nvlist_t **nvp) 619789Sahrens { 620789Sahrens char *packed; 621789Sahrens int error; 6225094Slling nvlist_t *list = NULL; 623789Sahrens 624789Sahrens /* 6252676Seschrock * Read in and unpack the user-supplied nvlist. 626789Sahrens */ 6275094Slling if (size == 0) 628789Sahrens return (EINVAL); 629789Sahrens 630789Sahrens packed = kmem_alloc(size, KM_SLEEP); 631789Sahrens 6325094Slling if ((error = xcopyin((void *)(uintptr_t)nvl, packed, size)) != 0) { 633789Sahrens kmem_free(packed, size); 634789Sahrens return (error); 635789Sahrens } 636789Sahrens 6375094Slling 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 6445094Slling *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; 6765094Slling nvlist_t *config, *props = NULL; 6774715Sek110237 char *buf; 678789Sahrens 6795094Slling if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 6805094Slling &config)) 6814988Sek110237 return (error); 6824715Sek110237 6835094Slling if (zc->zc_nvlist_src_size != 0 && (error = 6845094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 6855094Slling nvlist_free(config); 6865094Slling return (error); 6875094Slling } 6885094Slling 6894988Sek110237 buf = history_str_get(zc); 690789Sahrens 6915094Slling error = spa_create(zc->zc_name, config, props, buf); 692789Sahrens 6934988Sek110237 if (buf != NULL) 6944988Sek110237 history_str_free(buf); 6955094Slling 696789Sahrens nvlist_free(config); 697789Sahrens 6985094Slling if (props) 6995094Slling nvlist_free(props); 7005094Slling 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; 7175094Slling nvlist_t *config, *props = NULL; 718789Sahrens uint64_t guid; 719789Sahrens 7205094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7215094Slling &config)) != 0) 722789Sahrens return (error); 723789Sahrens 7245094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7255094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7265094Slling nvlist_free(config); 7275094Slling return (error); 7285094Slling } 7295094Slling 730789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 7311544Seschrock guid != zc->zc_guid) 732789Sahrens error = EINVAL; 733789Sahrens else 7345094Slling error = spa_import(zc->zc_name, config, props); 735789Sahrens 736789Sahrens nvlist_free(config); 737789Sahrens 7385094Slling if (props) 7395094Slling nvlist_free(props); 7405094Slling 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 8065094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 8075094Slling &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*5118Slling if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) { 865*5118Slling spa_close(spa, FTAG); 866*5118Slling return (EINVAL); 867*5118Slling } 868*5118Slling 8695094Slling spa_upgrade(spa, zc->zc_cookie); 8702926Sek110237 spa_close(spa, FTAG); 8712926Sek110237 8722926Sek110237 return (error); 8732926Sek110237 } 8742926Sek110237 8752926Sek110237 static int 8762926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 8772926Sek110237 { 8782926Sek110237 spa_t *spa; 8792926Sek110237 char *hist_buf; 8802926Sek110237 uint64_t size; 8812926Sek110237 int error; 8822926Sek110237 8832926Sek110237 if ((size = zc->zc_history_len) == 0) 8842926Sek110237 return (EINVAL); 8852926Sek110237 8862926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8872926Sek110237 return (error); 8882926Sek110237 8894577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 8903863Sek110237 spa_close(spa, FTAG); 8913863Sek110237 return (ENOTSUP); 8923863Sek110237 } 8933863Sek110237 8942926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 8952926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 8962926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 8974543Smarks error = xcopyout(hist_buf, 8984543Smarks (char *)(uintptr_t)zc->zc_history, 8992926Sek110237 zc->zc_history_len); 9002926Sek110237 } 9012926Sek110237 9022926Sek110237 spa_close(spa, FTAG); 9032926Sek110237 kmem_free(hist_buf, size); 9042926Sek110237 return (error); 9052926Sek110237 } 9062926Sek110237 9072926Sek110237 static int 9083444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 9093444Sek110237 { 9103444Sek110237 int error; 9113444Sek110237 9123912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 9133444Sek110237 return (error); 9143444Sek110237 9153444Sek110237 return (0); 9163444Sek110237 } 9173444Sek110237 9183444Sek110237 static int 9193444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 9203444Sek110237 { 9213444Sek110237 objset_t *osp; 9223444Sek110237 int error; 9233444Sek110237 9243444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 9253444Sek110237 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) 9263444Sek110237 return (error); 9273444Sek110237 9283444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 9293444Sek110237 sizeof (zc->zc_value)); 9303444Sek110237 dmu_objset_close(osp); 9313444Sek110237 9323444Sek110237 return (error); 9333444Sek110237 } 9343444Sek110237 9353444Sek110237 static int 936789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 937789Sahrens { 938789Sahrens spa_t *spa; 939789Sahrens int error; 940789Sahrens nvlist_t *config; 941789Sahrens 942789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 943789Sahrens if (error != 0) 944789Sahrens return (error); 945789Sahrens 9463912Slling /* 9473912Slling * A root pool with concatenated devices is not supported. 9483912Slling * Thus, can not add a device to a root pool with one device. 9493912Slling */ 9503912Slling if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0) { 9513912Slling spa_close(spa, FTAG); 9523912Slling return (EDOM); 9533912Slling } 9543912Slling 9555094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 9565094Slling &config)) == 0) { 957789Sahrens error = spa_vdev_add(spa, config); 958789Sahrens nvlist_free(config); 959789Sahrens } 960789Sahrens spa_close(spa, FTAG); 961789Sahrens return (error); 962789Sahrens } 963789Sahrens 964789Sahrens static int 965789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 966789Sahrens { 9672082Seschrock spa_t *spa; 9682082Seschrock int error; 9692082Seschrock 9702082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 9712082Seschrock if (error != 0) 9722082Seschrock return (error); 9732082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 9742082Seschrock spa_close(spa, FTAG); 9752082Seschrock return (error); 976789Sahrens } 977789Sahrens 978789Sahrens static int 9794451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 980789Sahrens { 981789Sahrens spa_t *spa; 982789Sahrens int error; 9834451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 984789Sahrens 9852926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 986789Sahrens return (error); 9874451Seschrock switch (zc->zc_cookie) { 9884451Seschrock case VDEV_STATE_ONLINE: 9894451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 9904451Seschrock break; 9914451Seschrock 9924451Seschrock case VDEV_STATE_OFFLINE: 9934451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 9944451Seschrock break; 995789Sahrens 9964451Seschrock case VDEV_STATE_FAULTED: 9974451Seschrock error = vdev_fault(spa, zc->zc_guid); 9984451Seschrock break; 999789Sahrens 10004451Seschrock case VDEV_STATE_DEGRADED: 10014451Seschrock error = vdev_degrade(spa, zc->zc_guid); 10024451Seschrock break; 10034451Seschrock 10044451Seschrock default: 10054451Seschrock error = EINVAL; 10064451Seschrock } 10074451Seschrock zc->zc_cookie = newstate; 1008789Sahrens spa_close(spa, FTAG); 1009789Sahrens return (error); 1010789Sahrens } 1011789Sahrens 1012789Sahrens static int 1013789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 1014789Sahrens { 1015789Sahrens spa_t *spa; 1016789Sahrens int replacing = zc->zc_cookie; 1017789Sahrens nvlist_t *config; 1018789Sahrens int error; 1019789Sahrens 10202926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1021789Sahrens return (error); 1022789Sahrens 10235094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 10245094Slling &config)) == 0) { 10251544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 1026789Sahrens nvlist_free(config); 1027789Sahrens } 1028789Sahrens 1029789Sahrens spa_close(spa, FTAG); 1030789Sahrens return (error); 1031789Sahrens } 1032789Sahrens 1033789Sahrens static int 1034789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 1035789Sahrens { 1036789Sahrens spa_t *spa; 1037789Sahrens int error; 1038789Sahrens 10392926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1040789Sahrens return (error); 1041789Sahrens 10421544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1043789Sahrens 1044789Sahrens spa_close(spa, FTAG); 1045789Sahrens return (error); 1046789Sahrens } 1047789Sahrens 1048789Sahrens static int 10491354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 10501354Seschrock { 10511354Seschrock spa_t *spa; 10522676Seschrock char *path = zc->zc_value; 10531544Seschrock uint64_t guid = zc->zc_guid; 10541354Seschrock int error; 10551354Seschrock 10561354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10571354Seschrock if (error != 0) 10581354Seschrock return (error); 10591354Seschrock 10601354Seschrock error = spa_vdev_setpath(spa, guid, path); 10611354Seschrock spa_close(spa, FTAG); 10621354Seschrock return (error); 10631354Seschrock } 10641354Seschrock 10651354Seschrock static int 1066789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1067789Sahrens { 1068789Sahrens objset_t *os = NULL; 1069789Sahrens int error; 10701356Seschrock nvlist_t *nv; 1071789Sahrens 1072789Sahrens retry: 1073789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1074789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1075789Sahrens if (error != 0) { 1076789Sahrens /* 1077789Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1078789Sahrens * the objset is held exclusively. Fortunately this hold is 1079789Sahrens * only for a short while, so we retry here. 1080789Sahrens * This avoids user code having to handle EBUSY, 1081789Sahrens * for example for a "zfs list". 1082789Sahrens */ 1083789Sahrens if (error == EBUSY) { 1084789Sahrens delay(1); 1085789Sahrens goto retry; 1086789Sahrens } 1087789Sahrens return (error); 1088789Sahrens } 1089789Sahrens 10902885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1091789Sahrens 10922856Snd150628 if (zc->zc_nvlist_dst != 0 && 10931356Seschrock (error = dsl_prop_get_all(os, &nv)) == 0) { 10942885Sahrens dmu_objset_stats(os, nv); 10953087Sahrens /* 10964577Sahrens * NB: {zpl,zvol}_get_stats() will read the objset contents, 10973087Sahrens * which we aren't supposed to do with a 10983087Sahrens * DS_MODE_STANDARD open, because it could be 10993087Sahrens * inconsistent. So this is a bit of a workaround... 11003087Sahrens */ 11014577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 11024577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 11034577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 11044577Sahrens else if (dmu_objset_type(os) == DMU_OST_ZFS) 11054577Sahrens (void) zfs_get_stats(os, nv); 11064577Sahrens } 11072676Seschrock error = put_nvlist(zc, nv); 11081356Seschrock nvlist_free(nv); 11091356Seschrock } 1110789Sahrens 11112676Seschrock spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value)); 11121544Seschrock 1113789Sahrens dmu_objset_close(os); 1114789Sahrens return (error); 1115789Sahrens } 1116789Sahrens 1117789Sahrens static int 1118789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1119789Sahrens { 1120885Sahrens objset_t *os; 1121789Sahrens int error; 1122789Sahrens char *p; 1123789Sahrens 1124885Sahrens retry: 1125885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1126885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1127885Sahrens if (error != 0) { 1128885Sahrens /* 1129885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1130885Sahrens * the objset is held exclusively. Fortunately this hold is 1131885Sahrens * only for a short while, so we retry here. 1132885Sahrens * This avoids user code having to handle EBUSY, 1133885Sahrens * for example for a "zfs list". 1134885Sahrens */ 1135885Sahrens if (error == EBUSY) { 1136885Sahrens delay(1); 1137885Sahrens goto retry; 1138885Sahrens } 1139885Sahrens if (error == ENOENT) 1140885Sahrens error = ESRCH; 1141885Sahrens return (error); 1142789Sahrens } 1143789Sahrens 1144789Sahrens p = strrchr(zc->zc_name, '/'); 1145789Sahrens if (p == NULL || p[1] != '\0') 1146789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1147789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1148789Sahrens 1149789Sahrens do { 1150885Sahrens error = dmu_dir_list_next(os, 1151885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1152885Sahrens NULL, &zc->zc_cookie); 1153789Sahrens if (error == ENOENT) 1154789Sahrens error = ESRCH; 1155885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1156789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 1157789Sahrens 1158885Sahrens /* 1159885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1160885Sahrens * try to get stats for it. Userland will skip over it. 1161885Sahrens */ 1162885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1163885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1164789Sahrens 1165885Sahrens dmu_objset_close(os); 1166789Sahrens return (error); 1167789Sahrens } 1168789Sahrens 1169789Sahrens static int 1170789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1171789Sahrens { 1172885Sahrens objset_t *os; 1173789Sahrens int error; 1174789Sahrens 1175789Sahrens retry: 1176885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1177885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1178885Sahrens if (error != 0) { 1179789Sahrens /* 1180885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1181789Sahrens * the objset is held exclusively. Fortunately this hold is 1182789Sahrens * only for a short while, so we retry here. 1183789Sahrens * This avoids user code having to handle EBUSY, 1184885Sahrens * for example for a "zfs list". 1185789Sahrens */ 1186789Sahrens if (error == EBUSY) { 1187789Sahrens delay(1); 1188789Sahrens goto retry; 1189789Sahrens } 1190789Sahrens if (error == ENOENT) 1191885Sahrens error = ESRCH; 1192789Sahrens return (error); 1193789Sahrens } 1194789Sahrens 11951003Slling /* 11961003Slling * A dataset name of maximum length cannot have any snapshots, 11971003Slling * so exit immediately. 11981003Slling */ 11991003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1200885Sahrens dmu_objset_close(os); 12011003Slling return (ESRCH); 1202789Sahrens } 1203789Sahrens 1204885Sahrens error = dmu_snapshot_list_next(os, 1205885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 1206885Sahrens zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie); 1207789Sahrens if (error == ENOENT) 1208789Sahrens error = ESRCH; 1209789Sahrens 1210885Sahrens if (error == 0) 1211885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1212789Sahrens 1213885Sahrens dmu_objset_close(os); 1214789Sahrens return (error); 1215789Sahrens } 1216789Sahrens 1217789Sahrens static int 12184787Sahrens zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) 1219789Sahrens { 12202676Seschrock nvpair_t *elem; 12212676Seschrock int error; 12222676Seschrock uint64_t intval; 12232676Seschrock char *strval; 12242676Seschrock 12254543Smarks /* 12264543Smarks * First validate permission to set all of the properties 12274543Smarks */ 12282676Seschrock elem = NULL; 12292676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 12304670Sahrens const char *propname = nvpair_name(elem); 12314670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 12322676Seschrock 12335094Slling if (prop == ZPROP_INVAL) { 12342676Seschrock /* 12352676Seschrock * If this is a user-defined property, it must be a 12362676Seschrock * string, and there is no further validation to do. 12372676Seschrock */ 12382676Seschrock if (!zfs_prop_user(propname) || 12392676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 12402676Seschrock return (EINVAL); 12412676Seschrock 12424543Smarks error = zfs_secpolicy_write_perms(name, 12434787Sahrens ZFS_DELEG_PERM_USERPROP, CRED()); 12444670Sahrens if (error) 12454670Sahrens return (error); 12464543Smarks continue; 12472676Seschrock } 12482676Seschrock 12494787Sahrens if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 12504670Sahrens return (error); 12512676Seschrock 12524670Sahrens /* 12534670Sahrens * Check that this value is valid for this pool version 12544670Sahrens */ 12554670Sahrens switch (prop) { 12563886Sahl case ZFS_PROP_COMPRESSION: 12573886Sahl /* 12583886Sahl * If the user specified gzip compression, make sure 12593886Sahl * the SPA supports it. We ignore any errors here since 12603886Sahl * we'll catch them later. 12613886Sahl */ 12623886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 12633886Sahl nvpair_value_uint64(elem, &intval) == 0 && 12643886Sahl intval >= ZIO_COMPRESS_GZIP_1 && 12653886Sahl intval <= ZIO_COMPRESS_GZIP_9) { 12664543Smarks spa_t *spa; 12674543Smarks 12684603Sahrens if (spa_open(name, &spa, FTAG) == 0) { 12693886Sahl if (spa_version(spa) < 12704577Sahrens SPA_VERSION_GZIP_COMPRESSION) { 12713886Sahl spa_close(spa, FTAG); 12723886Sahl return (ENOTSUP); 12733886Sahl } 12743886Sahl 12753886Sahl spa_close(spa, FTAG); 12763886Sahl } 12773886Sahl } 12783886Sahl break; 12794603Sahrens 12804603Sahrens case ZFS_PROP_COPIES: 12814603Sahrens { 12824603Sahrens spa_t *spa; 12834603Sahrens 12844603Sahrens if (spa_open(name, &spa, FTAG) == 0) { 12854603Sahrens if (spa_version(spa) < 12864603Sahrens SPA_VERSION_DITTO_BLOCKS) { 12874603Sahrens spa_close(spa, FTAG); 12884603Sahrens return (ENOTSUP); 12894603Sahrens } 12904603Sahrens spa_close(spa, FTAG); 12914603Sahrens } 12924603Sahrens break; 12934603Sahrens } 12942676Seschrock } 12954543Smarks } 12964543Smarks 12974543Smarks elem = NULL; 12984543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 12994670Sahrens const char *propname = nvpair_name(elem); 13004670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 13014543Smarks 13025094Slling if (prop == ZPROP_INVAL) { 13034543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 13044543Smarks error = dsl_prop_set(name, propname, 1, 13054543Smarks strlen(strval) + 1, strval); 13064543Smarks if (error == 0) 13074543Smarks continue; 13084543Smarks else 13094543Smarks return (error); 13104543Smarks } 13112676Seschrock 13122676Seschrock switch (prop) { 13132676Seschrock case ZFS_PROP_QUOTA: 13142676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13154577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 13162676Seschrock return (error); 13172676Seschrock break; 13182676Seschrock 13192676Seschrock case ZFS_PROP_RESERVATION: 13202676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13212676Seschrock (error = dsl_dir_set_reservation(name, 13222676Seschrock intval)) != 0) 13232676Seschrock return (error); 13242676Seschrock break; 1325789Sahrens 13262676Seschrock case ZFS_PROP_VOLSIZE: 13272676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13284787Sahrens (error = zvol_set_volsize(name, 13294787Sahrens ddi_driver_major(zfs_dip), intval)) != 0) 13302676Seschrock return (error); 13312676Seschrock break; 13322676Seschrock 13332676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 13342676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13354577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 13364577Sahrens return (error); 13374577Sahrens break; 13384577Sahrens 13394577Sahrens case ZFS_PROP_VERSION: 13404577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13414577Sahrens (error = zfs_set_version(name, intval)) != 0) 13422676Seschrock return (error); 13432676Seschrock break; 13442676Seschrock 13452676Seschrock default: 13462676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 13472676Seschrock if (zfs_prop_get_type(prop) != 13484787Sahrens PROP_TYPE_STRING) 13492676Seschrock return (EINVAL); 13502717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 13512717Seschrock if ((error = dsl_prop_set(name, 13522676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 13532717Seschrock strval)) != 0) 13542717Seschrock return (error); 13552676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 13562885Sahrens const char *unused; 13572885Sahrens 13582717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 13592676Seschrock 13602676Seschrock switch (zfs_prop_get_type(prop)) { 13614787Sahrens case PROP_TYPE_NUMBER: 13622676Seschrock break; 13634787Sahrens case PROP_TYPE_STRING: 13642717Seschrock return (EINVAL); 13654787Sahrens case PROP_TYPE_INDEX: 13662717Seschrock if (zfs_prop_index_to_string(prop, 13672717Seschrock intval, &unused) != 0) 13682717Seschrock return (EINVAL); 13692676Seschrock break; 13702676Seschrock default: 13714577Sahrens cmn_err(CE_PANIC, 13724577Sahrens "unknown property type"); 13732676Seschrock break; 13742676Seschrock } 13752676Seschrock 13762717Seschrock if ((error = dsl_prop_set(name, propname, 13772717Seschrock 8, 1, &intval)) != 0) 13782717Seschrock return (error); 13792676Seschrock } else { 13802676Seschrock return (EINVAL); 13812676Seschrock } 13822676Seschrock break; 13832676Seschrock } 13842676Seschrock } 13852676Seschrock 13862676Seschrock return (0); 1387789Sahrens } 1388789Sahrens 1389789Sahrens static int 13902676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1391789Sahrens { 13922676Seschrock nvlist_t *nvl; 13932676Seschrock int error; 1394789Sahrens 13955094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 13965094Slling &nvl)) != 0) 13972676Seschrock return (error); 13982676Seschrock 13994787Sahrens error = zfs_set_prop_nvlist(zc->zc_name, nvl); 14004543Smarks 14012676Seschrock nvlist_free(nvl); 14022676Seschrock return (error); 1403789Sahrens } 1404789Sahrens 1405789Sahrens static int 14064849Sahrens zfs_ioc_inherit_prop(zfs_cmd_t *zc) 14074849Sahrens { 14084849Sahrens /* the property name has been validated by zfs_secpolicy_inherit() */ 14094849Sahrens return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 14104849Sahrens } 14114849Sahrens 14124849Sahrens static int 14134098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 14143912Slling { 14155094Slling nvlist_t *props; 14163912Slling spa_t *spa; 14175094Slling int error; 14183912Slling 14195094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 14205094Slling &props))) 14213912Slling return (error); 14223912Slling 14233912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 14245094Slling nvlist_free(props); 14253912Slling return (error); 14263912Slling } 14273912Slling 14285094Slling error = spa_prop_set(spa, props); 14293912Slling 14305094Slling nvlist_free(props); 14313912Slling spa_close(spa, FTAG); 14323912Slling 14333912Slling return (error); 14343912Slling } 14353912Slling 14363912Slling static int 14374098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 14383912Slling { 14393912Slling spa_t *spa; 14403912Slling int error; 14413912Slling nvlist_t *nvp = NULL; 14423912Slling 14433912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 14443912Slling return (error); 14453912Slling 14465094Slling error = spa_prop_get(spa, &nvp); 14473912Slling 14483912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 14493912Slling error = put_nvlist(zc, nvp); 14503912Slling else 14513912Slling error = EFAULT; 14523912Slling 14533912Slling spa_close(spa, FTAG); 14543912Slling 14553912Slling if (nvp) 14563912Slling nvlist_free(nvp); 14573912Slling return (error); 14583912Slling } 14593912Slling 14603912Slling static int 14614543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 14624543Smarks { 14634543Smarks nvlist_t *nvp; 14644543Smarks int error; 14654543Smarks uint32_t uid; 14664543Smarks uint32_t gid; 14674543Smarks uint32_t *groups; 14684543Smarks uint_t group_cnt; 14694543Smarks cred_t *usercred; 14704543Smarks 14715094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 14725094Slling &nvp)) != 0) { 14734543Smarks return (error); 14744543Smarks } 14754543Smarks 14764543Smarks if ((error = nvlist_lookup_uint32(nvp, 14774543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 14784543Smarks nvlist_free(nvp); 14794543Smarks return (EPERM); 14804543Smarks } 14814543Smarks 14824543Smarks if ((error = nvlist_lookup_uint32(nvp, 14834543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 14844543Smarks nvlist_free(nvp); 14854543Smarks return (EPERM); 14864543Smarks } 14874543Smarks 14884543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 14894543Smarks &groups, &group_cnt)) != 0) { 14904543Smarks nvlist_free(nvp); 14914543Smarks return (EPERM); 14924543Smarks } 14934543Smarks usercred = cralloc(); 14944543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 14954543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 14964543Smarks nvlist_free(nvp); 14974543Smarks crfree(usercred); 14984543Smarks return (EPERM); 14994543Smarks } 15004543Smarks nvlist_free(nvp); 15014543Smarks error = dsl_deleg_access(zc->zc_name, 15024787Sahrens zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); 15034543Smarks crfree(usercred); 15044543Smarks return (error); 15054543Smarks } 15064543Smarks 15074543Smarks static int 15084543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 15094543Smarks { 15104543Smarks int error; 15114543Smarks nvlist_t *fsaclnv = NULL; 15124543Smarks 15135094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15145094Slling &fsaclnv)) != 0) 15154543Smarks return (error); 15164543Smarks 15174543Smarks /* 15184543Smarks * Verify nvlist is constructed correctly 15194543Smarks */ 15204543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 15214543Smarks nvlist_free(fsaclnv); 15224543Smarks return (EINVAL); 15234543Smarks } 15244543Smarks 15254543Smarks /* 15264543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 15274543Smarks * that user is allowed to hand out each permission in 15284543Smarks * the nvlist(s) 15294543Smarks */ 15304543Smarks 15314787Sahrens error = secpolicy_zfs(CRED()); 15324543Smarks if (error) { 15334787Sahrens if (zc->zc_perm_action == B_FALSE) { 15344787Sahrens error = dsl_deleg_can_allow(zc->zc_name, 15354787Sahrens fsaclnv, CRED()); 15364787Sahrens } else { 15374787Sahrens error = dsl_deleg_can_unallow(zc->zc_name, 15384787Sahrens fsaclnv, CRED()); 15394787Sahrens } 15404543Smarks } 15414543Smarks 15424543Smarks if (error == 0) 15434543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 15444543Smarks 15454543Smarks nvlist_free(fsaclnv); 15464543Smarks return (error); 15474543Smarks } 15484543Smarks 15494543Smarks static int 15504543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 15514543Smarks { 15524543Smarks nvlist_t *nvp; 15534543Smarks int error; 15544543Smarks 15554543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 15564543Smarks error = put_nvlist(zc, nvp); 15574543Smarks nvlist_free(nvp); 15584543Smarks } 15594543Smarks 15604543Smarks return (error); 15614543Smarks } 15624543Smarks 15634543Smarks static int 1564789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1565789Sahrens { 15664787Sahrens return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); 1567789Sahrens } 1568789Sahrens 1569789Sahrens static int 1570789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1571789Sahrens { 15722676Seschrock return (zvol_remove_minor(zc->zc_name)); 1573789Sahrens } 1574789Sahrens 1575789Sahrens /* 1576789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1577789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1578789Sahrens * is responsible for releasing the returned vfs pointer. 1579789Sahrens */ 1580789Sahrens static vfs_t * 1581789Sahrens zfs_get_vfs(const char *resource) 1582789Sahrens { 1583789Sahrens struct vfs *vfsp; 1584789Sahrens struct vfs *vfs_found = NULL; 1585789Sahrens 1586789Sahrens vfs_list_read_lock(); 1587789Sahrens vfsp = rootvfs; 1588789Sahrens do { 1589789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1590789Sahrens VFS_HOLD(vfsp); 1591789Sahrens vfs_found = vfsp; 1592789Sahrens break; 1593789Sahrens } 1594789Sahrens vfsp = vfsp->vfs_next; 1595789Sahrens } while (vfsp != rootvfs); 1596789Sahrens vfs_list_unlock(); 1597789Sahrens return (vfs_found); 1598789Sahrens } 1599789Sahrens 16004543Smarks /* ARGSUSED */ 1601789Sahrens static void 16024543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1603789Sahrens { 16044577Sahrens nvlist_t *nvprops = arg; 16054577Sahrens uint64_t version = ZPL_VERSION; 16064577Sahrens 16074577Sahrens (void) nvlist_lookup_uint64(nvprops, 16084577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version); 16094577Sahrens 16104577Sahrens zfs_create_fs(os, cr, version, tx); 1611789Sahrens } 1612789Sahrens 1613789Sahrens static int 1614789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1615789Sahrens { 1616789Sahrens objset_t *clone; 1617789Sahrens int error = 0; 16184543Smarks nvlist_t *nvprops = NULL; 16194543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1620789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1621789Sahrens 1622789Sahrens switch (type) { 1623789Sahrens 1624789Sahrens case DMU_OST_ZFS: 1625789Sahrens cbfunc = zfs_create_cb; 1626789Sahrens break; 1627789Sahrens 1628789Sahrens case DMU_OST_ZVOL: 1629789Sahrens cbfunc = zvol_create_cb; 1630789Sahrens break; 1631789Sahrens 1632789Sahrens default: 16332199Sahrens cbfunc = NULL; 16342199Sahrens } 16352199Sahrens if (strchr(zc->zc_name, '@')) 1636789Sahrens return (EINVAL); 1637789Sahrens 16382676Seschrock if (zc->zc_nvlist_src != NULL && 16395094Slling (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16405094Slling &nvprops)) != 0) 16412676Seschrock return (error); 16422676Seschrock 16432676Seschrock if (zc->zc_value[0] != '\0') { 1644789Sahrens /* 1645789Sahrens * We're creating a clone of an existing snapshot. 1646789Sahrens */ 16472676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 16482676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 16494543Smarks nvlist_free(nvprops); 1650789Sahrens return (EINVAL); 16512676Seschrock } 1652789Sahrens 16532676Seschrock error = dmu_objset_open(zc->zc_value, type, 1654789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 16552676Seschrock if (error) { 16564543Smarks nvlist_free(nvprops); 1657789Sahrens return (error); 16582676Seschrock } 1659789Sahrens error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); 1660789Sahrens dmu_objset_close(clone); 1661789Sahrens } else { 16622676Seschrock if (cbfunc == NULL) { 16634543Smarks nvlist_free(nvprops); 16642199Sahrens return (EINVAL); 16652676Seschrock } 16662676Seschrock 1667789Sahrens if (type == DMU_OST_ZVOL) { 16682676Seschrock uint64_t volsize, volblocksize; 16692676Seschrock 16704543Smarks if (nvprops == NULL || 16714543Smarks nvlist_lookup_uint64(nvprops, 16722676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 16732676Seschrock &volsize) != 0) { 16744543Smarks nvlist_free(nvprops); 16752676Seschrock return (EINVAL); 16762676Seschrock } 16772676Seschrock 16784543Smarks if ((error = nvlist_lookup_uint64(nvprops, 16792676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 16802676Seschrock &volblocksize)) != 0 && error != ENOENT) { 16814543Smarks nvlist_free(nvprops); 16822676Seschrock return (EINVAL); 16832676Seschrock } 16841133Seschrock 16852676Seschrock if (error != 0) 16862676Seschrock volblocksize = zfs_prop_default_numeric( 16872676Seschrock ZFS_PROP_VOLBLOCKSIZE); 16882676Seschrock 16892676Seschrock if ((error = zvol_check_volblocksize( 16902676Seschrock volblocksize)) != 0 || 16912676Seschrock (error = zvol_check_volsize(volsize, 16922676Seschrock volblocksize)) != 0) { 16934543Smarks nvlist_free(nvprops); 1694789Sahrens return (error); 16952676Seschrock } 16964577Sahrens } else if (type == DMU_OST_ZFS) { 16974577Sahrens uint64_t version; 16984577Sahrens 16994577Sahrens if (0 == nvlist_lookup_uint64(nvprops, 17004577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version) && 17014577Sahrens (version < ZPL_VERSION_INITIAL || 17024577Sahrens version > ZPL_VERSION)) { 17034577Sahrens nvlist_free(nvprops); 17044577Sahrens return (EINVAL); 17054577Sahrens } 17062676Seschrock } 17071133Seschrock 17082676Seschrock error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, 17094543Smarks nvprops); 1710789Sahrens } 17112676Seschrock 17122676Seschrock /* 17132676Seschrock * It would be nice to do this atomically. 17142676Seschrock */ 17152676Seschrock if (error == 0) { 17164787Sahrens if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) 17172676Seschrock (void) dmu_objset_destroy(zc->zc_name); 17182676Seschrock } 17192676Seschrock 17204543Smarks nvlist_free(nvprops); 1721789Sahrens return (error); 1722789Sahrens } 1723789Sahrens 1724789Sahrens static int 17252199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 17262199Sahrens { 17272676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 17282199Sahrens return (EINVAL); 17292199Sahrens return (dmu_objset_snapshot(zc->zc_name, 17302676Seschrock zc->zc_value, zc->zc_cookie)); 17312199Sahrens } 17322199Sahrens 17334007Smmusante int 17342199Sahrens zfs_unmount_snap(char *name, void *arg) 1735789Sahrens { 17362199Sahrens char *snapname = arg; 17372199Sahrens char *cp; 17382417Sahrens vfs_t *vfsp = NULL; 17392199Sahrens 17402199Sahrens /* 17412199Sahrens * Snapshots (which are under .zfs control) must be unmounted 17422199Sahrens * before they can be destroyed. 17432199Sahrens */ 17442199Sahrens 17452199Sahrens if (snapname) { 17462199Sahrens (void) strcat(name, "@"); 17472199Sahrens (void) strcat(name, snapname); 17482199Sahrens vfsp = zfs_get_vfs(name); 17492199Sahrens cp = strchr(name, '@'); 17502199Sahrens *cp = '\0'; 17512417Sahrens } else if (strchr(name, '@')) { 17522199Sahrens vfsp = zfs_get_vfs(name); 17532199Sahrens } 17542199Sahrens 17552199Sahrens if (vfsp) { 17562199Sahrens /* 17572199Sahrens * Always force the unmount for snapshots. 17582199Sahrens */ 17592199Sahrens int flag = MS_FORCE; 1760789Sahrens int err; 1761789Sahrens 17622199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 17632199Sahrens VFS_RELE(vfsp); 17642199Sahrens return (err); 17652199Sahrens } 17662199Sahrens VFS_RELE(vfsp); 17672199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 17682199Sahrens return (err); 17692199Sahrens } 17702199Sahrens return (0); 17712199Sahrens } 17722199Sahrens 17732199Sahrens static int 17742199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 17752199Sahrens { 17762199Sahrens int err; 1777789Sahrens 17782676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 17792199Sahrens return (EINVAL); 17802199Sahrens err = dmu_objset_find(zc->zc_name, 17812676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 17822199Sahrens if (err) 17832199Sahrens return (err); 17842676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 17852199Sahrens } 17862199Sahrens 17872199Sahrens static int 17882199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 17892199Sahrens { 17902199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 17912199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 17922199Sahrens if (err) 17932199Sahrens return (err); 1794789Sahrens } 1795789Sahrens 1796789Sahrens return (dmu_objset_destroy(zc->zc_name)); 1797789Sahrens } 1798789Sahrens 1799789Sahrens static int 1800789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 1801789Sahrens { 1802789Sahrens return (dmu_objset_rollback(zc->zc_name)); 1803789Sahrens } 1804789Sahrens 1805789Sahrens static int 1806789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 1807789Sahrens { 18084490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 18094007Smmusante 18102676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 18112676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) 1812789Sahrens return (EINVAL); 1813789Sahrens 18144007Smmusante /* 18154007Smmusante * Unmount snapshot unless we're doing a recursive rename, 18164007Smmusante * in which case the dataset code figures out which snapshots 18174007Smmusante * to unmount. 18184007Smmusante */ 18194007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 1820789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 18212199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18222199Sahrens if (err) 18232199Sahrens return (err); 1824789Sahrens } 1825789Sahrens 18264007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 1827789Sahrens } 1828789Sahrens 1829789Sahrens static int 1830789Sahrens zfs_ioc_recvbackup(zfs_cmd_t *zc) 1831789Sahrens { 1832789Sahrens file_t *fp; 1833789Sahrens int error, fd; 18342885Sahrens offset_t new_off; 1835789Sahrens 18363265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 18373265Sahrens strchr(zc->zc_value, '@') == NULL) 18383265Sahrens return (EINVAL); 18393265Sahrens 1840789Sahrens fd = zc->zc_cookie; 1841789Sahrens fp = getf(fd); 1842789Sahrens if (fp == NULL) 1843789Sahrens return (EBADF); 18442676Seschrock error = dmu_recvbackup(zc->zc_value, &zc->zc_begin_record, 18452676Seschrock &zc->zc_cookie, (boolean_t)zc->zc_guid, fp->f_vnode, 18462665Snd150628 fp->f_offset); 18472885Sahrens 18482885Sahrens new_off = fp->f_offset + zc->zc_cookie; 18492885Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &new_off) == 0) 18502885Sahrens fp->f_offset = new_off; 18512885Sahrens 1852789Sahrens releasef(fd); 1853789Sahrens return (error); 1854789Sahrens } 1855789Sahrens 1856789Sahrens static int 1857789Sahrens zfs_ioc_sendbackup(zfs_cmd_t *zc) 1858789Sahrens { 1859789Sahrens objset_t *fromsnap = NULL; 1860789Sahrens objset_t *tosnap; 1861789Sahrens file_t *fp; 1862789Sahrens int error; 1863789Sahrens 1864789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1865789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); 1866789Sahrens if (error) 1867789Sahrens return (error); 1868789Sahrens 18692676Seschrock if (zc->zc_value[0] != '\0') { 18702885Sahrens char buf[MAXPATHLEN]; 18712885Sahrens char *cp; 18722885Sahrens 18732885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 18742885Sahrens cp = strchr(buf, '@'); 18752885Sahrens if (cp) 18762885Sahrens *(cp+1) = 0; 18772885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 18782885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 1879789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); 1880789Sahrens if (error) { 1881789Sahrens dmu_objset_close(tosnap); 1882789Sahrens return (error); 1883789Sahrens } 1884789Sahrens } 1885789Sahrens 1886789Sahrens fp = getf(zc->zc_cookie); 1887789Sahrens if (fp == NULL) { 1888789Sahrens dmu_objset_close(tosnap); 1889789Sahrens if (fromsnap) 1890789Sahrens dmu_objset_close(fromsnap); 1891789Sahrens return (EBADF); 1892789Sahrens } 1893789Sahrens 1894789Sahrens error = dmu_sendbackup(tosnap, fromsnap, fp->f_vnode); 1895789Sahrens 1896789Sahrens releasef(zc->zc_cookie); 1897789Sahrens if (fromsnap) 1898789Sahrens dmu_objset_close(fromsnap); 1899789Sahrens dmu_objset_close(tosnap); 1900789Sahrens return (error); 1901789Sahrens } 1902789Sahrens 19031544Seschrock static int 19041544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 19051544Seschrock { 19061544Seschrock int id, error; 19071544Seschrock 19081544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 19091544Seschrock &zc->zc_inject_record); 19101544Seschrock 19111544Seschrock if (error == 0) 19121544Seschrock zc->zc_guid = (uint64_t)id; 19131544Seschrock 19141544Seschrock return (error); 19151544Seschrock } 19161544Seschrock 19171544Seschrock static int 19181544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 19191544Seschrock { 19201544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 19211544Seschrock } 19221544Seschrock 19231544Seschrock static int 19241544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 19251544Seschrock { 19261544Seschrock int id = (int)zc->zc_guid; 19271544Seschrock int error; 19281544Seschrock 19291544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 19301544Seschrock &zc->zc_inject_record); 19311544Seschrock 19321544Seschrock zc->zc_guid = id; 19331544Seschrock 19341544Seschrock return (error); 19351544Seschrock } 19361544Seschrock 19371544Seschrock static int 19381544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 19391544Seschrock { 19401544Seschrock spa_t *spa; 19411544Seschrock int error; 19422676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 19431544Seschrock 19441544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 19451544Seschrock return (error); 19461544Seschrock 19472676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 19481544Seschrock &count); 19491544Seschrock if (error == 0) 19502676Seschrock zc->zc_nvlist_dst_size = count; 19511544Seschrock else 19522676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 19531544Seschrock 19541544Seschrock spa_close(spa, FTAG); 19551544Seschrock 19561544Seschrock return (error); 19571544Seschrock } 19581544Seschrock 19591544Seschrock static int 19601544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 19611544Seschrock { 19621544Seschrock spa_t *spa; 19631544Seschrock vdev_t *vd; 19644808Sek110237 uint64_t txg; 19651544Seschrock int error; 19661544Seschrock 19671544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 19681544Seschrock return (error); 19691544Seschrock 19704451Seschrock txg = spa_vdev_enter(spa); 19711544Seschrock 19722676Seschrock if (zc->zc_guid == 0) { 19731544Seschrock vd = NULL; 19742676Seschrock } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { 19754451Seschrock (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 19761544Seschrock spa_close(spa, FTAG); 19771544Seschrock return (ENODEV); 19781544Seschrock } 19791544Seschrock 19801544Seschrock vdev_clear(spa, vd); 19811544Seschrock 19824451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 19831544Seschrock 19841544Seschrock spa_close(spa, FTAG); 19851544Seschrock 19861544Seschrock return (0); 19871544Seschrock } 19881544Seschrock 19891544Seschrock static int 19902082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 19912082Seschrock { 19922417Sahrens char *cp; 19932417Sahrens 19942417Sahrens /* 19952417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 19962417Sahrens * it's easier. 19972417Sahrens */ 19982676Seschrock cp = strchr(zc->zc_value, '@'); 19992417Sahrens if (cp) 20002417Sahrens *cp = '\0'; 20012676Seschrock (void) dmu_objset_find(zc->zc_value, 20022417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 20032082Seschrock return (dsl_dataset_promote(zc->zc_name)); 20042082Seschrock } 20052082Seschrock 20064543Smarks /* 20074543Smarks * We don't want to have a hard dependency 20084543Smarks * against some special symbols in sharefs 20094543Smarks * and nfs. Determine them if needed when 20104543Smarks * the first file system is shared. 20114543Smarks * Neither sharefs or nfs are unloadable modules. 20124543Smarks */ 20134543Smarks int (*zexport_fs)(void *arg); 20144543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 20154543Smarks 20164543Smarks int zfs_share_inited; 20174543Smarks ddi_modhandle_t nfs_mod; 20184543Smarks ddi_modhandle_t sharefs_mod; 20194543Smarks kmutex_t zfs_share_lock; 20204543Smarks 20214543Smarks static int 20224543Smarks zfs_ioc_share(zfs_cmd_t *zc) 20234543Smarks { 20244543Smarks int error; 20254543Smarks int opcode; 20264543Smarks 20274543Smarks if (zfs_share_inited == 0) { 20284543Smarks mutex_enter(&zfs_share_lock); 20294543Smarks nfs_mod = ddi_modopen("fs/nfs", KRTLD_MODE_FIRST, &error); 20304543Smarks sharefs_mod = ddi_modopen("fs/sharefs", 20314543Smarks KRTLD_MODE_FIRST, &error); 20324543Smarks if (nfs_mod == NULL || sharefs_mod == NULL) { 20334543Smarks mutex_exit(&zfs_share_lock); 20344543Smarks return (ENOSYS); 20354543Smarks } 20364543Smarks if (zexport_fs == NULL && ((zexport_fs = (int (*)(void *)) 20374543Smarks ddi_modsym(nfs_mod, "nfs_export", &error)) == NULL)) { 20384543Smarks mutex_exit(&zfs_share_lock); 20394543Smarks return (ENOSYS); 20404543Smarks } 20414543Smarks 20424543Smarks if (zshare_fs == NULL && ((zshare_fs = 20434543Smarks (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 20444543Smarks ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 20454543Smarks mutex_exit(&zfs_share_lock); 20464543Smarks return (ENOSYS); 20474543Smarks } 20484543Smarks zfs_share_inited = 1; 20494543Smarks mutex_exit(&zfs_share_lock); 20504543Smarks } 20514543Smarks 20524543Smarks if (error = zexport_fs((void *)(uintptr_t)zc->zc_share.z_exportdata)) 20534543Smarks return (error); 20544543Smarks 20554543Smarks opcode = (zc->zc_share.z_sharetype == B_TRUE) ? 20564543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 20574543Smarks 20584543Smarks error = zshare_fs(opcode, 20594543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 20604543Smarks zc->zc_share.z_sharemax); 20614543Smarks 20624543Smarks return (error); 20634543Smarks 20644543Smarks } 20654543Smarks 20664543Smarks /* 20674988Sek110237 * pool create, destroy, and export don't log the history as part of 20684988Sek110237 * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export 20694988Sek110237 * do the logging of those commands. 20704543Smarks */ 2071789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 20724715Sek110237 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 20734577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 20744577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20754577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 20764577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 20774577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 20784577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 20794577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20804577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 20814577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20824577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 20834577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20844577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20854577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20864577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20874577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 20884577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 20894577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 20904543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 20914577Sahrens DATASET_NAME, B_FALSE }, 20924543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 20934577Sahrens DATASET_NAME, B_FALSE }, 20944577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 20954577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 20964577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 20974577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 20984577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 20994577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 21004577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 21014577Sahrens { zfs_ioc_recvbackup, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 21024577Sahrens { zfs_ioc_sendbackup, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 21034577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21044577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21054577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21064577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 21074577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21084577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 21094577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 21104577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 21114577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21124577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21134577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21144577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 21154577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 21164577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 21174543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 21184577Sahrens DATASET_NAME, B_FALSE }, 21194849Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }, 21204849Sahrens { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE }, 2121789Sahrens }; 2122789Sahrens 2123789Sahrens static int 2124789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2125789Sahrens { 2126789Sahrens zfs_cmd_t *zc; 2127789Sahrens uint_t vec; 21282199Sahrens int error, rc; 2129789Sahrens 2130789Sahrens if (getminor(dev) != 0) 2131789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2132789Sahrens 2133789Sahrens vec = cmd - ZFS_IOC; 21344787Sahrens ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); 2135789Sahrens 2136789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2137789Sahrens return (EINVAL); 2138789Sahrens 2139789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2140789Sahrens 2141789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2142789Sahrens 21434787Sahrens if (error == 0) 21444543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2145789Sahrens 2146789Sahrens /* 2147789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2148789Sahrens * the lower layers. 2149789Sahrens */ 2150789Sahrens if (error == 0) { 2151789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2152789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 21534577Sahrens case POOL_NAME: 2154789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2155789Sahrens error = EINVAL; 2156789Sahrens break; 2157789Sahrens 21584577Sahrens case DATASET_NAME: 2159789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2160789Sahrens error = EINVAL; 2161789Sahrens break; 21622856Snd150628 21634577Sahrens case NO_NAME: 21642856Snd150628 break; 2165789Sahrens } 2166789Sahrens } 2167789Sahrens 2168789Sahrens if (error == 0) 2169789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2170789Sahrens 21712199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 21724543Smarks if (error == 0) { 21732199Sahrens error = rc; 21744543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 21754543Smarks zfs_log_history(zc); 21764543Smarks } 2177789Sahrens 2178789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2179789Sahrens return (error); 2180789Sahrens } 2181789Sahrens 2182789Sahrens static int 2183789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2184789Sahrens { 2185789Sahrens if (cmd != DDI_ATTACH) 2186789Sahrens return (DDI_FAILURE); 2187789Sahrens 2188789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2189789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2190789Sahrens return (DDI_FAILURE); 2191789Sahrens 2192789Sahrens zfs_dip = dip; 2193789Sahrens 2194789Sahrens ddi_report_dev(dip); 2195789Sahrens 2196789Sahrens return (DDI_SUCCESS); 2197789Sahrens } 2198789Sahrens 2199789Sahrens static int 2200789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2201789Sahrens { 2202789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2203789Sahrens return (DDI_FAILURE); 2204789Sahrens 2205789Sahrens if (cmd != DDI_DETACH) 2206789Sahrens return (DDI_FAILURE); 2207789Sahrens 2208789Sahrens zfs_dip = NULL; 2209789Sahrens 2210789Sahrens ddi_prop_remove_all(dip); 2211789Sahrens ddi_remove_minor_node(dip, NULL); 2212789Sahrens 2213789Sahrens return (DDI_SUCCESS); 2214789Sahrens } 2215789Sahrens 2216789Sahrens /*ARGSUSED*/ 2217789Sahrens static int 2218789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2219789Sahrens { 2220789Sahrens switch (infocmd) { 2221789Sahrens case DDI_INFO_DEVT2DEVINFO: 2222789Sahrens *result = zfs_dip; 2223789Sahrens return (DDI_SUCCESS); 2224789Sahrens 2225789Sahrens case DDI_INFO_DEVT2INSTANCE: 2226849Sbonwick *result = (void *)0; 2227789Sahrens return (DDI_SUCCESS); 2228789Sahrens } 2229789Sahrens 2230789Sahrens return (DDI_FAILURE); 2231789Sahrens } 2232789Sahrens 2233789Sahrens /* 2234789Sahrens * OK, so this is a little weird. 2235789Sahrens * 2236789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2237789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2238789Sahrens * 2239789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2240789Sahrens * so most of the standard driver entry points are in zvol.c. 2241789Sahrens */ 2242789Sahrens static struct cb_ops zfs_cb_ops = { 2243789Sahrens zvol_open, /* open */ 2244789Sahrens zvol_close, /* close */ 2245789Sahrens zvol_strategy, /* strategy */ 2246789Sahrens nodev, /* print */ 2247789Sahrens nodev, /* dump */ 2248789Sahrens zvol_read, /* read */ 2249789Sahrens zvol_write, /* write */ 2250789Sahrens zfsdev_ioctl, /* ioctl */ 2251789Sahrens nodev, /* devmap */ 2252789Sahrens nodev, /* mmap */ 2253789Sahrens nodev, /* segmap */ 2254789Sahrens nochpoll, /* poll */ 2255789Sahrens ddi_prop_op, /* prop_op */ 2256789Sahrens NULL, /* streamtab */ 2257789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2258789Sahrens CB_REV, /* version */ 22593638Sbillm nodev, /* async read */ 22603638Sbillm nodev, /* async write */ 2261789Sahrens }; 2262789Sahrens 2263789Sahrens static struct dev_ops zfs_dev_ops = { 2264789Sahrens DEVO_REV, /* version */ 2265789Sahrens 0, /* refcnt */ 2266789Sahrens zfs_info, /* info */ 2267789Sahrens nulldev, /* identify */ 2268789Sahrens nulldev, /* probe */ 2269789Sahrens zfs_attach, /* attach */ 2270789Sahrens zfs_detach, /* detach */ 2271789Sahrens nodev, /* reset */ 2272789Sahrens &zfs_cb_ops, /* driver operations */ 2273789Sahrens NULL /* no bus operations */ 2274789Sahrens }; 2275789Sahrens 2276789Sahrens static struct modldrv zfs_modldrv = { 22774577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 22782676Seschrock &zfs_dev_ops 2279789Sahrens }; 2280789Sahrens 2281789Sahrens static struct modlinkage modlinkage = { 2282789Sahrens MODREV_1, 2283789Sahrens (void *)&zfs_modlfs, 2284789Sahrens (void *)&zfs_modldrv, 2285789Sahrens NULL 2286789Sahrens }; 2287789Sahrens 22884720Sfr157268 22894720Sfr157268 uint_t zfs_fsyncer_key; 22904720Sfr157268 2291789Sahrens int 2292789Sahrens _init(void) 2293789Sahrens { 2294789Sahrens int error; 2295789Sahrens 2296849Sbonwick spa_init(FREAD | FWRITE); 2297849Sbonwick zfs_init(); 2298849Sbonwick zvol_init(); 2299849Sbonwick 2300849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 2301849Sbonwick zvol_fini(); 2302849Sbonwick zfs_fini(); 2303849Sbonwick spa_fini(); 2304789Sahrens return (error); 2305849Sbonwick } 2306789Sahrens 23074720Sfr157268 tsd_create(&zfs_fsyncer_key, NULL); 23084720Sfr157268 2309789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 2310789Sahrens ASSERT(error == 0); 23114543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 2312789Sahrens 2313789Sahrens return (0); 2314789Sahrens } 2315789Sahrens 2316789Sahrens int 2317789Sahrens _fini(void) 2318789Sahrens { 2319789Sahrens int error; 2320789Sahrens 23211544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 2322789Sahrens return (EBUSY); 2323789Sahrens 2324789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 2325789Sahrens return (error); 2326789Sahrens 2327789Sahrens zvol_fini(); 2328789Sahrens zfs_fini(); 2329789Sahrens spa_fini(); 23304543Smarks if (zfs_share_inited) { 23314543Smarks (void) ddi_modclose(nfs_mod); 23324543Smarks (void) ddi_modclose(sharefs_mod); 23334543Smarks } 2334789Sahrens 23354720Sfr157268 tsd_destroy(&zfs_fsyncer_key); 2336789Sahrens ldi_ident_release(zfs_li); 2337789Sahrens zfs_li = NULL; 23384543Smarks mutex_destroy(&zfs_share_lock); 2339789Sahrens 2340789Sahrens return (error); 2341789Sahrens } 2342789Sahrens 2343789Sahrens int 2344789Sahrens _info(struct modinfo *modinfop) 2345789Sahrens { 2346789Sahrens return (mod_info(&modlinkage, modinfop)); 2347789Sahrens } 2348