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 283*4787Sahrens return (zfs_secpolicy_write_perms(name, zfs_prop_to_name(prop), cr)); 284789Sahrens } 285789Sahrens 2864543Smarks int 2874543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) 2884543Smarks { 2894543Smarks int error; 2904543Smarks 2914543Smarks error = zfs_dozonecheck(zc->zc_name, cr); 2924543Smarks if (error) 2934543Smarks return (error); 2944543Smarks 2954543Smarks /* 2964543Smarks * permission to set permissions will be evaluated later in 2974543Smarks * dsl_deleg_can_allow() 2984543Smarks */ 2994543Smarks return (0); 3004543Smarks } 3014543Smarks 3024543Smarks int 3034543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) 3044543Smarks { 3054543Smarks int error; 3064543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3074543Smarks ZFS_DELEG_PERM_ROLLBACK, cr); 3084543Smarks if (error == 0) 3094543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3104543Smarks ZFS_DELEG_PERM_MOUNT, cr); 3114543Smarks return (error); 3124543Smarks } 3134543Smarks 3144543Smarks int 3154543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) 3164543Smarks { 3174543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 3184543Smarks ZFS_DELEG_PERM_SEND, cr)); 3194543Smarks } 3204543Smarks 3214543Smarks int 3224543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) 3234543Smarks { 3244543Smarks if (!INGLOBALZONE(curproc)) 3254543Smarks return (EPERM); 3264543Smarks 3274543Smarks if (secpolicy_nfs(CRED()) == 0) { 3284543Smarks return (0); 3294543Smarks } else { 3304543Smarks vnode_t *vp; 3314543Smarks int error; 3324543Smarks 3334543Smarks if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, 3344543Smarks NO_FOLLOW, NULL, &vp)) != 0) 3354543Smarks return (error); 3364543Smarks 3374543Smarks /* Now make sure mntpnt and dataset are ZFS */ 3384543Smarks 3394543Smarks if (vp->v_vfsp->vfs_fstype != zfsfstype || 3404543Smarks (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), 3414543Smarks zc->zc_name) != 0)) { 3424543Smarks VN_RELE(vp); 3434543Smarks return (EPERM); 3444543Smarks } 3454543Smarks 3464543Smarks VN_RELE(vp); 3474543Smarks return (dsl_deleg_access(zc->zc_name, 3484543Smarks ZFS_DELEG_PERM_SHARE, cr)); 3494543Smarks } 3504543Smarks } 3514543Smarks 352789Sahrens static int 3534543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize) 354789Sahrens { 355789Sahrens char *cp; 356789Sahrens 357789Sahrens /* 358789Sahrens * Remove the @bla or /bla from the end of the name to get the parent. 359789Sahrens */ 3604543Smarks (void) strncpy(parent, datasetname, parentsize); 3614543Smarks cp = strrchr(parent, '@'); 362789Sahrens if (cp != NULL) { 363789Sahrens cp[0] = '\0'; 364789Sahrens } else { 3654543Smarks cp = strrchr(parent, '/'); 366789Sahrens if (cp == NULL) 367789Sahrens return (ENOENT); 368789Sahrens cp[0] = '\0'; 369789Sahrens } 370789Sahrens 3714543Smarks return (0); 3724543Smarks } 3734543Smarks 3744543Smarks int 3754543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 3764543Smarks { 3774543Smarks int error; 3784543Smarks 3794543Smarks if ((error = zfs_secpolicy_write_perms(name, 3804543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 3814543Smarks return (error); 3824543Smarks 3834543Smarks return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); 3844543Smarks } 3854543Smarks 3864543Smarks static int 3874543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) 3884543Smarks { 3894543Smarks return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); 3904543Smarks } 3914543Smarks 3924543Smarks /* 3934543Smarks * Must have sys_config privilege to check the iscsi permission 3944543Smarks */ 3954543Smarks /* ARGSUSED */ 3964543Smarks static int 3974543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) 3984543Smarks { 3994543Smarks return (secpolicy_zfs(cr)); 4004543Smarks } 4014543Smarks 4024543Smarks int 4034543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 4044543Smarks { 4054543Smarks char parentname[MAXNAMELEN]; 4064543Smarks int error; 4074543Smarks 4084543Smarks if ((error = zfs_secpolicy_write_perms(from, 4094543Smarks ZFS_DELEG_PERM_RENAME, cr)) != 0) 4104543Smarks return (error); 4114543Smarks 4124543Smarks if ((error = zfs_secpolicy_write_perms(from, 4134543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4144543Smarks return (error); 4154543Smarks 4164543Smarks if ((error = zfs_get_parent(to, parentname, 4174543Smarks sizeof (parentname))) != 0) 4184543Smarks return (error); 4194543Smarks 4204543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4214543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 4224543Smarks return (error); 4234543Smarks 4244543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4254543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4264543Smarks return (error); 4274543Smarks 4284543Smarks return (error); 4294543Smarks } 4304543Smarks 4314543Smarks static int 4324543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) 4334543Smarks { 4344543Smarks return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); 4354543Smarks } 4364543Smarks 4374543Smarks static int 4384543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) 4394543Smarks { 4404543Smarks char parentname[MAXNAMELEN]; 4414543Smarks objset_t *clone; 4424543Smarks int error; 4434543Smarks 4444543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4454543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4464543Smarks if (error) 4474543Smarks return (error); 4484543Smarks 4494543Smarks error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 4504543Smarks DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 4514543Smarks 4524543Smarks if (error == 0) { 4534543Smarks dsl_dataset_t *pclone = NULL; 4544543Smarks dsl_dir_t *dd; 4554543Smarks dd = clone->os->os_dsl_dataset->ds_dir; 4564543Smarks 4574543Smarks rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 4584543Smarks error = dsl_dataset_open_obj(dd->dd_pool, 4594543Smarks dd->dd_phys->dd_clone_parent_obj, NULL, 4604543Smarks DS_MODE_NONE, FTAG, &pclone); 4614543Smarks rw_exit(&dd->dd_pool->dp_config_rwlock); 4624543Smarks if (error) { 4634543Smarks dmu_objset_close(clone); 4644543Smarks return (error); 4654543Smarks } 4664543Smarks 4674543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4684543Smarks ZFS_DELEG_PERM_MOUNT, cr); 4694543Smarks 4704543Smarks dsl_dataset_name(pclone, parentname); 4714543Smarks dmu_objset_close(clone); 4724543Smarks dsl_dataset_close(pclone, DS_MODE_NONE, FTAG); 4734543Smarks if (error == 0) 4744543Smarks error = zfs_secpolicy_write_perms(parentname, 4754543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4764543Smarks } 4774543Smarks return (error); 4784543Smarks } 4794543Smarks 4804543Smarks static int 4814543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) 4824543Smarks { 4834543Smarks int error; 4844543Smarks 4854543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 4864543Smarks ZFS_DELEG_PERM_RECEIVE, cr)) != 0) 4874543Smarks return (error); 4884543Smarks 4894543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 4904543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4914543Smarks return (error); 4924543Smarks 4934543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 4944543Smarks ZFS_DELEG_PERM_CREATE, cr)); 4954543Smarks } 4964543Smarks 4974543Smarks int 4984543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 4994543Smarks { 5004543Smarks int error; 5014543Smarks 5024543Smarks if ((error = zfs_secpolicy_write_perms(name, 5034543Smarks ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) 5044543Smarks return (error); 5054543Smarks 5064543Smarks error = zfs_secpolicy_write_perms(name, 5074543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5084543Smarks 5094543Smarks return (error); 5104543Smarks } 5114543Smarks 5124543Smarks static int 5134543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) 5144543Smarks { 5154543Smarks 5164543Smarks return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); 5174543Smarks } 5184543Smarks 5194543Smarks static int 5204543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) 5214543Smarks { 5224543Smarks char parentname[MAXNAMELEN]; 5234543Smarks int error; 5244543Smarks 5254543Smarks if ((error = zfs_get_parent(zc->zc_name, parentname, 5264543Smarks sizeof (parentname))) != 0) 5274543Smarks return (error); 5284543Smarks 5294543Smarks if (zc->zc_value[0] != '\0') { 5304543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_value, 5314543Smarks ZFS_DELEG_PERM_CLONE, cr)) != 0) 5324543Smarks return (error); 5334543Smarks } 5344543Smarks 5354543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 5364543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 5374543Smarks return (error); 5384543Smarks 5394543Smarks error = zfs_secpolicy_write_perms(parentname, 5404543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5414543Smarks 5424543Smarks return (error); 5434543Smarks } 5444543Smarks 5454543Smarks static int 5464543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) 5474543Smarks { 5484543Smarks int error; 5494543Smarks 5504543Smarks error = secpolicy_fs_unmount(cr, NULL); 5514543Smarks if (error) { 5524543Smarks error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); 5534543Smarks } 5544543Smarks return (error); 555789Sahrens } 556789Sahrens 557789Sahrens /* 558789Sahrens * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires 559789Sahrens * SYS_CONFIG privilege, which is not available in a local zone. 560789Sahrens */ 561789Sahrens /* ARGSUSED */ 562789Sahrens static int 5634543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) 564789Sahrens { 565789Sahrens if (secpolicy_sys_config(cr, B_FALSE) != 0) 566789Sahrens return (EPERM); 567789Sahrens 568789Sahrens return (0); 569789Sahrens } 570789Sahrens 571789Sahrens /* 5724543Smarks * Just like zfs_secpolicy_config, except that we will check for 5734543Smarks * mount permission on the dataset for permission to create/remove 5744543Smarks * the minor nodes. 5754543Smarks */ 5764543Smarks static int 5774543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) 5784543Smarks { 5794543Smarks if (secpolicy_sys_config(cr, B_FALSE) != 0) { 5804543Smarks return (dsl_deleg_access(zc->zc_name, 5814543Smarks ZFS_DELEG_PERM_MOUNT, cr)); 5824543Smarks } 5834543Smarks 5844543Smarks return (0); 5854543Smarks } 5864543Smarks 5874543Smarks /* 5881544Seschrock * Policy for fault injection. Requires all privileges. 5891544Seschrock */ 5901544Seschrock /* ARGSUSED */ 5911544Seschrock static int 5924543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) 5931544Seschrock { 5941544Seschrock return (secpolicy_zinject(cr)); 5951544Seschrock } 5961544Seschrock 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 1178*4787Sahrens zfs_set_prop_nvlist(const char *name, 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, 1203*4787Sahrens ZFS_DELEG_PERM_USERPROP, CRED()); 12044670Sahrens if (error) 12054670Sahrens return (error); 12064543Smarks continue; 12072676Seschrock } 12082676Seschrock 1209*4787Sahrens if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 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 || 1288*4787Sahrens (error = zvol_set_volsize(name, 1289*4787Sahrens ddi_driver_major(zfs_dip), intval)) != 0) 12902676Seschrock return (error); 12912676Seschrock break; 12922676Seschrock 12932676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 12942676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 12954577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 12964577Sahrens return (error); 12974577Sahrens break; 12984577Sahrens 12994577Sahrens case ZFS_PROP_VERSION: 13004577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13014577Sahrens (error = zfs_set_version(name, intval)) != 0) 13022676Seschrock return (error); 13032676Seschrock break; 13042676Seschrock 13052676Seschrock default: 13062676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 13072676Seschrock if (zfs_prop_get_type(prop) != 1308*4787Sahrens PROP_TYPE_STRING) 13092676Seschrock return (EINVAL); 13102717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 13112717Seschrock if ((error = dsl_prop_set(name, 13122676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 13132717Seschrock strval)) != 0) 13142717Seschrock return (error); 13152676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 13162885Sahrens const char *unused; 13172885Sahrens 13182717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 13192676Seschrock 13202676Seschrock switch (zfs_prop_get_type(prop)) { 1321*4787Sahrens case PROP_TYPE_NUMBER: 13222676Seschrock break; 1323*4787Sahrens case PROP_TYPE_BOOLEAN: 13242676Seschrock if (intval > 1) 13252717Seschrock return (EINVAL); 13262676Seschrock break; 1327*4787Sahrens case PROP_TYPE_STRING: 13282717Seschrock return (EINVAL); 1329*4787Sahrens case PROP_TYPE_INDEX: 13302717Seschrock if (zfs_prop_index_to_string(prop, 13312717Seschrock intval, &unused) != 0) 13322717Seschrock return (EINVAL); 13332676Seschrock break; 13342676Seschrock default: 13354577Sahrens cmn_err(CE_PANIC, 13364577Sahrens "unknown property type"); 13372676Seschrock break; 13382676Seschrock } 13392676Seschrock 13402717Seschrock if ((error = dsl_prop_set(name, propname, 13412717Seschrock 8, 1, &intval)) != 0) 13422717Seschrock return (error); 13432676Seschrock } else { 13442676Seschrock return (EINVAL); 13452676Seschrock } 13462676Seschrock break; 13472676Seschrock } 13482676Seschrock } 13492676Seschrock 13502676Seschrock return (0); 1351789Sahrens } 1352789Sahrens 1353789Sahrens static int 13542676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1355789Sahrens { 13562676Seschrock nvlist_t *nvl; 13572676Seschrock int error; 1358789Sahrens 13592676Seschrock /* 13602676Seschrock * If zc_value is set, then this is an attempt to inherit a value. 13612676Seschrock * Otherwise, zc_nvlist refers to a list of properties to set. 13622676Seschrock */ 13632676Seschrock if (zc->zc_value[0] != '\0') { 13644670Sahrens zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); 13654670Sahrens 13664670Sahrens if (prop == ZFS_PROP_INVAL) { 13674670Sahrens if (!zfs_prop_user(zc->zc_value)) 13684670Sahrens return (EINVAL); 13694670Sahrens error = zfs_secpolicy_write_perms(zc->zc_name, 1370*4787Sahrens ZFS_DELEG_PERM_USERPROP, CRED()); 13714670Sahrens } else { 13724670Sahrens if (!zfs_prop_inheritable(prop)) 13734670Sahrens return (EINVAL); 13744670Sahrens error = zfs_secpolicy_setprop(zc->zc_name, 1375*4787Sahrens prop, 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 1386*4787Sahrens error = zfs_set_prop_nvlist(zc->zc_name, nvl); 13874543Smarks 13882676Seschrock nvlist_free(nvl); 13892676Seschrock return (error); 1390789Sahrens } 1391789Sahrens 1392789Sahrens static int 13934098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 13943912Slling { 13953912Slling nvlist_t *nvl; 13963912Slling int error, reset_bootfs = 0; 13973912Slling uint64_t objnum; 13984543Smarks uint64_t intval; 13993912Slling zpool_prop_t prop; 14003912Slling nvpair_t *elem; 14013912Slling char *propname, *strval; 14023912Slling spa_t *spa; 14033912Slling vdev_t *rvdev; 14043912Slling char *vdev_type; 14053912Slling objset_t *os; 14063912Slling 14073912Slling if ((error = get_nvlist(zc, &nvl)) != 0) 14083912Slling return (error); 14093912Slling 14103912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 14113912Slling nvlist_free(nvl); 14123912Slling return (error); 14133912Slling } 14143912Slling 14154577Sahrens if (spa_version(spa) < SPA_VERSION_BOOTFS) { 14163912Slling nvlist_free(nvl); 14173912Slling spa_close(spa, FTAG); 14183912Slling return (ENOTSUP); 14193912Slling } 14203912Slling 14213912Slling elem = NULL; 14223912Slling while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 14233912Slling 14243912Slling propname = nvpair_name(elem); 14253912Slling 14263912Slling if ((prop = zpool_name_to_prop(propname)) == 14273912Slling ZFS_PROP_INVAL) { 14283912Slling nvlist_free(nvl); 14293912Slling spa_close(spa, FTAG); 14303912Slling return (EINVAL); 14313912Slling } 14323912Slling 14333912Slling switch (prop) { 14344543Smarks case ZPOOL_PROP_DELEGATION: 14354543Smarks VERIFY(nvpair_value_uint64(elem, &intval) == 0); 14364543Smarks if (intval > 1) 14374543Smarks error = EINVAL; 14384543Smarks break; 14394451Seschrock case ZPOOL_PROP_BOOTFS: 14403912Slling /* 14413912Slling * A bootable filesystem can not be on a RAIDZ pool 14423912Slling * nor a striped pool with more than 1 device. 14433912Slling */ 14443912Slling rvdev = spa->spa_root_vdev; 14453912Slling vdev_type = 14463912Slling rvdev->vdev_child[0]->vdev_ops->vdev_op_type; 14473912Slling if (strcmp(vdev_type, VDEV_TYPE_RAIDZ) == 0 || 14483912Slling (strcmp(vdev_type, VDEV_TYPE_MIRROR) != 0 && 14493912Slling rvdev->vdev_children > 1)) { 14503912Slling error = ENOTSUP; 14513912Slling break; 14523912Slling } 14533912Slling 14543912Slling reset_bootfs = 1; 14553912Slling 14563912Slling VERIFY(nvpair_value_string(elem, &strval) == 0); 14573912Slling if (strval == NULL || strval[0] == '\0') { 14584451Seschrock objnum = zpool_prop_default_numeric( 14594451Seschrock ZPOOL_PROP_BOOTFS); 14603912Slling break; 14613912Slling } 14623912Slling 14633912Slling if (error = dmu_objset_open(strval, DMU_OST_ZFS, 14643912Slling DS_MODE_STANDARD | DS_MODE_READONLY, &os)) 14653912Slling break; 14663912Slling objnum = dmu_objset_id(os); 14673912Slling dmu_objset_close(os); 14683912Slling break; 14693912Slling } 14703912Slling 14713912Slling if (error) 14723912Slling break; 14733912Slling } 14743912Slling if (error == 0) { 14753912Slling if (reset_bootfs) { 14763912Slling VERIFY(nvlist_remove(nvl, 14774451Seschrock zpool_prop_to_name(ZPOOL_PROP_BOOTFS), 14783912Slling DATA_TYPE_STRING) == 0); 14793912Slling VERIFY(nvlist_add_uint64(nvl, 14804451Seschrock zpool_prop_to_name(ZPOOL_PROP_BOOTFS), 14814451Seschrock objnum) == 0); 14823912Slling } 14833912Slling error = spa_set_props(spa, nvl); 14843912Slling } 14853912Slling 14863912Slling nvlist_free(nvl); 14873912Slling spa_close(spa, FTAG); 14883912Slling 14893912Slling return (error); 14903912Slling } 14913912Slling 14923912Slling static int 14934098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 14943912Slling { 14953912Slling spa_t *spa; 14963912Slling int error; 14973912Slling nvlist_t *nvp = NULL; 14983912Slling 14993912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 15003912Slling return (error); 15013912Slling 15023912Slling error = spa_get_props(spa, &nvp); 15033912Slling 15043912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 15053912Slling error = put_nvlist(zc, nvp); 15063912Slling else 15073912Slling error = EFAULT; 15083912Slling 15093912Slling spa_close(spa, FTAG); 15103912Slling 15113912Slling if (nvp) 15123912Slling nvlist_free(nvp); 15133912Slling return (error); 15143912Slling } 15153912Slling 15163912Slling static int 15174543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 15184543Smarks { 15194543Smarks nvlist_t *nvp; 15204543Smarks int error; 15214543Smarks uint32_t uid; 15224543Smarks uint32_t gid; 15234543Smarks uint32_t *groups; 15244543Smarks uint_t group_cnt; 15254543Smarks cred_t *usercred; 15264543Smarks 15274543Smarks if ((error = get_nvlist(zc, &nvp)) != 0) { 15284543Smarks return (error); 15294543Smarks } 15304543Smarks 15314543Smarks if ((error = nvlist_lookup_uint32(nvp, 15324543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 15334543Smarks nvlist_free(nvp); 15344543Smarks return (EPERM); 15354543Smarks } 15364543Smarks 15374543Smarks if ((error = nvlist_lookup_uint32(nvp, 15384543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 15394543Smarks nvlist_free(nvp); 15404543Smarks return (EPERM); 15414543Smarks } 15424543Smarks 15434543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 15444543Smarks &groups, &group_cnt)) != 0) { 15454543Smarks nvlist_free(nvp); 15464543Smarks return (EPERM); 15474543Smarks } 15484543Smarks usercred = cralloc(); 15494543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 15504543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 15514543Smarks nvlist_free(nvp); 15524543Smarks crfree(usercred); 15534543Smarks return (EPERM); 15544543Smarks } 15554543Smarks nvlist_free(nvp); 15564543Smarks error = dsl_deleg_access(zc->zc_name, 1557*4787Sahrens zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); 15584543Smarks crfree(usercred); 15594543Smarks return (error); 15604543Smarks } 15614543Smarks 15624543Smarks static int 15634543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 15644543Smarks { 15654543Smarks int error; 15664543Smarks nvlist_t *fsaclnv = NULL; 15674543Smarks 15684543Smarks if ((error = get_nvlist(zc, &fsaclnv)) != 0) 15694543Smarks return (error); 15704543Smarks 15714543Smarks /* 15724543Smarks * Verify nvlist is constructed correctly 15734543Smarks */ 15744543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 15754543Smarks nvlist_free(fsaclnv); 15764543Smarks return (EINVAL); 15774543Smarks } 15784543Smarks 15794543Smarks /* 15804543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 15814543Smarks * that user is allowed to hand out each permission in 15824543Smarks * the nvlist(s) 15834543Smarks */ 15844543Smarks 1585*4787Sahrens error = secpolicy_zfs(CRED()); 15864543Smarks if (error) { 1587*4787Sahrens if (zc->zc_perm_action == B_FALSE) { 1588*4787Sahrens error = dsl_deleg_can_allow(zc->zc_name, 1589*4787Sahrens fsaclnv, CRED()); 1590*4787Sahrens } else { 1591*4787Sahrens error = dsl_deleg_can_unallow(zc->zc_name, 1592*4787Sahrens fsaclnv, CRED()); 1593*4787Sahrens } 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 { 1620*4787Sahrens return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); 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) { 1769*4787Sahrens if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) 17702676Seschrock (void) dmu_objset_destroy(zc->zc_name); 17712676Seschrock } 17722676Seschrock 17734543Smarks nvlist_free(nvprops); 1774789Sahrens return (error); 1775789Sahrens } 1776789Sahrens 1777789Sahrens static int 17782199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 17792199Sahrens { 17802676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 17812199Sahrens return (EINVAL); 17822199Sahrens return (dmu_objset_snapshot(zc->zc_name, 17832676Seschrock zc->zc_value, zc->zc_cookie)); 17842199Sahrens } 17852199Sahrens 17864007Smmusante int 17872199Sahrens zfs_unmount_snap(char *name, void *arg) 1788789Sahrens { 17892199Sahrens char *snapname = arg; 17902199Sahrens char *cp; 17912417Sahrens vfs_t *vfsp = NULL; 17922199Sahrens 17932199Sahrens /* 17942199Sahrens * Snapshots (which are under .zfs control) must be unmounted 17952199Sahrens * before they can be destroyed. 17962199Sahrens */ 17972199Sahrens 17982199Sahrens if (snapname) { 17992199Sahrens (void) strcat(name, "@"); 18002199Sahrens (void) strcat(name, snapname); 18012199Sahrens vfsp = zfs_get_vfs(name); 18022199Sahrens cp = strchr(name, '@'); 18032199Sahrens *cp = '\0'; 18042417Sahrens } else if (strchr(name, '@')) { 18052199Sahrens vfsp = zfs_get_vfs(name); 18062199Sahrens } 18072199Sahrens 18082199Sahrens if (vfsp) { 18092199Sahrens /* 18102199Sahrens * Always force the unmount for snapshots. 18112199Sahrens */ 18122199Sahrens int flag = MS_FORCE; 1813789Sahrens int err; 1814789Sahrens 18152199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 18162199Sahrens VFS_RELE(vfsp); 18172199Sahrens return (err); 18182199Sahrens } 18192199Sahrens VFS_RELE(vfsp); 18202199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 18212199Sahrens return (err); 18222199Sahrens } 18232199Sahrens return (0); 18242199Sahrens } 18252199Sahrens 18262199Sahrens static int 18272199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 18282199Sahrens { 18292199Sahrens int err; 1830789Sahrens 18312676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 18322199Sahrens return (EINVAL); 18332199Sahrens err = dmu_objset_find(zc->zc_name, 18342676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 18352199Sahrens if (err) 18362199Sahrens return (err); 18372676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 18382199Sahrens } 18392199Sahrens 18402199Sahrens static int 18412199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 18422199Sahrens { 18432199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 18442199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18452199Sahrens if (err) 18462199Sahrens return (err); 1847789Sahrens } 1848789Sahrens 1849789Sahrens return (dmu_objset_destroy(zc->zc_name)); 1850789Sahrens } 1851789Sahrens 1852789Sahrens static int 1853789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 1854789Sahrens { 1855789Sahrens return (dmu_objset_rollback(zc->zc_name)); 1856789Sahrens } 1857789Sahrens 1858789Sahrens static int 1859789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 1860789Sahrens { 18614490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 18624007Smmusante 18632676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 18642676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) 1865789Sahrens return (EINVAL); 1866789Sahrens 18674007Smmusante /* 18684007Smmusante * Unmount snapshot unless we're doing a recursive rename, 18694007Smmusante * in which case the dataset code figures out which snapshots 18704007Smmusante * to unmount. 18714007Smmusante */ 18724007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 1873789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 18742199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18752199Sahrens if (err) 18762199Sahrens return (err); 1877789Sahrens } 1878789Sahrens 18794007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 1880789Sahrens } 1881789Sahrens 1882789Sahrens static int 1883789Sahrens zfs_ioc_recvbackup(zfs_cmd_t *zc) 1884789Sahrens { 1885789Sahrens file_t *fp; 1886789Sahrens int error, fd; 18872885Sahrens offset_t new_off; 1888789Sahrens 18893265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 18903265Sahrens strchr(zc->zc_value, '@') == NULL) 18913265Sahrens return (EINVAL); 18923265Sahrens 1893789Sahrens fd = zc->zc_cookie; 1894789Sahrens fp = getf(fd); 1895789Sahrens if (fp == NULL) 1896789Sahrens return (EBADF); 18972676Seschrock error = dmu_recvbackup(zc->zc_value, &zc->zc_begin_record, 18982676Seschrock &zc->zc_cookie, (boolean_t)zc->zc_guid, fp->f_vnode, 18992665Snd150628 fp->f_offset); 19002885Sahrens 19012885Sahrens new_off = fp->f_offset + zc->zc_cookie; 19022885Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &new_off) == 0) 19032885Sahrens fp->f_offset = new_off; 19042885Sahrens 1905789Sahrens releasef(fd); 1906789Sahrens return (error); 1907789Sahrens } 1908789Sahrens 1909789Sahrens static int 1910789Sahrens zfs_ioc_sendbackup(zfs_cmd_t *zc) 1911789Sahrens { 1912789Sahrens objset_t *fromsnap = NULL; 1913789Sahrens objset_t *tosnap; 1914789Sahrens file_t *fp; 1915789Sahrens int error; 1916789Sahrens 1917789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1918789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); 1919789Sahrens if (error) 1920789Sahrens return (error); 1921789Sahrens 19222676Seschrock if (zc->zc_value[0] != '\0') { 19232885Sahrens char buf[MAXPATHLEN]; 19242885Sahrens char *cp; 19252885Sahrens 19262885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 19272885Sahrens cp = strchr(buf, '@'); 19282885Sahrens if (cp) 19292885Sahrens *(cp+1) = 0; 19302885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 19312885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 1932789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); 1933789Sahrens if (error) { 1934789Sahrens dmu_objset_close(tosnap); 1935789Sahrens return (error); 1936789Sahrens } 1937789Sahrens } 1938789Sahrens 1939789Sahrens fp = getf(zc->zc_cookie); 1940789Sahrens if (fp == NULL) { 1941789Sahrens dmu_objset_close(tosnap); 1942789Sahrens if (fromsnap) 1943789Sahrens dmu_objset_close(fromsnap); 1944789Sahrens return (EBADF); 1945789Sahrens } 1946789Sahrens 1947789Sahrens error = dmu_sendbackup(tosnap, fromsnap, fp->f_vnode); 1948789Sahrens 1949789Sahrens releasef(zc->zc_cookie); 1950789Sahrens if (fromsnap) 1951789Sahrens dmu_objset_close(fromsnap); 1952789Sahrens dmu_objset_close(tosnap); 1953789Sahrens return (error); 1954789Sahrens } 1955789Sahrens 19561544Seschrock static int 19571544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 19581544Seschrock { 19591544Seschrock int id, error; 19601544Seschrock 19611544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 19621544Seschrock &zc->zc_inject_record); 19631544Seschrock 19641544Seschrock if (error == 0) 19651544Seschrock zc->zc_guid = (uint64_t)id; 19661544Seschrock 19671544Seschrock return (error); 19681544Seschrock } 19691544Seschrock 19701544Seschrock static int 19711544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 19721544Seschrock { 19731544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 19741544Seschrock } 19751544Seschrock 19761544Seschrock static int 19771544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 19781544Seschrock { 19791544Seschrock int id = (int)zc->zc_guid; 19801544Seschrock int error; 19811544Seschrock 19821544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 19831544Seschrock &zc->zc_inject_record); 19841544Seschrock 19851544Seschrock zc->zc_guid = id; 19861544Seschrock 19871544Seschrock return (error); 19881544Seschrock } 19891544Seschrock 19901544Seschrock static int 19911544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 19921544Seschrock { 19931544Seschrock spa_t *spa; 19941544Seschrock int error; 19952676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 19961544Seschrock 19971544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 19981544Seschrock return (error); 19991544Seschrock 20002676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 20011544Seschrock &count); 20021544Seschrock if (error == 0) 20032676Seschrock zc->zc_nvlist_dst_size = count; 20041544Seschrock else 20052676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 20061544Seschrock 20071544Seschrock spa_close(spa, FTAG); 20081544Seschrock 20091544Seschrock return (error); 20101544Seschrock } 20111544Seschrock 20121544Seschrock static int 20131544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 20141544Seschrock { 20151544Seschrock spa_t *spa; 20161544Seschrock vdev_t *vd; 20171544Seschrock int error; 20184451Seschrock uint64_t txg; 20191544Seschrock 20201544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 20211544Seschrock return (error); 20221544Seschrock 20234451Seschrock txg = spa_vdev_enter(spa); 20241544Seschrock 20252676Seschrock if (zc->zc_guid == 0) { 20261544Seschrock vd = NULL; 20272676Seschrock } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { 20284451Seschrock (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 20291544Seschrock spa_close(spa, FTAG); 20301544Seschrock return (ENODEV); 20311544Seschrock } 20321544Seschrock 20331544Seschrock vdev_clear(spa, vd); 20341544Seschrock 20354451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 20361544Seschrock 20371544Seschrock spa_close(spa, FTAG); 20381544Seschrock 20391544Seschrock return (0); 20401544Seschrock } 20411544Seschrock 20421544Seschrock static int 20432082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 20442082Seschrock { 20452417Sahrens char *cp; 20462417Sahrens 20472417Sahrens /* 20482417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 20492417Sahrens * it's easier. 20502417Sahrens */ 20512676Seschrock cp = strchr(zc->zc_value, '@'); 20522417Sahrens if (cp) 20532417Sahrens *cp = '\0'; 20542676Seschrock (void) dmu_objset_find(zc->zc_value, 20552417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 20562082Seschrock return (dsl_dataset_promote(zc->zc_name)); 20572082Seschrock } 20582082Seschrock 20594543Smarks /* 20604543Smarks * We don't want to have a hard dependency 20614543Smarks * against some special symbols in sharefs 20624543Smarks * and nfs. Determine them if needed when 20634543Smarks * the first file system is shared. 20644543Smarks * Neither sharefs or nfs are unloadable modules. 20654543Smarks */ 20664543Smarks int (*zexport_fs)(void *arg); 20674543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 20684543Smarks 20694543Smarks int zfs_share_inited; 20704543Smarks ddi_modhandle_t nfs_mod; 20714543Smarks ddi_modhandle_t sharefs_mod; 20724543Smarks kmutex_t zfs_share_lock; 20734543Smarks 20744543Smarks static int 20754543Smarks zfs_ioc_share(zfs_cmd_t *zc) 20764543Smarks { 20774543Smarks int error; 20784543Smarks int opcode; 20794543Smarks 20804543Smarks if (zfs_share_inited == 0) { 20814543Smarks mutex_enter(&zfs_share_lock); 20824543Smarks nfs_mod = ddi_modopen("fs/nfs", KRTLD_MODE_FIRST, &error); 20834543Smarks sharefs_mod = ddi_modopen("fs/sharefs", 20844543Smarks KRTLD_MODE_FIRST, &error); 20854543Smarks if (nfs_mod == NULL || sharefs_mod == NULL) { 20864543Smarks mutex_exit(&zfs_share_lock); 20874543Smarks return (ENOSYS); 20884543Smarks } 20894543Smarks if (zexport_fs == NULL && ((zexport_fs = (int (*)(void *)) 20904543Smarks ddi_modsym(nfs_mod, "nfs_export", &error)) == NULL)) { 20914543Smarks mutex_exit(&zfs_share_lock); 20924543Smarks return (ENOSYS); 20934543Smarks } 20944543Smarks 20954543Smarks if (zshare_fs == NULL && ((zshare_fs = 20964543Smarks (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 20974543Smarks ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 20984543Smarks mutex_exit(&zfs_share_lock); 20994543Smarks return (ENOSYS); 21004543Smarks } 21014543Smarks zfs_share_inited = 1; 21024543Smarks mutex_exit(&zfs_share_lock); 21034543Smarks } 21044543Smarks 21054543Smarks if (error = zexport_fs((void *)(uintptr_t)zc->zc_share.z_exportdata)) 21064543Smarks return (error); 21074543Smarks 21084543Smarks opcode = (zc->zc_share.z_sharetype == B_TRUE) ? 21094543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 21104543Smarks 21114543Smarks error = zshare_fs(opcode, 21124543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 21134543Smarks zc->zc_share.z_sharemax); 21144543Smarks 21154543Smarks return (error); 21164543Smarks 21174543Smarks } 21184543Smarks 21194543Smarks /* 21204543Smarks * pool destroy and pool export don't log the history as part of zfsdev_ioctl, 21214543Smarks * but rather zfs_ioc_pool_create, and zfs_ioc_pool_export do the loggin 21224543Smarks * of those commands. 21234543Smarks */ 2124789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 21254715Sek110237 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21264577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21274577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21284577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21294577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 21304577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 21314577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21324577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21334577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21344577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21354577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21364577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21374577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21384577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21394577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21404577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21414577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21424577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 21434543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 21444577Sahrens DATASET_NAME, B_FALSE }, 21454543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 21464577Sahrens DATASET_NAME, B_FALSE }, 21474577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 21484577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 21494577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 21504577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 21514577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 21524577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 21534577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 21544577Sahrens { zfs_ioc_recvbackup, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 21554577Sahrens { zfs_ioc_sendbackup, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 21564577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21574577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21584577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 21594577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 21604577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21614577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 21624577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 21634577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 21644577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21654577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21664577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21674577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 21684577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 21694577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 21704543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 21714577Sahrens DATASET_NAME, B_FALSE }, 21724577Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE } 2173789Sahrens }; 2174789Sahrens 2175789Sahrens static int 2176789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2177789Sahrens { 2178789Sahrens zfs_cmd_t *zc; 2179789Sahrens uint_t vec; 21802199Sahrens int error, rc; 2181789Sahrens 2182789Sahrens if (getminor(dev) != 0) 2183789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2184789Sahrens 2185789Sahrens vec = cmd - ZFS_IOC; 2186*4787Sahrens ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); 2187789Sahrens 2188789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2189789Sahrens return (EINVAL); 2190789Sahrens 2191789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2192789Sahrens 2193789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2194789Sahrens 2195*4787Sahrens if (error == 0) 21964543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2197789Sahrens 2198789Sahrens /* 2199789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2200789Sahrens * the lower layers. 2201789Sahrens */ 2202789Sahrens if (error == 0) { 2203789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2204789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 22054577Sahrens case POOL_NAME: 2206789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2207789Sahrens error = EINVAL; 2208789Sahrens break; 2209789Sahrens 22104577Sahrens case DATASET_NAME: 2211789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2212789Sahrens error = EINVAL; 2213789Sahrens break; 22142856Snd150628 22154577Sahrens case NO_NAME: 22162856Snd150628 break; 2217789Sahrens } 2218789Sahrens } 2219789Sahrens 2220789Sahrens if (error == 0) 2221789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2222789Sahrens 22232199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 22244543Smarks if (error == 0) { 22252199Sahrens error = rc; 22264543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 22274543Smarks zfs_log_history(zc); 22284543Smarks } 2229789Sahrens 2230789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2231789Sahrens return (error); 2232789Sahrens } 2233789Sahrens 2234789Sahrens static int 2235789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2236789Sahrens { 2237789Sahrens if (cmd != DDI_ATTACH) 2238789Sahrens return (DDI_FAILURE); 2239789Sahrens 2240789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2241789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2242789Sahrens return (DDI_FAILURE); 2243789Sahrens 2244789Sahrens zfs_dip = dip; 2245789Sahrens 2246789Sahrens ddi_report_dev(dip); 2247789Sahrens 2248789Sahrens return (DDI_SUCCESS); 2249789Sahrens } 2250789Sahrens 2251789Sahrens static int 2252789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2253789Sahrens { 2254789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2255789Sahrens return (DDI_FAILURE); 2256789Sahrens 2257789Sahrens if (cmd != DDI_DETACH) 2258789Sahrens return (DDI_FAILURE); 2259789Sahrens 2260789Sahrens zfs_dip = NULL; 2261789Sahrens 2262789Sahrens ddi_prop_remove_all(dip); 2263789Sahrens ddi_remove_minor_node(dip, NULL); 2264789Sahrens 2265789Sahrens return (DDI_SUCCESS); 2266789Sahrens } 2267789Sahrens 2268789Sahrens /*ARGSUSED*/ 2269789Sahrens static int 2270789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2271789Sahrens { 2272789Sahrens switch (infocmd) { 2273789Sahrens case DDI_INFO_DEVT2DEVINFO: 2274789Sahrens *result = zfs_dip; 2275789Sahrens return (DDI_SUCCESS); 2276789Sahrens 2277789Sahrens case DDI_INFO_DEVT2INSTANCE: 2278849Sbonwick *result = (void *)0; 2279789Sahrens return (DDI_SUCCESS); 2280789Sahrens } 2281789Sahrens 2282789Sahrens return (DDI_FAILURE); 2283789Sahrens } 2284789Sahrens 2285789Sahrens /* 2286789Sahrens * OK, so this is a little weird. 2287789Sahrens * 2288789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2289789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2290789Sahrens * 2291789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2292789Sahrens * so most of the standard driver entry points are in zvol.c. 2293789Sahrens */ 2294789Sahrens static struct cb_ops zfs_cb_ops = { 2295789Sahrens zvol_open, /* open */ 2296789Sahrens zvol_close, /* close */ 2297789Sahrens zvol_strategy, /* strategy */ 2298789Sahrens nodev, /* print */ 2299789Sahrens nodev, /* dump */ 2300789Sahrens zvol_read, /* read */ 2301789Sahrens zvol_write, /* write */ 2302789Sahrens zfsdev_ioctl, /* ioctl */ 2303789Sahrens nodev, /* devmap */ 2304789Sahrens nodev, /* mmap */ 2305789Sahrens nodev, /* segmap */ 2306789Sahrens nochpoll, /* poll */ 2307789Sahrens ddi_prop_op, /* prop_op */ 2308789Sahrens NULL, /* streamtab */ 2309789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2310789Sahrens CB_REV, /* version */ 23113638Sbillm nodev, /* async read */ 23123638Sbillm nodev, /* async write */ 2313789Sahrens }; 2314789Sahrens 2315789Sahrens static struct dev_ops zfs_dev_ops = { 2316789Sahrens DEVO_REV, /* version */ 2317789Sahrens 0, /* refcnt */ 2318789Sahrens zfs_info, /* info */ 2319789Sahrens nulldev, /* identify */ 2320789Sahrens nulldev, /* probe */ 2321789Sahrens zfs_attach, /* attach */ 2322789Sahrens zfs_detach, /* detach */ 2323789Sahrens nodev, /* reset */ 2324789Sahrens &zfs_cb_ops, /* driver operations */ 2325789Sahrens NULL /* no bus operations */ 2326789Sahrens }; 2327789Sahrens 2328789Sahrens static struct modldrv zfs_modldrv = { 23294577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 23302676Seschrock &zfs_dev_ops 2331789Sahrens }; 2332789Sahrens 2333789Sahrens static struct modlinkage modlinkage = { 2334789Sahrens MODREV_1, 2335789Sahrens (void *)&zfs_modlfs, 2336789Sahrens (void *)&zfs_modldrv, 2337789Sahrens NULL 2338789Sahrens }; 2339789Sahrens 23404720Sfr157268 23414720Sfr157268 uint_t zfs_fsyncer_key; 23424720Sfr157268 2343789Sahrens int 2344789Sahrens _init(void) 2345789Sahrens { 2346789Sahrens int error; 2347789Sahrens 2348849Sbonwick spa_init(FREAD | FWRITE); 2349849Sbonwick zfs_init(); 2350849Sbonwick zvol_init(); 2351849Sbonwick 2352849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 2353849Sbonwick zvol_fini(); 2354849Sbonwick zfs_fini(); 2355849Sbonwick spa_fini(); 2356789Sahrens return (error); 2357849Sbonwick } 2358789Sahrens 23594720Sfr157268 tsd_create(&zfs_fsyncer_key, NULL); 23604720Sfr157268 2361789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 2362789Sahrens ASSERT(error == 0); 23634543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 2364789Sahrens 2365789Sahrens return (0); 2366789Sahrens } 2367789Sahrens 2368789Sahrens int 2369789Sahrens _fini(void) 2370789Sahrens { 2371789Sahrens int error; 2372789Sahrens 23731544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 2374789Sahrens return (EBUSY); 2375789Sahrens 2376789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 2377789Sahrens return (error); 2378789Sahrens 2379789Sahrens zvol_fini(); 2380789Sahrens zfs_fini(); 2381789Sahrens spa_fini(); 23824543Smarks if (zfs_share_inited) { 23834543Smarks (void) ddi_modclose(nfs_mod); 23844543Smarks (void) ddi_modclose(sharefs_mod); 23854543Smarks } 2386789Sahrens 23874720Sfr157268 tsd_destroy(&zfs_fsyncer_key); 2388789Sahrens ldi_ident_release(zfs_li); 2389789Sahrens zfs_li = NULL; 23904543Smarks mutex_destroy(&zfs_share_lock); 2391789Sahrens 2392789Sahrens return (error); 2393789Sahrens } 2394789Sahrens 2395789Sahrens int 2396789Sahrens _info(struct modinfo *modinfop) 2397789Sahrens { 2398789Sahrens return (mod_info(&modlinkage, modinfop)); 2399789Sahrens } 2400