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> 66*5326Sek110237 #include <sys/zfs_vfsops.h> 67*5326Sek110237 #include <sys/dmu_objset.h> 68789Sahrens 69789Sahrens #include "zfs_namecheck.h" 702676Seschrock #include "zfs_prop.h" 714543Smarks #include "zfs_deleg.h" 72789Sahrens 73789Sahrens extern struct modlfs zfs_modlfs; 74789Sahrens 75789Sahrens extern void zfs_init(void); 76789Sahrens extern void zfs_fini(void); 77789Sahrens 78789Sahrens ldi_ident_t zfs_li = NULL; 79789Sahrens dev_info_t *zfs_dip; 80789Sahrens 81789Sahrens typedef int zfs_ioc_func_t(zfs_cmd_t *); 824543Smarks typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *); 83789Sahrens 84789Sahrens typedef struct zfs_ioc_vec { 85789Sahrens zfs_ioc_func_t *zvec_func; 86789Sahrens zfs_secpolicy_func_t *zvec_secpolicy; 87789Sahrens enum { 884577Sahrens NO_NAME, 894577Sahrens POOL_NAME, 904577Sahrens DATASET_NAME 914543Smarks } zvec_namecheck; 924543Smarks boolean_t zvec_his_log; 93789Sahrens } zfs_ioc_vec_t; 94789Sahrens 95789Sahrens /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */ 96789Sahrens void 97789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 98789Sahrens { 99789Sahrens const char *newfile; 100789Sahrens char buf[256]; 101789Sahrens va_list adx; 102789Sahrens 103789Sahrens /* 104789Sahrens * Get rid of annoying "../common/" prefix to filename. 105789Sahrens */ 106789Sahrens newfile = strrchr(file, '/'); 107789Sahrens if (newfile != NULL) { 108789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 109789Sahrens } else { 110789Sahrens newfile = file; 111789Sahrens } 112789Sahrens 113789Sahrens va_start(adx, fmt); 114789Sahrens (void) vsnprintf(buf, sizeof (buf), fmt, adx); 115789Sahrens va_end(adx); 116789Sahrens 117789Sahrens /* 118789Sahrens * To get this data, use the zfs-dprintf probe as so: 119789Sahrens * dtrace -q -n 'zfs-dprintf \ 120789Sahrens * /stringof(arg0) == "dbuf.c"/ \ 121789Sahrens * {printf("%s: %s", stringof(arg1), stringof(arg3))}' 122789Sahrens * arg0 = file name 123789Sahrens * arg1 = function name 124789Sahrens * arg2 = line number 125789Sahrens * arg3 = message 126789Sahrens */ 127789Sahrens DTRACE_PROBE4(zfs__dprintf, 128789Sahrens char *, newfile, char *, func, int, line, char *, buf); 129789Sahrens } 130789Sahrens 1314543Smarks static void 1324715Sek110237 history_str_free(char *buf) 1334715Sek110237 { 1344715Sek110237 kmem_free(buf, HIS_MAX_RECORD_LEN); 1354715Sek110237 } 1364715Sek110237 1374715Sek110237 static char * 1384715Sek110237 history_str_get(zfs_cmd_t *zc) 1394715Sek110237 { 1404715Sek110237 char *buf; 1414715Sek110237 1424715Sek110237 if (zc->zc_history == NULL) 1434715Sek110237 return (NULL); 1444715Sek110237 1454715Sek110237 buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP); 1464715Sek110237 if (copyinstr((void *)(uintptr_t)zc->zc_history, 1474715Sek110237 buf, HIS_MAX_RECORD_LEN, NULL) != 0) { 1484715Sek110237 history_str_free(buf); 1494715Sek110237 return (NULL); 1504715Sek110237 } 1514715Sek110237 1524715Sek110237 buf[HIS_MAX_RECORD_LEN -1] = '\0'; 1534715Sek110237 1544715Sek110237 return (buf); 1554715Sek110237 } 1564715Sek110237 1574715Sek110237 static void 1584543Smarks zfs_log_history(zfs_cmd_t *zc) 1594543Smarks { 1604543Smarks spa_t *spa; 1614603Sahrens char *buf; 1624543Smarks 1634715Sek110237 if ((buf = history_str_get(zc)) == NULL) 1644577Sahrens return; 1654577Sahrens 1664715Sek110237 if (spa_open(zc->zc_name, &spa, FTAG) == 0) { 1674715Sek110237 if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY) 1684715Sek110237 (void) spa_history_log(spa, buf, LOG_CMD_NORMAL); 1694715Sek110237 spa_close(spa, FTAG); 1704543Smarks } 1714715Sek110237 history_str_free(buf); 1724543Smarks } 1734543Smarks 174789Sahrens /* 175789Sahrens * Policy for top-level read operations (list pools). Requires no privileges, 176789Sahrens * and can be used in the local zone, as there is no associated dataset. 177789Sahrens */ 178789Sahrens /* ARGSUSED */ 179789Sahrens static int 1804543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) 181789Sahrens { 182789Sahrens return (0); 183789Sahrens } 184789Sahrens 185789Sahrens /* 186789Sahrens * Policy for dataset read operations (list children, get statistics). Requires 187789Sahrens * no privileges, but must be visible in the local zone. 188789Sahrens */ 189789Sahrens /* ARGSUSED */ 190789Sahrens static int 1914543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) 192789Sahrens { 193789Sahrens if (INGLOBALZONE(curproc) || 1944543Smarks zone_dataset_visible(zc->zc_name, NULL)) 195789Sahrens return (0); 196789Sahrens 197789Sahrens return (ENOENT); 198789Sahrens } 199789Sahrens 200789Sahrens static int 201789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr) 202789Sahrens { 203789Sahrens uint64_t zoned; 204789Sahrens int writable = 1; 205789Sahrens 206789Sahrens /* 207789Sahrens * The dataset must be visible by this zone -- check this first 208789Sahrens * so they don't see EPERM on something they shouldn't know about. 209789Sahrens */ 210789Sahrens if (!INGLOBALZONE(curproc) && 211789Sahrens !zone_dataset_visible(dataset, &writable)) 212789Sahrens return (ENOENT); 213789Sahrens 214789Sahrens if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) 215789Sahrens return (ENOENT); 216789Sahrens 217789Sahrens if (INGLOBALZONE(curproc)) { 218789Sahrens /* 219789Sahrens * If the fs is zoned, only root can access it from the 220789Sahrens * global zone. 221789Sahrens */ 222789Sahrens if (secpolicy_zfs(cr) && zoned) 223789Sahrens return (EPERM); 224789Sahrens } else { 225789Sahrens /* 226789Sahrens * If we are in a local zone, the 'zoned' property must be set. 227789Sahrens */ 228789Sahrens if (!zoned) 229789Sahrens return (EPERM); 230789Sahrens 231789Sahrens /* must be writable by this zone */ 232789Sahrens if (!writable) 233789Sahrens return (EPERM); 234789Sahrens } 235789Sahrens return (0); 236789Sahrens } 237789Sahrens 238789Sahrens int 2394543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) 240789Sahrens { 241789Sahrens int error; 242789Sahrens 2434543Smarks error = zfs_dozonecheck(name, cr); 2444543Smarks if (error == 0) { 2454543Smarks error = secpolicy_zfs(cr); 2464670Sahrens if (error) 2474543Smarks error = dsl_deleg_access(name, perm, cr); 2484543Smarks } 2494543Smarks return (error); 2504543Smarks } 2514543Smarks 2524543Smarks static int 2534543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) 2544543Smarks { 2554543Smarks /* 2564543Smarks * Check permissions for special properties. 2574543Smarks */ 2584543Smarks switch (prop) { 2594543Smarks case ZFS_PROP_ZONED: 2604543Smarks /* 2614543Smarks * Disallow setting of 'zoned' from within a local zone. 2624543Smarks */ 2634543Smarks if (!INGLOBALZONE(curproc)) 2644543Smarks return (EPERM); 2654543Smarks break; 266789Sahrens 2674543Smarks case ZFS_PROP_QUOTA: 2684543Smarks if (!INGLOBALZONE(curproc)) { 2694543Smarks uint64_t zoned; 2704543Smarks char setpoint[MAXNAMELEN]; 2714543Smarks /* 2724543Smarks * Unprivileged users are allowed to modify the 2734543Smarks * quota on things *under* (ie. contained by) 2744543Smarks * the thing they own. 2754543Smarks */ 2764543Smarks if (dsl_prop_get_integer(name, "zoned", &zoned, 2774543Smarks setpoint)) 2784543Smarks return (EPERM); 2794670Sahrens if (!zoned || strlen(name) <= strlen(setpoint)) 2804543Smarks return (EPERM); 2814543Smarks } 2824670Sahrens break; 2834543Smarks } 2844543Smarks 2854787Sahrens return (zfs_secpolicy_write_perms(name, zfs_prop_to_name(prop), cr)); 286789Sahrens } 287789Sahrens 2884543Smarks int 2894543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) 2904543Smarks { 2914543Smarks int error; 2924543Smarks 2934543Smarks error = zfs_dozonecheck(zc->zc_name, cr); 2944543Smarks if (error) 2954543Smarks return (error); 2964543Smarks 2974543Smarks /* 2984543Smarks * permission to set permissions will be evaluated later in 2994543Smarks * dsl_deleg_can_allow() 3004543Smarks */ 3014543Smarks return (0); 3024543Smarks } 3034543Smarks 3044543Smarks int 3054543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) 3064543Smarks { 3074543Smarks int error; 3084543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3094543Smarks ZFS_DELEG_PERM_ROLLBACK, cr); 3104543Smarks if (error == 0) 3114543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3124543Smarks ZFS_DELEG_PERM_MOUNT, cr); 3134543Smarks return (error); 3144543Smarks } 3154543Smarks 3164543Smarks int 3174543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) 3184543Smarks { 3194543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 3204543Smarks ZFS_DELEG_PERM_SEND, cr)); 3214543Smarks } 3224543Smarks 3234543Smarks int 3244543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) 3254543Smarks { 3264543Smarks if (!INGLOBALZONE(curproc)) 3274543Smarks return (EPERM); 3284543Smarks 3294543Smarks if (secpolicy_nfs(CRED()) == 0) { 3304543Smarks return (0); 3314543Smarks } else { 3324543Smarks vnode_t *vp; 3334543Smarks int error; 3344543Smarks 3354543Smarks if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, 3364543Smarks NO_FOLLOW, NULL, &vp)) != 0) 3374543Smarks return (error); 3384543Smarks 3394543Smarks /* Now make sure mntpnt and dataset are ZFS */ 3404543Smarks 3414543Smarks if (vp->v_vfsp->vfs_fstype != zfsfstype || 3424543Smarks (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), 3434543Smarks zc->zc_name) != 0)) { 3444543Smarks VN_RELE(vp); 3454543Smarks return (EPERM); 3464543Smarks } 3474543Smarks 3484543Smarks VN_RELE(vp); 3494543Smarks return (dsl_deleg_access(zc->zc_name, 3504543Smarks ZFS_DELEG_PERM_SHARE, cr)); 3514543Smarks } 3524543Smarks } 3534543Smarks 354789Sahrens static int 3554543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize) 356789Sahrens { 357789Sahrens char *cp; 358789Sahrens 359789Sahrens /* 360789Sahrens * Remove the @bla or /bla from the end of the name to get the parent. 361789Sahrens */ 3624543Smarks (void) strncpy(parent, datasetname, parentsize); 3634543Smarks cp = strrchr(parent, '@'); 364789Sahrens if (cp != NULL) { 365789Sahrens cp[0] = '\0'; 366789Sahrens } else { 3674543Smarks cp = strrchr(parent, '/'); 368789Sahrens if (cp == NULL) 369789Sahrens return (ENOENT); 370789Sahrens cp[0] = '\0'; 371789Sahrens } 372789Sahrens 3734543Smarks return (0); 3744543Smarks } 3754543Smarks 3764543Smarks int 3774543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 3784543Smarks { 3794543Smarks int error; 3804543Smarks 3814543Smarks if ((error = zfs_secpolicy_write_perms(name, 3824543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 3834543Smarks return (error); 3844543Smarks 3854543Smarks return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); 3864543Smarks } 3874543Smarks 3884543Smarks static int 3894543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) 3904543Smarks { 3914543Smarks return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); 3924543Smarks } 3934543Smarks 3944543Smarks /* 3954543Smarks * Must have sys_config privilege to check the iscsi permission 3964543Smarks */ 3974543Smarks /* ARGSUSED */ 3984543Smarks static int 3994543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) 4004543Smarks { 4014543Smarks return (secpolicy_zfs(cr)); 4024543Smarks } 4034543Smarks 4044543Smarks int 4054543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 4064543Smarks { 4074543Smarks char parentname[MAXNAMELEN]; 4084543Smarks int error; 4094543Smarks 4104543Smarks if ((error = zfs_secpolicy_write_perms(from, 4114543Smarks ZFS_DELEG_PERM_RENAME, cr)) != 0) 4124543Smarks return (error); 4134543Smarks 4144543Smarks if ((error = zfs_secpolicy_write_perms(from, 4154543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4164543Smarks return (error); 4174543Smarks 4184543Smarks if ((error = zfs_get_parent(to, parentname, 4194543Smarks sizeof (parentname))) != 0) 4204543Smarks return (error); 4214543Smarks 4224543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4234543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 4244543Smarks return (error); 4254543Smarks 4264543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4274543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4284543Smarks return (error); 4294543Smarks 4304543Smarks return (error); 4314543Smarks } 4324543Smarks 4334543Smarks static int 4344543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) 4354543Smarks { 4364543Smarks return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); 4374543Smarks } 4384543Smarks 4394543Smarks static int 4404543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) 4414543Smarks { 4424543Smarks char parentname[MAXNAMELEN]; 4434543Smarks objset_t *clone; 4444543Smarks int error; 4454543Smarks 4464543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4474543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4484543Smarks if (error) 4494543Smarks return (error); 4504543Smarks 4514543Smarks error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 4524543Smarks DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 4534543Smarks 4544543Smarks if (error == 0) { 4554543Smarks dsl_dataset_t *pclone = NULL; 4564543Smarks dsl_dir_t *dd; 4574543Smarks dd = clone->os->os_dsl_dataset->ds_dir; 4584543Smarks 4594543Smarks rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 4604543Smarks error = dsl_dataset_open_obj(dd->dd_pool, 4614543Smarks dd->dd_phys->dd_clone_parent_obj, NULL, 4624543Smarks DS_MODE_NONE, FTAG, &pclone); 4634543Smarks rw_exit(&dd->dd_pool->dp_config_rwlock); 4644543Smarks if (error) { 4654543Smarks dmu_objset_close(clone); 4664543Smarks return (error); 4674543Smarks } 4684543Smarks 4694543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4704543Smarks ZFS_DELEG_PERM_MOUNT, cr); 4714543Smarks 4724543Smarks dsl_dataset_name(pclone, parentname); 4734543Smarks dmu_objset_close(clone); 4744543Smarks dsl_dataset_close(pclone, DS_MODE_NONE, FTAG); 4754543Smarks if (error == 0) 4764543Smarks error = zfs_secpolicy_write_perms(parentname, 4774543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4784543Smarks } 4794543Smarks return (error); 4804543Smarks } 4814543Smarks 4824543Smarks static int 4834543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) 4844543Smarks { 4854543Smarks int error; 4864543Smarks 4874543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 4884543Smarks ZFS_DELEG_PERM_RECEIVE, cr)) != 0) 4894543Smarks return (error); 4904543Smarks 4914543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 4924543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4934543Smarks return (error); 4944543Smarks 4954543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 4964543Smarks ZFS_DELEG_PERM_CREATE, cr)); 4974543Smarks } 4984543Smarks 4994543Smarks int 5004543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 5014543Smarks { 5024543Smarks int error; 5034543Smarks 5044543Smarks if ((error = zfs_secpolicy_write_perms(name, 5054543Smarks ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) 5064543Smarks return (error); 5074543Smarks 5084543Smarks error = zfs_secpolicy_write_perms(name, 5094543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5104543Smarks 5114543Smarks return (error); 5124543Smarks } 5134543Smarks 5144543Smarks static int 5154543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) 5164543Smarks { 5174543Smarks 5184543Smarks return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); 5194543Smarks } 5204543Smarks 5214543Smarks static int 5224543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) 5234543Smarks { 5244543Smarks char parentname[MAXNAMELEN]; 5254543Smarks int error; 5264543Smarks 5274543Smarks if ((error = zfs_get_parent(zc->zc_name, parentname, 5284543Smarks sizeof (parentname))) != 0) 5294543Smarks return (error); 5304543Smarks 5314543Smarks if (zc->zc_value[0] != '\0') { 5324543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_value, 5334543Smarks ZFS_DELEG_PERM_CLONE, cr)) != 0) 5344543Smarks return (error); 5354543Smarks } 5364543Smarks 5374543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 5384543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 5394543Smarks return (error); 5404543Smarks 5414543Smarks error = zfs_secpolicy_write_perms(parentname, 5424543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5434543Smarks 5444543Smarks return (error); 5454543Smarks } 5464543Smarks 5474543Smarks static int 5484543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) 5494543Smarks { 5504543Smarks int error; 5514543Smarks 5524543Smarks error = secpolicy_fs_unmount(cr, NULL); 5534543Smarks if (error) { 5544543Smarks error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); 5554543Smarks } 5564543Smarks return (error); 557789Sahrens } 558789Sahrens 559789Sahrens /* 560789Sahrens * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires 561789Sahrens * SYS_CONFIG privilege, which is not available in a local zone. 562789Sahrens */ 563789Sahrens /* ARGSUSED */ 564789Sahrens static int 5654543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) 566789Sahrens { 567789Sahrens if (secpolicy_sys_config(cr, B_FALSE) != 0) 568789Sahrens return (EPERM); 569789Sahrens 570789Sahrens return (0); 571789Sahrens } 572789Sahrens 573789Sahrens /* 5744543Smarks * Just like zfs_secpolicy_config, except that we will check for 5754543Smarks * mount permission on the dataset for permission to create/remove 5764543Smarks * the minor nodes. 5774543Smarks */ 5784543Smarks static int 5794543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) 5804543Smarks { 5814543Smarks if (secpolicy_sys_config(cr, B_FALSE) != 0) { 5824543Smarks return (dsl_deleg_access(zc->zc_name, 5834543Smarks ZFS_DELEG_PERM_MOUNT, cr)); 5844543Smarks } 5854543Smarks 5864543Smarks return (0); 5874543Smarks } 5884543Smarks 5894543Smarks /* 5901544Seschrock * Policy for fault injection. Requires all privileges. 5911544Seschrock */ 5921544Seschrock /* ARGSUSED */ 5931544Seschrock static int 5944543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) 5951544Seschrock { 5961544Seschrock return (secpolicy_zinject(cr)); 5971544Seschrock } 5981544Seschrock 5994849Sahrens static int 6004849Sahrens zfs_secpolicy_inherit(zfs_cmd_t *zc, cred_t *cr) 6014849Sahrens { 6024849Sahrens zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); 6034849Sahrens 6045094Slling if (prop == ZPROP_INVAL) { 6054849Sahrens if (!zfs_prop_user(zc->zc_value)) 6064849Sahrens return (EINVAL); 6074849Sahrens return (zfs_secpolicy_write_perms(zc->zc_name, 6084849Sahrens ZFS_DELEG_PERM_USERPROP, cr)); 6094849Sahrens } else { 6104849Sahrens if (!zfs_prop_inheritable(prop)) 6114849Sahrens return (EINVAL); 6124849Sahrens return (zfs_secpolicy_setprop(zc->zc_name, prop, cr)); 6134849Sahrens } 6144849Sahrens } 6154849Sahrens 6161544Seschrock /* 617789Sahrens * Returns the nvlist as specified by the user in the zfs_cmd_t. 618789Sahrens */ 619789Sahrens static int 6205094Slling get_nvlist(uint64_t nvl, uint64_t size, nvlist_t **nvp) 621789Sahrens { 622789Sahrens char *packed; 623789Sahrens int error; 6245094Slling nvlist_t *list = NULL; 625789Sahrens 626789Sahrens /* 6272676Seschrock * Read in and unpack the user-supplied nvlist. 628789Sahrens */ 6295094Slling if (size == 0) 630789Sahrens return (EINVAL); 631789Sahrens 632789Sahrens packed = kmem_alloc(size, KM_SLEEP); 633789Sahrens 6345094Slling if ((error = xcopyin((void *)(uintptr_t)nvl, packed, size)) != 0) { 635789Sahrens kmem_free(packed, size); 636789Sahrens return (error); 637789Sahrens } 638789Sahrens 6395094Slling if ((error = nvlist_unpack(packed, size, &list, 0)) != 0) { 640789Sahrens kmem_free(packed, size); 641789Sahrens return (error); 642789Sahrens } 643789Sahrens 644789Sahrens kmem_free(packed, size); 645789Sahrens 6465094Slling *nvp = list; 647789Sahrens return (0); 648789Sahrens } 649789Sahrens 650789Sahrens static int 6512676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 6522676Seschrock { 6532676Seschrock char *packed = NULL; 6542676Seschrock size_t size; 6552676Seschrock int error; 6562676Seschrock 6572676Seschrock VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 6582676Seschrock 6592676Seschrock if (size > zc->zc_nvlist_dst_size) { 6602676Seschrock error = ENOMEM; 6612676Seschrock } else { 6624611Smarks packed = kmem_alloc(size, KM_SLEEP); 6632676Seschrock VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 6642676Seschrock KM_SLEEP) == 0); 6652676Seschrock error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 6662676Seschrock size); 6672676Seschrock kmem_free(packed, size); 6682676Seschrock } 6692676Seschrock 6702676Seschrock zc->zc_nvlist_dst_size = size; 6712676Seschrock return (error); 6722676Seschrock } 6732676Seschrock 6742676Seschrock static int 675789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc) 676789Sahrens { 677789Sahrens int error; 6785094Slling nvlist_t *config, *props = NULL; 6794715Sek110237 char *buf; 680789Sahrens 6815094Slling if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 6825094Slling &config)) 6834988Sek110237 return (error); 6844715Sek110237 6855094Slling if (zc->zc_nvlist_src_size != 0 && (error = 6865094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 6875094Slling nvlist_free(config); 6885094Slling return (error); 6895094Slling } 6905094Slling 6914988Sek110237 buf = history_str_get(zc); 692789Sahrens 6935094Slling error = spa_create(zc->zc_name, config, props, buf); 694789Sahrens 6954988Sek110237 if (buf != NULL) 6964988Sek110237 history_str_free(buf); 6975094Slling 698789Sahrens nvlist_free(config); 699789Sahrens 7005094Slling if (props) 7015094Slling nvlist_free(props); 7025094Slling 703789Sahrens return (error); 704789Sahrens } 705789Sahrens 706789Sahrens static int 707789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc) 708789Sahrens { 7094543Smarks int error; 7104543Smarks zfs_log_history(zc); 7114543Smarks error = spa_destroy(zc->zc_name); 7124543Smarks return (error); 713789Sahrens } 714789Sahrens 715789Sahrens static int 716789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc) 717789Sahrens { 718789Sahrens int error; 7195094Slling nvlist_t *config, *props = NULL; 720789Sahrens uint64_t guid; 721789Sahrens 7225094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7235094Slling &config)) != 0) 724789Sahrens return (error); 725789Sahrens 7265094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7275094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7285094Slling nvlist_free(config); 7295094Slling return (error); 7305094Slling } 7315094Slling 732789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 7331544Seschrock guid != zc->zc_guid) 734789Sahrens error = EINVAL; 735789Sahrens else 7365094Slling error = spa_import(zc->zc_name, config, props); 737789Sahrens 738789Sahrens nvlist_free(config); 739789Sahrens 7405094Slling if (props) 7415094Slling nvlist_free(props); 7425094Slling 743789Sahrens return (error); 744789Sahrens } 745789Sahrens 746789Sahrens static int 747789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc) 748789Sahrens { 7494543Smarks int error; 7504543Smarks zfs_log_history(zc); 7514543Smarks error = spa_export(zc->zc_name, NULL); 7524543Smarks return (error); 753789Sahrens } 754789Sahrens 755789Sahrens static int 756789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc) 757789Sahrens { 758789Sahrens nvlist_t *configs; 759789Sahrens int error; 760789Sahrens 761789Sahrens if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 762789Sahrens return (EEXIST); 763789Sahrens 7642676Seschrock error = put_nvlist(zc, configs); 765789Sahrens 766789Sahrens nvlist_free(configs); 767789Sahrens 768789Sahrens return (error); 769789Sahrens } 770789Sahrens 771789Sahrens static int 772789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc) 773789Sahrens { 774789Sahrens nvlist_t *config; 775789Sahrens int error; 7761544Seschrock int ret = 0; 777789Sahrens 7782676Seschrock error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 7792676Seschrock sizeof (zc->zc_value)); 780789Sahrens 781789Sahrens if (config != NULL) { 7822676Seschrock ret = put_nvlist(zc, config); 783789Sahrens nvlist_free(config); 7841544Seschrock 7851544Seschrock /* 7861544Seschrock * The config may be present even if 'error' is non-zero. 7871544Seschrock * In this case we return success, and preserve the real errno 7881544Seschrock * in 'zc_cookie'. 7891544Seschrock */ 7901544Seschrock zc->zc_cookie = error; 791789Sahrens } else { 7921544Seschrock ret = error; 793789Sahrens } 794789Sahrens 7951544Seschrock return (ret); 796789Sahrens } 797789Sahrens 798789Sahrens /* 799789Sahrens * Try to import the given pool, returning pool stats as appropriate so that 800789Sahrens * user land knows which devices are available and overall pool health. 801789Sahrens */ 802789Sahrens static int 803789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 804789Sahrens { 805789Sahrens nvlist_t *tryconfig, *config; 806789Sahrens int error; 807789Sahrens 8085094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 8095094Slling &tryconfig)) != 0) 810789Sahrens return (error); 811789Sahrens 812789Sahrens config = spa_tryimport(tryconfig); 813789Sahrens 814789Sahrens nvlist_free(tryconfig); 815789Sahrens 816789Sahrens if (config == NULL) 817789Sahrens return (EINVAL); 818789Sahrens 8192676Seschrock error = put_nvlist(zc, config); 820789Sahrens nvlist_free(config); 821789Sahrens 822789Sahrens return (error); 823789Sahrens } 824789Sahrens 825789Sahrens static int 826789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc) 827789Sahrens { 828789Sahrens spa_t *spa; 829789Sahrens int error; 830789Sahrens 8312926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8322926Sek110237 return (error); 8332926Sek110237 8344808Sek110237 mutex_enter(&spa_namespace_lock); 8352926Sek110237 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); 8364808Sek110237 mutex_exit(&spa_namespace_lock); 8372926Sek110237 8382926Sek110237 spa_close(spa, FTAG); 8392926Sek110237 840789Sahrens return (error); 841789Sahrens } 842789Sahrens 843789Sahrens static int 844789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 845789Sahrens { 846789Sahrens spa_t *spa; 847789Sahrens int error; 848789Sahrens 849789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 850789Sahrens if (error == 0) { 851789Sahrens spa_freeze(spa); 852789Sahrens spa_close(spa, FTAG); 853789Sahrens } 854789Sahrens return (error); 855789Sahrens } 856789Sahrens 857789Sahrens static int 8581760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 8591760Seschrock { 8601760Seschrock spa_t *spa; 8611760Seschrock int error; 8621760Seschrock 8632926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8642926Sek110237 return (error); 8652926Sek110237 8665118Slling if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) { 8675118Slling spa_close(spa, FTAG); 8685118Slling return (EINVAL); 8695118Slling } 8705118Slling 8715094Slling spa_upgrade(spa, zc->zc_cookie); 8722926Sek110237 spa_close(spa, FTAG); 8732926Sek110237 8742926Sek110237 return (error); 8752926Sek110237 } 8762926Sek110237 8772926Sek110237 static int 8782926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 8792926Sek110237 { 8802926Sek110237 spa_t *spa; 8812926Sek110237 char *hist_buf; 8822926Sek110237 uint64_t size; 8832926Sek110237 int error; 8842926Sek110237 8852926Sek110237 if ((size = zc->zc_history_len) == 0) 8862926Sek110237 return (EINVAL); 8872926Sek110237 8882926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8892926Sek110237 return (error); 8902926Sek110237 8914577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 8923863Sek110237 spa_close(spa, FTAG); 8933863Sek110237 return (ENOTSUP); 8943863Sek110237 } 8953863Sek110237 8962926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 8972926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 8982926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 8994543Smarks error = xcopyout(hist_buf, 9004543Smarks (char *)(uintptr_t)zc->zc_history, 9012926Sek110237 zc->zc_history_len); 9022926Sek110237 } 9032926Sek110237 9042926Sek110237 spa_close(spa, FTAG); 9052926Sek110237 kmem_free(hist_buf, size); 9062926Sek110237 return (error); 9072926Sek110237 } 9082926Sek110237 9092926Sek110237 static int 9103444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 9113444Sek110237 { 9123444Sek110237 int error; 9133444Sek110237 9143912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 9153444Sek110237 return (error); 9163444Sek110237 9173444Sek110237 return (0); 9183444Sek110237 } 9193444Sek110237 9203444Sek110237 static int 9213444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 9223444Sek110237 { 9233444Sek110237 objset_t *osp; 9243444Sek110237 int error; 9253444Sek110237 9263444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 9273444Sek110237 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) 9283444Sek110237 return (error); 9293444Sek110237 9303444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 9313444Sek110237 sizeof (zc->zc_value)); 9323444Sek110237 dmu_objset_close(osp); 9333444Sek110237 9343444Sek110237 return (error); 9353444Sek110237 } 9363444Sek110237 9373444Sek110237 static int 938789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 939789Sahrens { 940789Sahrens spa_t *spa; 941789Sahrens int error; 942789Sahrens nvlist_t *config; 943789Sahrens 944789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 945789Sahrens if (error != 0) 946789Sahrens return (error); 947789Sahrens 9483912Slling /* 9493912Slling * A root pool with concatenated devices is not supported. 9503912Slling * Thus, can not add a device to a root pool with one device. 9513912Slling */ 9523912Slling if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0) { 9533912Slling spa_close(spa, FTAG); 9543912Slling return (EDOM); 9553912Slling } 9563912Slling 9575094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 9585094Slling &config)) == 0) { 959789Sahrens error = spa_vdev_add(spa, config); 960789Sahrens nvlist_free(config); 961789Sahrens } 962789Sahrens spa_close(spa, FTAG); 963789Sahrens return (error); 964789Sahrens } 965789Sahrens 966789Sahrens static int 967789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 968789Sahrens { 9692082Seschrock spa_t *spa; 9702082Seschrock int error; 9712082Seschrock 9722082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 9732082Seschrock if (error != 0) 9742082Seschrock return (error); 9752082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 9762082Seschrock spa_close(spa, FTAG); 9772082Seschrock return (error); 978789Sahrens } 979789Sahrens 980789Sahrens static int 9814451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 982789Sahrens { 983789Sahrens spa_t *spa; 984789Sahrens int error; 9854451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 986789Sahrens 9872926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 988789Sahrens return (error); 9894451Seschrock switch (zc->zc_cookie) { 9904451Seschrock case VDEV_STATE_ONLINE: 9914451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 9924451Seschrock break; 9934451Seschrock 9944451Seschrock case VDEV_STATE_OFFLINE: 9954451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 9964451Seschrock break; 997789Sahrens 9984451Seschrock case VDEV_STATE_FAULTED: 9994451Seschrock error = vdev_fault(spa, zc->zc_guid); 10004451Seschrock break; 1001789Sahrens 10024451Seschrock case VDEV_STATE_DEGRADED: 10034451Seschrock error = vdev_degrade(spa, zc->zc_guid); 10044451Seschrock break; 10054451Seschrock 10064451Seschrock default: 10074451Seschrock error = EINVAL; 10084451Seschrock } 10094451Seschrock zc->zc_cookie = newstate; 1010789Sahrens spa_close(spa, FTAG); 1011789Sahrens return (error); 1012789Sahrens } 1013789Sahrens 1014789Sahrens static int 1015789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 1016789Sahrens { 1017789Sahrens spa_t *spa; 1018789Sahrens int replacing = zc->zc_cookie; 1019789Sahrens nvlist_t *config; 1020789Sahrens int error; 1021789Sahrens 10222926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1023789Sahrens return (error); 1024789Sahrens 10255094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 10265094Slling &config)) == 0) { 10271544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 1028789Sahrens nvlist_free(config); 1029789Sahrens } 1030789Sahrens 1031789Sahrens spa_close(spa, FTAG); 1032789Sahrens return (error); 1033789Sahrens } 1034789Sahrens 1035789Sahrens static int 1036789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 1037789Sahrens { 1038789Sahrens spa_t *spa; 1039789Sahrens int error; 1040789Sahrens 10412926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1042789Sahrens return (error); 1043789Sahrens 10441544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1045789Sahrens 1046789Sahrens spa_close(spa, FTAG); 1047789Sahrens return (error); 1048789Sahrens } 1049789Sahrens 1050789Sahrens static int 10511354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 10521354Seschrock { 10531354Seschrock spa_t *spa; 10542676Seschrock char *path = zc->zc_value; 10551544Seschrock uint64_t guid = zc->zc_guid; 10561354Seschrock int error; 10571354Seschrock 10581354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10591354Seschrock if (error != 0) 10601354Seschrock return (error); 10611354Seschrock 10621354Seschrock error = spa_vdev_setpath(spa, guid, path); 10631354Seschrock spa_close(spa, FTAG); 10641354Seschrock return (error); 10651354Seschrock } 10661354Seschrock 10671354Seschrock static int 1068789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1069789Sahrens { 1070789Sahrens objset_t *os = NULL; 1071789Sahrens int error; 10721356Seschrock nvlist_t *nv; 1073789Sahrens 1074789Sahrens retry: 1075789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1076789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1077789Sahrens if (error != 0) { 1078789Sahrens /* 1079789Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1080789Sahrens * the objset is held exclusively. Fortunately this hold is 1081789Sahrens * only for a short while, so we retry here. 1082789Sahrens * This avoids user code having to handle EBUSY, 1083789Sahrens * for example for a "zfs list". 1084789Sahrens */ 1085789Sahrens if (error == EBUSY) { 1086789Sahrens delay(1); 1087789Sahrens goto retry; 1088789Sahrens } 1089789Sahrens return (error); 1090789Sahrens } 1091789Sahrens 10922885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1093789Sahrens 10942856Snd150628 if (zc->zc_nvlist_dst != 0 && 10951356Seschrock (error = dsl_prop_get_all(os, &nv)) == 0) { 10962885Sahrens dmu_objset_stats(os, nv); 10973087Sahrens /* 10985147Srm160521 * NB: zvol_get_stats() will read the objset contents, 10993087Sahrens * which we aren't supposed to do with a 11003087Sahrens * DS_MODE_STANDARD open, because it could be 11013087Sahrens * inconsistent. So this is a bit of a workaround... 11023087Sahrens */ 11034577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 11044577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 11054577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 11064577Sahrens } 11072676Seschrock error = put_nvlist(zc, nv); 11081356Seschrock nvlist_free(nv); 11091356Seschrock } 1110789Sahrens 11112676Seschrock spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value)); 11121544Seschrock 1113789Sahrens dmu_objset_close(os); 1114789Sahrens return (error); 1115789Sahrens } 1116789Sahrens 1117789Sahrens static int 11185147Srm160521 zfs_ioc_objset_version(zfs_cmd_t *zc) 11195147Srm160521 { 11205147Srm160521 objset_t *os = NULL; 11215147Srm160521 int error; 11225147Srm160521 11235147Srm160521 retry: 11245147Srm160521 error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 11255147Srm160521 DS_MODE_STANDARD | DS_MODE_READONLY, &os); 11265147Srm160521 if (error != 0) { 11275147Srm160521 /* 11285147Srm160521 * This is ugly: dmu_objset_open() can return EBUSY if 11295147Srm160521 * the objset is held exclusively. Fortunately this hold is 11305147Srm160521 * only for a short while, so we retry here. 11315147Srm160521 * This avoids user code having to handle EBUSY, 11325147Srm160521 * for example for a "zfs list". 11335147Srm160521 */ 11345147Srm160521 if (error == EBUSY) { 11355147Srm160521 delay(1); 11365147Srm160521 goto retry; 11375147Srm160521 } 11385147Srm160521 return (error); 11395147Srm160521 } 11405147Srm160521 11415147Srm160521 dmu_objset_fast_stat(os, &zc->zc_objset_stats); 11425147Srm160521 11435147Srm160521 /* 11445147Srm160521 * NB: zfs_get_version() will read the objset contents, 11455147Srm160521 * which we aren't supposed to do with a 11465147Srm160521 * DS_MODE_STANDARD open, because it could be 11475147Srm160521 * inconsistent. So this is a bit of a workaround... 11485147Srm160521 */ 11495147Srm160521 zc->zc_cookie = 0; 11505147Srm160521 if (!zc->zc_objset_stats.dds_inconsistent) 11515147Srm160521 if (dmu_objset_type(os) == DMU_OST_ZFS) 11525147Srm160521 (void) zfs_get_version(os, &zc->zc_cookie); 11535147Srm160521 11545147Srm160521 dmu_objset_close(os); 11555147Srm160521 return (0); 11565147Srm160521 } 11575147Srm160521 11585147Srm160521 static int 1159789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1160789Sahrens { 1161885Sahrens objset_t *os; 1162789Sahrens int error; 1163789Sahrens char *p; 1164789Sahrens 1165885Sahrens retry: 1166885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1167885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1168885Sahrens if (error != 0) { 1169885Sahrens /* 1170885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1171885Sahrens * the objset is held exclusively. Fortunately this hold is 1172885Sahrens * only for a short while, so we retry here. 1173885Sahrens * This avoids user code having to handle EBUSY, 1174885Sahrens * for example for a "zfs list". 1175885Sahrens */ 1176885Sahrens if (error == EBUSY) { 1177885Sahrens delay(1); 1178885Sahrens goto retry; 1179885Sahrens } 1180885Sahrens if (error == ENOENT) 1181885Sahrens error = ESRCH; 1182885Sahrens return (error); 1183789Sahrens } 1184789Sahrens 1185789Sahrens p = strrchr(zc->zc_name, '/'); 1186789Sahrens if (p == NULL || p[1] != '\0') 1187789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1188789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1189789Sahrens 1190789Sahrens do { 1191885Sahrens error = dmu_dir_list_next(os, 1192885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1193885Sahrens NULL, &zc->zc_cookie); 1194789Sahrens if (error == ENOENT) 1195789Sahrens error = ESRCH; 1196885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1197789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 1198789Sahrens 1199885Sahrens /* 1200885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1201885Sahrens * try to get stats for it. Userland will skip over it. 1202885Sahrens */ 1203885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1204885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1205789Sahrens 1206885Sahrens dmu_objset_close(os); 1207789Sahrens return (error); 1208789Sahrens } 1209789Sahrens 1210789Sahrens static int 1211789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1212789Sahrens { 1213885Sahrens objset_t *os; 1214789Sahrens int error; 1215789Sahrens 1216789Sahrens retry: 1217885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1218885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1219885Sahrens if (error != 0) { 1220789Sahrens /* 1221885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1222789Sahrens * the objset is held exclusively. Fortunately this hold is 1223789Sahrens * only for a short while, so we retry here. 1224789Sahrens * This avoids user code having to handle EBUSY, 1225885Sahrens * for example for a "zfs list". 1226789Sahrens */ 1227789Sahrens if (error == EBUSY) { 1228789Sahrens delay(1); 1229789Sahrens goto retry; 1230789Sahrens } 1231789Sahrens if (error == ENOENT) 1232885Sahrens error = ESRCH; 1233789Sahrens return (error); 1234789Sahrens } 1235789Sahrens 12361003Slling /* 12371003Slling * A dataset name of maximum length cannot have any snapshots, 12381003Slling * so exit immediately. 12391003Slling */ 12401003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1241885Sahrens dmu_objset_close(os); 12421003Slling return (ESRCH); 1243789Sahrens } 1244789Sahrens 1245885Sahrens error = dmu_snapshot_list_next(os, 1246885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 1247885Sahrens zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie); 1248789Sahrens if (error == ENOENT) 1249789Sahrens error = ESRCH; 1250789Sahrens 1251885Sahrens if (error == 0) 1252885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1253789Sahrens 1254885Sahrens dmu_objset_close(os); 1255789Sahrens return (error); 1256789Sahrens } 1257789Sahrens 1258789Sahrens static int 12594787Sahrens zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) 1260789Sahrens { 12612676Seschrock nvpair_t *elem; 12622676Seschrock int error; 12632676Seschrock uint64_t intval; 12642676Seschrock char *strval; 12652676Seschrock 12664543Smarks /* 12674543Smarks * First validate permission to set all of the properties 12684543Smarks */ 12692676Seschrock elem = NULL; 12702676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 12714670Sahrens const char *propname = nvpair_name(elem); 12724670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 12732676Seschrock 12745094Slling if (prop == ZPROP_INVAL) { 12752676Seschrock /* 12762676Seschrock * If this is a user-defined property, it must be a 12772676Seschrock * string, and there is no further validation to do. 12782676Seschrock */ 12792676Seschrock if (!zfs_prop_user(propname) || 12802676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 12812676Seschrock return (EINVAL); 12822676Seschrock 12834543Smarks error = zfs_secpolicy_write_perms(name, 12844787Sahrens ZFS_DELEG_PERM_USERPROP, CRED()); 12854670Sahrens if (error) 12864670Sahrens return (error); 12874543Smarks continue; 12882676Seschrock } 12892676Seschrock 12904787Sahrens if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 12914670Sahrens return (error); 12922676Seschrock 12934670Sahrens /* 12944670Sahrens * Check that this value is valid for this pool version 12954670Sahrens */ 12964670Sahrens switch (prop) { 12973886Sahl case ZFS_PROP_COMPRESSION: 12983886Sahl /* 12993886Sahl * If the user specified gzip compression, make sure 13003886Sahl * the SPA supports it. We ignore any errors here since 13013886Sahl * we'll catch them later. 13023886Sahl */ 13033886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 13043886Sahl nvpair_value_uint64(elem, &intval) == 0 && 13053886Sahl intval >= ZIO_COMPRESS_GZIP_1 && 13063886Sahl intval <= ZIO_COMPRESS_GZIP_9) { 13074543Smarks spa_t *spa; 13084543Smarks 13094603Sahrens if (spa_open(name, &spa, FTAG) == 0) { 13103886Sahl if (spa_version(spa) < 13114577Sahrens SPA_VERSION_GZIP_COMPRESSION) { 13123886Sahl spa_close(spa, FTAG); 13133886Sahl return (ENOTSUP); 13143886Sahl } 13153886Sahl 13163886Sahl spa_close(spa, FTAG); 13173886Sahl } 13183886Sahl } 13193886Sahl break; 13204603Sahrens 13214603Sahrens case ZFS_PROP_COPIES: 13224603Sahrens { 13234603Sahrens spa_t *spa; 13244603Sahrens 13254603Sahrens if (spa_open(name, &spa, FTAG) == 0) { 13264603Sahrens if (spa_version(spa) < 13274603Sahrens SPA_VERSION_DITTO_BLOCKS) { 13284603Sahrens spa_close(spa, FTAG); 13294603Sahrens return (ENOTSUP); 13304603Sahrens } 13314603Sahrens spa_close(spa, FTAG); 13324603Sahrens } 13334603Sahrens break; 13344603Sahrens } 13352676Seschrock } 13364543Smarks } 13374543Smarks 13384543Smarks elem = NULL; 13394543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 13404670Sahrens const char *propname = nvpair_name(elem); 13414670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 13424543Smarks 13435094Slling if (prop == ZPROP_INVAL) { 13444543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 13454543Smarks error = dsl_prop_set(name, propname, 1, 13464543Smarks strlen(strval) + 1, strval); 13474543Smarks if (error == 0) 13484543Smarks continue; 13494543Smarks else 13504543Smarks return (error); 13514543Smarks } 13522676Seschrock 13532676Seschrock switch (prop) { 13542676Seschrock case ZFS_PROP_QUOTA: 13552676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13564577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 13572676Seschrock return (error); 13582676Seschrock break; 13592676Seschrock 13602676Seschrock case ZFS_PROP_RESERVATION: 13612676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13622676Seschrock (error = dsl_dir_set_reservation(name, 13632676Seschrock intval)) != 0) 13642676Seschrock return (error); 13652676Seschrock break; 1366789Sahrens 13672676Seschrock case ZFS_PROP_VOLSIZE: 13682676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13694787Sahrens (error = zvol_set_volsize(name, 13704787Sahrens ddi_driver_major(zfs_dip), intval)) != 0) 13712676Seschrock return (error); 13722676Seschrock break; 13732676Seschrock 13742676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 13752676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13764577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 13774577Sahrens return (error); 13784577Sahrens break; 13794577Sahrens 13804577Sahrens case ZFS_PROP_VERSION: 13814577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13824577Sahrens (error = zfs_set_version(name, intval)) != 0) 13832676Seschrock return (error); 13842676Seschrock break; 13852676Seschrock 13862676Seschrock default: 13872676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 13882676Seschrock if (zfs_prop_get_type(prop) != 13894787Sahrens PROP_TYPE_STRING) 13902676Seschrock return (EINVAL); 13912717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 13922717Seschrock if ((error = dsl_prop_set(name, 13932676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 13942717Seschrock strval)) != 0) 13952717Seschrock return (error); 13962676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 13972885Sahrens const char *unused; 13982885Sahrens 13992717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 14002676Seschrock 14012676Seschrock switch (zfs_prop_get_type(prop)) { 14024787Sahrens case PROP_TYPE_NUMBER: 14032676Seschrock break; 14044787Sahrens case PROP_TYPE_STRING: 14052717Seschrock return (EINVAL); 14064787Sahrens case PROP_TYPE_INDEX: 14072717Seschrock if (zfs_prop_index_to_string(prop, 14082717Seschrock intval, &unused) != 0) 14092717Seschrock return (EINVAL); 14102676Seschrock break; 14112676Seschrock default: 14124577Sahrens cmn_err(CE_PANIC, 14134577Sahrens "unknown property type"); 14142676Seschrock break; 14152676Seschrock } 14162676Seschrock 14172717Seschrock if ((error = dsl_prop_set(name, propname, 14182717Seschrock 8, 1, &intval)) != 0) 14192717Seschrock return (error); 14202676Seschrock } else { 14212676Seschrock return (EINVAL); 14222676Seschrock } 14232676Seschrock break; 14242676Seschrock } 14252676Seschrock } 14262676Seschrock 14272676Seschrock return (0); 1428789Sahrens } 1429789Sahrens 1430789Sahrens static int 14312676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1432789Sahrens { 14332676Seschrock nvlist_t *nvl; 14342676Seschrock int error; 1435789Sahrens 14365094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 14375094Slling &nvl)) != 0) 14382676Seschrock return (error); 14392676Seschrock 14404787Sahrens error = zfs_set_prop_nvlist(zc->zc_name, nvl); 14414543Smarks 14422676Seschrock nvlist_free(nvl); 14432676Seschrock return (error); 1444789Sahrens } 1445789Sahrens 1446789Sahrens static int 14474849Sahrens zfs_ioc_inherit_prop(zfs_cmd_t *zc) 14484849Sahrens { 14494849Sahrens /* the property name has been validated by zfs_secpolicy_inherit() */ 14504849Sahrens return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 14514849Sahrens } 14524849Sahrens 14534849Sahrens static int 14544098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 14553912Slling { 14565094Slling nvlist_t *props; 14573912Slling spa_t *spa; 14585094Slling int error; 14593912Slling 14605094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 14615094Slling &props))) 14623912Slling return (error); 14633912Slling 14643912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 14655094Slling nvlist_free(props); 14663912Slling return (error); 14673912Slling } 14683912Slling 14695094Slling error = spa_prop_set(spa, props); 14703912Slling 14715094Slling nvlist_free(props); 14723912Slling spa_close(spa, FTAG); 14733912Slling 14743912Slling return (error); 14753912Slling } 14763912Slling 14773912Slling static int 14784098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 14793912Slling { 14803912Slling spa_t *spa; 14813912Slling int error; 14823912Slling nvlist_t *nvp = NULL; 14833912Slling 14843912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 14853912Slling return (error); 14863912Slling 14875094Slling error = spa_prop_get(spa, &nvp); 14883912Slling 14893912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 14903912Slling error = put_nvlist(zc, nvp); 14913912Slling else 14923912Slling error = EFAULT; 14933912Slling 14943912Slling spa_close(spa, FTAG); 14953912Slling 14963912Slling if (nvp) 14973912Slling nvlist_free(nvp); 14983912Slling return (error); 14993912Slling } 15003912Slling 15013912Slling static int 15024543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 15034543Smarks { 15044543Smarks nvlist_t *nvp; 15054543Smarks int error; 15064543Smarks uint32_t uid; 15074543Smarks uint32_t gid; 15084543Smarks uint32_t *groups; 15094543Smarks uint_t group_cnt; 15104543Smarks cred_t *usercred; 15114543Smarks 15125094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15135094Slling &nvp)) != 0) { 15144543Smarks return (error); 15154543Smarks } 15164543Smarks 15174543Smarks if ((error = nvlist_lookup_uint32(nvp, 15184543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 15194543Smarks nvlist_free(nvp); 15204543Smarks return (EPERM); 15214543Smarks } 15224543Smarks 15234543Smarks if ((error = nvlist_lookup_uint32(nvp, 15244543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 15254543Smarks nvlist_free(nvp); 15264543Smarks return (EPERM); 15274543Smarks } 15284543Smarks 15294543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 15304543Smarks &groups, &group_cnt)) != 0) { 15314543Smarks nvlist_free(nvp); 15324543Smarks return (EPERM); 15334543Smarks } 15344543Smarks usercred = cralloc(); 15354543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 15364543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 15374543Smarks nvlist_free(nvp); 15384543Smarks crfree(usercred); 15394543Smarks return (EPERM); 15404543Smarks } 15414543Smarks nvlist_free(nvp); 15424543Smarks error = dsl_deleg_access(zc->zc_name, 15434787Sahrens zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); 15444543Smarks crfree(usercred); 15454543Smarks return (error); 15464543Smarks } 15474543Smarks 15484543Smarks static int 15494543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 15504543Smarks { 15514543Smarks int error; 15524543Smarks nvlist_t *fsaclnv = NULL; 15534543Smarks 15545094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15555094Slling &fsaclnv)) != 0) 15564543Smarks return (error); 15574543Smarks 15584543Smarks /* 15594543Smarks * Verify nvlist is constructed correctly 15604543Smarks */ 15614543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 15624543Smarks nvlist_free(fsaclnv); 15634543Smarks return (EINVAL); 15644543Smarks } 15654543Smarks 15664543Smarks /* 15674543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 15684543Smarks * that user is allowed to hand out each permission in 15694543Smarks * the nvlist(s) 15704543Smarks */ 15714543Smarks 15724787Sahrens error = secpolicy_zfs(CRED()); 15734543Smarks if (error) { 15744787Sahrens if (zc->zc_perm_action == B_FALSE) { 15754787Sahrens error = dsl_deleg_can_allow(zc->zc_name, 15764787Sahrens fsaclnv, CRED()); 15774787Sahrens } else { 15784787Sahrens error = dsl_deleg_can_unallow(zc->zc_name, 15794787Sahrens fsaclnv, CRED()); 15804787Sahrens } 15814543Smarks } 15824543Smarks 15834543Smarks if (error == 0) 15844543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 15854543Smarks 15864543Smarks nvlist_free(fsaclnv); 15874543Smarks return (error); 15884543Smarks } 15894543Smarks 15904543Smarks static int 15914543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 15924543Smarks { 15934543Smarks nvlist_t *nvp; 15944543Smarks int error; 15954543Smarks 15964543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 15974543Smarks error = put_nvlist(zc, nvp); 15984543Smarks nvlist_free(nvp); 15994543Smarks } 16004543Smarks 16014543Smarks return (error); 16024543Smarks } 16034543Smarks 16044543Smarks static int 1605789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1606789Sahrens { 16074787Sahrens return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); 1608789Sahrens } 1609789Sahrens 1610789Sahrens static int 1611789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1612789Sahrens { 16132676Seschrock return (zvol_remove_minor(zc->zc_name)); 1614789Sahrens } 1615789Sahrens 1616789Sahrens /* 1617789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1618789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1619789Sahrens * is responsible for releasing the returned vfs pointer. 1620789Sahrens */ 1621789Sahrens static vfs_t * 1622789Sahrens zfs_get_vfs(const char *resource) 1623789Sahrens { 1624789Sahrens struct vfs *vfsp; 1625789Sahrens struct vfs *vfs_found = NULL; 1626789Sahrens 1627789Sahrens vfs_list_read_lock(); 1628789Sahrens vfsp = rootvfs; 1629789Sahrens do { 1630789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1631789Sahrens VFS_HOLD(vfsp); 1632789Sahrens vfs_found = vfsp; 1633789Sahrens break; 1634789Sahrens } 1635789Sahrens vfsp = vfsp->vfs_next; 1636789Sahrens } while (vfsp != rootvfs); 1637789Sahrens vfs_list_unlock(); 1638789Sahrens return (vfs_found); 1639789Sahrens } 1640789Sahrens 16414543Smarks /* ARGSUSED */ 1642789Sahrens static void 16434543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1644789Sahrens { 16454577Sahrens nvlist_t *nvprops = arg; 16464577Sahrens uint64_t version = ZPL_VERSION; 16474577Sahrens 16484577Sahrens (void) nvlist_lookup_uint64(nvprops, 16494577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version); 16504577Sahrens 16514577Sahrens zfs_create_fs(os, cr, version, tx); 1652789Sahrens } 1653789Sahrens 1654789Sahrens static int 1655789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1656789Sahrens { 1657789Sahrens objset_t *clone; 1658789Sahrens int error = 0; 16594543Smarks nvlist_t *nvprops = NULL; 16604543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1661789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1662789Sahrens 1663789Sahrens switch (type) { 1664789Sahrens 1665789Sahrens case DMU_OST_ZFS: 1666789Sahrens cbfunc = zfs_create_cb; 1667789Sahrens break; 1668789Sahrens 1669789Sahrens case DMU_OST_ZVOL: 1670789Sahrens cbfunc = zvol_create_cb; 1671789Sahrens break; 1672789Sahrens 1673789Sahrens default: 16742199Sahrens cbfunc = NULL; 16752199Sahrens } 1676*5326Sek110237 if (strchr(zc->zc_name, '@') || 1677*5326Sek110237 strchr(zc->zc_name, '%')) 1678789Sahrens return (EINVAL); 1679789Sahrens 16802676Seschrock if (zc->zc_nvlist_src != NULL && 16815094Slling (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16825094Slling &nvprops)) != 0) 16832676Seschrock return (error); 16842676Seschrock 16852676Seschrock if (zc->zc_value[0] != '\0') { 1686789Sahrens /* 1687789Sahrens * We're creating a clone of an existing snapshot. 1688789Sahrens */ 16892676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 16902676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 16914543Smarks nvlist_free(nvprops); 1692789Sahrens return (EINVAL); 16932676Seschrock } 1694789Sahrens 16952676Seschrock error = dmu_objset_open(zc->zc_value, type, 1696789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 16972676Seschrock if (error) { 16984543Smarks nvlist_free(nvprops); 1699789Sahrens return (error); 17002676Seschrock } 1701789Sahrens error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); 1702789Sahrens dmu_objset_close(clone); 1703789Sahrens } else { 17042676Seschrock if (cbfunc == NULL) { 17054543Smarks nvlist_free(nvprops); 17062199Sahrens return (EINVAL); 17072676Seschrock } 17082676Seschrock 1709789Sahrens if (type == DMU_OST_ZVOL) { 17102676Seschrock uint64_t volsize, volblocksize; 17112676Seschrock 17124543Smarks if (nvprops == NULL || 17134543Smarks nvlist_lookup_uint64(nvprops, 17142676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 17152676Seschrock &volsize) != 0) { 17164543Smarks nvlist_free(nvprops); 17172676Seschrock return (EINVAL); 17182676Seschrock } 17192676Seschrock 17204543Smarks if ((error = nvlist_lookup_uint64(nvprops, 17212676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 17222676Seschrock &volblocksize)) != 0 && error != ENOENT) { 17234543Smarks nvlist_free(nvprops); 17242676Seschrock return (EINVAL); 17252676Seschrock } 17261133Seschrock 17272676Seschrock if (error != 0) 17282676Seschrock volblocksize = zfs_prop_default_numeric( 17292676Seschrock ZFS_PROP_VOLBLOCKSIZE); 17302676Seschrock 17312676Seschrock if ((error = zvol_check_volblocksize( 17322676Seschrock volblocksize)) != 0 || 17332676Seschrock (error = zvol_check_volsize(volsize, 17342676Seschrock volblocksize)) != 0) { 17354543Smarks nvlist_free(nvprops); 1736789Sahrens return (error); 17372676Seschrock } 17384577Sahrens } else if (type == DMU_OST_ZFS) { 17394577Sahrens uint64_t version; 17404577Sahrens 17414577Sahrens if (0 == nvlist_lookup_uint64(nvprops, 17424577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version) && 17434577Sahrens (version < ZPL_VERSION_INITIAL || 17444577Sahrens version > ZPL_VERSION)) { 17454577Sahrens nvlist_free(nvprops); 17464577Sahrens return (EINVAL); 17474577Sahrens } 17482676Seschrock } 17491133Seschrock 17502676Seschrock error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, 17514543Smarks nvprops); 1752789Sahrens } 17532676Seschrock 17542676Seschrock /* 17552676Seschrock * It would be nice to do this atomically. 17562676Seschrock */ 17572676Seschrock if (error == 0) { 17584787Sahrens if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) 17592676Seschrock (void) dmu_objset_destroy(zc->zc_name); 17602676Seschrock } 17612676Seschrock 17624543Smarks nvlist_free(nvprops); 1763789Sahrens return (error); 1764789Sahrens } 1765789Sahrens 1766789Sahrens static int 17672199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 17682199Sahrens { 17692676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 17702199Sahrens return (EINVAL); 17712199Sahrens return (dmu_objset_snapshot(zc->zc_name, 17722676Seschrock zc->zc_value, zc->zc_cookie)); 17732199Sahrens } 17742199Sahrens 17754007Smmusante int 17762199Sahrens zfs_unmount_snap(char *name, void *arg) 1777789Sahrens { 17782199Sahrens char *snapname = arg; 17792199Sahrens char *cp; 17802417Sahrens vfs_t *vfsp = NULL; 17812199Sahrens 17822199Sahrens /* 17832199Sahrens * Snapshots (which are under .zfs control) must be unmounted 17842199Sahrens * before they can be destroyed. 17852199Sahrens */ 17862199Sahrens 17872199Sahrens if (snapname) { 17882199Sahrens (void) strcat(name, "@"); 17892199Sahrens (void) strcat(name, snapname); 17902199Sahrens vfsp = zfs_get_vfs(name); 17912199Sahrens cp = strchr(name, '@'); 17922199Sahrens *cp = '\0'; 17932417Sahrens } else if (strchr(name, '@')) { 17942199Sahrens vfsp = zfs_get_vfs(name); 17952199Sahrens } 17962199Sahrens 17972199Sahrens if (vfsp) { 17982199Sahrens /* 17992199Sahrens * Always force the unmount for snapshots. 18002199Sahrens */ 18012199Sahrens int flag = MS_FORCE; 1802789Sahrens int err; 1803789Sahrens 18042199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 18052199Sahrens VFS_RELE(vfsp); 18062199Sahrens return (err); 18072199Sahrens } 18082199Sahrens VFS_RELE(vfsp); 18092199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 18102199Sahrens return (err); 18112199Sahrens } 18122199Sahrens return (0); 18132199Sahrens } 18142199Sahrens 18152199Sahrens static int 18162199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 18172199Sahrens { 18182199Sahrens int err; 1819789Sahrens 18202676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 18212199Sahrens return (EINVAL); 18222199Sahrens err = dmu_objset_find(zc->zc_name, 18232676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 18242199Sahrens if (err) 18252199Sahrens return (err); 18262676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 18272199Sahrens } 18282199Sahrens 18292199Sahrens static int 18302199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 18312199Sahrens { 18322199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 18332199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18342199Sahrens if (err) 18352199Sahrens return (err); 1836789Sahrens } 1837789Sahrens 1838789Sahrens return (dmu_objset_destroy(zc->zc_name)); 1839789Sahrens } 1840789Sahrens 1841789Sahrens static int 1842789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 1843789Sahrens { 1844789Sahrens return (dmu_objset_rollback(zc->zc_name)); 1845789Sahrens } 1846789Sahrens 1847789Sahrens static int 1848789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 1849789Sahrens { 18504490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 18514007Smmusante 18522676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 1853*5326Sek110237 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 1854*5326Sek110237 strchr(zc->zc_value, '%')) 1855789Sahrens return (EINVAL); 1856789Sahrens 18574007Smmusante /* 18584007Smmusante * Unmount snapshot unless we're doing a recursive rename, 18594007Smmusante * in which case the dataset code figures out which snapshots 18604007Smmusante * to unmount. 18614007Smmusante */ 18624007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 1863789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 18642199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18652199Sahrens if (err) 18662199Sahrens return (err); 1867789Sahrens } 1868789Sahrens 18694007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 1870789Sahrens } 1871789Sahrens 1872789Sahrens static int 1873789Sahrens zfs_ioc_recvbackup(zfs_cmd_t *zc) 1874789Sahrens { 1875789Sahrens file_t *fp; 1876*5326Sek110237 offset_t new_off; 1877*5326Sek110237 objset_t *os; 1878*5326Sek110237 zfsvfs_t *zfsvfs = NULL; 1879*5326Sek110237 char *cp; 1880*5326Sek110237 char cosname[MAXNAMELEN]; 1881*5326Sek110237 boolean_t force = (boolean_t)zc->zc_guid; 1882789Sahrens int error, fd; 1883789Sahrens 18843265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 1885*5326Sek110237 strchr(zc->zc_value, '@') == NULL || 1886*5326Sek110237 strchr(zc->zc_value, '%')) 18873265Sahrens return (EINVAL); 18883265Sahrens 1889789Sahrens fd = zc->zc_cookie; 1890789Sahrens fp = getf(fd); 1891789Sahrens if (fp == NULL) 1892789Sahrens return (EBADF); 1893*5326Sek110237 1894*5326Sek110237 /* 1895*5326Sek110237 * Get the zfsvfs for the receiving objset. There 1896*5326Sek110237 * won't be one if we're operating on a zvol, if the 1897*5326Sek110237 * objset doesn't exist yet, or is not mounted. 1898*5326Sek110237 */ 1899*5326Sek110237 cp = strchr(zc->zc_value, '@'); 1900*5326Sek110237 *cp = '\0'; 1901*5326Sek110237 error = dmu_objset_open(zc->zc_value, DMU_OST_ANY, 1902*5326Sek110237 DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1903*5326Sek110237 *cp = '@'; 1904*5326Sek110237 if (!error) { 1905*5326Sek110237 if (dmu_objset_type(os) == DMU_OST_ZFS) { 1906*5326Sek110237 mutex_enter(&os->os->os_user_ptr_lock); 1907*5326Sek110237 zfsvfs = dmu_objset_get_user(os); 1908*5326Sek110237 if (zfsvfs != NULL) 1909*5326Sek110237 VFS_HOLD(zfsvfs->z_vfs); 1910*5326Sek110237 mutex_exit(&os->os->os_user_ptr_lock); 1911*5326Sek110237 } 1912*5326Sek110237 dmu_objset_close(os); 1913*5326Sek110237 } 1914*5326Sek110237 19152676Seschrock error = dmu_recvbackup(zc->zc_value, &zc->zc_begin_record, 1916*5326Sek110237 &zc->zc_cookie, force, zfsvfs != NULL, fp->f_vnode, 1917*5326Sek110237 fp->f_offset, cosname); 1918*5326Sek110237 1919*5326Sek110237 /* 1920*5326Sek110237 * For incremental snapshots where we created a 1921*5326Sek110237 * temporary clone, we now swap zfsvfs::z_os with 1922*5326Sek110237 * the newly created and received "cosname". 1923*5326Sek110237 */ 1924*5326Sek110237 if (!error && zfsvfs != NULL) { 1925*5326Sek110237 char osname[MAXNAMELEN]; 1926*5326Sek110237 int mode; 1927*5326Sek110237 1928*5326Sek110237 error = zfs_suspend_fs(zfsvfs, osname, &mode); 1929*5326Sek110237 if (!error) { 1930*5326Sek110237 int swap_err; 1931*5326Sek110237 int snap_err = 0; 19322885Sahrens 1933*5326Sek110237 swap_err = dsl_dataset_clone_swap(cosname, force); 1934*5326Sek110237 if (!swap_err) { 1935*5326Sek110237 char *cp = strrchr(zc->zc_value, '@'); 1936*5326Sek110237 1937*5326Sek110237 *cp = '\0'; 1938*5326Sek110237 snap_err = dmu_replay_end_snapshot(zc->zc_value, 1939*5326Sek110237 &zc->zc_begin_record); 1940*5326Sek110237 *cp = '@'; 1941*5326Sek110237 } 1942*5326Sek110237 error = zfs_resume_fs(zfsvfs, osname, mode); 1943*5326Sek110237 if (!error) 1944*5326Sek110237 error = swap_err; 1945*5326Sek110237 if (!error) 1946*5326Sek110237 error = snap_err; 1947*5326Sek110237 } 1948*5326Sek110237 1949*5326Sek110237 /* destroy the clone we created */ 1950*5326Sek110237 (void) dmu_objset_destroy(cosname); 1951*5326Sek110237 } 1952*5326Sek110237 if (zfsvfs != NULL) 1953*5326Sek110237 VFS_RELE(zfsvfs->z_vfs); 19542885Sahrens new_off = fp->f_offset + zc->zc_cookie; 19552885Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &new_off) == 0) 19562885Sahrens fp->f_offset = new_off; 19572885Sahrens 1958789Sahrens releasef(fd); 1959789Sahrens return (error); 1960789Sahrens } 1961789Sahrens 1962789Sahrens static int 1963789Sahrens zfs_ioc_sendbackup(zfs_cmd_t *zc) 1964789Sahrens { 1965789Sahrens objset_t *fromsnap = NULL; 1966789Sahrens objset_t *tosnap; 1967789Sahrens file_t *fp; 1968789Sahrens int error; 1969789Sahrens 1970789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1971789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); 1972789Sahrens if (error) 1973789Sahrens return (error); 1974789Sahrens 19752676Seschrock if (zc->zc_value[0] != '\0') { 19762885Sahrens char buf[MAXPATHLEN]; 19772885Sahrens char *cp; 19782885Sahrens 19792885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 19802885Sahrens cp = strchr(buf, '@'); 19812885Sahrens if (cp) 19822885Sahrens *(cp+1) = 0; 19832885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 19842885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 1985789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); 1986789Sahrens if (error) { 1987789Sahrens dmu_objset_close(tosnap); 1988789Sahrens return (error); 1989789Sahrens } 1990789Sahrens } 1991789Sahrens 1992789Sahrens fp = getf(zc->zc_cookie); 1993789Sahrens if (fp == NULL) { 1994789Sahrens dmu_objset_close(tosnap); 1995789Sahrens if (fromsnap) 1996789Sahrens dmu_objset_close(fromsnap); 1997789Sahrens return (EBADF); 1998789Sahrens } 1999789Sahrens 2000789Sahrens error = dmu_sendbackup(tosnap, fromsnap, fp->f_vnode); 2001789Sahrens 2002789Sahrens releasef(zc->zc_cookie); 2003789Sahrens if (fromsnap) 2004789Sahrens dmu_objset_close(fromsnap); 2005789Sahrens dmu_objset_close(tosnap); 2006789Sahrens return (error); 2007789Sahrens } 2008789Sahrens 20091544Seschrock static int 20101544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 20111544Seschrock { 20121544Seschrock int id, error; 20131544Seschrock 20141544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 20151544Seschrock &zc->zc_inject_record); 20161544Seschrock 20171544Seschrock if (error == 0) 20181544Seschrock zc->zc_guid = (uint64_t)id; 20191544Seschrock 20201544Seschrock return (error); 20211544Seschrock } 20221544Seschrock 20231544Seschrock static int 20241544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 20251544Seschrock { 20261544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 20271544Seschrock } 20281544Seschrock 20291544Seschrock static int 20301544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 20311544Seschrock { 20321544Seschrock int id = (int)zc->zc_guid; 20331544Seschrock int error; 20341544Seschrock 20351544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 20361544Seschrock &zc->zc_inject_record); 20371544Seschrock 20381544Seschrock zc->zc_guid = id; 20391544Seschrock 20401544Seschrock return (error); 20411544Seschrock } 20421544Seschrock 20431544Seschrock static int 20441544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 20451544Seschrock { 20461544Seschrock spa_t *spa; 20471544Seschrock int error; 20482676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 20491544Seschrock 20501544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 20511544Seschrock return (error); 20521544Seschrock 20532676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 20541544Seschrock &count); 20551544Seschrock if (error == 0) 20562676Seschrock zc->zc_nvlist_dst_size = count; 20571544Seschrock else 20582676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 20591544Seschrock 20601544Seschrock spa_close(spa, FTAG); 20611544Seschrock 20621544Seschrock return (error); 20631544Seschrock } 20641544Seschrock 20651544Seschrock static int 20661544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 20671544Seschrock { 20681544Seschrock spa_t *spa; 20691544Seschrock vdev_t *vd; 20704808Sek110237 uint64_t txg; 20711544Seschrock int error; 20721544Seschrock 20731544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 20741544Seschrock return (error); 20751544Seschrock 20764451Seschrock txg = spa_vdev_enter(spa); 20771544Seschrock 20782676Seschrock if (zc->zc_guid == 0) { 20791544Seschrock vd = NULL; 20802676Seschrock } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { 20814451Seschrock (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 20821544Seschrock spa_close(spa, FTAG); 20831544Seschrock return (ENODEV); 20841544Seschrock } 20851544Seschrock 20861544Seschrock vdev_clear(spa, vd); 20871544Seschrock 20884451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 20891544Seschrock 20901544Seschrock spa_close(spa, FTAG); 20911544Seschrock 20921544Seschrock return (0); 20931544Seschrock } 20941544Seschrock 20951544Seschrock static int 20962082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 20972082Seschrock { 20982417Sahrens char *cp; 20992417Sahrens 21002417Sahrens /* 21012417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 21022417Sahrens * it's easier. 21032417Sahrens */ 21042676Seschrock cp = strchr(zc->zc_value, '@'); 21052417Sahrens if (cp) 21062417Sahrens *cp = '\0'; 21072676Seschrock (void) dmu_objset_find(zc->zc_value, 21082417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 21092082Seschrock return (dsl_dataset_promote(zc->zc_name)); 21102082Seschrock } 21112082Seschrock 21124543Smarks /* 21134543Smarks * We don't want to have a hard dependency 21144543Smarks * against some special symbols in sharefs 21154543Smarks * and nfs. Determine them if needed when 21164543Smarks * the first file system is shared. 21174543Smarks * Neither sharefs or nfs are unloadable modules. 21184543Smarks */ 21194543Smarks int (*zexport_fs)(void *arg); 21204543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 21214543Smarks 21224543Smarks int zfs_share_inited; 21234543Smarks ddi_modhandle_t nfs_mod; 21244543Smarks ddi_modhandle_t sharefs_mod; 21254543Smarks kmutex_t zfs_share_lock; 21264543Smarks 21274543Smarks static int 21284543Smarks zfs_ioc_share(zfs_cmd_t *zc) 21294543Smarks { 21304543Smarks int error; 21314543Smarks int opcode; 21324543Smarks 21334543Smarks if (zfs_share_inited == 0) { 21344543Smarks mutex_enter(&zfs_share_lock); 21354543Smarks nfs_mod = ddi_modopen("fs/nfs", KRTLD_MODE_FIRST, &error); 21364543Smarks sharefs_mod = ddi_modopen("fs/sharefs", 21374543Smarks KRTLD_MODE_FIRST, &error); 21384543Smarks if (nfs_mod == NULL || sharefs_mod == NULL) { 21394543Smarks mutex_exit(&zfs_share_lock); 21404543Smarks return (ENOSYS); 21414543Smarks } 21424543Smarks if (zexport_fs == NULL && ((zexport_fs = (int (*)(void *)) 21434543Smarks ddi_modsym(nfs_mod, "nfs_export", &error)) == NULL)) { 21444543Smarks mutex_exit(&zfs_share_lock); 21454543Smarks return (ENOSYS); 21464543Smarks } 21474543Smarks 21484543Smarks if (zshare_fs == NULL && ((zshare_fs = 21494543Smarks (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 21504543Smarks ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 21514543Smarks mutex_exit(&zfs_share_lock); 21524543Smarks return (ENOSYS); 21534543Smarks } 21544543Smarks zfs_share_inited = 1; 21554543Smarks mutex_exit(&zfs_share_lock); 21564543Smarks } 21574543Smarks 21584543Smarks if (error = zexport_fs((void *)(uintptr_t)zc->zc_share.z_exportdata)) 21594543Smarks return (error); 21604543Smarks 21614543Smarks opcode = (zc->zc_share.z_sharetype == B_TRUE) ? 21624543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 21634543Smarks 21644543Smarks error = zshare_fs(opcode, 21654543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 21664543Smarks zc->zc_share.z_sharemax); 21674543Smarks 21684543Smarks return (error); 21694543Smarks 21704543Smarks } 21714543Smarks 21724543Smarks /* 21734988Sek110237 * pool create, destroy, and export don't log the history as part of 21744988Sek110237 * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export 21754988Sek110237 * do the logging of those commands. 21764543Smarks */ 2177789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 21784715Sek110237 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21794577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21804577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21814577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21824577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 21834577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 21844577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21854577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21864577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 21874577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21884577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21894577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21904577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21914577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21924577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21934577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 21944577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 21954577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 21965147Srm160521 { zfs_ioc_objset_version, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 21974543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 21984577Sahrens DATASET_NAME, B_FALSE }, 21994543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 22004577Sahrens DATASET_NAME, B_FALSE }, 22014577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 22024577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 22034577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 22044577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 22054577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 22064577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 22074577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 22084577Sahrens { zfs_ioc_recvbackup, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 22094577Sahrens { zfs_ioc_sendbackup, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 22104577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 22114577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 22124577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 22134577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 22144577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 22154577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 22164577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 22174577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 22184577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 22194577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 22204577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 22214577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 22224577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 22234577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 22244543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 22254577Sahrens DATASET_NAME, B_FALSE }, 22264849Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }, 22274849Sahrens { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE }, 2228789Sahrens }; 2229789Sahrens 2230789Sahrens static int 2231789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2232789Sahrens { 2233789Sahrens zfs_cmd_t *zc; 2234789Sahrens uint_t vec; 22352199Sahrens int error, rc; 2236789Sahrens 2237789Sahrens if (getminor(dev) != 0) 2238789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2239789Sahrens 2240789Sahrens vec = cmd - ZFS_IOC; 22414787Sahrens ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); 2242789Sahrens 2243789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2244789Sahrens return (EINVAL); 2245789Sahrens 2246789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2247789Sahrens 2248789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2249789Sahrens 22504787Sahrens if (error == 0) 22514543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2252789Sahrens 2253789Sahrens /* 2254789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2255789Sahrens * the lower layers. 2256789Sahrens */ 2257789Sahrens if (error == 0) { 2258789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2259789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 22604577Sahrens case POOL_NAME: 2261789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2262789Sahrens error = EINVAL; 2263789Sahrens break; 2264789Sahrens 22654577Sahrens case DATASET_NAME: 2266789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2267789Sahrens error = EINVAL; 2268789Sahrens break; 22692856Snd150628 22704577Sahrens case NO_NAME: 22712856Snd150628 break; 2272789Sahrens } 2273789Sahrens } 2274789Sahrens 2275789Sahrens if (error == 0) 2276789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2277789Sahrens 22782199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 22794543Smarks if (error == 0) { 22802199Sahrens error = rc; 22814543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 22824543Smarks zfs_log_history(zc); 22834543Smarks } 2284789Sahrens 2285789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2286789Sahrens return (error); 2287789Sahrens } 2288789Sahrens 2289789Sahrens static int 2290789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2291789Sahrens { 2292789Sahrens if (cmd != DDI_ATTACH) 2293789Sahrens return (DDI_FAILURE); 2294789Sahrens 2295789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2296789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2297789Sahrens return (DDI_FAILURE); 2298789Sahrens 2299789Sahrens zfs_dip = dip; 2300789Sahrens 2301789Sahrens ddi_report_dev(dip); 2302789Sahrens 2303789Sahrens return (DDI_SUCCESS); 2304789Sahrens } 2305789Sahrens 2306789Sahrens static int 2307789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2308789Sahrens { 2309789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2310789Sahrens return (DDI_FAILURE); 2311789Sahrens 2312789Sahrens if (cmd != DDI_DETACH) 2313789Sahrens return (DDI_FAILURE); 2314789Sahrens 2315789Sahrens zfs_dip = NULL; 2316789Sahrens 2317789Sahrens ddi_prop_remove_all(dip); 2318789Sahrens ddi_remove_minor_node(dip, NULL); 2319789Sahrens 2320789Sahrens return (DDI_SUCCESS); 2321789Sahrens } 2322789Sahrens 2323789Sahrens /*ARGSUSED*/ 2324789Sahrens static int 2325789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2326789Sahrens { 2327789Sahrens switch (infocmd) { 2328789Sahrens case DDI_INFO_DEVT2DEVINFO: 2329789Sahrens *result = zfs_dip; 2330789Sahrens return (DDI_SUCCESS); 2331789Sahrens 2332789Sahrens case DDI_INFO_DEVT2INSTANCE: 2333849Sbonwick *result = (void *)0; 2334789Sahrens return (DDI_SUCCESS); 2335789Sahrens } 2336789Sahrens 2337789Sahrens return (DDI_FAILURE); 2338789Sahrens } 2339789Sahrens 2340789Sahrens /* 2341789Sahrens * OK, so this is a little weird. 2342789Sahrens * 2343789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2344789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2345789Sahrens * 2346789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2347789Sahrens * so most of the standard driver entry points are in zvol.c. 2348789Sahrens */ 2349789Sahrens static struct cb_ops zfs_cb_ops = { 2350789Sahrens zvol_open, /* open */ 2351789Sahrens zvol_close, /* close */ 2352789Sahrens zvol_strategy, /* strategy */ 2353789Sahrens nodev, /* print */ 2354789Sahrens nodev, /* dump */ 2355789Sahrens zvol_read, /* read */ 2356789Sahrens zvol_write, /* write */ 2357789Sahrens zfsdev_ioctl, /* ioctl */ 2358789Sahrens nodev, /* devmap */ 2359789Sahrens nodev, /* mmap */ 2360789Sahrens nodev, /* segmap */ 2361789Sahrens nochpoll, /* poll */ 2362789Sahrens ddi_prop_op, /* prop_op */ 2363789Sahrens NULL, /* streamtab */ 2364789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2365789Sahrens CB_REV, /* version */ 23663638Sbillm nodev, /* async read */ 23673638Sbillm nodev, /* async write */ 2368789Sahrens }; 2369789Sahrens 2370789Sahrens static struct dev_ops zfs_dev_ops = { 2371789Sahrens DEVO_REV, /* version */ 2372789Sahrens 0, /* refcnt */ 2373789Sahrens zfs_info, /* info */ 2374789Sahrens nulldev, /* identify */ 2375789Sahrens nulldev, /* probe */ 2376789Sahrens zfs_attach, /* attach */ 2377789Sahrens zfs_detach, /* detach */ 2378789Sahrens nodev, /* reset */ 2379789Sahrens &zfs_cb_ops, /* driver operations */ 2380789Sahrens NULL /* no bus operations */ 2381789Sahrens }; 2382789Sahrens 2383789Sahrens static struct modldrv zfs_modldrv = { 23844577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 23852676Seschrock &zfs_dev_ops 2386789Sahrens }; 2387789Sahrens 2388789Sahrens static struct modlinkage modlinkage = { 2389789Sahrens MODREV_1, 2390789Sahrens (void *)&zfs_modlfs, 2391789Sahrens (void *)&zfs_modldrv, 2392789Sahrens NULL 2393789Sahrens }; 2394789Sahrens 23954720Sfr157268 23964720Sfr157268 uint_t zfs_fsyncer_key; 2397*5326Sek110237 extern uint_t rrw_tsd_key; 23984720Sfr157268 2399789Sahrens int 2400789Sahrens _init(void) 2401789Sahrens { 2402789Sahrens int error; 2403789Sahrens 2404849Sbonwick spa_init(FREAD | FWRITE); 2405849Sbonwick zfs_init(); 2406849Sbonwick zvol_init(); 2407849Sbonwick 2408849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 2409849Sbonwick zvol_fini(); 2410849Sbonwick zfs_fini(); 2411849Sbonwick spa_fini(); 2412789Sahrens return (error); 2413849Sbonwick } 2414789Sahrens 24154720Sfr157268 tsd_create(&zfs_fsyncer_key, NULL); 2416*5326Sek110237 tsd_create(&rrw_tsd_key, NULL); 24174720Sfr157268 2418789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 2419789Sahrens ASSERT(error == 0); 24204543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 2421789Sahrens 2422789Sahrens return (0); 2423789Sahrens } 2424789Sahrens 2425789Sahrens int 2426789Sahrens _fini(void) 2427789Sahrens { 2428789Sahrens int error; 2429789Sahrens 24301544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 2431789Sahrens return (EBUSY); 2432789Sahrens 2433789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 2434789Sahrens return (error); 2435789Sahrens 2436789Sahrens zvol_fini(); 2437789Sahrens zfs_fini(); 2438789Sahrens spa_fini(); 24394543Smarks if (zfs_share_inited) { 24404543Smarks (void) ddi_modclose(nfs_mod); 24414543Smarks (void) ddi_modclose(sharefs_mod); 24424543Smarks } 2443789Sahrens 24444720Sfr157268 tsd_destroy(&zfs_fsyncer_key); 2445789Sahrens ldi_ident_release(zfs_li); 2446789Sahrens zfs_li = NULL; 24474543Smarks mutex_destroy(&zfs_share_lock); 2448789Sahrens 2449789Sahrens return (error); 2450789Sahrens } 2451789Sahrens 2452789Sahrens int 2453789Sahrens _info(struct modinfo *modinfop) 2454789Sahrens { 2455789Sahrens return (mod_info(&modlinkage, modinfop)); 2456789Sahrens } 2457