1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51485Slling * Common Development and Distribution License (the "License"). 61485Slling * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 223444Sek110237 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27789Sahrens 28789Sahrens #include <sys/types.h> 29789Sahrens #include <sys/param.h> 30789Sahrens #include <sys/errno.h> 31789Sahrens #include <sys/uio.h> 32789Sahrens #include <sys/buf.h> 33789Sahrens #include <sys/modctl.h> 34789Sahrens #include <sys/open.h> 35789Sahrens #include <sys/file.h> 36789Sahrens #include <sys/kmem.h> 37789Sahrens #include <sys/conf.h> 38789Sahrens #include <sys/cmn_err.h> 39789Sahrens #include <sys/stat.h> 40789Sahrens #include <sys/zfs_ioctl.h> 41789Sahrens #include <sys/zap.h> 42789Sahrens #include <sys/spa.h> 433912Slling #include <sys/spa_impl.h> 44789Sahrens #include <sys/vdev.h> 453912Slling #include <sys/vdev_impl.h> 46789Sahrens #include <sys/dmu.h> 47789Sahrens #include <sys/dsl_dir.h> 48789Sahrens #include <sys/dsl_dataset.h> 49789Sahrens #include <sys/dsl_prop.h> 504543Smarks #include <sys/dsl_deleg.h> 514543Smarks #include <sys/dmu_objset.h> 52789Sahrens #include <sys/ddi.h> 53789Sahrens #include <sys/sunddi.h> 54789Sahrens #include <sys/sunldi.h> 55789Sahrens #include <sys/policy.h> 56789Sahrens #include <sys/zone.h> 57789Sahrens #include <sys/nvpair.h> 58789Sahrens #include <sys/pathname.h> 59789Sahrens #include <sys/mount.h> 60789Sahrens #include <sys/sdt.h> 61789Sahrens #include <sys/fs/zfs.h> 62789Sahrens #include <sys/zfs_ctldir.h> 632885Sahrens #include <sys/zvol.h> 644543Smarks #include <sharefs/share.h> 654577Sahrens #include <sys/zfs_znode.h> 66789Sahrens 67789Sahrens #include "zfs_namecheck.h" 682676Seschrock #include "zfs_prop.h" 694543Smarks #include "zfs_deleg.h" 70789Sahrens 71789Sahrens extern struct modlfs zfs_modlfs; 72789Sahrens 73789Sahrens extern void zfs_init(void); 74789Sahrens extern void zfs_fini(void); 75789Sahrens 76789Sahrens ldi_ident_t zfs_li = NULL; 77789Sahrens dev_info_t *zfs_dip; 78789Sahrens 79789Sahrens typedef int zfs_ioc_func_t(zfs_cmd_t *); 804543Smarks typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *); 81789Sahrens 82789Sahrens typedef struct zfs_ioc_vec { 83789Sahrens zfs_ioc_func_t *zvec_func; 84789Sahrens zfs_secpolicy_func_t *zvec_secpolicy; 85789Sahrens enum { 864577Sahrens NO_NAME, 874577Sahrens POOL_NAME, 884577Sahrens DATASET_NAME 894543Smarks } zvec_namecheck; 904543Smarks boolean_t zvec_his_log; 91789Sahrens } zfs_ioc_vec_t; 92789Sahrens 93789Sahrens /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */ 94789Sahrens void 95789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 96789Sahrens { 97789Sahrens const char *newfile; 98789Sahrens char buf[256]; 99789Sahrens va_list adx; 100789Sahrens 101789Sahrens /* 102789Sahrens * Get rid of annoying "../common/" prefix to filename. 103789Sahrens */ 104789Sahrens newfile = strrchr(file, '/'); 105789Sahrens if (newfile != NULL) { 106789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 107789Sahrens } else { 108789Sahrens newfile = file; 109789Sahrens } 110789Sahrens 111789Sahrens va_start(adx, fmt); 112789Sahrens (void) vsnprintf(buf, sizeof (buf), fmt, adx); 113789Sahrens va_end(adx); 114789Sahrens 115789Sahrens /* 116789Sahrens * To get this data, use the zfs-dprintf probe as so: 117789Sahrens * dtrace -q -n 'zfs-dprintf \ 118789Sahrens * /stringof(arg0) == "dbuf.c"/ \ 119789Sahrens * {printf("%s: %s", stringof(arg1), stringof(arg3))}' 120789Sahrens * arg0 = file name 121789Sahrens * arg1 = function name 122789Sahrens * arg2 = line number 123789Sahrens * arg3 = message 124789Sahrens */ 125789Sahrens DTRACE_PROBE4(zfs__dprintf, 126789Sahrens char *, newfile, char *, func, int, line, char *, buf); 127789Sahrens } 128789Sahrens 1294543Smarks static void 1304543Smarks zfs_log_history(zfs_cmd_t *zc) 1314543Smarks { 1324543Smarks spa_t *spa; 133*4603Sahrens char *buf; 1344543Smarks 1354543Smarks if (zc->zc_history == NULL) 1364543Smarks return; 1374543Smarks 1384577Sahrens if (zc->zc_history_offset != LOG_CMD_POOL_CREATE && 1394577Sahrens zc->zc_history_offset != LOG_CMD_NORMAL) 1404577Sahrens return; 1414577Sahrens 1424543Smarks buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP); 1434543Smarks if (copyinstr((void *)(uintptr_t)zc->zc_history, 1444543Smarks buf, HIS_MAX_RECORD_LEN, NULL) != 0) { 1454543Smarks kmem_free(buf, HIS_MAX_RECORD_LEN); 1464543Smarks return; 1474543Smarks } 1484543Smarks 1494543Smarks buf[HIS_MAX_RECORD_LEN -1] = '\0'; 1504543Smarks 151*4603Sahrens if (spa_open(zc->zc_name, &spa, FTAG) != 0) { 1524543Smarks kmem_free(buf, HIS_MAX_RECORD_LEN); 1534543Smarks return; 1544543Smarks } 1554543Smarks 1564577Sahrens if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY) 1574543Smarks (void) spa_history_log(spa, buf, zc->zc_history_offset); 1584543Smarks 1594543Smarks spa_close(spa, FTAG); 1604543Smarks kmem_free(buf, HIS_MAX_RECORD_LEN); 1614543Smarks } 1624543Smarks 163789Sahrens /* 164789Sahrens * Policy for top-level read operations (list pools). Requires no privileges, 165789Sahrens * and can be used in the local zone, as there is no associated dataset. 166789Sahrens */ 167789Sahrens /* ARGSUSED */ 168789Sahrens static int 1694543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) 170789Sahrens { 171789Sahrens return (0); 172789Sahrens } 173789Sahrens 174789Sahrens /* 175789Sahrens * Policy for dataset read operations (list children, get statistics). Requires 176789Sahrens * no privileges, but must be visible in the local zone. 177789Sahrens */ 178789Sahrens /* ARGSUSED */ 179789Sahrens static int 1804543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) 181789Sahrens { 182789Sahrens if (INGLOBALZONE(curproc) || 1834543Smarks zone_dataset_visible(zc->zc_name, NULL)) 184789Sahrens return (0); 185789Sahrens 186789Sahrens return (ENOENT); 187789Sahrens } 188789Sahrens 189789Sahrens static int 190789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr) 191789Sahrens { 192789Sahrens uint64_t zoned; 193789Sahrens int writable = 1; 194789Sahrens 195789Sahrens /* 196789Sahrens * The dataset must be visible by this zone -- check this first 197789Sahrens * so they don't see EPERM on something they shouldn't know about. 198789Sahrens */ 199789Sahrens if (!INGLOBALZONE(curproc) && 200789Sahrens !zone_dataset_visible(dataset, &writable)) 201789Sahrens return (ENOENT); 202789Sahrens 203789Sahrens if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) 204789Sahrens return (ENOENT); 205789Sahrens 206789Sahrens if (INGLOBALZONE(curproc)) { 207789Sahrens /* 208789Sahrens * If the fs is zoned, only root can access it from the 209789Sahrens * global zone. 210789Sahrens */ 211789Sahrens if (secpolicy_zfs(cr) && zoned) 212789Sahrens return (EPERM); 213789Sahrens } else { 214789Sahrens /* 215789Sahrens * If we are in a local zone, the 'zoned' property must be set. 216789Sahrens */ 217789Sahrens if (!zoned) 218789Sahrens return (EPERM); 219789Sahrens 220789Sahrens /* must be writable by this zone */ 221789Sahrens if (!writable) 222789Sahrens return (EPERM); 223789Sahrens } 224789Sahrens return (0); 225789Sahrens } 226789Sahrens 227789Sahrens int 2284543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) 229789Sahrens { 230789Sahrens int error; 231789Sahrens 2324543Smarks error = zfs_dozonecheck(name, cr); 2334543Smarks if (error == 0) { 2344543Smarks error = secpolicy_zfs(cr); 2354543Smarks if (error) { 2364543Smarks error = dsl_deleg_access(name, perm, cr); 2374543Smarks } 2384543Smarks } 2394543Smarks return (error); 2404543Smarks } 2414543Smarks 2424543Smarks static int 2434543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) 2444543Smarks { 2454543Smarks int error = 0; 2464543Smarks 2474543Smarks /* 2484543Smarks * Check permissions for special properties. 2494543Smarks */ 2504543Smarks switch (prop) { 2514543Smarks case ZFS_PROP_ZONED: 2524543Smarks /* 2534543Smarks * Disallow setting of 'zoned' from within a local zone. 2544543Smarks */ 2554543Smarks if (!INGLOBALZONE(curproc)) 2564543Smarks return (EPERM); 2574543Smarks break; 258789Sahrens 2594543Smarks case ZFS_PROP_QUOTA: 2604543Smarks if (error = 2614543Smarks zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_QUOTA, cr)) 2624543Smarks return (error); 2634543Smarks 2644543Smarks if (!INGLOBALZONE(curproc)) { 2654543Smarks uint64_t zoned; 2664543Smarks char setpoint[MAXNAMELEN]; 2674543Smarks int dslen; 2684543Smarks /* 2694543Smarks * Unprivileged users are allowed to modify the 2704543Smarks * quota on things *under* (ie. contained by) 2714543Smarks * the thing they own. 2724543Smarks */ 2734543Smarks if (dsl_prop_get_integer(name, "zoned", &zoned, 2744543Smarks setpoint)) 2754543Smarks return (EPERM); 2764543Smarks if (!zoned) /* this shouldn't happen */ 2774543Smarks return (EPERM); 2784543Smarks dslen = strlen(name); 2794543Smarks if (dslen <= strlen(setpoint)) 2804543Smarks return (EPERM); 2814543Smarks } 2824543Smarks default: 2834543Smarks error = zfs_secpolicy_write_perms(name, 2844543Smarks zfs_prop_perm(prop), cr); 2854543Smarks } 2864543Smarks 2874543Smarks return (error); 288789Sahrens } 289789Sahrens 2904543Smarks int 2914543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) 2924543Smarks { 2934543Smarks int error; 2944543Smarks 2954543Smarks error = zfs_dozonecheck(zc->zc_name, cr); 2964543Smarks if (error) 2974543Smarks return (error); 2984543Smarks 2994543Smarks /* 3004543Smarks * permission to set permissions will be evaluated later in 3014543Smarks * dsl_deleg_can_allow() 3024543Smarks */ 3034543Smarks return (0); 3044543Smarks } 3054543Smarks 3064543Smarks int 3074543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) 3084543Smarks { 3094543Smarks int error; 3104543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3114543Smarks ZFS_DELEG_PERM_ROLLBACK, cr); 3124543Smarks if (error == 0) 3134543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3144543Smarks ZFS_DELEG_PERM_MOUNT, cr); 3154543Smarks return (error); 3164543Smarks } 3174543Smarks 3184543Smarks int 3194543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) 3204543Smarks { 3214543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 3224543Smarks ZFS_DELEG_PERM_SEND, cr)); 3234543Smarks } 3244543Smarks 3254543Smarks int 3264543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) 3274543Smarks { 3284543Smarks if (!INGLOBALZONE(curproc)) 3294543Smarks return (EPERM); 3304543Smarks 3314543Smarks if (secpolicy_nfs(CRED()) == 0) { 3324543Smarks return (0); 3334543Smarks } else { 3344543Smarks vnode_t *vp; 3354543Smarks int error; 3364543Smarks 3374543Smarks if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, 3384543Smarks NO_FOLLOW, NULL, &vp)) != 0) 3394543Smarks return (error); 3404543Smarks 3414543Smarks /* Now make sure mntpnt and dataset are ZFS */ 3424543Smarks 3434543Smarks if (vp->v_vfsp->vfs_fstype != zfsfstype || 3444543Smarks (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), 3454543Smarks zc->zc_name) != 0)) { 3464543Smarks VN_RELE(vp); 3474543Smarks return (EPERM); 3484543Smarks } 3494543Smarks 3504543Smarks VN_RELE(vp); 3514543Smarks return (dsl_deleg_access(zc->zc_name, 3524543Smarks ZFS_DELEG_PERM_SHARE, cr)); 3534543Smarks } 3544543Smarks } 3554543Smarks 356789Sahrens static int 3574543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize) 358789Sahrens { 359789Sahrens char *cp; 360789Sahrens 361789Sahrens /* 362789Sahrens * Remove the @bla or /bla from the end of the name to get the parent. 363789Sahrens */ 3644543Smarks (void) strncpy(parent, datasetname, parentsize); 3654543Smarks cp = strrchr(parent, '@'); 366789Sahrens if (cp != NULL) { 367789Sahrens cp[0] = '\0'; 368789Sahrens } else { 3694543Smarks cp = strrchr(parent, '/'); 370789Sahrens if (cp == NULL) 371789Sahrens return (ENOENT); 372789Sahrens cp[0] = '\0'; 373789Sahrens } 374789Sahrens 3754543Smarks return (0); 3764543Smarks } 3774543Smarks 3784543Smarks int 3794543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 3804543Smarks { 3814543Smarks int error; 3824543Smarks 3834543Smarks if ((error = zfs_secpolicy_write_perms(name, 3844543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 3854543Smarks return (error); 3864543Smarks 3874543Smarks return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); 3884543Smarks } 3894543Smarks 3904543Smarks static int 3914543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) 3924543Smarks { 3934543Smarks return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); 3944543Smarks } 3954543Smarks 3964543Smarks /* 3974543Smarks * Must have sys_config privilege to check the iscsi permission 3984543Smarks */ 3994543Smarks /* ARGSUSED */ 4004543Smarks static int 4014543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) 4024543Smarks { 4034543Smarks return (secpolicy_zfs(cr)); 4044543Smarks } 4054543Smarks 4064543Smarks int 4074543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 4084543Smarks { 4094543Smarks char parentname[MAXNAMELEN]; 4104543Smarks int error; 4114543Smarks 4124543Smarks if ((error = zfs_secpolicy_write_perms(from, 4134543Smarks ZFS_DELEG_PERM_RENAME, cr)) != 0) 4144543Smarks return (error); 4154543Smarks 4164543Smarks if ((error = zfs_secpolicy_write_perms(from, 4174543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4184543Smarks return (error); 4194543Smarks 4204543Smarks if ((error = zfs_get_parent(to, parentname, 4214543Smarks sizeof (parentname))) != 0) 4224543Smarks return (error); 4234543Smarks 4244543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4254543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 4264543Smarks return (error); 4274543Smarks 4284543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4294543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4304543Smarks return (error); 4314543Smarks 4324543Smarks return (error); 4334543Smarks } 4344543Smarks 4354543Smarks static int 4364543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) 4374543Smarks { 4384543Smarks return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); 4394543Smarks } 4404543Smarks 4414543Smarks static int 4424543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) 4434543Smarks { 4444543Smarks char parentname[MAXNAMELEN]; 4454543Smarks objset_t *clone; 4464543Smarks int error; 4474543Smarks 4484543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4494543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4504543Smarks if (error) 4514543Smarks return (error); 4524543Smarks 4534543Smarks error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 4544543Smarks DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 4554543Smarks 4564543Smarks if (error == 0) { 4574543Smarks dsl_dataset_t *pclone = NULL; 4584543Smarks dsl_dir_t *dd; 4594543Smarks dd = clone->os->os_dsl_dataset->ds_dir; 4604543Smarks 4614543Smarks rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 4624543Smarks error = dsl_dataset_open_obj(dd->dd_pool, 4634543Smarks dd->dd_phys->dd_clone_parent_obj, NULL, 4644543Smarks DS_MODE_NONE, FTAG, &pclone); 4654543Smarks rw_exit(&dd->dd_pool->dp_config_rwlock); 4664543Smarks if (error) { 4674543Smarks dmu_objset_close(clone); 4684543Smarks return (error); 4694543Smarks } 4704543Smarks 4714543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4724543Smarks ZFS_DELEG_PERM_MOUNT, cr); 4734543Smarks 4744543Smarks dsl_dataset_name(pclone, parentname); 4754543Smarks dmu_objset_close(clone); 4764543Smarks dsl_dataset_close(pclone, DS_MODE_NONE, FTAG); 4774543Smarks if (error == 0) 4784543Smarks error = zfs_secpolicy_write_perms(parentname, 4794543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4804543Smarks } 4814543Smarks return (error); 4824543Smarks } 4834543Smarks 4844543Smarks static int 4854543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) 4864543Smarks { 4874543Smarks int error; 4884543Smarks 4894543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 4904543Smarks ZFS_DELEG_PERM_RECEIVE, cr)) != 0) 4914543Smarks return (error); 4924543Smarks 4934543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 4944543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4954543Smarks return (error); 4964543Smarks 4974543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 4984543Smarks ZFS_DELEG_PERM_CREATE, cr)); 4994543Smarks } 5004543Smarks 5014543Smarks int 5024543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 5034543Smarks { 5044543Smarks int error; 5054543Smarks 5064543Smarks if ((error = zfs_secpolicy_write_perms(name, 5074543Smarks ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) 5084543Smarks return (error); 5094543Smarks 5104543Smarks error = zfs_secpolicy_write_perms(name, 5114543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5124543Smarks 5134543Smarks return (error); 5144543Smarks } 5154543Smarks 5164543Smarks static int 5174543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) 5184543Smarks { 5194543Smarks 5204543Smarks return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); 5214543Smarks } 5224543Smarks 5234543Smarks static int 5244543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) 5254543Smarks { 5264543Smarks char parentname[MAXNAMELEN]; 5274543Smarks int error; 5284543Smarks 5294543Smarks if ((error = zfs_get_parent(zc->zc_name, parentname, 5304543Smarks sizeof (parentname))) != 0) 5314543Smarks return (error); 5324543Smarks 5334543Smarks if (zc->zc_value[0] != '\0') { 5344543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_value, 5354543Smarks ZFS_DELEG_PERM_CLONE, cr)) != 0) 5364543Smarks return (error); 5374543Smarks } 5384543Smarks 5394543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 5404543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 5414543Smarks return (error); 5424543Smarks 5434543Smarks error = zfs_secpolicy_write_perms(parentname, 5444543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5454543Smarks 5464543Smarks return (error); 5474543Smarks } 5484543Smarks 5494543Smarks static int 5504543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) 5514543Smarks { 5524543Smarks int error; 5534543Smarks 5544543Smarks error = secpolicy_fs_unmount(cr, NULL); 5554543Smarks if (error) { 5564543Smarks error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); 5574543Smarks } 5584543Smarks return (error); 559789Sahrens } 560789Sahrens 561789Sahrens /* 562789Sahrens * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires 563789Sahrens * SYS_CONFIG privilege, which is not available in a local zone. 564789Sahrens */ 565789Sahrens /* ARGSUSED */ 566789Sahrens static int 5674543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) 568789Sahrens { 569789Sahrens if (secpolicy_sys_config(cr, B_FALSE) != 0) 570789Sahrens return (EPERM); 571789Sahrens 572789Sahrens return (0); 573789Sahrens } 574789Sahrens 575789Sahrens /* 5764543Smarks * Just like zfs_secpolicy_config, except that we will check for 5774543Smarks * mount permission on the dataset for permission to create/remove 5784543Smarks * the minor nodes. 5794543Smarks */ 5804543Smarks static int 5814543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) 5824543Smarks { 5834543Smarks if (secpolicy_sys_config(cr, B_FALSE) != 0) { 5844543Smarks return (dsl_deleg_access(zc->zc_name, 5854543Smarks ZFS_DELEG_PERM_MOUNT, cr)); 5864543Smarks } 5874543Smarks 5884543Smarks return (0); 5894543Smarks } 5904543Smarks 5914543Smarks /* 5921544Seschrock * Policy for fault injection. Requires all privileges. 5931544Seschrock */ 5941544Seschrock /* ARGSUSED */ 5951544Seschrock static int 5964543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) 5971544Seschrock { 5981544Seschrock return (secpolicy_zinject(cr)); 5991544Seschrock } 6001544Seschrock 6011544Seschrock /* 602789Sahrens * Returns the nvlist as specified by the user in the zfs_cmd_t. 603789Sahrens */ 604789Sahrens static int 6052676Seschrock get_nvlist(zfs_cmd_t *zc, nvlist_t **nvp) 606789Sahrens { 607789Sahrens char *packed; 608789Sahrens size_t size; 609789Sahrens int error; 610789Sahrens nvlist_t *config = NULL; 611789Sahrens 612789Sahrens /* 6132676Seschrock * Read in and unpack the user-supplied nvlist. 614789Sahrens */ 6152676Seschrock if ((size = zc->zc_nvlist_src_size) == 0) 616789Sahrens return (EINVAL); 617789Sahrens 618789Sahrens packed = kmem_alloc(size, KM_SLEEP); 619789Sahrens 6202676Seschrock if ((error = xcopyin((void *)(uintptr_t)zc->zc_nvlist_src, packed, 621789Sahrens size)) != 0) { 622789Sahrens kmem_free(packed, size); 623789Sahrens return (error); 624789Sahrens } 625789Sahrens 626789Sahrens if ((error = nvlist_unpack(packed, size, &config, 0)) != 0) { 627789Sahrens kmem_free(packed, size); 628789Sahrens return (error); 629789Sahrens } 630789Sahrens 631789Sahrens kmem_free(packed, size); 632789Sahrens 633789Sahrens *nvp = config; 634789Sahrens return (0); 635789Sahrens } 636789Sahrens 637789Sahrens static int 6382676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 6392676Seschrock { 6402676Seschrock char *packed = NULL; 6412676Seschrock size_t size; 6422676Seschrock int error; 6432676Seschrock 6442676Seschrock VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 6452676Seschrock 6462676Seschrock if (size > zc->zc_nvlist_dst_size) { 6472676Seschrock error = ENOMEM; 6482676Seschrock } else { 6492676Seschrock VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 6502676Seschrock KM_SLEEP) == 0); 6512676Seschrock error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 6522676Seschrock size); 6532676Seschrock kmem_free(packed, size); 6542676Seschrock } 6552676Seschrock 6562676Seschrock zc->zc_nvlist_dst_size = size; 6572676Seschrock return (error); 6582676Seschrock } 6592676Seschrock 6602676Seschrock static int 661789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc) 662789Sahrens { 663789Sahrens int error; 664789Sahrens nvlist_t *config; 665789Sahrens 6662676Seschrock if ((error = get_nvlist(zc, &config)) != 0) 667789Sahrens return (error); 668789Sahrens 6692676Seschrock error = spa_create(zc->zc_name, config, zc->zc_value[0] == '\0' ? 6702676Seschrock NULL : zc->zc_value); 671789Sahrens 672789Sahrens nvlist_free(config); 673789Sahrens 674789Sahrens return (error); 675789Sahrens } 676789Sahrens 677789Sahrens static int 678789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc) 679789Sahrens { 6804543Smarks int error; 6814543Smarks zfs_log_history(zc); 6824543Smarks error = spa_destroy(zc->zc_name); 6834543Smarks return (error); 684789Sahrens } 685789Sahrens 686789Sahrens static int 687789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc) 688789Sahrens { 689789Sahrens int error; 690789Sahrens nvlist_t *config; 691789Sahrens uint64_t guid; 692789Sahrens 6932676Seschrock if ((error = get_nvlist(zc, &config)) != 0) 694789Sahrens return (error); 695789Sahrens 696789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 6971544Seschrock guid != zc->zc_guid) 698789Sahrens error = EINVAL; 699789Sahrens else 700789Sahrens error = spa_import(zc->zc_name, config, 7012676Seschrock zc->zc_value[0] == '\0' ? NULL : zc->zc_value); 702789Sahrens 703789Sahrens nvlist_free(config); 704789Sahrens 705789Sahrens return (error); 706789Sahrens } 707789Sahrens 708789Sahrens static int 709789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc) 710789Sahrens { 7114543Smarks int error; 7124543Smarks zfs_log_history(zc); 7134543Smarks error = spa_export(zc->zc_name, NULL); 7144543Smarks return (error); 715789Sahrens } 716789Sahrens 717789Sahrens static int 718789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc) 719789Sahrens { 720789Sahrens nvlist_t *configs; 721789Sahrens int error; 722789Sahrens 723789Sahrens if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 724789Sahrens return (EEXIST); 725789Sahrens 7262676Seschrock error = put_nvlist(zc, configs); 727789Sahrens 728789Sahrens nvlist_free(configs); 729789Sahrens 730789Sahrens return (error); 731789Sahrens } 732789Sahrens 733789Sahrens static int 734789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc) 735789Sahrens { 736789Sahrens nvlist_t *config; 737789Sahrens int error; 7381544Seschrock int ret = 0; 739789Sahrens 7402676Seschrock error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 7412676Seschrock sizeof (zc->zc_value)); 742789Sahrens 743789Sahrens if (config != NULL) { 7442676Seschrock ret = put_nvlist(zc, config); 745789Sahrens nvlist_free(config); 7461544Seschrock 7471544Seschrock /* 7481544Seschrock * The config may be present even if 'error' is non-zero. 7491544Seschrock * In this case we return success, and preserve the real errno 7501544Seschrock * in 'zc_cookie'. 7511544Seschrock */ 7521544Seschrock zc->zc_cookie = error; 753789Sahrens } else { 7541544Seschrock ret = error; 755789Sahrens } 756789Sahrens 7571544Seschrock return (ret); 758789Sahrens } 759789Sahrens 760789Sahrens /* 761789Sahrens * Try to import the given pool, returning pool stats as appropriate so that 762789Sahrens * user land knows which devices are available and overall pool health. 763789Sahrens */ 764789Sahrens static int 765789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 766789Sahrens { 767789Sahrens nvlist_t *tryconfig, *config; 768789Sahrens int error; 769789Sahrens 7702676Seschrock if ((error = get_nvlist(zc, &tryconfig)) != 0) 771789Sahrens return (error); 772789Sahrens 773789Sahrens config = spa_tryimport(tryconfig); 774789Sahrens 775789Sahrens nvlist_free(tryconfig); 776789Sahrens 777789Sahrens if (config == NULL) 778789Sahrens return (EINVAL); 779789Sahrens 7802676Seschrock error = put_nvlist(zc, config); 781789Sahrens nvlist_free(config); 782789Sahrens 783789Sahrens return (error); 784789Sahrens } 785789Sahrens 786789Sahrens static int 787789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc) 788789Sahrens { 789789Sahrens spa_t *spa; 790789Sahrens int error; 791789Sahrens 7922926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 7932926Sek110237 return (error); 7942926Sek110237 7954451Seschrock spa_config_enter(spa, RW_READER, FTAG); 7962926Sek110237 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); 7974451Seschrock spa_config_exit(spa, FTAG); 7982926Sek110237 7992926Sek110237 spa_close(spa, FTAG); 8002926Sek110237 801789Sahrens return (error); 802789Sahrens } 803789Sahrens 804789Sahrens static int 805789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 806789Sahrens { 807789Sahrens spa_t *spa; 808789Sahrens int error; 809789Sahrens 810789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 811789Sahrens if (error == 0) { 812789Sahrens spa_freeze(spa); 813789Sahrens spa_close(spa, FTAG); 814789Sahrens } 815789Sahrens return (error); 816789Sahrens } 817789Sahrens 818789Sahrens static int 8191760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 8201760Seschrock { 8211760Seschrock spa_t *spa; 8221760Seschrock int error; 8231760Seschrock 8242926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8252926Sek110237 return (error); 8262926Sek110237 8272926Sek110237 spa_upgrade(spa); 8282926Sek110237 spa_close(spa, FTAG); 8292926Sek110237 8302926Sek110237 return (error); 8312926Sek110237 } 8322926Sek110237 8332926Sek110237 static int 8342926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 8352926Sek110237 { 8362926Sek110237 spa_t *spa; 8372926Sek110237 char *hist_buf; 8382926Sek110237 uint64_t size; 8392926Sek110237 int error; 8402926Sek110237 8412926Sek110237 if ((size = zc->zc_history_len) == 0) 8422926Sek110237 return (EINVAL); 8432926Sek110237 8442926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8452926Sek110237 return (error); 8462926Sek110237 8474577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 8483863Sek110237 spa_close(spa, FTAG); 8493863Sek110237 return (ENOTSUP); 8503863Sek110237 } 8513863Sek110237 8522926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 8532926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 8542926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 8554543Smarks error = xcopyout(hist_buf, 8564543Smarks (char *)(uintptr_t)zc->zc_history, 8572926Sek110237 zc->zc_history_len); 8582926Sek110237 } 8592926Sek110237 8602926Sek110237 spa_close(spa, FTAG); 8612926Sek110237 kmem_free(hist_buf, size); 8622926Sek110237 return (error); 8632926Sek110237 } 8642926Sek110237 8652926Sek110237 static int 8663444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 8673444Sek110237 { 8683444Sek110237 int error; 8693444Sek110237 8703912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 8713444Sek110237 return (error); 8723444Sek110237 8733444Sek110237 return (0); 8743444Sek110237 } 8753444Sek110237 8763444Sek110237 static int 8773444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 8783444Sek110237 { 8793444Sek110237 objset_t *osp; 8803444Sek110237 int error; 8813444Sek110237 8823444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 8833444Sek110237 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) 8843444Sek110237 return (error); 8853444Sek110237 8863444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 8873444Sek110237 sizeof (zc->zc_value)); 8883444Sek110237 dmu_objset_close(osp); 8893444Sek110237 8903444Sek110237 return (error); 8913444Sek110237 } 8923444Sek110237 8933444Sek110237 static int 894789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 895789Sahrens { 896789Sahrens spa_t *spa; 897789Sahrens int error; 898789Sahrens nvlist_t *config; 899789Sahrens 900789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 901789Sahrens if (error != 0) 902789Sahrens return (error); 903789Sahrens 9043912Slling /* 9053912Slling * A root pool with concatenated devices is not supported. 9063912Slling * Thus, can not add a device to a root pool with one device. 9073912Slling */ 9083912Slling if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0) { 9093912Slling spa_close(spa, FTAG); 9103912Slling return (EDOM); 9113912Slling } 9123912Slling 9132676Seschrock if ((error = get_nvlist(zc, &config)) == 0) { 914789Sahrens error = spa_vdev_add(spa, config); 915789Sahrens nvlist_free(config); 916789Sahrens } 917789Sahrens spa_close(spa, FTAG); 918789Sahrens return (error); 919789Sahrens } 920789Sahrens 921789Sahrens static int 922789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 923789Sahrens { 9242082Seschrock spa_t *spa; 9252082Seschrock int error; 9262082Seschrock 9272082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 9282082Seschrock if (error != 0) 9292082Seschrock return (error); 9302082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 9312082Seschrock spa_close(spa, FTAG); 9322082Seschrock return (error); 933789Sahrens } 934789Sahrens 935789Sahrens static int 9364451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 937789Sahrens { 938789Sahrens spa_t *spa; 939789Sahrens int error; 9404451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 941789Sahrens 9422926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 943789Sahrens return (error); 9444451Seschrock switch (zc->zc_cookie) { 9454451Seschrock case VDEV_STATE_ONLINE: 9464451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 9474451Seschrock break; 9484451Seschrock 9494451Seschrock case VDEV_STATE_OFFLINE: 9504451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 9514451Seschrock break; 952789Sahrens 9534451Seschrock case VDEV_STATE_FAULTED: 9544451Seschrock error = vdev_fault(spa, zc->zc_guid); 9554451Seschrock break; 956789Sahrens 9574451Seschrock case VDEV_STATE_DEGRADED: 9584451Seschrock error = vdev_degrade(spa, zc->zc_guid); 9594451Seschrock break; 9604451Seschrock 9614451Seschrock default: 9624451Seschrock error = EINVAL; 9634451Seschrock } 9644451Seschrock zc->zc_cookie = newstate; 965789Sahrens spa_close(spa, FTAG); 966789Sahrens return (error); 967789Sahrens } 968789Sahrens 969789Sahrens static int 970789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 971789Sahrens { 972789Sahrens spa_t *spa; 973789Sahrens int replacing = zc->zc_cookie; 974789Sahrens nvlist_t *config; 975789Sahrens int error; 976789Sahrens 9772926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 978789Sahrens return (error); 979789Sahrens 9802676Seschrock if ((error = get_nvlist(zc, &config)) == 0) { 9811544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 982789Sahrens nvlist_free(config); 983789Sahrens } 984789Sahrens 985789Sahrens spa_close(spa, FTAG); 986789Sahrens return (error); 987789Sahrens } 988789Sahrens 989789Sahrens static int 990789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 991789Sahrens { 992789Sahrens spa_t *spa; 993789Sahrens int error; 994789Sahrens 9952926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 996789Sahrens return (error); 997789Sahrens 9981544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 999789Sahrens 1000789Sahrens spa_close(spa, FTAG); 1001789Sahrens return (error); 1002789Sahrens } 1003789Sahrens 1004789Sahrens static int 10051354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 10061354Seschrock { 10071354Seschrock spa_t *spa; 10082676Seschrock char *path = zc->zc_value; 10091544Seschrock uint64_t guid = zc->zc_guid; 10101354Seschrock int error; 10111354Seschrock 10121354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10131354Seschrock if (error != 0) 10141354Seschrock return (error); 10151354Seschrock 10161354Seschrock error = spa_vdev_setpath(spa, guid, path); 10171354Seschrock spa_close(spa, FTAG); 10181354Seschrock return (error); 10191354Seschrock } 10201354Seschrock 10211354Seschrock static int 1022789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1023789Sahrens { 1024789Sahrens objset_t *os = NULL; 1025789Sahrens int error; 10261356Seschrock nvlist_t *nv; 1027789Sahrens 1028789Sahrens retry: 1029789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1030789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1031789Sahrens if (error != 0) { 1032789Sahrens /* 1033789Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1034789Sahrens * the objset is held exclusively. Fortunately this hold is 1035789Sahrens * only for a short while, so we retry here. 1036789Sahrens * This avoids user code having to handle EBUSY, 1037789Sahrens * for example for a "zfs list". 1038789Sahrens */ 1039789Sahrens if (error == EBUSY) { 1040789Sahrens delay(1); 1041789Sahrens goto retry; 1042789Sahrens } 1043789Sahrens return (error); 1044789Sahrens } 1045789Sahrens 10462885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1047789Sahrens 10482856Snd150628 if (zc->zc_nvlist_dst != 0 && 10491356Seschrock (error = dsl_prop_get_all(os, &nv)) == 0) { 10502885Sahrens dmu_objset_stats(os, nv); 10513087Sahrens /* 10524577Sahrens * NB: {zpl,zvol}_get_stats() will read the objset contents, 10533087Sahrens * which we aren't supposed to do with a 10543087Sahrens * DS_MODE_STANDARD open, because it could be 10553087Sahrens * inconsistent. So this is a bit of a workaround... 10563087Sahrens */ 10574577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 10584577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 10594577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 10604577Sahrens else if (dmu_objset_type(os) == DMU_OST_ZFS) 10614577Sahrens (void) zfs_get_stats(os, nv); 10624577Sahrens } 10632676Seschrock error = put_nvlist(zc, nv); 10641356Seschrock nvlist_free(nv); 10651356Seschrock } 1066789Sahrens 10672676Seschrock spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value)); 10681544Seschrock 1069789Sahrens dmu_objset_close(os); 1070789Sahrens return (error); 1071789Sahrens } 1072789Sahrens 1073789Sahrens static int 1074789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1075789Sahrens { 1076885Sahrens objset_t *os; 1077789Sahrens int error; 1078789Sahrens char *p; 1079789Sahrens 1080885Sahrens retry: 1081885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1082885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1083885Sahrens if (error != 0) { 1084885Sahrens /* 1085885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1086885Sahrens * the objset is held exclusively. Fortunately this hold is 1087885Sahrens * only for a short while, so we retry here. 1088885Sahrens * This avoids user code having to handle EBUSY, 1089885Sahrens * for example for a "zfs list". 1090885Sahrens */ 1091885Sahrens if (error == EBUSY) { 1092885Sahrens delay(1); 1093885Sahrens goto retry; 1094885Sahrens } 1095885Sahrens if (error == ENOENT) 1096885Sahrens error = ESRCH; 1097885Sahrens return (error); 1098789Sahrens } 1099789Sahrens 1100789Sahrens p = strrchr(zc->zc_name, '/'); 1101789Sahrens if (p == NULL || p[1] != '\0') 1102789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1103789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1104789Sahrens 1105789Sahrens do { 1106885Sahrens error = dmu_dir_list_next(os, 1107885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1108885Sahrens NULL, &zc->zc_cookie); 1109789Sahrens if (error == ENOENT) 1110789Sahrens error = ESRCH; 1111885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1112789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 1113789Sahrens 1114885Sahrens /* 1115885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1116885Sahrens * try to get stats for it. Userland will skip over it. 1117885Sahrens */ 1118885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1119885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1120789Sahrens 1121885Sahrens dmu_objset_close(os); 1122789Sahrens return (error); 1123789Sahrens } 1124789Sahrens 1125789Sahrens static int 1126789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1127789Sahrens { 1128885Sahrens objset_t *os; 1129789Sahrens int error; 1130789Sahrens 1131789Sahrens retry: 1132885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1133885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1134885Sahrens if (error != 0) { 1135789Sahrens /* 1136885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1137789Sahrens * the objset is held exclusively. Fortunately this hold is 1138789Sahrens * only for a short while, so we retry here. 1139789Sahrens * This avoids user code having to handle EBUSY, 1140885Sahrens * for example for a "zfs list". 1141789Sahrens */ 1142789Sahrens if (error == EBUSY) { 1143789Sahrens delay(1); 1144789Sahrens goto retry; 1145789Sahrens } 1146789Sahrens if (error == ENOENT) 1147885Sahrens error = ESRCH; 1148789Sahrens return (error); 1149789Sahrens } 1150789Sahrens 11511003Slling /* 11521003Slling * A dataset name of maximum length cannot have any snapshots, 11531003Slling * so exit immediately. 11541003Slling */ 11551003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1156885Sahrens dmu_objset_close(os); 11571003Slling return (ESRCH); 1158789Sahrens } 1159789Sahrens 1160885Sahrens error = dmu_snapshot_list_next(os, 1161885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 1162885Sahrens zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie); 1163789Sahrens if (error == ENOENT) 1164789Sahrens error = ESRCH; 1165789Sahrens 1166885Sahrens if (error == 0) 1167885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1168789Sahrens 1169885Sahrens dmu_objset_close(os); 1170789Sahrens return (error); 1171789Sahrens } 1172789Sahrens 1173789Sahrens static int 11742676Seschrock zfs_set_prop_nvlist(const char *name, dev_t dev, cred_t *cr, nvlist_t *nvl) 1175789Sahrens { 11762676Seschrock nvpair_t *elem; 11772676Seschrock int error; 11782676Seschrock const char *propname; 11792676Seschrock zfs_prop_t prop; 11802676Seschrock uint64_t intval; 11812676Seschrock char *strval; 11822676Seschrock 11834543Smarks /* 11844543Smarks * First validate permission to set all of the properties 11854543Smarks */ 11862676Seschrock elem = NULL; 11872676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 11882676Seschrock propname = nvpair_name(elem); 11892676Seschrock 11902676Seschrock if ((prop = zfs_name_to_prop(propname)) == 11912676Seschrock ZFS_PROP_INVAL) { 11922676Seschrock /* 11932676Seschrock * If this is a user-defined property, it must be a 11942676Seschrock * string, and there is no further validation to do. 11952676Seschrock */ 11962676Seschrock if (!zfs_prop_user(propname) || 11972676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 11982676Seschrock return (EINVAL); 11992676Seschrock 12004543Smarks error = zfs_secpolicy_write_perms(name, 12014543Smarks ZFS_DELEG_PERM_USERPROP, cr); 12024543Smarks if (error) { 12034543Smarks return (EPERM); 12044543Smarks } 12054543Smarks continue; 12062676Seschrock } 12072676Seschrock 12082676Seschrock /* 12094543Smarks * Check permissions for special properties 12102676Seschrock */ 12114543Smarks 12122676Seschrock switch (prop) { 12132676Seschrock case ZFS_PROP_ZONED: 12142676Seschrock /* 12152676Seschrock * Disallow setting of 'zoned' from within a local zone. 12162676Seschrock */ 12172676Seschrock if (!INGLOBALZONE(curproc)) 12182676Seschrock return (EPERM); 12192676Seschrock break; 12202676Seschrock 12212676Seschrock case ZFS_PROP_QUOTA: 12222676Seschrock if (error = zfs_dozonecheck(name, cr)) 12232676Seschrock return (error); 12242676Seschrock 12252676Seschrock if (!INGLOBALZONE(curproc)) { 12262676Seschrock uint64_t zoned; 12272676Seschrock char setpoint[MAXNAMELEN]; 12282676Seschrock int dslen; 12292676Seschrock /* 12302676Seschrock * Unprivileged users are allowed to modify the 12312676Seschrock * quota on things *under* (ie. contained by) 12322676Seschrock * the thing they own. 12332676Seschrock */ 12342676Seschrock if (dsl_prop_get_integer(name, "zoned", &zoned, 12352676Seschrock setpoint)) 12362676Seschrock return (EPERM); 12372676Seschrock if (!zoned) /* this shouldn't happen */ 12382676Seschrock return (EPERM); 12392676Seschrock dslen = strlen(name); 12402676Seschrock if (dslen <= strlen(setpoint)) 12412676Seschrock return (EPERM); 12422676Seschrock } 12433886Sahl break; 12443886Sahl 12453886Sahl case ZFS_PROP_COMPRESSION: 12463886Sahl /* 12473886Sahl * If the user specified gzip compression, make sure 12483886Sahl * the SPA supports it. We ignore any errors here since 12493886Sahl * we'll catch them later. 12503886Sahl */ 12513886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 12523886Sahl nvpair_value_uint64(elem, &intval) == 0 && 12533886Sahl intval >= ZIO_COMPRESS_GZIP_1 && 12543886Sahl intval <= ZIO_COMPRESS_GZIP_9) { 12554543Smarks spa_t *spa; 12564543Smarks 1257*4603Sahrens if (spa_open(name, &spa, FTAG) == 0) { 12583886Sahl if (spa_version(spa) < 12594577Sahrens SPA_VERSION_GZIP_COMPRESSION) { 12603886Sahl spa_close(spa, FTAG); 12613886Sahl return (ENOTSUP); 12623886Sahl } 12633886Sahl 12643886Sahl spa_close(spa, FTAG); 12653886Sahl } 12663886Sahl } 12673886Sahl break; 1268*4603Sahrens 1269*4603Sahrens case ZFS_PROP_COPIES: 1270*4603Sahrens { 1271*4603Sahrens spa_t *spa; 1272*4603Sahrens 1273*4603Sahrens if (spa_open(name, &spa, FTAG) == 0) { 1274*4603Sahrens if (spa_version(spa) < 1275*4603Sahrens SPA_VERSION_DITTO_BLOCKS) { 1276*4603Sahrens spa_close(spa, FTAG); 1277*4603Sahrens return (ENOTSUP); 1278*4603Sahrens } 1279*4603Sahrens spa_close(spa, FTAG); 1280*4603Sahrens } 1281*4603Sahrens break; 1282*4603Sahrens } 12832676Seschrock } 12844543Smarks if ((error = zfs_secpolicy_setprop(name, prop, cr)) != 0) 12854543Smarks return (error); 12864543Smarks } 12874543Smarks 12884543Smarks elem = NULL; 12894543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 12904543Smarks propname = nvpair_name(elem); 12914543Smarks 12924543Smarks if ((prop = zfs_name_to_prop(propname)) == 12934543Smarks ZFS_PROP_INVAL) { 12944543Smarks 12954543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 12964543Smarks error = dsl_prop_set(name, propname, 1, 12974543Smarks strlen(strval) + 1, strval); 12984543Smarks if (error == 0) 12994543Smarks continue; 13004543Smarks else 13014543Smarks return (error); 13024543Smarks } 13032676Seschrock 13042676Seschrock switch (prop) { 13052676Seschrock case ZFS_PROP_QUOTA: 13062676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13074577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 13082676Seschrock return (error); 13092676Seschrock break; 13102676Seschrock 13112676Seschrock case ZFS_PROP_RESERVATION: 13122676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13132676Seschrock (error = dsl_dir_set_reservation(name, 13142676Seschrock intval)) != 0) 13152676Seschrock return (error); 13162676Seschrock break; 1317789Sahrens 13182676Seschrock case ZFS_PROP_VOLSIZE: 13192676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13204577Sahrens (error = zvol_set_volsize(name, dev, intval)) != 0) 13212676Seschrock return (error); 13222676Seschrock break; 13232676Seschrock 13242676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 13252676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13264577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 13274577Sahrens return (error); 13284577Sahrens break; 13294577Sahrens 13304577Sahrens case ZFS_PROP_VERSION: 13314577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13324577Sahrens (error = zfs_set_version(name, intval)) != 0) 13332676Seschrock return (error); 13342676Seschrock break; 13352676Seschrock 13362676Seschrock default: 13372676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 13382676Seschrock if (zfs_prop_get_type(prop) != 13392676Seschrock prop_type_string) 13402676Seschrock return (EINVAL); 13412717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 13422717Seschrock if ((error = dsl_prop_set(name, 13432676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 13442717Seschrock strval)) != 0) 13452717Seschrock return (error); 13462676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 13472885Sahrens const char *unused; 13482885Sahrens 13492717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 13502676Seschrock 13512676Seschrock switch (zfs_prop_get_type(prop)) { 13522676Seschrock case prop_type_number: 13532676Seschrock break; 13542676Seschrock case prop_type_boolean: 13552676Seschrock if (intval > 1) 13562717Seschrock return (EINVAL); 13572676Seschrock break; 13582676Seschrock case prop_type_string: 13592717Seschrock return (EINVAL); 13602676Seschrock case prop_type_index: 13612717Seschrock if (zfs_prop_index_to_string(prop, 13622717Seschrock intval, &unused) != 0) 13632717Seschrock return (EINVAL); 13642676Seschrock break; 13652676Seschrock default: 13664577Sahrens cmn_err(CE_PANIC, 13674577Sahrens "unknown property type"); 13682676Seschrock break; 13692676Seschrock } 13702676Seschrock 13712717Seschrock if ((error = dsl_prop_set(name, propname, 13722717Seschrock 8, 1, &intval)) != 0) 13732717Seschrock return (error); 13742676Seschrock } else { 13752676Seschrock return (EINVAL); 13762676Seschrock } 13772676Seschrock break; 13782676Seschrock } 13792676Seschrock } 13802676Seschrock 13812676Seschrock return (0); 1382789Sahrens } 1383789Sahrens 1384789Sahrens static int 13852676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1386789Sahrens { 13872676Seschrock nvlist_t *nvl; 13882676Seschrock int error; 13892676Seschrock zfs_prop_t prop; 1390789Sahrens 13912676Seschrock /* 13922676Seschrock * If zc_value is set, then this is an attempt to inherit a value. 13932676Seschrock * Otherwise, zc_nvlist refers to a list of properties to set. 13942676Seschrock */ 13952676Seschrock if (zc->zc_value[0] != '\0') { 13962676Seschrock if (!zfs_prop_user(zc->zc_value) && 13972676Seschrock ((prop = zfs_name_to_prop(zc->zc_value)) == 13982676Seschrock ZFS_PROP_INVAL || 13992676Seschrock !zfs_prop_inheritable(prop))) 14002676Seschrock return (EINVAL); 14012676Seschrock 14022676Seschrock return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 14032676Seschrock } 14042676Seschrock 14052676Seschrock if ((error = get_nvlist(zc, &nvl)) != 0) 14062676Seschrock return (error); 14072676Seschrock 14082676Seschrock error = zfs_set_prop_nvlist(zc->zc_name, zc->zc_dev, 14092676Seschrock (cred_t *)(uintptr_t)zc->zc_cred, nvl); 14104543Smarks 14112676Seschrock nvlist_free(nvl); 14122676Seschrock return (error); 1413789Sahrens } 1414789Sahrens 1415789Sahrens static int 14164098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 14173912Slling { 14183912Slling nvlist_t *nvl; 14193912Slling int error, reset_bootfs = 0; 14203912Slling uint64_t objnum; 14214543Smarks uint64_t intval; 14223912Slling zpool_prop_t prop; 14233912Slling nvpair_t *elem; 14243912Slling char *propname, *strval; 14253912Slling spa_t *spa; 14263912Slling vdev_t *rvdev; 14273912Slling char *vdev_type; 14283912Slling objset_t *os; 14293912Slling 14303912Slling if ((error = get_nvlist(zc, &nvl)) != 0) 14313912Slling return (error); 14323912Slling 14333912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 14343912Slling nvlist_free(nvl); 14353912Slling return (error); 14363912Slling } 14373912Slling 14384577Sahrens if (spa_version(spa) < SPA_VERSION_BOOTFS) { 14393912Slling nvlist_free(nvl); 14403912Slling spa_close(spa, FTAG); 14413912Slling return (ENOTSUP); 14423912Slling } 14433912Slling 14443912Slling elem = NULL; 14453912Slling while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 14463912Slling 14473912Slling propname = nvpair_name(elem); 14483912Slling 14493912Slling if ((prop = zpool_name_to_prop(propname)) == 14503912Slling ZFS_PROP_INVAL) { 14513912Slling nvlist_free(nvl); 14523912Slling spa_close(spa, FTAG); 14533912Slling return (EINVAL); 14543912Slling } 14553912Slling 14563912Slling switch (prop) { 14574543Smarks case ZPOOL_PROP_DELEGATION: 14584543Smarks VERIFY(nvpair_value_uint64(elem, &intval) == 0); 14594543Smarks if (intval > 1) 14604543Smarks error = EINVAL; 14614543Smarks break; 14624451Seschrock case ZPOOL_PROP_BOOTFS: 14633912Slling /* 14643912Slling * A bootable filesystem can not be on a RAIDZ pool 14653912Slling * nor a striped pool with more than 1 device. 14663912Slling */ 14673912Slling rvdev = spa->spa_root_vdev; 14683912Slling vdev_type = 14693912Slling rvdev->vdev_child[0]->vdev_ops->vdev_op_type; 14703912Slling if (strcmp(vdev_type, VDEV_TYPE_RAIDZ) == 0 || 14713912Slling (strcmp(vdev_type, VDEV_TYPE_MIRROR) != 0 && 14723912Slling rvdev->vdev_children > 1)) { 14733912Slling error = ENOTSUP; 14743912Slling break; 14753912Slling } 14763912Slling 14773912Slling reset_bootfs = 1; 14783912Slling 14793912Slling VERIFY(nvpair_value_string(elem, &strval) == 0); 14803912Slling if (strval == NULL || strval[0] == '\0') { 14814451Seschrock objnum = zpool_prop_default_numeric( 14824451Seschrock ZPOOL_PROP_BOOTFS); 14833912Slling break; 14843912Slling } 14853912Slling 14863912Slling if (error = dmu_objset_open(strval, DMU_OST_ZFS, 14873912Slling DS_MODE_STANDARD | DS_MODE_READONLY, &os)) 14883912Slling break; 14893912Slling objnum = dmu_objset_id(os); 14903912Slling dmu_objset_close(os); 14913912Slling break; 14923912Slling } 14933912Slling 14943912Slling if (error) 14953912Slling break; 14963912Slling } 14973912Slling if (error == 0) { 14983912Slling if (reset_bootfs) { 14993912Slling VERIFY(nvlist_remove(nvl, 15004451Seschrock zpool_prop_to_name(ZPOOL_PROP_BOOTFS), 15013912Slling DATA_TYPE_STRING) == 0); 15023912Slling VERIFY(nvlist_add_uint64(nvl, 15034451Seschrock zpool_prop_to_name(ZPOOL_PROP_BOOTFS), 15044451Seschrock objnum) == 0); 15053912Slling } 15063912Slling error = spa_set_props(spa, nvl); 15073912Slling } 15083912Slling 15093912Slling nvlist_free(nvl); 15103912Slling spa_close(spa, FTAG); 15113912Slling 15123912Slling return (error); 15133912Slling } 15143912Slling 15153912Slling static int 15164098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 15173912Slling { 15183912Slling spa_t *spa; 15193912Slling int error; 15203912Slling nvlist_t *nvp = NULL; 15213912Slling 15223912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 15233912Slling return (error); 15243912Slling 15253912Slling error = spa_get_props(spa, &nvp); 15263912Slling 15273912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 15283912Slling error = put_nvlist(zc, nvp); 15293912Slling else 15303912Slling error = EFAULT; 15313912Slling 15323912Slling spa_close(spa, FTAG); 15333912Slling 15343912Slling if (nvp) 15353912Slling nvlist_free(nvp); 15363912Slling return (error); 15373912Slling } 15383912Slling 15393912Slling static int 15404543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 15414543Smarks { 15424543Smarks nvlist_t *nvp; 15434543Smarks int error; 15444543Smarks uint32_t uid; 15454543Smarks uint32_t gid; 15464543Smarks uint32_t *groups; 15474543Smarks uint_t group_cnt; 15484543Smarks cred_t *usercred; 15494543Smarks 15504543Smarks if ((error = get_nvlist(zc, &nvp)) != 0) { 15514543Smarks return (error); 15524543Smarks } 15534543Smarks 15544543Smarks if ((error = nvlist_lookup_uint32(nvp, 15554543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 15564543Smarks nvlist_free(nvp); 15574543Smarks return (EPERM); 15584543Smarks } 15594543Smarks 15604543Smarks if ((error = nvlist_lookup_uint32(nvp, 15614543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 15624543Smarks nvlist_free(nvp); 15634543Smarks return (EPERM); 15644543Smarks } 15654543Smarks 15664543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 15674543Smarks &groups, &group_cnt)) != 0) { 15684543Smarks nvlist_free(nvp); 15694543Smarks return (EPERM); 15704543Smarks } 15714543Smarks usercred = cralloc(); 15724543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 15734543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 15744543Smarks nvlist_free(nvp); 15754543Smarks crfree(usercred); 15764543Smarks return (EPERM); 15774543Smarks } 15784543Smarks nvlist_free(nvp); 15794543Smarks error = dsl_deleg_access(zc->zc_name, 15804543Smarks ZFS_DELEG_PERM_SHAREISCSI, usercred); 15814543Smarks crfree(usercred); 15824543Smarks return (error); 15834543Smarks } 15844543Smarks 15854543Smarks static int 15864543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 15874543Smarks { 15884543Smarks int error; 15894543Smarks nvlist_t *fsaclnv = NULL; 15904543Smarks cred_t *cr; 15914543Smarks 15924543Smarks if ((error = get_nvlist(zc, &fsaclnv)) != 0) 15934543Smarks return (error); 15944543Smarks 15954543Smarks /* 15964543Smarks * Verify nvlist is constructed correctly 15974543Smarks */ 15984543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 15994543Smarks nvlist_free(fsaclnv); 16004543Smarks return (EINVAL); 16014543Smarks } 16024543Smarks 16034543Smarks /* 16044543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 16054543Smarks * that user is allowed to hand out each permission in 16064543Smarks * the nvlist(s) 16074543Smarks */ 16084543Smarks 16094543Smarks cr = (cred_t *)(uintptr_t)zc->zc_cred; 16104543Smarks error = secpolicy_zfs(cr); 16114543Smarks if (error) { 16124543Smarks if (zc->zc_perm_action == B_FALSE) 16134543Smarks error = dsl_deleg_can_allow(zc->zc_name, fsaclnv, cr); 16144543Smarks else 16154543Smarks error = dsl_deleg_can_unallow(zc->zc_name, fsaclnv, cr); 16164543Smarks } 16174543Smarks 16184543Smarks if (error == 0) 16194543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 16204543Smarks 16214543Smarks nvlist_free(fsaclnv); 16224543Smarks return (error); 16234543Smarks } 16244543Smarks 16254543Smarks static int 16264543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 16274543Smarks { 16284543Smarks nvlist_t *nvp; 16294543Smarks int error; 16304543Smarks 16314543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 16324543Smarks error = put_nvlist(zc, nvp); 16334543Smarks nvlist_free(nvp); 16344543Smarks } 16354543Smarks 16364543Smarks return (error); 16374543Smarks } 16384543Smarks 16394543Smarks static int 1640789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1641789Sahrens { 16422676Seschrock return (zvol_create_minor(zc->zc_name, zc->zc_dev)); 1643789Sahrens } 1644789Sahrens 1645789Sahrens static int 1646789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1647789Sahrens { 16482676Seschrock return (zvol_remove_minor(zc->zc_name)); 1649789Sahrens } 1650789Sahrens 1651789Sahrens /* 1652789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1653789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1654789Sahrens * is responsible for releasing the returned vfs pointer. 1655789Sahrens */ 1656789Sahrens static vfs_t * 1657789Sahrens zfs_get_vfs(const char *resource) 1658789Sahrens { 1659789Sahrens struct vfs *vfsp; 1660789Sahrens struct vfs *vfs_found = NULL; 1661789Sahrens 1662789Sahrens vfs_list_read_lock(); 1663789Sahrens vfsp = rootvfs; 1664789Sahrens do { 1665789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1666789Sahrens VFS_HOLD(vfsp); 1667789Sahrens vfs_found = vfsp; 1668789Sahrens break; 1669789Sahrens } 1670789Sahrens vfsp = vfsp->vfs_next; 1671789Sahrens } while (vfsp != rootvfs); 1672789Sahrens vfs_list_unlock(); 1673789Sahrens return (vfs_found); 1674789Sahrens } 1675789Sahrens 16764543Smarks /* ARGSUSED */ 1677789Sahrens static void 16784543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1679789Sahrens { 16804577Sahrens nvlist_t *nvprops = arg; 16814577Sahrens uint64_t version = ZPL_VERSION; 16824577Sahrens 16834577Sahrens (void) nvlist_lookup_uint64(nvprops, 16844577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version); 16854577Sahrens 16864577Sahrens zfs_create_fs(os, cr, version, tx); 1687789Sahrens } 1688789Sahrens 1689789Sahrens static int 1690789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1691789Sahrens { 1692789Sahrens objset_t *clone; 1693789Sahrens int error = 0; 16944543Smarks nvlist_t *nvprops = NULL; 16954543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1696789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1697789Sahrens 1698789Sahrens switch (type) { 1699789Sahrens 1700789Sahrens case DMU_OST_ZFS: 1701789Sahrens cbfunc = zfs_create_cb; 1702789Sahrens break; 1703789Sahrens 1704789Sahrens case DMU_OST_ZVOL: 1705789Sahrens cbfunc = zvol_create_cb; 1706789Sahrens break; 1707789Sahrens 1708789Sahrens default: 17092199Sahrens cbfunc = NULL; 17102199Sahrens } 17112199Sahrens if (strchr(zc->zc_name, '@')) 1712789Sahrens return (EINVAL); 1713789Sahrens 17142676Seschrock if (zc->zc_nvlist_src != NULL && 17154543Smarks (error = get_nvlist(zc, &nvprops)) != 0) 17162676Seschrock return (error); 17172676Seschrock 17182676Seschrock if (zc->zc_value[0] != '\0') { 1719789Sahrens /* 1720789Sahrens * We're creating a clone of an existing snapshot. 1721789Sahrens */ 17222676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 17232676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 17244543Smarks nvlist_free(nvprops); 1725789Sahrens return (EINVAL); 17262676Seschrock } 1727789Sahrens 17282676Seschrock error = dmu_objset_open(zc->zc_value, type, 1729789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 17302676Seschrock if (error) { 17314543Smarks nvlist_free(nvprops); 1732789Sahrens return (error); 17332676Seschrock } 1734789Sahrens error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); 1735789Sahrens dmu_objset_close(clone); 1736789Sahrens } else { 17372676Seschrock if (cbfunc == NULL) { 17384543Smarks nvlist_free(nvprops); 17392199Sahrens return (EINVAL); 17402676Seschrock } 17412676Seschrock 1742789Sahrens if (type == DMU_OST_ZVOL) { 17432676Seschrock uint64_t volsize, volblocksize; 17442676Seschrock 17454543Smarks if (nvprops == NULL || 17464543Smarks nvlist_lookup_uint64(nvprops, 17472676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 17482676Seschrock &volsize) != 0) { 17494543Smarks nvlist_free(nvprops); 17502676Seschrock return (EINVAL); 17512676Seschrock } 17522676Seschrock 17534543Smarks if ((error = nvlist_lookup_uint64(nvprops, 17542676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 17552676Seschrock &volblocksize)) != 0 && error != ENOENT) { 17564543Smarks nvlist_free(nvprops); 17572676Seschrock return (EINVAL); 17582676Seschrock } 17591133Seschrock 17602676Seschrock if (error != 0) 17612676Seschrock volblocksize = zfs_prop_default_numeric( 17622676Seschrock ZFS_PROP_VOLBLOCKSIZE); 17632676Seschrock 17642676Seschrock if ((error = zvol_check_volblocksize( 17652676Seschrock volblocksize)) != 0 || 17662676Seschrock (error = zvol_check_volsize(volsize, 17672676Seschrock volblocksize)) != 0) { 17684543Smarks nvlist_free(nvprops); 1769789Sahrens return (error); 17702676Seschrock } 17714577Sahrens } else if (type == DMU_OST_ZFS) { 17724577Sahrens uint64_t version; 17734577Sahrens 17744577Sahrens if (0 == nvlist_lookup_uint64(nvprops, 17754577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version) && 17764577Sahrens (version < ZPL_VERSION_INITIAL || 17774577Sahrens version > ZPL_VERSION)) { 17784577Sahrens nvlist_free(nvprops); 17794577Sahrens return (EINVAL); 17804577Sahrens } 17812676Seschrock } 17821133Seschrock 17832676Seschrock error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, 17844543Smarks nvprops); 1785789Sahrens } 17862676Seschrock 17872676Seschrock /* 17882676Seschrock * It would be nice to do this atomically. 17892676Seschrock */ 17902676Seschrock if (error == 0) { 17912676Seschrock if ((error = zfs_set_prop_nvlist(zc->zc_name, 17922676Seschrock zc->zc_dev, (cred_t *)(uintptr_t)zc->zc_cred, 17934543Smarks nvprops)) != 0) 17942676Seschrock (void) dmu_objset_destroy(zc->zc_name); 17952676Seschrock } 17962676Seschrock 17974543Smarks nvlist_free(nvprops); 1798789Sahrens return (error); 1799789Sahrens } 1800789Sahrens 1801789Sahrens static int 18022199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 18032199Sahrens { 18042676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 18052199Sahrens return (EINVAL); 18062199Sahrens return (dmu_objset_snapshot(zc->zc_name, 18072676Seschrock zc->zc_value, zc->zc_cookie)); 18082199Sahrens } 18092199Sahrens 18104007Smmusante int 18112199Sahrens zfs_unmount_snap(char *name, void *arg) 1812789Sahrens { 18132199Sahrens char *snapname = arg; 18142199Sahrens char *cp; 18152417Sahrens vfs_t *vfsp = NULL; 18162199Sahrens 18172199Sahrens /* 18182199Sahrens * Snapshots (which are under .zfs control) must be unmounted 18192199Sahrens * before they can be destroyed. 18202199Sahrens */ 18212199Sahrens 18222199Sahrens if (snapname) { 18232199Sahrens (void) strcat(name, "@"); 18242199Sahrens (void) strcat(name, snapname); 18252199Sahrens vfsp = zfs_get_vfs(name); 18262199Sahrens cp = strchr(name, '@'); 18272199Sahrens *cp = '\0'; 18282417Sahrens } else if (strchr(name, '@')) { 18292199Sahrens vfsp = zfs_get_vfs(name); 18302199Sahrens } 18312199Sahrens 18322199Sahrens if (vfsp) { 18332199Sahrens /* 18342199Sahrens * Always force the unmount for snapshots. 18352199Sahrens */ 18362199Sahrens int flag = MS_FORCE; 1837789Sahrens int err; 1838789Sahrens 18392199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 18402199Sahrens VFS_RELE(vfsp); 18412199Sahrens return (err); 18422199Sahrens } 18432199Sahrens VFS_RELE(vfsp); 18442199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 18452199Sahrens return (err); 18462199Sahrens } 18472199Sahrens return (0); 18482199Sahrens } 18492199Sahrens 18502199Sahrens static int 18512199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 18522199Sahrens { 18532199Sahrens int err; 1854789Sahrens 18552676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 18562199Sahrens return (EINVAL); 18572199Sahrens err = dmu_objset_find(zc->zc_name, 18582676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 18592199Sahrens if (err) 18602199Sahrens return (err); 18612676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 18622199Sahrens } 18632199Sahrens 18642199Sahrens static int 18652199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 18662199Sahrens { 18672199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 18682199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18692199Sahrens if (err) 18702199Sahrens return (err); 1871789Sahrens } 1872789Sahrens 1873789Sahrens return (dmu_objset_destroy(zc->zc_name)); 1874789Sahrens } 1875789Sahrens 1876789Sahrens static int 1877789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 1878789Sahrens { 1879789Sahrens return (dmu_objset_rollback(zc->zc_name)); 1880789Sahrens } 1881789Sahrens 1882789Sahrens static int 1883789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 1884789Sahrens { 18854490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 18864007Smmusante 18872676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 18882676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) 1889789Sahrens return (EINVAL); 1890789Sahrens 18914007Smmusante /* 18924007Smmusante * Unmount snapshot unless we're doing a recursive rename, 18934007Smmusante * in which case the dataset code figures out which snapshots 18944007Smmusante * to unmount. 18954007Smmusante */ 18964007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 1897789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 18982199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18992199Sahrens if (err) 19002199Sahrens return (err); 1901789Sahrens } 1902789Sahrens 19034007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 1904789Sahrens } 1905789Sahrens 1906789Sahrens static int 1907789Sahrens zfs_ioc_recvbackup(zfs_cmd_t *zc) 1908789Sahrens { 1909789Sahrens file_t *fp; 1910789Sahrens int error, fd; 19112885Sahrens offset_t new_off; 1912789Sahrens 19133265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 19143265Sahrens strchr(zc->zc_value, '@') == NULL) 19153265Sahrens return (EINVAL); 19163265Sahrens 1917789Sahrens fd = zc->zc_cookie; 1918789Sahrens fp = getf(fd); 1919789Sahrens if (fp == NULL) 1920789Sahrens return (EBADF); 19212676Seschrock error = dmu_recvbackup(zc->zc_value, &zc->zc_begin_record, 19222676Seschrock &zc->zc_cookie, (boolean_t)zc->zc_guid, fp->f_vnode, 19232665Snd150628 fp->f_offset); 19242885Sahrens 19252885Sahrens new_off = fp->f_offset + zc->zc_cookie; 19262885Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &new_off) == 0) 19272885Sahrens fp->f_offset = new_off; 19282885Sahrens 1929789Sahrens releasef(fd); 1930789Sahrens return (error); 1931789Sahrens } 1932789Sahrens 1933789Sahrens static int 1934789Sahrens zfs_ioc_sendbackup(zfs_cmd_t *zc) 1935789Sahrens { 1936789Sahrens objset_t *fromsnap = NULL; 1937789Sahrens objset_t *tosnap; 1938789Sahrens file_t *fp; 1939789Sahrens int error; 1940789Sahrens 1941789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1942789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); 1943789Sahrens if (error) 1944789Sahrens return (error); 1945789Sahrens 19462676Seschrock if (zc->zc_value[0] != '\0') { 19472885Sahrens char buf[MAXPATHLEN]; 19482885Sahrens char *cp; 19492885Sahrens 19502885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 19512885Sahrens cp = strchr(buf, '@'); 19522885Sahrens if (cp) 19532885Sahrens *(cp+1) = 0; 19542885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 19552885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 1956789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); 1957789Sahrens if (error) { 1958789Sahrens dmu_objset_close(tosnap); 1959789Sahrens return (error); 1960789Sahrens } 1961789Sahrens } 1962789Sahrens 1963789Sahrens fp = getf(zc->zc_cookie); 1964789Sahrens if (fp == NULL) { 1965789Sahrens dmu_objset_close(tosnap); 1966789Sahrens if (fromsnap) 1967789Sahrens dmu_objset_close(fromsnap); 1968789Sahrens return (EBADF); 1969789Sahrens } 1970789Sahrens 1971789Sahrens error = dmu_sendbackup(tosnap, fromsnap, fp->f_vnode); 1972789Sahrens 1973789Sahrens releasef(zc->zc_cookie); 1974789Sahrens if (fromsnap) 1975789Sahrens dmu_objset_close(fromsnap); 1976789Sahrens dmu_objset_close(tosnap); 1977789Sahrens return (error); 1978789Sahrens } 1979789Sahrens 19801544Seschrock static int 19811544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 19821544Seschrock { 19831544Seschrock int id, error; 19841544Seschrock 19851544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 19861544Seschrock &zc->zc_inject_record); 19871544Seschrock 19881544Seschrock if (error == 0) 19891544Seschrock zc->zc_guid = (uint64_t)id; 19901544Seschrock 19911544Seschrock return (error); 19921544Seschrock } 19931544Seschrock 19941544Seschrock static int 19951544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 19961544Seschrock { 19971544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 19981544Seschrock } 19991544Seschrock 20001544Seschrock static int 20011544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 20021544Seschrock { 20031544Seschrock int id = (int)zc->zc_guid; 20041544Seschrock int error; 20051544Seschrock 20061544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 20071544Seschrock &zc->zc_inject_record); 20081544Seschrock 20091544Seschrock zc->zc_guid = id; 20101544Seschrock 20111544Seschrock return (error); 20121544Seschrock } 20131544Seschrock 20141544Seschrock static int 20151544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 20161544Seschrock { 20171544Seschrock spa_t *spa; 20181544Seschrock int error; 20192676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 20201544Seschrock 20211544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 20221544Seschrock return (error); 20231544Seschrock 20242676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 20251544Seschrock &count); 20261544Seschrock if (error == 0) 20272676Seschrock zc->zc_nvlist_dst_size = count; 20281544Seschrock else 20292676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 20301544Seschrock 20311544Seschrock spa_close(spa, FTAG); 20321544Seschrock 20331544Seschrock return (error); 20341544Seschrock } 20351544Seschrock 20361544Seschrock static int 20371544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 20381544Seschrock { 20391544Seschrock spa_t *spa; 20401544Seschrock vdev_t *vd; 20411544Seschrock int error; 20424451Seschrock uint64_t txg; 20431544Seschrock 20441544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 20451544Seschrock return (error); 20461544Seschrock 20474451Seschrock txg = spa_vdev_enter(spa); 20481544Seschrock 20492676Seschrock if (zc->zc_guid == 0) { 20501544Seschrock vd = NULL; 20512676Seschrock } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { 20524451Seschrock (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 20531544Seschrock spa_close(spa, FTAG); 20541544Seschrock return (ENODEV); 20551544Seschrock } 20561544Seschrock 20571544Seschrock vdev_clear(spa, vd); 20581544Seschrock 20594451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 20601544Seschrock 20611544Seschrock spa_close(spa, FTAG); 20621544Seschrock 20631544Seschrock return (0); 20641544Seschrock } 20651544Seschrock 20661544Seschrock static int 20672082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 20682082Seschrock { 20692417Sahrens char *cp; 20702417Sahrens 20712417Sahrens /* 20722417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 20732417Sahrens * it's easier. 20742417Sahrens */ 20752676Seschrock cp = strchr(zc->zc_value, '@'); 20762417Sahrens if (cp) 20772417Sahrens *cp = '\0'; 20782676Seschrock (void) dmu_objset_find(zc->zc_value, 20792417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 20802082Seschrock return (dsl_dataset_promote(zc->zc_name)); 20812082Seschrock } 20822082Seschrock 20834543Smarks /* 20844543Smarks * We don't want to have a hard dependency 20854543Smarks * against some special symbols in sharefs 20864543Smarks * and nfs. Determine them if needed when 20874543Smarks * the first file system is shared. 20884543Smarks * Neither sharefs or nfs are unloadable modules. 20894543Smarks */ 20904543Smarks int (*zexport_fs)(void *arg); 20914543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 20924543Smarks 20934543Smarks int zfs_share_inited; 20944543Smarks ddi_modhandle_t nfs_mod; 20954543Smarks ddi_modhandle_t sharefs_mod; 20964543Smarks kmutex_t zfs_share_lock; 20974543Smarks 20984543Smarks static int 20994543Smarks zfs_ioc_share(zfs_cmd_t *zc) 21004543Smarks { 21014543Smarks int error; 21024543Smarks int opcode; 21034543Smarks 21044543Smarks if (zfs_share_inited == 0) { 21054543Smarks mutex_enter(&zfs_share_lock); 21064543Smarks nfs_mod = ddi_modopen("fs/nfs", KRTLD_MODE_FIRST, &error); 21074543Smarks sharefs_mod = ddi_modopen("fs/sharefs", 21084543Smarks KRTLD_MODE_FIRST, &error); 21094543Smarks if (nfs_mod == NULL || sharefs_mod == NULL) { 21104543Smarks mutex_exit(&zfs_share_lock); 21114543Smarks return (ENOSYS); 21124543Smarks } 21134543Smarks if (zexport_fs == NULL && ((zexport_fs = (int (*)(void *)) 21144543Smarks ddi_modsym(nfs_mod, "nfs_export", &error)) == NULL)) { 21154543Smarks mutex_exit(&zfs_share_lock); 21164543Smarks return (ENOSYS); 21174543Smarks } 21184543Smarks 21194543Smarks if (zshare_fs == NULL && ((zshare_fs = 21204543Smarks (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 21214543Smarks ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 21224543Smarks mutex_exit(&zfs_share_lock); 21234543Smarks return (ENOSYS); 21244543Smarks } 21254543Smarks zfs_share_inited = 1; 21264543Smarks mutex_exit(&zfs_share_lock); 21274543Smarks } 21284543Smarks 21294543Smarks if (error = zexport_fs((void *)(uintptr_t)zc->zc_share.z_exportdata)) 21304543Smarks return (error); 21314543Smarks 21324543Smarks opcode = (zc->zc_share.z_sharetype == B_TRUE) ? 21334543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 21344543Smarks 21354543Smarks error = zshare_fs(opcode, 21364543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 21374543Smarks zc->zc_share.z_sharemax); 21384543Smarks 21394543Smarks return (error); 21404543Smarks 21414543Smarks } 21424543Smarks 21434543Smarks /* 21444543Smarks * pool destroy and pool export don't log the history as part of zfsdev_ioctl, 21454543Smarks * but rather zfs_ioc_pool_create, and zfs_ioc_pool_export do the loggin 21464543Smarks * of those commands. 21474543Smarks */ 2148789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 21494577Sahrens { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21504577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21514577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21524577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21534577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 21544577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 21554577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21564577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21574577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21584577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21594577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21604577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21614577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21624577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21634577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21644577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21654577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21664577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 21674543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 21684577Sahrens DATASET_NAME, B_FALSE }, 21694543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 21704577Sahrens DATASET_NAME, B_FALSE }, 21714577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 21724577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 21734577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 21744577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 21754577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 21764577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 21774577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 21784577Sahrens { zfs_ioc_recvbackup, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 21794577Sahrens { zfs_ioc_sendbackup, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 21804577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21814577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21824577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21834577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 21844577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21854577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 21864577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 21874577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 21884577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21894577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21904577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21914577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 21924577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 21934577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 21944543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 21954577Sahrens DATASET_NAME, B_FALSE }, 21964577Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE } 2197789Sahrens }; 2198789Sahrens 2199789Sahrens static int 2200789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2201789Sahrens { 2202789Sahrens zfs_cmd_t *zc; 2203789Sahrens uint_t vec; 22042199Sahrens int error, rc; 2205789Sahrens 2206789Sahrens if (getminor(dev) != 0) 2207789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2208789Sahrens 2209789Sahrens vec = cmd - ZFS_IOC; 2210789Sahrens 2211789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2212789Sahrens return (EINVAL); 2213789Sahrens 2214789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2215789Sahrens 2216789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2217789Sahrens 2218789Sahrens if (error == 0) { 2219789Sahrens zc->zc_cred = (uintptr_t)cr; 2220789Sahrens zc->zc_dev = dev; 22214543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2222789Sahrens } 2223789Sahrens 2224789Sahrens /* 2225789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2226789Sahrens * the lower layers. 2227789Sahrens */ 2228789Sahrens if (error == 0) { 2229789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2230789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 22314577Sahrens case POOL_NAME: 2232789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2233789Sahrens error = EINVAL; 2234789Sahrens break; 2235789Sahrens 22364577Sahrens case DATASET_NAME: 2237789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2238789Sahrens error = EINVAL; 2239789Sahrens break; 22402856Snd150628 22414577Sahrens case NO_NAME: 22422856Snd150628 break; 2243789Sahrens } 2244789Sahrens } 2245789Sahrens 2246789Sahrens if (error == 0) 2247789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2248789Sahrens 22492199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 22504543Smarks if (error == 0) { 22512199Sahrens error = rc; 22524543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 22534543Smarks zfs_log_history(zc); 22544543Smarks } 2255789Sahrens 2256789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2257789Sahrens return (error); 2258789Sahrens } 2259789Sahrens 2260789Sahrens static int 2261789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2262789Sahrens { 2263789Sahrens if (cmd != DDI_ATTACH) 2264789Sahrens return (DDI_FAILURE); 2265789Sahrens 2266789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2267789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2268789Sahrens return (DDI_FAILURE); 2269789Sahrens 2270789Sahrens zfs_dip = dip; 2271789Sahrens 2272789Sahrens ddi_report_dev(dip); 2273789Sahrens 2274789Sahrens return (DDI_SUCCESS); 2275789Sahrens } 2276789Sahrens 2277789Sahrens static int 2278789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2279789Sahrens { 2280789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2281789Sahrens return (DDI_FAILURE); 2282789Sahrens 2283789Sahrens if (cmd != DDI_DETACH) 2284789Sahrens return (DDI_FAILURE); 2285789Sahrens 2286789Sahrens zfs_dip = NULL; 2287789Sahrens 2288789Sahrens ddi_prop_remove_all(dip); 2289789Sahrens ddi_remove_minor_node(dip, NULL); 2290789Sahrens 2291789Sahrens return (DDI_SUCCESS); 2292789Sahrens } 2293789Sahrens 2294789Sahrens /*ARGSUSED*/ 2295789Sahrens static int 2296789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2297789Sahrens { 2298789Sahrens switch (infocmd) { 2299789Sahrens case DDI_INFO_DEVT2DEVINFO: 2300789Sahrens *result = zfs_dip; 2301789Sahrens return (DDI_SUCCESS); 2302789Sahrens 2303789Sahrens case DDI_INFO_DEVT2INSTANCE: 2304849Sbonwick *result = (void *)0; 2305789Sahrens return (DDI_SUCCESS); 2306789Sahrens } 2307789Sahrens 2308789Sahrens return (DDI_FAILURE); 2309789Sahrens } 2310789Sahrens 2311789Sahrens /* 2312789Sahrens * OK, so this is a little weird. 2313789Sahrens * 2314789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2315789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2316789Sahrens * 2317789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2318789Sahrens * so most of the standard driver entry points are in zvol.c. 2319789Sahrens */ 2320789Sahrens static struct cb_ops zfs_cb_ops = { 2321789Sahrens zvol_open, /* open */ 2322789Sahrens zvol_close, /* close */ 2323789Sahrens zvol_strategy, /* strategy */ 2324789Sahrens nodev, /* print */ 2325789Sahrens nodev, /* dump */ 2326789Sahrens zvol_read, /* read */ 2327789Sahrens zvol_write, /* write */ 2328789Sahrens zfsdev_ioctl, /* ioctl */ 2329789Sahrens nodev, /* devmap */ 2330789Sahrens nodev, /* mmap */ 2331789Sahrens nodev, /* segmap */ 2332789Sahrens nochpoll, /* poll */ 2333789Sahrens ddi_prop_op, /* prop_op */ 2334789Sahrens NULL, /* streamtab */ 2335789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2336789Sahrens CB_REV, /* version */ 23373638Sbillm nodev, /* async read */ 23383638Sbillm nodev, /* async write */ 2339789Sahrens }; 2340789Sahrens 2341789Sahrens static struct dev_ops zfs_dev_ops = { 2342789Sahrens DEVO_REV, /* version */ 2343789Sahrens 0, /* refcnt */ 2344789Sahrens zfs_info, /* info */ 2345789Sahrens nulldev, /* identify */ 2346789Sahrens nulldev, /* probe */ 2347789Sahrens zfs_attach, /* attach */ 2348789Sahrens zfs_detach, /* detach */ 2349789Sahrens nodev, /* reset */ 2350789Sahrens &zfs_cb_ops, /* driver operations */ 2351789Sahrens NULL /* no bus operations */ 2352789Sahrens }; 2353789Sahrens 2354789Sahrens static struct modldrv zfs_modldrv = { 23554577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 23562676Seschrock &zfs_dev_ops 2357789Sahrens }; 2358789Sahrens 2359789Sahrens static struct modlinkage modlinkage = { 2360789Sahrens MODREV_1, 2361789Sahrens (void *)&zfs_modlfs, 2362789Sahrens (void *)&zfs_modldrv, 2363789Sahrens NULL 2364789Sahrens }; 2365789Sahrens 2366789Sahrens int 2367789Sahrens _init(void) 2368789Sahrens { 2369789Sahrens int error; 2370789Sahrens 2371849Sbonwick spa_init(FREAD | FWRITE); 2372849Sbonwick zfs_init(); 2373849Sbonwick zvol_init(); 2374849Sbonwick 2375849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 2376849Sbonwick zvol_fini(); 2377849Sbonwick zfs_fini(); 2378849Sbonwick spa_fini(); 2379789Sahrens return (error); 2380849Sbonwick } 2381789Sahrens 2382789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 2383789Sahrens ASSERT(error == 0); 23844543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 2385789Sahrens 2386789Sahrens return (0); 2387789Sahrens } 2388789Sahrens 2389789Sahrens int 2390789Sahrens _fini(void) 2391789Sahrens { 2392789Sahrens int error; 2393789Sahrens 23941544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 2395789Sahrens return (EBUSY); 2396789Sahrens 2397789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 2398789Sahrens return (error); 2399789Sahrens 2400789Sahrens zvol_fini(); 2401789Sahrens zfs_fini(); 2402789Sahrens spa_fini(); 24034543Smarks if (zfs_share_inited) { 24044543Smarks (void) ddi_modclose(nfs_mod); 24054543Smarks (void) ddi_modclose(sharefs_mod); 24064543Smarks } 2407789Sahrens 2408789Sahrens ldi_ident_release(zfs_li); 2409789Sahrens zfs_li = NULL; 24104543Smarks mutex_destroy(&zfs_share_lock); 2411789Sahrens 2412789Sahrens return (error); 2413789Sahrens } 2414789Sahrens 2415789Sahrens int 2416789Sahrens _info(struct modinfo *modinfop) 2417789Sahrens { 2418789Sahrens return (mod_info(&modlinkage, modinfop)); 2419789Sahrens } 2420