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 2834670Sahrens return (zfs_secpolicy_write_perms(name, zfs_prop_perm(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 5971544Seschrock /* 598789Sahrens * Returns the nvlist as specified by the user in the zfs_cmd_t. 599789Sahrens */ 600789Sahrens static int 6012676Seschrock get_nvlist(zfs_cmd_t *zc, nvlist_t **nvp) 602789Sahrens { 603789Sahrens char *packed; 604789Sahrens size_t size; 605789Sahrens int error; 606789Sahrens nvlist_t *config = NULL; 607789Sahrens 608789Sahrens /* 6092676Seschrock * Read in and unpack the user-supplied nvlist. 610789Sahrens */ 6112676Seschrock if ((size = zc->zc_nvlist_src_size) == 0) 612789Sahrens return (EINVAL); 613789Sahrens 614789Sahrens packed = kmem_alloc(size, KM_SLEEP); 615789Sahrens 6162676Seschrock if ((error = xcopyin((void *)(uintptr_t)zc->zc_nvlist_src, packed, 617789Sahrens size)) != 0) { 618789Sahrens kmem_free(packed, size); 619789Sahrens return (error); 620789Sahrens } 621789Sahrens 622789Sahrens if ((error = nvlist_unpack(packed, size, &config, 0)) != 0) { 623789Sahrens kmem_free(packed, size); 624789Sahrens return (error); 625789Sahrens } 626789Sahrens 627789Sahrens kmem_free(packed, size); 628789Sahrens 629789Sahrens *nvp = config; 630789Sahrens return (0); 631789Sahrens } 632789Sahrens 633789Sahrens static int 6342676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 6352676Seschrock { 6362676Seschrock char *packed = NULL; 6372676Seschrock size_t size; 6382676Seschrock int error; 6392676Seschrock 6402676Seschrock VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 6412676Seschrock 6422676Seschrock if (size > zc->zc_nvlist_dst_size) { 6432676Seschrock error = ENOMEM; 6442676Seschrock } else { 6454611Smarks packed = kmem_alloc(size, KM_SLEEP); 6462676Seschrock VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 6472676Seschrock KM_SLEEP) == 0); 6482676Seschrock error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 6492676Seschrock size); 6502676Seschrock kmem_free(packed, size); 6512676Seschrock } 6522676Seschrock 6532676Seschrock zc->zc_nvlist_dst_size = size; 6542676Seschrock return (error); 6552676Seschrock } 6562676Seschrock 6572676Seschrock static int 658789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc) 659789Sahrens { 660789Sahrens int error; 661789Sahrens nvlist_t *config; 6624715Sek110237 char *buf; 663789Sahrens 6644715Sek110237 if ((buf = history_str_get(zc)) == NULL) 6654715Sek110237 return (EINVAL); 6664715Sek110237 6674715Sek110237 if ((error = get_nvlist(zc, &config)) != 0) { 6684715Sek110237 history_str_free(buf); 669789Sahrens return (error); 6704715Sek110237 } 671789Sahrens 6722676Seschrock error = spa_create(zc->zc_name, config, zc->zc_value[0] == '\0' ? 6734715Sek110237 NULL : zc->zc_value, buf); 674789Sahrens 675789Sahrens nvlist_free(config); 6764715Sek110237 history_str_free(buf); 677789Sahrens 678789Sahrens return (error); 679789Sahrens } 680789Sahrens 681789Sahrens static int 682789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc) 683789Sahrens { 6844543Smarks int error; 6854543Smarks zfs_log_history(zc); 6864543Smarks error = spa_destroy(zc->zc_name); 6874543Smarks return (error); 688789Sahrens } 689789Sahrens 690789Sahrens static int 691789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc) 692789Sahrens { 693789Sahrens int error; 694789Sahrens nvlist_t *config; 695789Sahrens uint64_t guid; 696789Sahrens 6972676Seschrock if ((error = get_nvlist(zc, &config)) != 0) 698789Sahrens return (error); 699789Sahrens 700789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 7011544Seschrock guid != zc->zc_guid) 702789Sahrens error = EINVAL; 703789Sahrens else 704789Sahrens error = spa_import(zc->zc_name, config, 7052676Seschrock zc->zc_value[0] == '\0' ? NULL : zc->zc_value); 706789Sahrens 707789Sahrens nvlist_free(config); 708789Sahrens 709789Sahrens return (error); 710789Sahrens } 711789Sahrens 712789Sahrens static int 713789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc) 714789Sahrens { 7154543Smarks int error; 7164543Smarks zfs_log_history(zc); 7174543Smarks error = spa_export(zc->zc_name, NULL); 7184543Smarks return (error); 719789Sahrens } 720789Sahrens 721789Sahrens static int 722789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc) 723789Sahrens { 724789Sahrens nvlist_t *configs; 725789Sahrens int error; 726789Sahrens 727789Sahrens if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 728789Sahrens return (EEXIST); 729789Sahrens 7302676Seschrock error = put_nvlist(zc, configs); 731789Sahrens 732789Sahrens nvlist_free(configs); 733789Sahrens 734789Sahrens return (error); 735789Sahrens } 736789Sahrens 737789Sahrens static int 738789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc) 739789Sahrens { 740789Sahrens nvlist_t *config; 741789Sahrens int error; 7421544Seschrock int ret = 0; 743789Sahrens 7442676Seschrock error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 7452676Seschrock sizeof (zc->zc_value)); 746789Sahrens 747789Sahrens if (config != NULL) { 7482676Seschrock ret = put_nvlist(zc, config); 749789Sahrens nvlist_free(config); 7501544Seschrock 7511544Seschrock /* 7521544Seschrock * The config may be present even if 'error' is non-zero. 7531544Seschrock * In this case we return success, and preserve the real errno 7541544Seschrock * in 'zc_cookie'. 7551544Seschrock */ 7561544Seschrock zc->zc_cookie = error; 757789Sahrens } else { 7581544Seschrock ret = error; 759789Sahrens } 760789Sahrens 7611544Seschrock return (ret); 762789Sahrens } 763789Sahrens 764789Sahrens /* 765789Sahrens * Try to import the given pool, returning pool stats as appropriate so that 766789Sahrens * user land knows which devices are available and overall pool health. 767789Sahrens */ 768789Sahrens static int 769789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 770789Sahrens { 771789Sahrens nvlist_t *tryconfig, *config; 772789Sahrens int error; 773789Sahrens 7742676Seschrock if ((error = get_nvlist(zc, &tryconfig)) != 0) 775789Sahrens return (error); 776789Sahrens 777789Sahrens config = spa_tryimport(tryconfig); 778789Sahrens 779789Sahrens nvlist_free(tryconfig); 780789Sahrens 781789Sahrens if (config == NULL) 782789Sahrens return (EINVAL); 783789Sahrens 7842676Seschrock error = put_nvlist(zc, config); 785789Sahrens nvlist_free(config); 786789Sahrens 787789Sahrens return (error); 788789Sahrens } 789789Sahrens 790789Sahrens static int 791789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc) 792789Sahrens { 793789Sahrens spa_t *spa; 794789Sahrens int error; 795789Sahrens 7962926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 7972926Sek110237 return (error); 7982926Sek110237 7994451Seschrock spa_config_enter(spa, RW_READER, FTAG); 8002926Sek110237 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); 8014451Seschrock spa_config_exit(spa, FTAG); 8022926Sek110237 8032926Sek110237 spa_close(spa, FTAG); 8042926Sek110237 805789Sahrens return (error); 806789Sahrens } 807789Sahrens 808789Sahrens static int 809789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 810789Sahrens { 811789Sahrens spa_t *spa; 812789Sahrens int error; 813789Sahrens 814789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 815789Sahrens if (error == 0) { 816789Sahrens spa_freeze(spa); 817789Sahrens spa_close(spa, FTAG); 818789Sahrens } 819789Sahrens return (error); 820789Sahrens } 821789Sahrens 822789Sahrens static int 8231760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 8241760Seschrock { 8251760Seschrock spa_t *spa; 8261760Seschrock int error; 8271760Seschrock 8282926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8292926Sek110237 return (error); 8302926Sek110237 8312926Sek110237 spa_upgrade(spa); 8322926Sek110237 spa_close(spa, FTAG); 8332926Sek110237 8342926Sek110237 return (error); 8352926Sek110237 } 8362926Sek110237 8372926Sek110237 static int 8382926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 8392926Sek110237 { 8402926Sek110237 spa_t *spa; 8412926Sek110237 char *hist_buf; 8422926Sek110237 uint64_t size; 8432926Sek110237 int error; 8442926Sek110237 8452926Sek110237 if ((size = zc->zc_history_len) == 0) 8462926Sek110237 return (EINVAL); 8472926Sek110237 8482926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8492926Sek110237 return (error); 8502926Sek110237 8514577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 8523863Sek110237 spa_close(spa, FTAG); 8533863Sek110237 return (ENOTSUP); 8543863Sek110237 } 8553863Sek110237 8562926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 8572926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 8582926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 8594543Smarks error = xcopyout(hist_buf, 8604543Smarks (char *)(uintptr_t)zc->zc_history, 8612926Sek110237 zc->zc_history_len); 8622926Sek110237 } 8632926Sek110237 8642926Sek110237 spa_close(spa, FTAG); 8652926Sek110237 kmem_free(hist_buf, size); 8662926Sek110237 return (error); 8672926Sek110237 } 8682926Sek110237 8692926Sek110237 static int 8703444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 8713444Sek110237 { 8723444Sek110237 int error; 8733444Sek110237 8743912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 8753444Sek110237 return (error); 8763444Sek110237 8773444Sek110237 return (0); 8783444Sek110237 } 8793444Sek110237 8803444Sek110237 static int 8813444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 8823444Sek110237 { 8833444Sek110237 objset_t *osp; 8843444Sek110237 int error; 8853444Sek110237 8863444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 8873444Sek110237 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) 8883444Sek110237 return (error); 8893444Sek110237 8903444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 8913444Sek110237 sizeof (zc->zc_value)); 8923444Sek110237 dmu_objset_close(osp); 8933444Sek110237 8943444Sek110237 return (error); 8953444Sek110237 } 8963444Sek110237 8973444Sek110237 static int 898789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 899789Sahrens { 900789Sahrens spa_t *spa; 901789Sahrens int error; 902789Sahrens nvlist_t *config; 903789Sahrens 904789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 905789Sahrens if (error != 0) 906789Sahrens return (error); 907789Sahrens 9083912Slling /* 9093912Slling * A root pool with concatenated devices is not supported. 9103912Slling * Thus, can not add a device to a root pool with one device. 9113912Slling */ 9123912Slling if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0) { 9133912Slling spa_close(spa, FTAG); 9143912Slling return (EDOM); 9153912Slling } 9163912Slling 9172676Seschrock if ((error = get_nvlist(zc, &config)) == 0) { 918789Sahrens error = spa_vdev_add(spa, config); 919789Sahrens nvlist_free(config); 920789Sahrens } 921789Sahrens spa_close(spa, FTAG); 922789Sahrens return (error); 923789Sahrens } 924789Sahrens 925789Sahrens static int 926789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 927789Sahrens { 9282082Seschrock spa_t *spa; 9292082Seschrock int error; 9302082Seschrock 9312082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 9322082Seschrock if (error != 0) 9332082Seschrock return (error); 9342082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 9352082Seschrock spa_close(spa, FTAG); 9362082Seschrock return (error); 937789Sahrens } 938789Sahrens 939789Sahrens static int 9404451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 941789Sahrens { 942789Sahrens spa_t *spa; 943789Sahrens int error; 9444451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 945789Sahrens 9462926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 947789Sahrens return (error); 9484451Seschrock switch (zc->zc_cookie) { 9494451Seschrock case VDEV_STATE_ONLINE: 9504451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 9514451Seschrock break; 9524451Seschrock 9534451Seschrock case VDEV_STATE_OFFLINE: 9544451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 9554451Seschrock break; 956789Sahrens 9574451Seschrock case VDEV_STATE_FAULTED: 9584451Seschrock error = vdev_fault(spa, zc->zc_guid); 9594451Seschrock break; 960789Sahrens 9614451Seschrock case VDEV_STATE_DEGRADED: 9624451Seschrock error = vdev_degrade(spa, zc->zc_guid); 9634451Seschrock break; 9644451Seschrock 9654451Seschrock default: 9664451Seschrock error = EINVAL; 9674451Seschrock } 9684451Seschrock zc->zc_cookie = newstate; 969789Sahrens spa_close(spa, FTAG); 970789Sahrens return (error); 971789Sahrens } 972789Sahrens 973789Sahrens static int 974789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 975789Sahrens { 976789Sahrens spa_t *spa; 977789Sahrens int replacing = zc->zc_cookie; 978789Sahrens nvlist_t *config; 979789Sahrens int error; 980789Sahrens 9812926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 982789Sahrens return (error); 983789Sahrens 9842676Seschrock if ((error = get_nvlist(zc, &config)) == 0) { 9851544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 986789Sahrens nvlist_free(config); 987789Sahrens } 988789Sahrens 989789Sahrens spa_close(spa, FTAG); 990789Sahrens return (error); 991789Sahrens } 992789Sahrens 993789Sahrens static int 994789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 995789Sahrens { 996789Sahrens spa_t *spa; 997789Sahrens int error; 998789Sahrens 9992926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1000789Sahrens return (error); 1001789Sahrens 10021544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1003789Sahrens 1004789Sahrens spa_close(spa, FTAG); 1005789Sahrens return (error); 1006789Sahrens } 1007789Sahrens 1008789Sahrens static int 10091354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 10101354Seschrock { 10111354Seschrock spa_t *spa; 10122676Seschrock char *path = zc->zc_value; 10131544Seschrock uint64_t guid = zc->zc_guid; 10141354Seschrock int error; 10151354Seschrock 10161354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10171354Seschrock if (error != 0) 10181354Seschrock return (error); 10191354Seschrock 10201354Seschrock error = spa_vdev_setpath(spa, guid, path); 10211354Seschrock spa_close(spa, FTAG); 10221354Seschrock return (error); 10231354Seschrock } 10241354Seschrock 10251354Seschrock static int 1026789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1027789Sahrens { 1028789Sahrens objset_t *os = NULL; 1029789Sahrens int error; 10301356Seschrock nvlist_t *nv; 1031789Sahrens 1032789Sahrens retry: 1033789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1034789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1035789Sahrens if (error != 0) { 1036789Sahrens /* 1037789Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1038789Sahrens * the objset is held exclusively. Fortunately this hold is 1039789Sahrens * only for a short while, so we retry here. 1040789Sahrens * This avoids user code having to handle EBUSY, 1041789Sahrens * for example for a "zfs list". 1042789Sahrens */ 1043789Sahrens if (error == EBUSY) { 1044789Sahrens delay(1); 1045789Sahrens goto retry; 1046789Sahrens } 1047789Sahrens return (error); 1048789Sahrens } 1049789Sahrens 10502885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1051789Sahrens 10522856Snd150628 if (zc->zc_nvlist_dst != 0 && 10531356Seschrock (error = dsl_prop_get_all(os, &nv)) == 0) { 10542885Sahrens dmu_objset_stats(os, nv); 10553087Sahrens /* 10564577Sahrens * NB: {zpl,zvol}_get_stats() will read the objset contents, 10573087Sahrens * which we aren't supposed to do with a 10583087Sahrens * DS_MODE_STANDARD open, because it could be 10593087Sahrens * inconsistent. So this is a bit of a workaround... 10603087Sahrens */ 10614577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 10624577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 10634577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 10644577Sahrens else if (dmu_objset_type(os) == DMU_OST_ZFS) 10654577Sahrens (void) zfs_get_stats(os, nv); 10664577Sahrens } 10672676Seschrock error = put_nvlist(zc, nv); 10681356Seschrock nvlist_free(nv); 10691356Seschrock } 1070789Sahrens 10712676Seschrock spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value)); 10721544Seschrock 1073789Sahrens dmu_objset_close(os); 1074789Sahrens return (error); 1075789Sahrens } 1076789Sahrens 1077789Sahrens static int 1078789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1079789Sahrens { 1080885Sahrens objset_t *os; 1081789Sahrens int error; 1082789Sahrens char *p; 1083789Sahrens 1084885Sahrens retry: 1085885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1086885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1087885Sahrens if (error != 0) { 1088885Sahrens /* 1089885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1090885Sahrens * the objset is held exclusively. Fortunately this hold is 1091885Sahrens * only for a short while, so we retry here. 1092885Sahrens * This avoids user code having to handle EBUSY, 1093885Sahrens * for example for a "zfs list". 1094885Sahrens */ 1095885Sahrens if (error == EBUSY) { 1096885Sahrens delay(1); 1097885Sahrens goto retry; 1098885Sahrens } 1099885Sahrens if (error == ENOENT) 1100885Sahrens error = ESRCH; 1101885Sahrens return (error); 1102789Sahrens } 1103789Sahrens 1104789Sahrens p = strrchr(zc->zc_name, '/'); 1105789Sahrens if (p == NULL || p[1] != '\0') 1106789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1107789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1108789Sahrens 1109789Sahrens do { 1110885Sahrens error = dmu_dir_list_next(os, 1111885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1112885Sahrens NULL, &zc->zc_cookie); 1113789Sahrens if (error == ENOENT) 1114789Sahrens error = ESRCH; 1115885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1116789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 1117789Sahrens 1118885Sahrens /* 1119885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1120885Sahrens * try to get stats for it. Userland will skip over it. 1121885Sahrens */ 1122885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1123885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1124789Sahrens 1125885Sahrens dmu_objset_close(os); 1126789Sahrens return (error); 1127789Sahrens } 1128789Sahrens 1129789Sahrens static int 1130789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1131789Sahrens { 1132885Sahrens objset_t *os; 1133789Sahrens int error; 1134789Sahrens 1135789Sahrens retry: 1136885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1137885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1138885Sahrens if (error != 0) { 1139789Sahrens /* 1140885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1141789Sahrens * the objset is held exclusively. Fortunately this hold is 1142789Sahrens * only for a short while, so we retry here. 1143789Sahrens * This avoids user code having to handle EBUSY, 1144885Sahrens * for example for a "zfs list". 1145789Sahrens */ 1146789Sahrens if (error == EBUSY) { 1147789Sahrens delay(1); 1148789Sahrens goto retry; 1149789Sahrens } 1150789Sahrens if (error == ENOENT) 1151885Sahrens error = ESRCH; 1152789Sahrens return (error); 1153789Sahrens } 1154789Sahrens 11551003Slling /* 11561003Slling * A dataset name of maximum length cannot have any snapshots, 11571003Slling * so exit immediately. 11581003Slling */ 11591003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1160885Sahrens dmu_objset_close(os); 11611003Slling return (ESRCH); 1162789Sahrens } 1163789Sahrens 1164885Sahrens error = dmu_snapshot_list_next(os, 1165885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 1166885Sahrens zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie); 1167789Sahrens if (error == ENOENT) 1168789Sahrens error = ESRCH; 1169789Sahrens 1170885Sahrens if (error == 0) 1171885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1172789Sahrens 1173885Sahrens dmu_objset_close(os); 1174789Sahrens return (error); 1175789Sahrens } 1176789Sahrens 1177789Sahrens static int 11782676Seschrock zfs_set_prop_nvlist(const char *name, dev_t dev, cred_t *cr, nvlist_t *nvl) 1179789Sahrens { 11802676Seschrock nvpair_t *elem; 11812676Seschrock int error; 11822676Seschrock uint64_t intval; 11832676Seschrock char *strval; 11842676Seschrock 11854543Smarks /* 11864543Smarks * First validate permission to set all of the properties 11874543Smarks */ 11882676Seschrock elem = NULL; 11892676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 11904670Sahrens const char *propname = nvpair_name(elem); 11914670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 11922676Seschrock 11934670Sahrens if (prop == ZFS_PROP_INVAL) { 11942676Seschrock /* 11952676Seschrock * If this is a user-defined property, it must be a 11962676Seschrock * string, and there is no further validation to do. 11972676Seschrock */ 11982676Seschrock if (!zfs_prop_user(propname) || 11992676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 12002676Seschrock return (EINVAL); 12012676Seschrock 12024543Smarks error = zfs_secpolicy_write_perms(name, 12034543Smarks ZFS_DELEG_PERM_USERPROP, cr); 12044670Sahrens if (error) 12054670Sahrens return (error); 12064543Smarks continue; 12072676Seschrock } 12082676Seschrock 12094670Sahrens if ((error = zfs_secpolicy_setprop(name, prop, cr)) != 0) 12104670Sahrens return (error); 12112676Seschrock 12124670Sahrens /* 12134670Sahrens * Check that this value is valid for this pool version 12144670Sahrens */ 12154670Sahrens switch (prop) { 12163886Sahl case ZFS_PROP_COMPRESSION: 12173886Sahl /* 12183886Sahl * If the user specified gzip compression, make sure 12193886Sahl * the SPA supports it. We ignore any errors here since 12203886Sahl * we'll catch them later. 12213886Sahl */ 12223886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 12233886Sahl nvpair_value_uint64(elem, &intval) == 0 && 12243886Sahl intval >= ZIO_COMPRESS_GZIP_1 && 12253886Sahl intval <= ZIO_COMPRESS_GZIP_9) { 12264543Smarks spa_t *spa; 12274543Smarks 12284603Sahrens if (spa_open(name, &spa, FTAG) == 0) { 12293886Sahl if (spa_version(spa) < 12304577Sahrens SPA_VERSION_GZIP_COMPRESSION) { 12313886Sahl spa_close(spa, FTAG); 12323886Sahl return (ENOTSUP); 12333886Sahl } 12343886Sahl 12353886Sahl spa_close(spa, FTAG); 12363886Sahl } 12373886Sahl } 12383886Sahl break; 12394603Sahrens 12404603Sahrens case ZFS_PROP_COPIES: 12414603Sahrens { 12424603Sahrens spa_t *spa; 12434603Sahrens 12444603Sahrens if (spa_open(name, &spa, FTAG) == 0) { 12454603Sahrens if (spa_version(spa) < 12464603Sahrens SPA_VERSION_DITTO_BLOCKS) { 12474603Sahrens spa_close(spa, FTAG); 12484603Sahrens return (ENOTSUP); 12494603Sahrens } 12504603Sahrens spa_close(spa, FTAG); 12514603Sahrens } 12524603Sahrens break; 12534603Sahrens } 12542676Seschrock } 12554543Smarks } 12564543Smarks 12574543Smarks elem = NULL; 12584543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 12594670Sahrens const char *propname = nvpair_name(elem); 12604670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 12614543Smarks 12624670Sahrens if (prop == ZFS_PROP_INVAL) { 12634543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 12644543Smarks error = dsl_prop_set(name, propname, 1, 12654543Smarks strlen(strval) + 1, strval); 12664543Smarks if (error == 0) 12674543Smarks continue; 12684543Smarks else 12694543Smarks return (error); 12704543Smarks } 12712676Seschrock 12722676Seschrock switch (prop) { 12732676Seschrock case ZFS_PROP_QUOTA: 12742676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 12754577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 12762676Seschrock return (error); 12772676Seschrock break; 12782676Seschrock 12792676Seschrock case ZFS_PROP_RESERVATION: 12802676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 12812676Seschrock (error = dsl_dir_set_reservation(name, 12822676Seschrock intval)) != 0) 12832676Seschrock return (error); 12842676Seschrock break; 1285789Sahrens 12862676Seschrock case ZFS_PROP_VOLSIZE: 12872676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 12884577Sahrens (error = zvol_set_volsize(name, dev, intval)) != 0) 12892676Seschrock return (error); 12902676Seschrock break; 12912676Seschrock 12922676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 12932676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 12944577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 12954577Sahrens return (error); 12964577Sahrens break; 12974577Sahrens 12984577Sahrens case ZFS_PROP_VERSION: 12994577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13004577Sahrens (error = zfs_set_version(name, intval)) != 0) 13012676Seschrock return (error); 13022676Seschrock break; 13032676Seschrock 13042676Seschrock default: 13052676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 13062676Seschrock if (zfs_prop_get_type(prop) != 13072676Seschrock prop_type_string) 13082676Seschrock return (EINVAL); 13092717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 13102717Seschrock if ((error = dsl_prop_set(name, 13112676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 13122717Seschrock strval)) != 0) 13132717Seschrock return (error); 13142676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 13152885Sahrens const char *unused; 13162885Sahrens 13172717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 13182676Seschrock 13192676Seschrock switch (zfs_prop_get_type(prop)) { 13202676Seschrock case prop_type_number: 13212676Seschrock break; 13222676Seschrock case prop_type_boolean: 13232676Seschrock if (intval > 1) 13242717Seschrock return (EINVAL); 13252676Seschrock break; 13262676Seschrock case prop_type_string: 13272717Seschrock return (EINVAL); 13282676Seschrock case prop_type_index: 13292717Seschrock if (zfs_prop_index_to_string(prop, 13302717Seschrock intval, &unused) != 0) 13312717Seschrock return (EINVAL); 13322676Seschrock break; 13332676Seschrock default: 13344577Sahrens cmn_err(CE_PANIC, 13354577Sahrens "unknown property type"); 13362676Seschrock break; 13372676Seschrock } 13382676Seschrock 13392717Seschrock if ((error = dsl_prop_set(name, propname, 13402717Seschrock 8, 1, &intval)) != 0) 13412717Seschrock return (error); 13422676Seschrock } else { 13432676Seschrock return (EINVAL); 13442676Seschrock } 13452676Seschrock break; 13462676Seschrock } 13472676Seschrock } 13482676Seschrock 13492676Seschrock return (0); 1350789Sahrens } 1351789Sahrens 1352789Sahrens static int 13532676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1354789Sahrens { 13552676Seschrock nvlist_t *nvl; 13562676Seschrock int error; 1357789Sahrens 13582676Seschrock /* 13592676Seschrock * If zc_value is set, then this is an attempt to inherit a value. 13602676Seschrock * Otherwise, zc_nvlist refers to a list of properties to set. 13612676Seschrock */ 13622676Seschrock if (zc->zc_value[0] != '\0') { 13634670Sahrens zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); 13644670Sahrens 13654670Sahrens if (prop == ZFS_PROP_INVAL) { 13664670Sahrens if (!zfs_prop_user(zc->zc_value)) 13674670Sahrens return (EINVAL); 13684670Sahrens error = zfs_secpolicy_write_perms(zc->zc_name, 13694670Sahrens ZFS_DELEG_PERM_USERPROP, 13704670Sahrens (cred_t *)(uintptr_t)zc->zc_cred); 13714670Sahrens } else { 13724670Sahrens if (!zfs_prop_inheritable(prop)) 13734670Sahrens return (EINVAL); 13744670Sahrens error = zfs_secpolicy_setprop(zc->zc_name, 13754670Sahrens prop, (cred_t *)(uintptr_t)zc->zc_cred); 13764670Sahrens } 13774670Sahrens if (error) 13784670Sahrens return (error); 13792676Seschrock 13802676Seschrock return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 13812676Seschrock } 13822676Seschrock 13832676Seschrock if ((error = get_nvlist(zc, &nvl)) != 0) 13842676Seschrock return (error); 13852676Seschrock 13862676Seschrock error = zfs_set_prop_nvlist(zc->zc_name, zc->zc_dev, 13872676Seschrock (cred_t *)(uintptr_t)zc->zc_cred, nvl); 13884543Smarks 13892676Seschrock nvlist_free(nvl); 13902676Seschrock return (error); 1391789Sahrens } 1392789Sahrens 1393789Sahrens static int 13944098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 13953912Slling { 13963912Slling nvlist_t *nvl; 13973912Slling int error, reset_bootfs = 0; 13983912Slling uint64_t objnum; 13994543Smarks uint64_t intval; 14003912Slling zpool_prop_t prop; 14013912Slling nvpair_t *elem; 14023912Slling char *propname, *strval; 14033912Slling spa_t *spa; 14043912Slling vdev_t *rvdev; 14053912Slling char *vdev_type; 14063912Slling objset_t *os; 14073912Slling 14083912Slling if ((error = get_nvlist(zc, &nvl)) != 0) 14093912Slling return (error); 14103912Slling 14113912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 14123912Slling nvlist_free(nvl); 14133912Slling return (error); 14143912Slling } 14153912Slling 14164577Sahrens if (spa_version(spa) < SPA_VERSION_BOOTFS) { 14173912Slling nvlist_free(nvl); 14183912Slling spa_close(spa, FTAG); 14193912Slling return (ENOTSUP); 14203912Slling } 14213912Slling 14223912Slling elem = NULL; 14233912Slling while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 14243912Slling 14253912Slling propname = nvpair_name(elem); 14263912Slling 14273912Slling if ((prop = zpool_name_to_prop(propname)) == 14283912Slling ZFS_PROP_INVAL) { 14293912Slling nvlist_free(nvl); 14303912Slling spa_close(spa, FTAG); 14313912Slling return (EINVAL); 14323912Slling } 14333912Slling 14343912Slling switch (prop) { 14354543Smarks case ZPOOL_PROP_DELEGATION: 14364543Smarks VERIFY(nvpair_value_uint64(elem, &intval) == 0); 14374543Smarks if (intval > 1) 14384543Smarks error = EINVAL; 14394543Smarks break; 14404451Seschrock case ZPOOL_PROP_BOOTFS: 14413912Slling /* 14423912Slling * A bootable filesystem can not be on a RAIDZ pool 14433912Slling * nor a striped pool with more than 1 device. 14443912Slling */ 14453912Slling rvdev = spa->spa_root_vdev; 14463912Slling vdev_type = 14473912Slling rvdev->vdev_child[0]->vdev_ops->vdev_op_type; 14483912Slling if (strcmp(vdev_type, VDEV_TYPE_RAIDZ) == 0 || 14493912Slling (strcmp(vdev_type, VDEV_TYPE_MIRROR) != 0 && 14503912Slling rvdev->vdev_children > 1)) { 14513912Slling error = ENOTSUP; 14523912Slling break; 14533912Slling } 14543912Slling 14553912Slling reset_bootfs = 1; 14563912Slling 14573912Slling VERIFY(nvpair_value_string(elem, &strval) == 0); 14583912Slling if (strval == NULL || strval[0] == '\0') { 14594451Seschrock objnum = zpool_prop_default_numeric( 14604451Seschrock ZPOOL_PROP_BOOTFS); 14613912Slling break; 14623912Slling } 14633912Slling 14643912Slling if (error = dmu_objset_open(strval, DMU_OST_ZFS, 14653912Slling DS_MODE_STANDARD | DS_MODE_READONLY, &os)) 14663912Slling break; 14673912Slling objnum = dmu_objset_id(os); 14683912Slling dmu_objset_close(os); 14693912Slling break; 14703912Slling } 14713912Slling 14723912Slling if (error) 14733912Slling break; 14743912Slling } 14753912Slling if (error == 0) { 14763912Slling if (reset_bootfs) { 14773912Slling VERIFY(nvlist_remove(nvl, 14784451Seschrock zpool_prop_to_name(ZPOOL_PROP_BOOTFS), 14793912Slling DATA_TYPE_STRING) == 0); 14803912Slling VERIFY(nvlist_add_uint64(nvl, 14814451Seschrock zpool_prop_to_name(ZPOOL_PROP_BOOTFS), 14824451Seschrock objnum) == 0); 14833912Slling } 14843912Slling error = spa_set_props(spa, nvl); 14853912Slling } 14863912Slling 14873912Slling nvlist_free(nvl); 14883912Slling spa_close(spa, FTAG); 14893912Slling 14903912Slling return (error); 14913912Slling } 14923912Slling 14933912Slling static int 14944098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 14953912Slling { 14963912Slling spa_t *spa; 14973912Slling int error; 14983912Slling nvlist_t *nvp = NULL; 14993912Slling 15003912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 15013912Slling return (error); 15023912Slling 15033912Slling error = spa_get_props(spa, &nvp); 15043912Slling 15053912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 15063912Slling error = put_nvlist(zc, nvp); 15073912Slling else 15083912Slling error = EFAULT; 15093912Slling 15103912Slling spa_close(spa, FTAG); 15113912Slling 15123912Slling if (nvp) 15133912Slling nvlist_free(nvp); 15143912Slling return (error); 15153912Slling } 15163912Slling 15173912Slling static int 15184543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 15194543Smarks { 15204543Smarks nvlist_t *nvp; 15214543Smarks int error; 15224543Smarks uint32_t uid; 15234543Smarks uint32_t gid; 15244543Smarks uint32_t *groups; 15254543Smarks uint_t group_cnt; 15264543Smarks cred_t *usercred; 15274543Smarks 15284543Smarks if ((error = get_nvlist(zc, &nvp)) != 0) { 15294543Smarks return (error); 15304543Smarks } 15314543Smarks 15324543Smarks if ((error = nvlist_lookup_uint32(nvp, 15334543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 15344543Smarks nvlist_free(nvp); 15354543Smarks return (EPERM); 15364543Smarks } 15374543Smarks 15384543Smarks if ((error = nvlist_lookup_uint32(nvp, 15394543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 15404543Smarks nvlist_free(nvp); 15414543Smarks return (EPERM); 15424543Smarks } 15434543Smarks 15444543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 15454543Smarks &groups, &group_cnt)) != 0) { 15464543Smarks nvlist_free(nvp); 15474543Smarks return (EPERM); 15484543Smarks } 15494543Smarks usercred = cralloc(); 15504543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 15514543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 15524543Smarks nvlist_free(nvp); 15534543Smarks crfree(usercred); 15544543Smarks return (EPERM); 15554543Smarks } 15564543Smarks nvlist_free(nvp); 15574543Smarks error = dsl_deleg_access(zc->zc_name, 15584543Smarks ZFS_DELEG_PERM_SHAREISCSI, usercred); 15594543Smarks crfree(usercred); 15604543Smarks return (error); 15614543Smarks } 15624543Smarks 15634543Smarks static int 15644543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 15654543Smarks { 15664543Smarks int error; 15674543Smarks nvlist_t *fsaclnv = NULL; 15684543Smarks cred_t *cr; 15694543Smarks 15704543Smarks if ((error = get_nvlist(zc, &fsaclnv)) != 0) 15714543Smarks return (error); 15724543Smarks 15734543Smarks /* 15744543Smarks * Verify nvlist is constructed correctly 15754543Smarks */ 15764543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 15774543Smarks nvlist_free(fsaclnv); 15784543Smarks return (EINVAL); 15794543Smarks } 15804543Smarks 15814543Smarks /* 15824543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 15834543Smarks * that user is allowed to hand out each permission in 15844543Smarks * the nvlist(s) 15854543Smarks */ 15864543Smarks 15874543Smarks cr = (cred_t *)(uintptr_t)zc->zc_cred; 15884543Smarks error = secpolicy_zfs(cr); 15894543Smarks if (error) { 15904543Smarks if (zc->zc_perm_action == B_FALSE) 15914543Smarks error = dsl_deleg_can_allow(zc->zc_name, fsaclnv, cr); 15924543Smarks else 15934543Smarks error = dsl_deleg_can_unallow(zc->zc_name, fsaclnv, cr); 15944543Smarks } 15954543Smarks 15964543Smarks if (error == 0) 15974543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 15984543Smarks 15994543Smarks nvlist_free(fsaclnv); 16004543Smarks return (error); 16014543Smarks } 16024543Smarks 16034543Smarks static int 16044543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 16054543Smarks { 16064543Smarks nvlist_t *nvp; 16074543Smarks int error; 16084543Smarks 16094543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 16104543Smarks error = put_nvlist(zc, nvp); 16114543Smarks nvlist_free(nvp); 16124543Smarks } 16134543Smarks 16144543Smarks return (error); 16154543Smarks } 16164543Smarks 16174543Smarks static int 1618789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1619789Sahrens { 16202676Seschrock return (zvol_create_minor(zc->zc_name, zc->zc_dev)); 1621789Sahrens } 1622789Sahrens 1623789Sahrens static int 1624789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1625789Sahrens { 16262676Seschrock return (zvol_remove_minor(zc->zc_name)); 1627789Sahrens } 1628789Sahrens 1629789Sahrens /* 1630789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1631789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1632789Sahrens * is responsible for releasing the returned vfs pointer. 1633789Sahrens */ 1634789Sahrens static vfs_t * 1635789Sahrens zfs_get_vfs(const char *resource) 1636789Sahrens { 1637789Sahrens struct vfs *vfsp; 1638789Sahrens struct vfs *vfs_found = NULL; 1639789Sahrens 1640789Sahrens vfs_list_read_lock(); 1641789Sahrens vfsp = rootvfs; 1642789Sahrens do { 1643789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1644789Sahrens VFS_HOLD(vfsp); 1645789Sahrens vfs_found = vfsp; 1646789Sahrens break; 1647789Sahrens } 1648789Sahrens vfsp = vfsp->vfs_next; 1649789Sahrens } while (vfsp != rootvfs); 1650789Sahrens vfs_list_unlock(); 1651789Sahrens return (vfs_found); 1652789Sahrens } 1653789Sahrens 16544543Smarks /* ARGSUSED */ 1655789Sahrens static void 16564543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1657789Sahrens { 16584577Sahrens nvlist_t *nvprops = arg; 16594577Sahrens uint64_t version = ZPL_VERSION; 16604577Sahrens 16614577Sahrens (void) nvlist_lookup_uint64(nvprops, 16624577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version); 16634577Sahrens 16644577Sahrens zfs_create_fs(os, cr, version, tx); 1665789Sahrens } 1666789Sahrens 1667789Sahrens static int 1668789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1669789Sahrens { 1670789Sahrens objset_t *clone; 1671789Sahrens int error = 0; 16724543Smarks nvlist_t *nvprops = NULL; 16734543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1674789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1675789Sahrens 1676789Sahrens switch (type) { 1677789Sahrens 1678789Sahrens case DMU_OST_ZFS: 1679789Sahrens cbfunc = zfs_create_cb; 1680789Sahrens break; 1681789Sahrens 1682789Sahrens case DMU_OST_ZVOL: 1683789Sahrens cbfunc = zvol_create_cb; 1684789Sahrens break; 1685789Sahrens 1686789Sahrens default: 16872199Sahrens cbfunc = NULL; 16882199Sahrens } 16892199Sahrens if (strchr(zc->zc_name, '@')) 1690789Sahrens return (EINVAL); 1691789Sahrens 16922676Seschrock if (zc->zc_nvlist_src != NULL && 16934543Smarks (error = get_nvlist(zc, &nvprops)) != 0) 16942676Seschrock return (error); 16952676Seschrock 16962676Seschrock if (zc->zc_value[0] != '\0') { 1697789Sahrens /* 1698789Sahrens * We're creating a clone of an existing snapshot. 1699789Sahrens */ 17002676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 17012676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 17024543Smarks nvlist_free(nvprops); 1703789Sahrens return (EINVAL); 17042676Seschrock } 1705789Sahrens 17062676Seschrock error = dmu_objset_open(zc->zc_value, type, 1707789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 17082676Seschrock if (error) { 17094543Smarks nvlist_free(nvprops); 1710789Sahrens return (error); 17112676Seschrock } 1712789Sahrens error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); 1713789Sahrens dmu_objset_close(clone); 1714789Sahrens } else { 17152676Seschrock if (cbfunc == NULL) { 17164543Smarks nvlist_free(nvprops); 17172199Sahrens return (EINVAL); 17182676Seschrock } 17192676Seschrock 1720789Sahrens if (type == DMU_OST_ZVOL) { 17212676Seschrock uint64_t volsize, volblocksize; 17222676Seschrock 17234543Smarks if (nvprops == NULL || 17244543Smarks nvlist_lookup_uint64(nvprops, 17252676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 17262676Seschrock &volsize) != 0) { 17274543Smarks nvlist_free(nvprops); 17282676Seschrock return (EINVAL); 17292676Seschrock } 17302676Seschrock 17314543Smarks if ((error = nvlist_lookup_uint64(nvprops, 17322676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 17332676Seschrock &volblocksize)) != 0 && error != ENOENT) { 17344543Smarks nvlist_free(nvprops); 17352676Seschrock return (EINVAL); 17362676Seschrock } 17371133Seschrock 17382676Seschrock if (error != 0) 17392676Seschrock volblocksize = zfs_prop_default_numeric( 17402676Seschrock ZFS_PROP_VOLBLOCKSIZE); 17412676Seschrock 17422676Seschrock if ((error = zvol_check_volblocksize( 17432676Seschrock volblocksize)) != 0 || 17442676Seschrock (error = zvol_check_volsize(volsize, 17452676Seschrock volblocksize)) != 0) { 17464543Smarks nvlist_free(nvprops); 1747789Sahrens return (error); 17482676Seschrock } 17494577Sahrens } else if (type == DMU_OST_ZFS) { 17504577Sahrens uint64_t version; 17514577Sahrens 17524577Sahrens if (0 == nvlist_lookup_uint64(nvprops, 17534577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version) && 17544577Sahrens (version < ZPL_VERSION_INITIAL || 17554577Sahrens version > ZPL_VERSION)) { 17564577Sahrens nvlist_free(nvprops); 17574577Sahrens return (EINVAL); 17584577Sahrens } 17592676Seschrock } 17601133Seschrock 17612676Seschrock error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, 17624543Smarks nvprops); 1763789Sahrens } 17642676Seschrock 17652676Seschrock /* 17662676Seschrock * It would be nice to do this atomically. 17672676Seschrock */ 17682676Seschrock if (error == 0) { 17692676Seschrock if ((error = zfs_set_prop_nvlist(zc->zc_name, 17702676Seschrock zc->zc_dev, (cred_t *)(uintptr_t)zc->zc_cred, 17714543Smarks nvprops)) != 0) 17722676Seschrock (void) dmu_objset_destroy(zc->zc_name); 17732676Seschrock } 17742676Seschrock 17754543Smarks nvlist_free(nvprops); 1776789Sahrens return (error); 1777789Sahrens } 1778789Sahrens 1779789Sahrens static int 17802199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 17812199Sahrens { 17822676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 17832199Sahrens return (EINVAL); 17842199Sahrens return (dmu_objset_snapshot(zc->zc_name, 17852676Seschrock zc->zc_value, zc->zc_cookie)); 17862199Sahrens } 17872199Sahrens 17884007Smmusante int 17892199Sahrens zfs_unmount_snap(char *name, void *arg) 1790789Sahrens { 17912199Sahrens char *snapname = arg; 17922199Sahrens char *cp; 17932417Sahrens vfs_t *vfsp = NULL; 17942199Sahrens 17952199Sahrens /* 17962199Sahrens * Snapshots (which are under .zfs control) must be unmounted 17972199Sahrens * before they can be destroyed. 17982199Sahrens */ 17992199Sahrens 18002199Sahrens if (snapname) { 18012199Sahrens (void) strcat(name, "@"); 18022199Sahrens (void) strcat(name, snapname); 18032199Sahrens vfsp = zfs_get_vfs(name); 18042199Sahrens cp = strchr(name, '@'); 18052199Sahrens *cp = '\0'; 18062417Sahrens } else if (strchr(name, '@')) { 18072199Sahrens vfsp = zfs_get_vfs(name); 18082199Sahrens } 18092199Sahrens 18102199Sahrens if (vfsp) { 18112199Sahrens /* 18122199Sahrens * Always force the unmount for snapshots. 18132199Sahrens */ 18142199Sahrens int flag = MS_FORCE; 1815789Sahrens int err; 1816789Sahrens 18172199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 18182199Sahrens VFS_RELE(vfsp); 18192199Sahrens return (err); 18202199Sahrens } 18212199Sahrens VFS_RELE(vfsp); 18222199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 18232199Sahrens return (err); 18242199Sahrens } 18252199Sahrens return (0); 18262199Sahrens } 18272199Sahrens 18282199Sahrens static int 18292199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 18302199Sahrens { 18312199Sahrens int err; 1832789Sahrens 18332676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 18342199Sahrens return (EINVAL); 18352199Sahrens err = dmu_objset_find(zc->zc_name, 18362676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 18372199Sahrens if (err) 18382199Sahrens return (err); 18392676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 18402199Sahrens } 18412199Sahrens 18422199Sahrens static int 18432199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 18442199Sahrens { 18452199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 18462199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18472199Sahrens if (err) 18482199Sahrens return (err); 1849789Sahrens } 1850789Sahrens 1851789Sahrens return (dmu_objset_destroy(zc->zc_name)); 1852789Sahrens } 1853789Sahrens 1854789Sahrens static int 1855789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 1856789Sahrens { 1857789Sahrens return (dmu_objset_rollback(zc->zc_name)); 1858789Sahrens } 1859789Sahrens 1860789Sahrens static int 1861789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 1862789Sahrens { 18634490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 18644007Smmusante 18652676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 18662676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) 1867789Sahrens return (EINVAL); 1868789Sahrens 18694007Smmusante /* 18704007Smmusante * Unmount snapshot unless we're doing a recursive rename, 18714007Smmusante * in which case the dataset code figures out which snapshots 18724007Smmusante * to unmount. 18734007Smmusante */ 18744007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 1875789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 18762199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18772199Sahrens if (err) 18782199Sahrens return (err); 1879789Sahrens } 1880789Sahrens 18814007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 1882789Sahrens } 1883789Sahrens 1884789Sahrens static int 1885789Sahrens zfs_ioc_recvbackup(zfs_cmd_t *zc) 1886789Sahrens { 1887789Sahrens file_t *fp; 1888789Sahrens int error, fd; 18892885Sahrens offset_t new_off; 1890789Sahrens 18913265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 18923265Sahrens strchr(zc->zc_value, '@') == NULL) 18933265Sahrens return (EINVAL); 18943265Sahrens 1895789Sahrens fd = zc->zc_cookie; 1896789Sahrens fp = getf(fd); 1897789Sahrens if (fp == NULL) 1898789Sahrens return (EBADF); 18992676Seschrock error = dmu_recvbackup(zc->zc_value, &zc->zc_begin_record, 19002676Seschrock &zc->zc_cookie, (boolean_t)zc->zc_guid, fp->f_vnode, 19012665Snd150628 fp->f_offset); 19022885Sahrens 19032885Sahrens new_off = fp->f_offset + zc->zc_cookie; 19042885Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &new_off) == 0) 19052885Sahrens fp->f_offset = new_off; 19062885Sahrens 1907789Sahrens releasef(fd); 1908789Sahrens return (error); 1909789Sahrens } 1910789Sahrens 1911789Sahrens static int 1912789Sahrens zfs_ioc_sendbackup(zfs_cmd_t *zc) 1913789Sahrens { 1914789Sahrens objset_t *fromsnap = NULL; 1915789Sahrens objset_t *tosnap; 1916789Sahrens file_t *fp; 1917789Sahrens int error; 1918789Sahrens 1919789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1920789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); 1921789Sahrens if (error) 1922789Sahrens return (error); 1923789Sahrens 19242676Seschrock if (zc->zc_value[0] != '\0') { 19252885Sahrens char buf[MAXPATHLEN]; 19262885Sahrens char *cp; 19272885Sahrens 19282885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 19292885Sahrens cp = strchr(buf, '@'); 19302885Sahrens if (cp) 19312885Sahrens *(cp+1) = 0; 19322885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 19332885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 1934789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); 1935789Sahrens if (error) { 1936789Sahrens dmu_objset_close(tosnap); 1937789Sahrens return (error); 1938789Sahrens } 1939789Sahrens } 1940789Sahrens 1941789Sahrens fp = getf(zc->zc_cookie); 1942789Sahrens if (fp == NULL) { 1943789Sahrens dmu_objset_close(tosnap); 1944789Sahrens if (fromsnap) 1945789Sahrens dmu_objset_close(fromsnap); 1946789Sahrens return (EBADF); 1947789Sahrens } 1948789Sahrens 1949789Sahrens error = dmu_sendbackup(tosnap, fromsnap, fp->f_vnode); 1950789Sahrens 1951789Sahrens releasef(zc->zc_cookie); 1952789Sahrens if (fromsnap) 1953789Sahrens dmu_objset_close(fromsnap); 1954789Sahrens dmu_objset_close(tosnap); 1955789Sahrens return (error); 1956789Sahrens } 1957789Sahrens 19581544Seschrock static int 19591544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 19601544Seschrock { 19611544Seschrock int id, error; 19621544Seschrock 19631544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 19641544Seschrock &zc->zc_inject_record); 19651544Seschrock 19661544Seschrock if (error == 0) 19671544Seschrock zc->zc_guid = (uint64_t)id; 19681544Seschrock 19691544Seschrock return (error); 19701544Seschrock } 19711544Seschrock 19721544Seschrock static int 19731544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 19741544Seschrock { 19751544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 19761544Seschrock } 19771544Seschrock 19781544Seschrock static int 19791544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 19801544Seschrock { 19811544Seschrock int id = (int)zc->zc_guid; 19821544Seschrock int error; 19831544Seschrock 19841544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 19851544Seschrock &zc->zc_inject_record); 19861544Seschrock 19871544Seschrock zc->zc_guid = id; 19881544Seschrock 19891544Seschrock return (error); 19901544Seschrock } 19911544Seschrock 19921544Seschrock static int 19931544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 19941544Seschrock { 19951544Seschrock spa_t *spa; 19961544Seschrock int error; 19972676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 19981544Seschrock 19991544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 20001544Seschrock return (error); 20011544Seschrock 20022676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 20031544Seschrock &count); 20041544Seschrock if (error == 0) 20052676Seschrock zc->zc_nvlist_dst_size = count; 20061544Seschrock else 20072676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 20081544Seschrock 20091544Seschrock spa_close(spa, FTAG); 20101544Seschrock 20111544Seschrock return (error); 20121544Seschrock } 20131544Seschrock 20141544Seschrock static int 20151544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 20161544Seschrock { 20171544Seschrock spa_t *spa; 20181544Seschrock vdev_t *vd; 20191544Seschrock int error; 20204451Seschrock uint64_t txg; 20211544Seschrock 20221544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 20231544Seschrock return (error); 20241544Seschrock 20254451Seschrock txg = spa_vdev_enter(spa); 20261544Seschrock 20272676Seschrock if (zc->zc_guid == 0) { 20281544Seschrock vd = NULL; 20292676Seschrock } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { 20304451Seschrock (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 20311544Seschrock spa_close(spa, FTAG); 20321544Seschrock return (ENODEV); 20331544Seschrock } 20341544Seschrock 20351544Seschrock vdev_clear(spa, vd); 20361544Seschrock 20374451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 20381544Seschrock 20391544Seschrock spa_close(spa, FTAG); 20401544Seschrock 20411544Seschrock return (0); 20421544Seschrock } 20431544Seschrock 20441544Seschrock static int 20452082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 20462082Seschrock { 20472417Sahrens char *cp; 20482417Sahrens 20492417Sahrens /* 20502417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 20512417Sahrens * it's easier. 20522417Sahrens */ 20532676Seschrock cp = strchr(zc->zc_value, '@'); 20542417Sahrens if (cp) 20552417Sahrens *cp = '\0'; 20562676Seschrock (void) dmu_objset_find(zc->zc_value, 20572417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 20582082Seschrock return (dsl_dataset_promote(zc->zc_name)); 20592082Seschrock } 20602082Seschrock 20614543Smarks /* 20624543Smarks * We don't want to have a hard dependency 20634543Smarks * against some special symbols in sharefs 20644543Smarks * and nfs. Determine them if needed when 20654543Smarks * the first file system is shared. 20664543Smarks * Neither sharefs or nfs are unloadable modules. 20674543Smarks */ 20684543Smarks int (*zexport_fs)(void *arg); 20694543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 20704543Smarks 20714543Smarks int zfs_share_inited; 20724543Smarks ddi_modhandle_t nfs_mod; 20734543Smarks ddi_modhandle_t sharefs_mod; 20744543Smarks kmutex_t zfs_share_lock; 20754543Smarks 20764543Smarks static int 20774543Smarks zfs_ioc_share(zfs_cmd_t *zc) 20784543Smarks { 20794543Smarks int error; 20804543Smarks int opcode; 20814543Smarks 20824543Smarks if (zfs_share_inited == 0) { 20834543Smarks mutex_enter(&zfs_share_lock); 20844543Smarks nfs_mod = ddi_modopen("fs/nfs", KRTLD_MODE_FIRST, &error); 20854543Smarks sharefs_mod = ddi_modopen("fs/sharefs", 20864543Smarks KRTLD_MODE_FIRST, &error); 20874543Smarks if (nfs_mod == NULL || sharefs_mod == NULL) { 20884543Smarks mutex_exit(&zfs_share_lock); 20894543Smarks return (ENOSYS); 20904543Smarks } 20914543Smarks if (zexport_fs == NULL && ((zexport_fs = (int (*)(void *)) 20924543Smarks ddi_modsym(nfs_mod, "nfs_export", &error)) == NULL)) { 20934543Smarks mutex_exit(&zfs_share_lock); 20944543Smarks return (ENOSYS); 20954543Smarks } 20964543Smarks 20974543Smarks if (zshare_fs == NULL && ((zshare_fs = 20984543Smarks (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 20994543Smarks ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 21004543Smarks mutex_exit(&zfs_share_lock); 21014543Smarks return (ENOSYS); 21024543Smarks } 21034543Smarks zfs_share_inited = 1; 21044543Smarks mutex_exit(&zfs_share_lock); 21054543Smarks } 21064543Smarks 21074543Smarks if (error = zexport_fs((void *)(uintptr_t)zc->zc_share.z_exportdata)) 21084543Smarks return (error); 21094543Smarks 21104543Smarks opcode = (zc->zc_share.z_sharetype == B_TRUE) ? 21114543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 21124543Smarks 21134543Smarks error = zshare_fs(opcode, 21144543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 21154543Smarks zc->zc_share.z_sharemax); 21164543Smarks 21174543Smarks return (error); 21184543Smarks 21194543Smarks } 21204543Smarks 21214543Smarks /* 21224543Smarks * pool destroy and pool export don't log the history as part of zfsdev_ioctl, 21234543Smarks * but rather zfs_ioc_pool_create, and zfs_ioc_pool_export do the loggin 21244543Smarks * of those commands. 21254543Smarks */ 2126789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 21274715Sek110237 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21284577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21294577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21304577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21314577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 21324577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 21334577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21344577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21354577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21364577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21374577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21384577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21394577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21404577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21414577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21424577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21434577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21444577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 21454543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 21464577Sahrens DATASET_NAME, B_FALSE }, 21474543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 21484577Sahrens DATASET_NAME, B_FALSE }, 21494577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 21504577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 21514577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 21524577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 21534577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 21544577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 21554577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 21564577Sahrens { zfs_ioc_recvbackup, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 21574577Sahrens { zfs_ioc_sendbackup, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 21584577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21594577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21604577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21614577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 21624577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21634577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 21644577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 21654577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 21664577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21674577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21684577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21694577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 21704577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 21714577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 21724543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 21734577Sahrens DATASET_NAME, B_FALSE }, 21744577Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE } 2175789Sahrens }; 2176789Sahrens 2177789Sahrens static int 2178789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2179789Sahrens { 2180789Sahrens zfs_cmd_t *zc; 2181789Sahrens uint_t vec; 21822199Sahrens int error, rc; 2183789Sahrens 2184789Sahrens if (getminor(dev) != 0) 2185789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2186789Sahrens 2187789Sahrens vec = cmd - ZFS_IOC; 2188789Sahrens 2189789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2190789Sahrens return (EINVAL); 2191789Sahrens 2192789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2193789Sahrens 2194789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2195789Sahrens 2196789Sahrens if (error == 0) { 2197789Sahrens zc->zc_cred = (uintptr_t)cr; 2198789Sahrens zc->zc_dev = dev; 21994543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2200789Sahrens } 2201789Sahrens 2202789Sahrens /* 2203789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2204789Sahrens * the lower layers. 2205789Sahrens */ 2206789Sahrens if (error == 0) { 2207789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2208789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 22094577Sahrens case POOL_NAME: 2210789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2211789Sahrens error = EINVAL; 2212789Sahrens break; 2213789Sahrens 22144577Sahrens case DATASET_NAME: 2215789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2216789Sahrens error = EINVAL; 2217789Sahrens break; 22182856Snd150628 22194577Sahrens case NO_NAME: 22202856Snd150628 break; 2221789Sahrens } 2222789Sahrens } 2223789Sahrens 2224789Sahrens if (error == 0) 2225789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2226789Sahrens 22272199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 22284543Smarks if (error == 0) { 22292199Sahrens error = rc; 22304543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 22314543Smarks zfs_log_history(zc); 22324543Smarks } 2233789Sahrens 2234789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2235789Sahrens return (error); 2236789Sahrens } 2237789Sahrens 2238789Sahrens static int 2239789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2240789Sahrens { 2241789Sahrens if (cmd != DDI_ATTACH) 2242789Sahrens return (DDI_FAILURE); 2243789Sahrens 2244789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2245789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2246789Sahrens return (DDI_FAILURE); 2247789Sahrens 2248789Sahrens zfs_dip = dip; 2249789Sahrens 2250789Sahrens ddi_report_dev(dip); 2251789Sahrens 2252789Sahrens return (DDI_SUCCESS); 2253789Sahrens } 2254789Sahrens 2255789Sahrens static int 2256789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2257789Sahrens { 2258789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2259789Sahrens return (DDI_FAILURE); 2260789Sahrens 2261789Sahrens if (cmd != DDI_DETACH) 2262789Sahrens return (DDI_FAILURE); 2263789Sahrens 2264789Sahrens zfs_dip = NULL; 2265789Sahrens 2266789Sahrens ddi_prop_remove_all(dip); 2267789Sahrens ddi_remove_minor_node(dip, NULL); 2268789Sahrens 2269789Sahrens return (DDI_SUCCESS); 2270789Sahrens } 2271789Sahrens 2272789Sahrens /*ARGSUSED*/ 2273789Sahrens static int 2274789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2275789Sahrens { 2276789Sahrens switch (infocmd) { 2277789Sahrens case DDI_INFO_DEVT2DEVINFO: 2278789Sahrens *result = zfs_dip; 2279789Sahrens return (DDI_SUCCESS); 2280789Sahrens 2281789Sahrens case DDI_INFO_DEVT2INSTANCE: 2282849Sbonwick *result = (void *)0; 2283789Sahrens return (DDI_SUCCESS); 2284789Sahrens } 2285789Sahrens 2286789Sahrens return (DDI_FAILURE); 2287789Sahrens } 2288789Sahrens 2289789Sahrens /* 2290789Sahrens * OK, so this is a little weird. 2291789Sahrens * 2292789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2293789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2294789Sahrens * 2295789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2296789Sahrens * so most of the standard driver entry points are in zvol.c. 2297789Sahrens */ 2298789Sahrens static struct cb_ops zfs_cb_ops = { 2299789Sahrens zvol_open, /* open */ 2300789Sahrens zvol_close, /* close */ 2301789Sahrens zvol_strategy, /* strategy */ 2302789Sahrens nodev, /* print */ 2303789Sahrens nodev, /* dump */ 2304789Sahrens zvol_read, /* read */ 2305789Sahrens zvol_write, /* write */ 2306789Sahrens zfsdev_ioctl, /* ioctl */ 2307789Sahrens nodev, /* devmap */ 2308789Sahrens nodev, /* mmap */ 2309789Sahrens nodev, /* segmap */ 2310789Sahrens nochpoll, /* poll */ 2311789Sahrens ddi_prop_op, /* prop_op */ 2312789Sahrens NULL, /* streamtab */ 2313789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2314789Sahrens CB_REV, /* version */ 23153638Sbillm nodev, /* async read */ 23163638Sbillm nodev, /* async write */ 2317789Sahrens }; 2318789Sahrens 2319789Sahrens static struct dev_ops zfs_dev_ops = { 2320789Sahrens DEVO_REV, /* version */ 2321789Sahrens 0, /* refcnt */ 2322789Sahrens zfs_info, /* info */ 2323789Sahrens nulldev, /* identify */ 2324789Sahrens nulldev, /* probe */ 2325789Sahrens zfs_attach, /* attach */ 2326789Sahrens zfs_detach, /* detach */ 2327789Sahrens nodev, /* reset */ 2328789Sahrens &zfs_cb_ops, /* driver operations */ 2329789Sahrens NULL /* no bus operations */ 2330789Sahrens }; 2331789Sahrens 2332789Sahrens static struct modldrv zfs_modldrv = { 23334577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 23342676Seschrock &zfs_dev_ops 2335789Sahrens }; 2336789Sahrens 2337789Sahrens static struct modlinkage modlinkage = { 2338789Sahrens MODREV_1, 2339789Sahrens (void *)&zfs_modlfs, 2340789Sahrens (void *)&zfs_modldrv, 2341789Sahrens NULL 2342789Sahrens }; 2343789Sahrens 2344*4720Sfr157268 2345*4720Sfr157268 uint_t zfs_fsyncer_key; 2346*4720Sfr157268 2347789Sahrens int 2348789Sahrens _init(void) 2349789Sahrens { 2350789Sahrens int error; 2351789Sahrens 2352849Sbonwick spa_init(FREAD | FWRITE); 2353849Sbonwick zfs_init(); 2354849Sbonwick zvol_init(); 2355849Sbonwick 2356849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 2357849Sbonwick zvol_fini(); 2358849Sbonwick zfs_fini(); 2359849Sbonwick spa_fini(); 2360789Sahrens return (error); 2361849Sbonwick } 2362789Sahrens 2363*4720Sfr157268 tsd_create(&zfs_fsyncer_key, NULL); 2364*4720Sfr157268 2365789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 2366789Sahrens ASSERT(error == 0); 23674543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 2368789Sahrens 2369789Sahrens return (0); 2370789Sahrens } 2371789Sahrens 2372789Sahrens int 2373789Sahrens _fini(void) 2374789Sahrens { 2375789Sahrens int error; 2376789Sahrens 23771544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 2378789Sahrens return (EBUSY); 2379789Sahrens 2380789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 2381789Sahrens return (error); 2382789Sahrens 2383789Sahrens zvol_fini(); 2384789Sahrens zfs_fini(); 2385789Sahrens spa_fini(); 23864543Smarks if (zfs_share_inited) { 23874543Smarks (void) ddi_modclose(nfs_mod); 23884543Smarks (void) ddi_modclose(sharefs_mod); 23894543Smarks } 2390789Sahrens 2391*4720Sfr157268 tsd_destroy(&zfs_fsyncer_key); 2392789Sahrens ldi_ident_release(zfs_li); 2393789Sahrens zfs_li = NULL; 23944543Smarks mutex_destroy(&zfs_share_lock); 2395789Sahrens 2396789Sahrens return (error); 2397789Sahrens } 2398789Sahrens 2399789Sahrens int 2400789Sahrens _info(struct modinfo *modinfop) 2401789Sahrens { 2402789Sahrens return (mod_info(&modlinkage, modinfop)); 2403789Sahrens } 2404