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> 41*5331Samw #include <sys/zfs_i18n.h> 42*5331Samw #include <sys/zfs_znode.h> 43789Sahrens #include <sys/zap.h> 44789Sahrens #include <sys/spa.h> 453912Slling #include <sys/spa_impl.h> 46789Sahrens #include <sys/vdev.h> 473912Slling #include <sys/vdev_impl.h> 48789Sahrens #include <sys/dmu.h> 49789Sahrens #include <sys/dsl_dir.h> 50789Sahrens #include <sys/dsl_dataset.h> 51789Sahrens #include <sys/dsl_prop.h> 524543Smarks #include <sys/dsl_deleg.h> 534543Smarks #include <sys/dmu_objset.h> 54789Sahrens #include <sys/ddi.h> 55789Sahrens #include <sys/sunddi.h> 56789Sahrens #include <sys/sunldi.h> 57789Sahrens #include <sys/policy.h> 58789Sahrens #include <sys/zone.h> 59789Sahrens #include <sys/nvpair.h> 60789Sahrens #include <sys/pathname.h> 61789Sahrens #include <sys/mount.h> 62789Sahrens #include <sys/sdt.h> 63789Sahrens #include <sys/fs/zfs.h> 64789Sahrens #include <sys/zfs_ctldir.h> 65*5331Samw #include <sys/zfs_dir.h> 662885Sahrens #include <sys/zvol.h> 674543Smarks #include <sharefs/share.h> 684577Sahrens #include <sys/zfs_znode.h> 695326Sek110237 #include <sys/zfs_vfsops.h> 705326Sek110237 #include <sys/dmu_objset.h> 71789Sahrens 72789Sahrens #include "zfs_namecheck.h" 732676Seschrock #include "zfs_prop.h" 744543Smarks #include "zfs_deleg.h" 75789Sahrens 76789Sahrens extern struct modlfs zfs_modlfs; 77789Sahrens 78789Sahrens extern void zfs_init(void); 79789Sahrens extern void zfs_fini(void); 80789Sahrens 81789Sahrens ldi_ident_t zfs_li = NULL; 82789Sahrens dev_info_t *zfs_dip; 83789Sahrens 84789Sahrens typedef int zfs_ioc_func_t(zfs_cmd_t *); 854543Smarks typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *); 86789Sahrens 87789Sahrens typedef struct zfs_ioc_vec { 88789Sahrens zfs_ioc_func_t *zvec_func; 89789Sahrens zfs_secpolicy_func_t *zvec_secpolicy; 90789Sahrens enum { 914577Sahrens NO_NAME, 924577Sahrens POOL_NAME, 934577Sahrens DATASET_NAME 944543Smarks } zvec_namecheck; 954543Smarks boolean_t zvec_his_log; 96789Sahrens } zfs_ioc_vec_t; 97789Sahrens 98789Sahrens /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */ 99789Sahrens void 100789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 101789Sahrens { 102789Sahrens const char *newfile; 103789Sahrens char buf[256]; 104789Sahrens va_list adx; 105789Sahrens 106789Sahrens /* 107789Sahrens * Get rid of annoying "../common/" prefix to filename. 108789Sahrens */ 109789Sahrens newfile = strrchr(file, '/'); 110789Sahrens if (newfile != NULL) { 111789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 112789Sahrens } else { 113789Sahrens newfile = file; 114789Sahrens } 115789Sahrens 116789Sahrens va_start(adx, fmt); 117789Sahrens (void) vsnprintf(buf, sizeof (buf), fmt, adx); 118789Sahrens va_end(adx); 119789Sahrens 120789Sahrens /* 121789Sahrens * To get this data, use the zfs-dprintf probe as so: 122789Sahrens * dtrace -q -n 'zfs-dprintf \ 123789Sahrens * /stringof(arg0) == "dbuf.c"/ \ 124789Sahrens * {printf("%s: %s", stringof(arg1), stringof(arg3))}' 125789Sahrens * arg0 = file name 126789Sahrens * arg1 = function name 127789Sahrens * arg2 = line number 128789Sahrens * arg3 = message 129789Sahrens */ 130789Sahrens DTRACE_PROBE4(zfs__dprintf, 131789Sahrens char *, newfile, char *, func, int, line, char *, buf); 132789Sahrens } 133789Sahrens 1344543Smarks static void 1354715Sek110237 history_str_free(char *buf) 1364715Sek110237 { 1374715Sek110237 kmem_free(buf, HIS_MAX_RECORD_LEN); 1384715Sek110237 } 1394715Sek110237 1404715Sek110237 static char * 1414715Sek110237 history_str_get(zfs_cmd_t *zc) 1424715Sek110237 { 1434715Sek110237 char *buf; 1444715Sek110237 1454715Sek110237 if (zc->zc_history == NULL) 1464715Sek110237 return (NULL); 1474715Sek110237 1484715Sek110237 buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP); 1494715Sek110237 if (copyinstr((void *)(uintptr_t)zc->zc_history, 1504715Sek110237 buf, HIS_MAX_RECORD_LEN, NULL) != 0) { 1514715Sek110237 history_str_free(buf); 1524715Sek110237 return (NULL); 1534715Sek110237 } 1544715Sek110237 1554715Sek110237 buf[HIS_MAX_RECORD_LEN -1] = '\0'; 1564715Sek110237 1574715Sek110237 return (buf); 1584715Sek110237 } 1594715Sek110237 160*5331Samw static int 161*5331Samw zfs_check_version(const char *name, int version) 162*5331Samw { 163*5331Samw 164*5331Samw spa_t *spa; 165*5331Samw 166*5331Samw if (spa_open(name, &spa, FTAG) == 0) { 167*5331Samw if (spa_version(spa) < version) { 168*5331Samw spa_close(spa, FTAG); 169*5331Samw return (1); 170*5331Samw } 171*5331Samw spa_close(spa, FTAG); 172*5331Samw } 173*5331Samw return (0); 174*5331Samw } 175*5331Samw 1764715Sek110237 static void 1774543Smarks zfs_log_history(zfs_cmd_t *zc) 1784543Smarks { 1794543Smarks spa_t *spa; 1804603Sahrens char *buf; 1814543Smarks 1824715Sek110237 if ((buf = history_str_get(zc)) == NULL) 1834577Sahrens return; 1844577Sahrens 1854715Sek110237 if (spa_open(zc->zc_name, &spa, FTAG) == 0) { 1864715Sek110237 if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY) 1874715Sek110237 (void) spa_history_log(spa, buf, LOG_CMD_NORMAL); 1884715Sek110237 spa_close(spa, FTAG); 1894543Smarks } 1904715Sek110237 history_str_free(buf); 1914543Smarks } 1924543Smarks 193789Sahrens /* 194789Sahrens * Policy for top-level read operations (list pools). Requires no privileges, 195789Sahrens * and can be used in the local zone, as there is no associated dataset. 196789Sahrens */ 197789Sahrens /* ARGSUSED */ 198789Sahrens static int 1994543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) 200789Sahrens { 201789Sahrens return (0); 202789Sahrens } 203789Sahrens 204789Sahrens /* 205789Sahrens * Policy for dataset read operations (list children, get statistics). Requires 206789Sahrens * no privileges, but must be visible in the local zone. 207789Sahrens */ 208789Sahrens /* ARGSUSED */ 209789Sahrens static int 2104543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) 211789Sahrens { 212789Sahrens if (INGLOBALZONE(curproc) || 2134543Smarks zone_dataset_visible(zc->zc_name, NULL)) 214789Sahrens return (0); 215789Sahrens 216789Sahrens return (ENOENT); 217789Sahrens } 218789Sahrens 219789Sahrens static int 220789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr) 221789Sahrens { 222789Sahrens uint64_t zoned; 223789Sahrens int writable = 1; 224789Sahrens 225789Sahrens /* 226789Sahrens * The dataset must be visible by this zone -- check this first 227789Sahrens * so they don't see EPERM on something they shouldn't know about. 228789Sahrens */ 229789Sahrens if (!INGLOBALZONE(curproc) && 230789Sahrens !zone_dataset_visible(dataset, &writable)) 231789Sahrens return (ENOENT); 232789Sahrens 233789Sahrens if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) 234789Sahrens return (ENOENT); 235789Sahrens 236789Sahrens if (INGLOBALZONE(curproc)) { 237789Sahrens /* 238789Sahrens * If the fs is zoned, only root can access it from the 239789Sahrens * global zone. 240789Sahrens */ 241789Sahrens if (secpolicy_zfs(cr) && zoned) 242789Sahrens return (EPERM); 243789Sahrens } else { 244789Sahrens /* 245789Sahrens * If we are in a local zone, the 'zoned' property must be set. 246789Sahrens */ 247789Sahrens if (!zoned) 248789Sahrens return (EPERM); 249789Sahrens 250789Sahrens /* must be writable by this zone */ 251789Sahrens if (!writable) 252789Sahrens return (EPERM); 253789Sahrens } 254789Sahrens return (0); 255789Sahrens } 256789Sahrens 257789Sahrens int 2584543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) 259789Sahrens { 260789Sahrens int error; 261789Sahrens 2624543Smarks error = zfs_dozonecheck(name, cr); 2634543Smarks if (error == 0) { 2644543Smarks error = secpolicy_zfs(cr); 2654670Sahrens if (error) 2664543Smarks error = dsl_deleg_access(name, perm, cr); 2674543Smarks } 2684543Smarks return (error); 2694543Smarks } 2704543Smarks 2714543Smarks static int 2724543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) 2734543Smarks { 2744543Smarks /* 2754543Smarks * Check permissions for special properties. 2764543Smarks */ 2774543Smarks switch (prop) { 2784543Smarks case ZFS_PROP_ZONED: 2794543Smarks /* 2804543Smarks * Disallow setting of 'zoned' from within a local zone. 2814543Smarks */ 2824543Smarks if (!INGLOBALZONE(curproc)) 2834543Smarks return (EPERM); 2844543Smarks break; 285789Sahrens 2864543Smarks case ZFS_PROP_QUOTA: 2874543Smarks if (!INGLOBALZONE(curproc)) { 2884543Smarks uint64_t zoned; 2894543Smarks char setpoint[MAXNAMELEN]; 2904543Smarks /* 2914543Smarks * Unprivileged users are allowed to modify the 2924543Smarks * quota on things *under* (ie. contained by) 2934543Smarks * the thing they own. 2944543Smarks */ 2954543Smarks if (dsl_prop_get_integer(name, "zoned", &zoned, 2964543Smarks setpoint)) 2974543Smarks return (EPERM); 2984670Sahrens if (!zoned || strlen(name) <= strlen(setpoint)) 2994543Smarks return (EPERM); 3004543Smarks } 3014670Sahrens break; 3024543Smarks } 3034543Smarks 3044787Sahrens return (zfs_secpolicy_write_perms(name, zfs_prop_to_name(prop), cr)); 305789Sahrens } 306789Sahrens 3074543Smarks int 3084543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) 3094543Smarks { 3104543Smarks int error; 3114543Smarks 3124543Smarks error = zfs_dozonecheck(zc->zc_name, cr); 3134543Smarks if (error) 3144543Smarks return (error); 3154543Smarks 3164543Smarks /* 3174543Smarks * permission to set permissions will be evaluated later in 3184543Smarks * dsl_deleg_can_allow() 3194543Smarks */ 3204543Smarks return (0); 3214543Smarks } 3224543Smarks 3234543Smarks int 3244543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) 3254543Smarks { 3264543Smarks int error; 3274543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3284543Smarks ZFS_DELEG_PERM_ROLLBACK, cr); 3294543Smarks if (error == 0) 3304543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3314543Smarks ZFS_DELEG_PERM_MOUNT, cr); 3324543Smarks return (error); 3334543Smarks } 3344543Smarks 3354543Smarks int 3364543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) 3374543Smarks { 3384543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 3394543Smarks ZFS_DELEG_PERM_SEND, cr)); 3404543Smarks } 3414543Smarks 3424543Smarks int 3434543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) 3444543Smarks { 3454543Smarks if (!INGLOBALZONE(curproc)) 3464543Smarks return (EPERM); 3474543Smarks 3484543Smarks if (secpolicy_nfs(CRED()) == 0) { 3494543Smarks return (0); 3504543Smarks } else { 3514543Smarks vnode_t *vp; 3524543Smarks int error; 3534543Smarks 3544543Smarks if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, 3554543Smarks NO_FOLLOW, NULL, &vp)) != 0) 3564543Smarks return (error); 3574543Smarks 3584543Smarks /* Now make sure mntpnt and dataset are ZFS */ 3594543Smarks 3604543Smarks if (vp->v_vfsp->vfs_fstype != zfsfstype || 3614543Smarks (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), 3624543Smarks zc->zc_name) != 0)) { 3634543Smarks VN_RELE(vp); 3644543Smarks return (EPERM); 3654543Smarks } 3664543Smarks 3674543Smarks VN_RELE(vp); 3684543Smarks return (dsl_deleg_access(zc->zc_name, 3694543Smarks ZFS_DELEG_PERM_SHARE, cr)); 3704543Smarks } 3714543Smarks } 3724543Smarks 373789Sahrens static int 3744543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize) 375789Sahrens { 376789Sahrens char *cp; 377789Sahrens 378789Sahrens /* 379789Sahrens * Remove the @bla or /bla from the end of the name to get the parent. 380789Sahrens */ 3814543Smarks (void) strncpy(parent, datasetname, parentsize); 3824543Smarks cp = strrchr(parent, '@'); 383789Sahrens if (cp != NULL) { 384789Sahrens cp[0] = '\0'; 385789Sahrens } else { 3864543Smarks cp = strrchr(parent, '/'); 387789Sahrens if (cp == NULL) 388789Sahrens return (ENOENT); 389789Sahrens cp[0] = '\0'; 390789Sahrens } 391789Sahrens 3924543Smarks return (0); 3934543Smarks } 3944543Smarks 3954543Smarks int 3964543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 3974543Smarks { 3984543Smarks int error; 3994543Smarks 4004543Smarks if ((error = zfs_secpolicy_write_perms(name, 4014543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4024543Smarks return (error); 4034543Smarks 4044543Smarks return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); 4054543Smarks } 4064543Smarks 4074543Smarks static int 4084543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) 4094543Smarks { 4104543Smarks return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); 4114543Smarks } 4124543Smarks 4134543Smarks /* 4144543Smarks * Must have sys_config privilege to check the iscsi permission 4154543Smarks */ 4164543Smarks /* ARGSUSED */ 4174543Smarks static int 4184543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) 4194543Smarks { 4204543Smarks return (secpolicy_zfs(cr)); 4214543Smarks } 4224543Smarks 4234543Smarks int 4244543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 4254543Smarks { 4264543Smarks char parentname[MAXNAMELEN]; 4274543Smarks int error; 4284543Smarks 4294543Smarks if ((error = zfs_secpolicy_write_perms(from, 4304543Smarks ZFS_DELEG_PERM_RENAME, cr)) != 0) 4314543Smarks return (error); 4324543Smarks 4334543Smarks if ((error = zfs_secpolicy_write_perms(from, 4344543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4354543Smarks return (error); 4364543Smarks 4374543Smarks if ((error = zfs_get_parent(to, parentname, 4384543Smarks sizeof (parentname))) != 0) 4394543Smarks return (error); 4404543Smarks 4414543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4424543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 4434543Smarks return (error); 4444543Smarks 4454543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4464543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4474543Smarks return (error); 4484543Smarks 4494543Smarks return (error); 4504543Smarks } 4514543Smarks 4524543Smarks static int 4534543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) 4544543Smarks { 4554543Smarks return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); 4564543Smarks } 4574543Smarks 4584543Smarks static int 4594543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) 4604543Smarks { 4614543Smarks char parentname[MAXNAMELEN]; 4624543Smarks objset_t *clone; 4634543Smarks int error; 4644543Smarks 4654543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4664543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4674543Smarks if (error) 4684543Smarks return (error); 4694543Smarks 4704543Smarks error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 4714543Smarks DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 4724543Smarks 4734543Smarks if (error == 0) { 4744543Smarks dsl_dataset_t *pclone = NULL; 4754543Smarks dsl_dir_t *dd; 4764543Smarks dd = clone->os->os_dsl_dataset->ds_dir; 4774543Smarks 4784543Smarks rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 4794543Smarks error = dsl_dataset_open_obj(dd->dd_pool, 4804543Smarks dd->dd_phys->dd_clone_parent_obj, NULL, 4814543Smarks DS_MODE_NONE, FTAG, &pclone); 4824543Smarks rw_exit(&dd->dd_pool->dp_config_rwlock); 4834543Smarks if (error) { 4844543Smarks dmu_objset_close(clone); 4854543Smarks return (error); 4864543Smarks } 4874543Smarks 4884543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4894543Smarks ZFS_DELEG_PERM_MOUNT, cr); 4904543Smarks 4914543Smarks dsl_dataset_name(pclone, parentname); 4924543Smarks dmu_objset_close(clone); 4934543Smarks dsl_dataset_close(pclone, DS_MODE_NONE, FTAG); 4944543Smarks if (error == 0) 4954543Smarks error = zfs_secpolicy_write_perms(parentname, 4964543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4974543Smarks } 4984543Smarks return (error); 4994543Smarks } 5004543Smarks 5014543Smarks static int 5024543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) 5034543Smarks { 5044543Smarks int error; 5054543Smarks 5064543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5074543Smarks ZFS_DELEG_PERM_RECEIVE, cr)) != 0) 5084543Smarks return (error); 5094543Smarks 5104543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5114543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 5124543Smarks return (error); 5134543Smarks 5144543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 5154543Smarks ZFS_DELEG_PERM_CREATE, cr)); 5164543Smarks } 5174543Smarks 5184543Smarks int 5194543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 5204543Smarks { 5214543Smarks int error; 5224543Smarks 5234543Smarks if ((error = zfs_secpolicy_write_perms(name, 5244543Smarks ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) 5254543Smarks return (error); 5264543Smarks 5274543Smarks error = zfs_secpolicy_write_perms(name, 5284543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5294543Smarks 5304543Smarks return (error); 5314543Smarks } 5324543Smarks 5334543Smarks static int 5344543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) 5354543Smarks { 5364543Smarks 5374543Smarks return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); 5384543Smarks } 5394543Smarks 5404543Smarks static int 5414543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) 5424543Smarks { 5434543Smarks char parentname[MAXNAMELEN]; 5444543Smarks int error; 5454543Smarks 5464543Smarks if ((error = zfs_get_parent(zc->zc_name, parentname, 5474543Smarks sizeof (parentname))) != 0) 5484543Smarks return (error); 5494543Smarks 5504543Smarks if (zc->zc_value[0] != '\0') { 5514543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_value, 5524543Smarks ZFS_DELEG_PERM_CLONE, cr)) != 0) 5534543Smarks return (error); 5544543Smarks } 5554543Smarks 5564543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 5574543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 5584543Smarks return (error); 5594543Smarks 5604543Smarks error = zfs_secpolicy_write_perms(parentname, 5614543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5624543Smarks 5634543Smarks return (error); 5644543Smarks } 5654543Smarks 5664543Smarks static int 5674543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) 5684543Smarks { 5694543Smarks int error; 5704543Smarks 5714543Smarks error = secpolicy_fs_unmount(cr, NULL); 5724543Smarks if (error) { 5734543Smarks error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); 5744543Smarks } 5754543Smarks return (error); 576789Sahrens } 577789Sahrens 578789Sahrens /* 579789Sahrens * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires 580789Sahrens * SYS_CONFIG privilege, which is not available in a local zone. 581789Sahrens */ 582789Sahrens /* ARGSUSED */ 583789Sahrens static int 5844543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) 585789Sahrens { 586789Sahrens if (secpolicy_sys_config(cr, B_FALSE) != 0) 587789Sahrens return (EPERM); 588789Sahrens 589789Sahrens return (0); 590789Sahrens } 591789Sahrens 592789Sahrens /* 5934543Smarks * Just like zfs_secpolicy_config, except that we will check for 5944543Smarks * mount permission on the dataset for permission to create/remove 5954543Smarks * the minor nodes. 5964543Smarks */ 5974543Smarks static int 5984543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) 5994543Smarks { 6004543Smarks if (secpolicy_sys_config(cr, B_FALSE) != 0) { 6014543Smarks return (dsl_deleg_access(zc->zc_name, 6024543Smarks ZFS_DELEG_PERM_MOUNT, cr)); 6034543Smarks } 6044543Smarks 6054543Smarks return (0); 6064543Smarks } 6074543Smarks 6084543Smarks /* 6091544Seschrock * Policy for fault injection. Requires all privileges. 6101544Seschrock */ 6111544Seschrock /* ARGSUSED */ 6121544Seschrock static int 6134543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) 6141544Seschrock { 6151544Seschrock return (secpolicy_zinject(cr)); 6161544Seschrock } 6171544Seschrock 6184849Sahrens static int 6194849Sahrens zfs_secpolicy_inherit(zfs_cmd_t *zc, cred_t *cr) 6204849Sahrens { 6214849Sahrens zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); 6224849Sahrens 6235094Slling if (prop == ZPROP_INVAL) { 6244849Sahrens if (!zfs_prop_user(zc->zc_value)) 6254849Sahrens return (EINVAL); 6264849Sahrens return (zfs_secpolicy_write_perms(zc->zc_name, 6274849Sahrens ZFS_DELEG_PERM_USERPROP, cr)); 6284849Sahrens } else { 6294849Sahrens if (!zfs_prop_inheritable(prop)) 6304849Sahrens return (EINVAL); 6314849Sahrens return (zfs_secpolicy_setprop(zc->zc_name, prop, cr)); 6324849Sahrens } 6334849Sahrens } 6344849Sahrens 6351544Seschrock /* 636789Sahrens * Returns the nvlist as specified by the user in the zfs_cmd_t. 637789Sahrens */ 638789Sahrens static int 6395094Slling get_nvlist(uint64_t nvl, uint64_t size, nvlist_t **nvp) 640789Sahrens { 641789Sahrens char *packed; 642789Sahrens int error; 6435094Slling nvlist_t *list = NULL; 644789Sahrens 645789Sahrens /* 6462676Seschrock * Read in and unpack the user-supplied nvlist. 647789Sahrens */ 6485094Slling if (size == 0) 649789Sahrens return (EINVAL); 650789Sahrens 651789Sahrens packed = kmem_alloc(size, KM_SLEEP); 652789Sahrens 6535094Slling if ((error = xcopyin((void *)(uintptr_t)nvl, packed, size)) != 0) { 654789Sahrens kmem_free(packed, size); 655789Sahrens return (error); 656789Sahrens } 657789Sahrens 6585094Slling if ((error = nvlist_unpack(packed, size, &list, 0)) != 0) { 659789Sahrens kmem_free(packed, size); 660789Sahrens return (error); 661789Sahrens } 662789Sahrens 663789Sahrens kmem_free(packed, size); 664789Sahrens 6655094Slling *nvp = list; 666789Sahrens return (0); 667789Sahrens } 668789Sahrens 669789Sahrens static int 6702676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 6712676Seschrock { 6722676Seschrock char *packed = NULL; 6732676Seschrock size_t size; 6742676Seschrock int error; 6752676Seschrock 6762676Seschrock VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 6772676Seschrock 6782676Seschrock if (size > zc->zc_nvlist_dst_size) { 6792676Seschrock error = ENOMEM; 6802676Seschrock } else { 6814611Smarks packed = kmem_alloc(size, KM_SLEEP); 6822676Seschrock VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 6832676Seschrock KM_SLEEP) == 0); 6842676Seschrock error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 6852676Seschrock size); 6862676Seschrock kmem_free(packed, size); 6872676Seschrock } 6882676Seschrock 6892676Seschrock zc->zc_nvlist_dst_size = size; 6902676Seschrock return (error); 6912676Seschrock } 6922676Seschrock 6932676Seschrock static int 694789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc) 695789Sahrens { 696789Sahrens int error; 6975094Slling nvlist_t *config, *props = NULL; 6984715Sek110237 char *buf; 699789Sahrens 7005094Slling if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7015094Slling &config)) 7024988Sek110237 return (error); 7034715Sek110237 7045094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7055094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7065094Slling nvlist_free(config); 7075094Slling return (error); 7085094Slling } 7095094Slling 7104988Sek110237 buf = history_str_get(zc); 711789Sahrens 7125094Slling error = spa_create(zc->zc_name, config, props, buf); 713789Sahrens 7144988Sek110237 if (buf != NULL) 7154988Sek110237 history_str_free(buf); 7165094Slling 717789Sahrens nvlist_free(config); 718789Sahrens 7195094Slling if (props) 7205094Slling nvlist_free(props); 7215094Slling 722789Sahrens return (error); 723789Sahrens } 724789Sahrens 725789Sahrens static int 726789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc) 727789Sahrens { 7284543Smarks int error; 7294543Smarks zfs_log_history(zc); 7304543Smarks error = spa_destroy(zc->zc_name); 7314543Smarks return (error); 732789Sahrens } 733789Sahrens 734789Sahrens static int 735789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc) 736789Sahrens { 737789Sahrens int error; 7385094Slling nvlist_t *config, *props = NULL; 739789Sahrens uint64_t guid; 740789Sahrens 7415094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7425094Slling &config)) != 0) 743789Sahrens return (error); 744789Sahrens 7455094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7465094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7475094Slling nvlist_free(config); 7485094Slling return (error); 7495094Slling } 7505094Slling 751789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 7521544Seschrock guid != zc->zc_guid) 753789Sahrens error = EINVAL; 754789Sahrens else 7555094Slling error = spa_import(zc->zc_name, config, props); 756789Sahrens 757789Sahrens nvlist_free(config); 758789Sahrens 7595094Slling if (props) 7605094Slling nvlist_free(props); 7615094Slling 762789Sahrens return (error); 763789Sahrens } 764789Sahrens 765789Sahrens static int 766789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc) 767789Sahrens { 7684543Smarks int error; 7694543Smarks zfs_log_history(zc); 7704543Smarks error = spa_export(zc->zc_name, NULL); 7714543Smarks return (error); 772789Sahrens } 773789Sahrens 774789Sahrens static int 775789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc) 776789Sahrens { 777789Sahrens nvlist_t *configs; 778789Sahrens int error; 779789Sahrens 780789Sahrens if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 781789Sahrens return (EEXIST); 782789Sahrens 7832676Seschrock error = put_nvlist(zc, configs); 784789Sahrens 785789Sahrens nvlist_free(configs); 786789Sahrens 787789Sahrens return (error); 788789Sahrens } 789789Sahrens 790789Sahrens static int 791789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc) 792789Sahrens { 793789Sahrens nvlist_t *config; 794789Sahrens int error; 7951544Seschrock int ret = 0; 796789Sahrens 7972676Seschrock error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 7982676Seschrock sizeof (zc->zc_value)); 799789Sahrens 800789Sahrens if (config != NULL) { 8012676Seschrock ret = put_nvlist(zc, config); 802789Sahrens nvlist_free(config); 8031544Seschrock 8041544Seschrock /* 8051544Seschrock * The config may be present even if 'error' is non-zero. 8061544Seschrock * In this case we return success, and preserve the real errno 8071544Seschrock * in 'zc_cookie'. 8081544Seschrock */ 8091544Seschrock zc->zc_cookie = error; 810789Sahrens } else { 8111544Seschrock ret = error; 812789Sahrens } 813789Sahrens 8141544Seschrock return (ret); 815789Sahrens } 816789Sahrens 817789Sahrens /* 818789Sahrens * Try to import the given pool, returning pool stats as appropriate so that 819789Sahrens * user land knows which devices are available and overall pool health. 820789Sahrens */ 821789Sahrens static int 822789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 823789Sahrens { 824789Sahrens nvlist_t *tryconfig, *config; 825789Sahrens int error; 826789Sahrens 8275094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 8285094Slling &tryconfig)) != 0) 829789Sahrens return (error); 830789Sahrens 831789Sahrens config = spa_tryimport(tryconfig); 832789Sahrens 833789Sahrens nvlist_free(tryconfig); 834789Sahrens 835789Sahrens if (config == NULL) 836789Sahrens return (EINVAL); 837789Sahrens 8382676Seschrock error = put_nvlist(zc, config); 839789Sahrens nvlist_free(config); 840789Sahrens 841789Sahrens return (error); 842789Sahrens } 843789Sahrens 844789Sahrens static int 845789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc) 846789Sahrens { 847789Sahrens spa_t *spa; 848789Sahrens int error; 849789Sahrens 8502926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8512926Sek110237 return (error); 8522926Sek110237 8534808Sek110237 mutex_enter(&spa_namespace_lock); 8542926Sek110237 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); 8554808Sek110237 mutex_exit(&spa_namespace_lock); 8562926Sek110237 8572926Sek110237 spa_close(spa, FTAG); 8582926Sek110237 859789Sahrens return (error); 860789Sahrens } 861789Sahrens 862789Sahrens static int 863789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 864789Sahrens { 865789Sahrens spa_t *spa; 866789Sahrens int error; 867789Sahrens 868789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 869789Sahrens if (error == 0) { 870789Sahrens spa_freeze(spa); 871789Sahrens spa_close(spa, FTAG); 872789Sahrens } 873789Sahrens return (error); 874789Sahrens } 875789Sahrens 876789Sahrens static int 8771760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 8781760Seschrock { 8791760Seschrock spa_t *spa; 8801760Seschrock int error; 8811760Seschrock 8822926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8832926Sek110237 return (error); 8842926Sek110237 8855118Slling if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) { 8865118Slling spa_close(spa, FTAG); 8875118Slling return (EINVAL); 8885118Slling } 8895118Slling 8905094Slling spa_upgrade(spa, zc->zc_cookie); 8912926Sek110237 spa_close(spa, FTAG); 8922926Sek110237 8932926Sek110237 return (error); 8942926Sek110237 } 8952926Sek110237 8962926Sek110237 static int 8972926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 8982926Sek110237 { 8992926Sek110237 spa_t *spa; 9002926Sek110237 char *hist_buf; 9012926Sek110237 uint64_t size; 9022926Sek110237 int error; 9032926Sek110237 9042926Sek110237 if ((size = zc->zc_history_len) == 0) 9052926Sek110237 return (EINVAL); 9062926Sek110237 9072926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9082926Sek110237 return (error); 9092926Sek110237 9104577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 9113863Sek110237 spa_close(spa, FTAG); 9123863Sek110237 return (ENOTSUP); 9133863Sek110237 } 9143863Sek110237 9152926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 9162926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 9172926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 9184543Smarks error = xcopyout(hist_buf, 9194543Smarks (char *)(uintptr_t)zc->zc_history, 9202926Sek110237 zc->zc_history_len); 9212926Sek110237 } 9222926Sek110237 9232926Sek110237 spa_close(spa, FTAG); 9242926Sek110237 kmem_free(hist_buf, size); 9252926Sek110237 return (error); 9262926Sek110237 } 9272926Sek110237 9282926Sek110237 static int 9293444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 9303444Sek110237 { 9313444Sek110237 int error; 9323444Sek110237 9333912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 9343444Sek110237 return (error); 9353444Sek110237 9363444Sek110237 return (0); 9373444Sek110237 } 9383444Sek110237 9393444Sek110237 static int 9403444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 9413444Sek110237 { 9423444Sek110237 objset_t *osp; 9433444Sek110237 int error; 9443444Sek110237 9453444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 9463444Sek110237 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) 9473444Sek110237 return (error); 9483444Sek110237 9493444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 9503444Sek110237 sizeof (zc->zc_value)); 9513444Sek110237 dmu_objset_close(osp); 9523444Sek110237 9533444Sek110237 return (error); 9543444Sek110237 } 9553444Sek110237 9563444Sek110237 static int 957789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 958789Sahrens { 959789Sahrens spa_t *spa; 960789Sahrens int error; 961789Sahrens nvlist_t *config; 962789Sahrens 963789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 964789Sahrens if (error != 0) 965789Sahrens return (error); 966789Sahrens 9673912Slling /* 9683912Slling * A root pool with concatenated devices is not supported. 9693912Slling * Thus, can not add a device to a root pool with one device. 9703912Slling */ 9713912Slling if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0) { 9723912Slling spa_close(spa, FTAG); 9733912Slling return (EDOM); 9743912Slling } 9753912Slling 9765094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 9775094Slling &config)) == 0) { 978789Sahrens error = spa_vdev_add(spa, config); 979789Sahrens nvlist_free(config); 980789Sahrens } 981789Sahrens spa_close(spa, FTAG); 982789Sahrens return (error); 983789Sahrens } 984789Sahrens 985789Sahrens static int 986789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 987789Sahrens { 9882082Seschrock spa_t *spa; 9892082Seschrock int error; 9902082Seschrock 9912082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 9922082Seschrock if (error != 0) 9932082Seschrock return (error); 9942082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 9952082Seschrock spa_close(spa, FTAG); 9962082Seschrock return (error); 997789Sahrens } 998789Sahrens 999789Sahrens static int 10004451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 1001789Sahrens { 1002789Sahrens spa_t *spa; 1003789Sahrens int error; 10044451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 1005789Sahrens 10062926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1007789Sahrens return (error); 10084451Seschrock switch (zc->zc_cookie) { 10094451Seschrock case VDEV_STATE_ONLINE: 10104451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 10114451Seschrock break; 10124451Seschrock 10134451Seschrock case VDEV_STATE_OFFLINE: 10144451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 10154451Seschrock break; 1016789Sahrens 10174451Seschrock case VDEV_STATE_FAULTED: 10184451Seschrock error = vdev_fault(spa, zc->zc_guid); 10194451Seschrock break; 1020789Sahrens 10214451Seschrock case VDEV_STATE_DEGRADED: 10224451Seschrock error = vdev_degrade(spa, zc->zc_guid); 10234451Seschrock break; 10244451Seschrock 10254451Seschrock default: 10264451Seschrock error = EINVAL; 10274451Seschrock } 10284451Seschrock zc->zc_cookie = newstate; 1029789Sahrens spa_close(spa, FTAG); 1030789Sahrens return (error); 1031789Sahrens } 1032789Sahrens 1033789Sahrens static int 1034789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 1035789Sahrens { 1036789Sahrens spa_t *spa; 1037789Sahrens int replacing = zc->zc_cookie; 1038789Sahrens nvlist_t *config; 1039789Sahrens int error; 1040789Sahrens 10412926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1042789Sahrens return (error); 1043789Sahrens 10445094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 10455094Slling &config)) == 0) { 10461544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 1047789Sahrens nvlist_free(config); 1048789Sahrens } 1049789Sahrens 1050789Sahrens spa_close(spa, FTAG); 1051789Sahrens return (error); 1052789Sahrens } 1053789Sahrens 1054789Sahrens static int 1055789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 1056789Sahrens { 1057789Sahrens spa_t *spa; 1058789Sahrens int error; 1059789Sahrens 10602926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1061789Sahrens return (error); 1062789Sahrens 10631544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1064789Sahrens 1065789Sahrens spa_close(spa, FTAG); 1066789Sahrens return (error); 1067789Sahrens } 1068789Sahrens 1069789Sahrens static int 10701354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 10711354Seschrock { 10721354Seschrock spa_t *spa; 10732676Seschrock char *path = zc->zc_value; 10741544Seschrock uint64_t guid = zc->zc_guid; 10751354Seschrock int error; 10761354Seschrock 10771354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10781354Seschrock if (error != 0) 10791354Seschrock return (error); 10801354Seschrock 10811354Seschrock error = spa_vdev_setpath(spa, guid, path); 10821354Seschrock spa_close(spa, FTAG); 10831354Seschrock return (error); 10841354Seschrock } 10851354Seschrock 10861354Seschrock static int 1087789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1088789Sahrens { 1089789Sahrens objset_t *os = NULL; 1090789Sahrens int error; 10911356Seschrock nvlist_t *nv; 1092789Sahrens 1093789Sahrens retry: 1094789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1095789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1096789Sahrens if (error != 0) { 1097789Sahrens /* 1098789Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1099789Sahrens * the objset is held exclusively. Fortunately this hold is 1100789Sahrens * only for a short while, so we retry here. 1101789Sahrens * This avoids user code having to handle EBUSY, 1102789Sahrens * for example for a "zfs list". 1103789Sahrens */ 1104789Sahrens if (error == EBUSY) { 1105789Sahrens delay(1); 1106789Sahrens goto retry; 1107789Sahrens } 1108789Sahrens return (error); 1109789Sahrens } 1110789Sahrens 11112885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1112789Sahrens 11132856Snd150628 if (zc->zc_nvlist_dst != 0 && 11141356Seschrock (error = dsl_prop_get_all(os, &nv)) == 0) { 11152885Sahrens dmu_objset_stats(os, nv); 11163087Sahrens /* 11175147Srm160521 * NB: zvol_get_stats() will read the objset contents, 11183087Sahrens * which we aren't supposed to do with a 11193087Sahrens * DS_MODE_STANDARD open, because it could be 11203087Sahrens * inconsistent. So this is a bit of a workaround... 11213087Sahrens */ 11224577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 11234577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 11244577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 11254577Sahrens } 11262676Seschrock error = put_nvlist(zc, nv); 11271356Seschrock nvlist_free(nv); 11281356Seschrock } 1129789Sahrens 11302676Seschrock spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value)); 11311544Seschrock 1132789Sahrens dmu_objset_close(os); 1133789Sahrens return (error); 1134789Sahrens } 1135789Sahrens 1136789Sahrens static int 11375147Srm160521 zfs_ioc_objset_version(zfs_cmd_t *zc) 11385147Srm160521 { 11395147Srm160521 objset_t *os = NULL; 11405147Srm160521 int error; 11415147Srm160521 11425147Srm160521 retry: 11435147Srm160521 error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 11445147Srm160521 DS_MODE_STANDARD | DS_MODE_READONLY, &os); 11455147Srm160521 if (error != 0) { 11465147Srm160521 /* 11475147Srm160521 * This is ugly: dmu_objset_open() can return EBUSY if 11485147Srm160521 * the objset is held exclusively. Fortunately this hold is 11495147Srm160521 * only for a short while, so we retry here. 11505147Srm160521 * This avoids user code having to handle EBUSY, 11515147Srm160521 * for example for a "zfs list". 11525147Srm160521 */ 11535147Srm160521 if (error == EBUSY) { 11545147Srm160521 delay(1); 11555147Srm160521 goto retry; 11565147Srm160521 } 11575147Srm160521 return (error); 11585147Srm160521 } 11595147Srm160521 11605147Srm160521 dmu_objset_fast_stat(os, &zc->zc_objset_stats); 11615147Srm160521 11625147Srm160521 /* 11635147Srm160521 * NB: zfs_get_version() will read the objset contents, 11645147Srm160521 * which we aren't supposed to do with a 11655147Srm160521 * DS_MODE_STANDARD open, because it could be 11665147Srm160521 * inconsistent. So this is a bit of a workaround... 11675147Srm160521 */ 11685147Srm160521 zc->zc_cookie = 0; 11695147Srm160521 if (!zc->zc_objset_stats.dds_inconsistent) 11705147Srm160521 if (dmu_objset_type(os) == DMU_OST_ZFS) 11715147Srm160521 (void) zfs_get_version(os, &zc->zc_cookie); 11725147Srm160521 11735147Srm160521 dmu_objset_close(os); 11745147Srm160521 return (0); 11755147Srm160521 } 11765147Srm160521 11775147Srm160521 static int 1178789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1179789Sahrens { 1180885Sahrens objset_t *os; 1181789Sahrens int error; 1182789Sahrens char *p; 1183789Sahrens 1184885Sahrens retry: 1185885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1186885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1187885Sahrens if (error != 0) { 1188885Sahrens /* 1189885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1190885Sahrens * the objset is held exclusively. Fortunately this hold is 1191885Sahrens * only for a short while, so we retry here. 1192885Sahrens * This avoids user code having to handle EBUSY, 1193885Sahrens * for example for a "zfs list". 1194885Sahrens */ 1195885Sahrens if (error == EBUSY) { 1196885Sahrens delay(1); 1197885Sahrens goto retry; 1198885Sahrens } 1199885Sahrens if (error == ENOENT) 1200885Sahrens error = ESRCH; 1201885Sahrens return (error); 1202789Sahrens } 1203789Sahrens 1204789Sahrens p = strrchr(zc->zc_name, '/'); 1205789Sahrens if (p == NULL || p[1] != '\0') 1206789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1207789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1208789Sahrens 1209789Sahrens do { 1210885Sahrens error = dmu_dir_list_next(os, 1211885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1212885Sahrens NULL, &zc->zc_cookie); 1213789Sahrens if (error == ENOENT) 1214789Sahrens error = ESRCH; 1215885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1216789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 1217789Sahrens 1218885Sahrens /* 1219885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1220885Sahrens * try to get stats for it. Userland will skip over it. 1221885Sahrens */ 1222885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1223885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1224789Sahrens 1225885Sahrens dmu_objset_close(os); 1226789Sahrens return (error); 1227789Sahrens } 1228789Sahrens 1229789Sahrens static int 1230789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1231789Sahrens { 1232885Sahrens objset_t *os; 1233789Sahrens int error; 1234789Sahrens 1235789Sahrens retry: 1236885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1237885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1238885Sahrens if (error != 0) { 1239789Sahrens /* 1240885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1241789Sahrens * the objset is held exclusively. Fortunately this hold is 1242789Sahrens * only for a short while, so we retry here. 1243789Sahrens * This avoids user code having to handle EBUSY, 1244885Sahrens * for example for a "zfs list". 1245789Sahrens */ 1246789Sahrens if (error == EBUSY) { 1247789Sahrens delay(1); 1248789Sahrens goto retry; 1249789Sahrens } 1250789Sahrens if (error == ENOENT) 1251885Sahrens error = ESRCH; 1252789Sahrens return (error); 1253789Sahrens } 1254789Sahrens 12551003Slling /* 12561003Slling * A dataset name of maximum length cannot have any snapshots, 12571003Slling * so exit immediately. 12581003Slling */ 12591003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1260885Sahrens dmu_objset_close(os); 12611003Slling return (ESRCH); 1262789Sahrens } 1263789Sahrens 1264885Sahrens error = dmu_snapshot_list_next(os, 1265885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 1266885Sahrens zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie); 1267789Sahrens if (error == ENOENT) 1268789Sahrens error = ESRCH; 1269789Sahrens 1270885Sahrens if (error == 0) 1271885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1272789Sahrens 1273885Sahrens dmu_objset_close(os); 1274789Sahrens return (error); 1275789Sahrens } 1276789Sahrens 1277789Sahrens static int 12784787Sahrens zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) 1279789Sahrens { 12802676Seschrock nvpair_t *elem; 12812676Seschrock int error; 12822676Seschrock uint64_t intval; 12832676Seschrock char *strval; 12842676Seschrock 12854543Smarks /* 12864543Smarks * First validate permission to set all of the properties 12874543Smarks */ 12882676Seschrock elem = NULL; 12892676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 12904670Sahrens const char *propname = nvpair_name(elem); 12914670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 12922676Seschrock 12935094Slling if (prop == ZPROP_INVAL) { 12942676Seschrock /* 12952676Seschrock * If this is a user-defined property, it must be a 12962676Seschrock * string, and there is no further validation to do. 12972676Seschrock */ 12982676Seschrock if (!zfs_prop_user(propname) || 12992676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 13002676Seschrock return (EINVAL); 13012676Seschrock 1302*5331Samw if (error = zfs_secpolicy_write_perms(name, 1303*5331Samw ZFS_DELEG_PERM_USERPROP, CRED())) 13044670Sahrens return (error); 13054543Smarks continue; 13062676Seschrock } 13072676Seschrock 13084787Sahrens if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 13094670Sahrens return (error); 13102676Seschrock 13114670Sahrens /* 13124670Sahrens * Check that this value is valid for this pool version 13134670Sahrens */ 13144670Sahrens switch (prop) { 13153886Sahl case ZFS_PROP_COMPRESSION: 13163886Sahl /* 13173886Sahl * If the user specified gzip compression, make sure 13183886Sahl * the SPA supports it. We ignore any errors here since 13193886Sahl * we'll catch them later. 13203886Sahl */ 13213886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 13223886Sahl nvpair_value_uint64(elem, &intval) == 0 && 13233886Sahl intval >= ZIO_COMPRESS_GZIP_1 && 13243886Sahl intval <= ZIO_COMPRESS_GZIP_9) { 1325*5331Samw if (zfs_check_version(name, 1326*5331Samw SPA_VERSION_GZIP_COMPRESSION)) 1327*5331Samw return (ENOTSUP); 13283886Sahl } 13293886Sahl break; 13304603Sahrens 13314603Sahrens case ZFS_PROP_COPIES: 1332*5331Samw if (zfs_check_version(name, SPA_VERSION_DITTO_BLOCKS)) 1333*5331Samw return (ENOTSUP); 13344603Sahrens break; 1335*5331Samw case ZFS_PROP_NORMALIZE: 1336*5331Samw case ZFS_PROP_UTF8ONLY: 1337*5331Samw case ZFS_PROP_CASE: 1338*5331Samw if (zfs_check_version(name, SPA_VERSION_NORMALIZATION)) 1339*5331Samw return (ENOTSUP); 1340*5331Samw 13414603Sahrens } 1342*5331Samw if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 1343*5331Samw return (error); 13444543Smarks } 13454543Smarks 13464543Smarks elem = NULL; 13474543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 13484670Sahrens const char *propname = nvpair_name(elem); 13494670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 13504543Smarks 13515094Slling if (prop == ZPROP_INVAL) { 13524543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 13534543Smarks error = dsl_prop_set(name, propname, 1, 13544543Smarks strlen(strval) + 1, strval); 13554543Smarks if (error == 0) 13564543Smarks continue; 13574543Smarks else 13584543Smarks return (error); 13594543Smarks } 13602676Seschrock 13612676Seschrock switch (prop) { 13622676Seschrock case ZFS_PROP_QUOTA: 13632676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13644577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 13652676Seschrock return (error); 13662676Seschrock break; 13672676Seschrock 13682676Seschrock case ZFS_PROP_RESERVATION: 13692676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13702676Seschrock (error = dsl_dir_set_reservation(name, 13712676Seschrock intval)) != 0) 13722676Seschrock return (error); 13732676Seschrock break; 1374789Sahrens 13752676Seschrock case ZFS_PROP_VOLSIZE: 13762676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13774787Sahrens (error = zvol_set_volsize(name, 13784787Sahrens ddi_driver_major(zfs_dip), intval)) != 0) 13792676Seschrock return (error); 13802676Seschrock break; 13812676Seschrock 13822676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 13832676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13844577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 13854577Sahrens return (error); 13864577Sahrens break; 13874577Sahrens 13884577Sahrens case ZFS_PROP_VERSION: 13894577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13904577Sahrens (error = zfs_set_version(name, intval)) != 0) 13912676Seschrock return (error); 13922676Seschrock break; 13932676Seschrock 13942676Seschrock default: 13952676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 13962676Seschrock if (zfs_prop_get_type(prop) != 13974787Sahrens PROP_TYPE_STRING) 13982676Seschrock return (EINVAL); 13992717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 14002717Seschrock if ((error = dsl_prop_set(name, 14012676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 14022717Seschrock strval)) != 0) 14032717Seschrock return (error); 14042676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 14052885Sahrens const char *unused; 14062885Sahrens 14072717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 14082676Seschrock 14092676Seschrock switch (zfs_prop_get_type(prop)) { 14104787Sahrens case PROP_TYPE_NUMBER: 14112676Seschrock break; 14124787Sahrens case PROP_TYPE_STRING: 14132717Seschrock return (EINVAL); 14144787Sahrens case PROP_TYPE_INDEX: 14152717Seschrock if (zfs_prop_index_to_string(prop, 14162717Seschrock intval, &unused) != 0) 14172717Seschrock return (EINVAL); 14182676Seschrock break; 14192676Seschrock default: 14204577Sahrens cmn_err(CE_PANIC, 14214577Sahrens "unknown property type"); 14222676Seschrock break; 14232676Seschrock } 14242676Seschrock 14252717Seschrock if ((error = dsl_prop_set(name, propname, 14262717Seschrock 8, 1, &intval)) != 0) 14272717Seschrock return (error); 14282676Seschrock } else { 14292676Seschrock return (EINVAL); 14302676Seschrock } 14312676Seschrock break; 14322676Seschrock } 14332676Seschrock } 14342676Seschrock 14352676Seschrock return (0); 1436789Sahrens } 1437789Sahrens 1438789Sahrens static int 14392676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1440789Sahrens { 14412676Seschrock nvlist_t *nvl; 14422676Seschrock int error; 1443789Sahrens 14445094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 14455094Slling &nvl)) != 0) 14462676Seschrock return (error); 14472676Seschrock 14484787Sahrens error = zfs_set_prop_nvlist(zc->zc_name, nvl); 14494543Smarks 14502676Seschrock nvlist_free(nvl); 14512676Seschrock return (error); 1452789Sahrens } 1453789Sahrens 1454789Sahrens static int 14554849Sahrens zfs_ioc_inherit_prop(zfs_cmd_t *zc) 14564849Sahrens { 14574849Sahrens /* the property name has been validated by zfs_secpolicy_inherit() */ 14584849Sahrens return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 14594849Sahrens } 14604849Sahrens 14614849Sahrens static int 14624098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 14633912Slling { 14645094Slling nvlist_t *props; 14653912Slling spa_t *spa; 14665094Slling int error; 14673912Slling 14685094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 14695094Slling &props))) 14703912Slling return (error); 14713912Slling 14723912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 14735094Slling nvlist_free(props); 14743912Slling return (error); 14753912Slling } 14763912Slling 14775094Slling error = spa_prop_set(spa, props); 14783912Slling 14795094Slling nvlist_free(props); 14803912Slling spa_close(spa, FTAG); 14813912Slling 14823912Slling return (error); 14833912Slling } 14843912Slling 14853912Slling static int 14864098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 14873912Slling { 14883912Slling spa_t *spa; 14893912Slling int error; 14903912Slling nvlist_t *nvp = NULL; 14913912Slling 14923912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 14933912Slling return (error); 14943912Slling 14955094Slling error = spa_prop_get(spa, &nvp); 14963912Slling 14973912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 14983912Slling error = put_nvlist(zc, nvp); 14993912Slling else 15003912Slling error = EFAULT; 15013912Slling 15023912Slling spa_close(spa, FTAG); 15033912Slling 15043912Slling if (nvp) 15053912Slling nvlist_free(nvp); 15063912Slling return (error); 15073912Slling } 15083912Slling 15093912Slling static int 15104543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 15114543Smarks { 15124543Smarks nvlist_t *nvp; 15134543Smarks int error; 15144543Smarks uint32_t uid; 15154543Smarks uint32_t gid; 15164543Smarks uint32_t *groups; 15174543Smarks uint_t group_cnt; 15184543Smarks cred_t *usercred; 15194543Smarks 15205094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15215094Slling &nvp)) != 0) { 15224543Smarks return (error); 15234543Smarks } 15244543Smarks 15254543Smarks if ((error = nvlist_lookup_uint32(nvp, 15264543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 15274543Smarks nvlist_free(nvp); 15284543Smarks return (EPERM); 15294543Smarks } 15304543Smarks 15314543Smarks if ((error = nvlist_lookup_uint32(nvp, 15324543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 15334543Smarks nvlist_free(nvp); 15344543Smarks return (EPERM); 15354543Smarks } 15364543Smarks 15374543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 15384543Smarks &groups, &group_cnt)) != 0) { 15394543Smarks nvlist_free(nvp); 15404543Smarks return (EPERM); 15414543Smarks } 15424543Smarks usercred = cralloc(); 15434543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 15444543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 15454543Smarks nvlist_free(nvp); 15464543Smarks crfree(usercred); 15474543Smarks return (EPERM); 15484543Smarks } 15494543Smarks nvlist_free(nvp); 15504543Smarks error = dsl_deleg_access(zc->zc_name, 15514787Sahrens zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); 15524543Smarks crfree(usercred); 15534543Smarks return (error); 15544543Smarks } 15554543Smarks 15564543Smarks static int 15574543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 15584543Smarks { 15594543Smarks int error; 15604543Smarks nvlist_t *fsaclnv = NULL; 15614543Smarks 15625094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15635094Slling &fsaclnv)) != 0) 15644543Smarks return (error); 15654543Smarks 15664543Smarks /* 15674543Smarks * Verify nvlist is constructed correctly 15684543Smarks */ 15694543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 15704543Smarks nvlist_free(fsaclnv); 15714543Smarks return (EINVAL); 15724543Smarks } 15734543Smarks 15744543Smarks /* 15754543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 15764543Smarks * that user is allowed to hand out each permission in 15774543Smarks * the nvlist(s) 15784543Smarks */ 15794543Smarks 15804787Sahrens error = secpolicy_zfs(CRED()); 15814543Smarks if (error) { 15824787Sahrens if (zc->zc_perm_action == B_FALSE) { 15834787Sahrens error = dsl_deleg_can_allow(zc->zc_name, 15844787Sahrens fsaclnv, CRED()); 15854787Sahrens } else { 15864787Sahrens error = dsl_deleg_can_unallow(zc->zc_name, 15874787Sahrens fsaclnv, CRED()); 15884787Sahrens } 15894543Smarks } 15904543Smarks 15914543Smarks if (error == 0) 15924543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 15934543Smarks 15944543Smarks nvlist_free(fsaclnv); 15954543Smarks return (error); 15964543Smarks } 15974543Smarks 15984543Smarks static int 15994543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 16004543Smarks { 16014543Smarks nvlist_t *nvp; 16024543Smarks int error; 16034543Smarks 16044543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 16054543Smarks error = put_nvlist(zc, nvp); 16064543Smarks nvlist_free(nvp); 16074543Smarks } 16084543Smarks 16094543Smarks return (error); 16104543Smarks } 16114543Smarks 16124543Smarks static int 1613789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1614789Sahrens { 16154787Sahrens return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); 1616789Sahrens } 1617789Sahrens 1618789Sahrens static int 1619789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1620789Sahrens { 16212676Seschrock return (zvol_remove_minor(zc->zc_name)); 1622789Sahrens } 1623789Sahrens 1624789Sahrens /* 1625789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1626789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1627789Sahrens * is responsible for releasing the returned vfs pointer. 1628789Sahrens */ 1629789Sahrens static vfs_t * 1630789Sahrens zfs_get_vfs(const char *resource) 1631789Sahrens { 1632789Sahrens struct vfs *vfsp; 1633789Sahrens struct vfs *vfs_found = NULL; 1634789Sahrens 1635789Sahrens vfs_list_read_lock(); 1636789Sahrens vfsp = rootvfs; 1637789Sahrens do { 1638789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1639789Sahrens VFS_HOLD(vfsp); 1640789Sahrens vfs_found = vfsp; 1641789Sahrens break; 1642789Sahrens } 1643789Sahrens vfsp = vfsp->vfs_next; 1644789Sahrens } while (vfsp != rootvfs); 1645789Sahrens vfs_list_unlock(); 1646789Sahrens return (vfs_found); 1647789Sahrens } 1648789Sahrens 16494543Smarks /* ARGSUSED */ 1650789Sahrens static void 16514543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1652789Sahrens { 1653*5331Samw zfs_creat_t *zct = arg; 1654*5331Samw uint64_t version; 1655*5331Samw 1656*5331Samw if (spa_version(dmu_objset_spa(os)) >= SPA_VERSION_FUID) 1657*5331Samw version = ZPL_VERSION; 1658*5331Samw else 1659*5331Samw version = ZPL_VERSION_FUID - 1; 1660*5331Samw 1661*5331Samw (void) nvlist_lookup_uint64(zct->zct_props, 16624577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version); 16634577Sahrens 1664*5331Samw zfs_create_fs(os, cr, version, zct->zct_norm, tx); 1665*5331Samw } 1666*5331Samw 1667*5331Samw /* 1668*5331Samw * zfs_prop_lookup() 1669*5331Samw * 1670*5331Samw * Look for the property first in the existing property nvlist. If 1671*5331Samw * it's already present, you're done. If it's not there, attempt to 1672*5331Samw * find the property value from a parent dataset. If that fails, fall 1673*5331Samw * back to the property's default value. In either of these two 1674*5331Samw * cases, if update is TRUE, add a value for the property to the 1675*5331Samw * property nvlist. 1676*5331Samw * 1677*5331Samw * If the rval pointer is non-NULL, copy the discovered value to rval. 1678*5331Samw * 1679*5331Samw * If we get any unexpected errors, bail and return the error number 1680*5331Samw * to the caller. 1681*5331Samw * 1682*5331Samw * If we succeed, return 0. 1683*5331Samw */ 1684*5331Samw static int 1685*5331Samw zfs_prop_lookup(const char *parentname, zfs_prop_t propnum, 1686*5331Samw nvlist_t *proplist, uint64_t *rval, boolean_t update) 1687*5331Samw { 1688*5331Samw const char *propname; 1689*5331Samw uint64_t value; 1690*5331Samw int error = ENOENT; 1691*5331Samw 1692*5331Samw propname = zfs_prop_to_name(propnum); 1693*5331Samw if (proplist != NULL) 1694*5331Samw error = nvlist_lookup_uint64(proplist, propname, &value); 1695*5331Samw if (error == ENOENT) { 1696*5331Samw error = dsl_prop_get_integer(parentname, propname, 1697*5331Samw &value, NULL); 1698*5331Samw if (error == ENOENT) 1699*5331Samw value = zfs_prop_default_numeric(propnum); 1700*5331Samw else if (error != 0) 1701*5331Samw return (error); 1702*5331Samw if (update) { 1703*5331Samw ASSERT(proplist != NULL); 1704*5331Samw error = nvlist_add_uint64(proplist, propname, value); 1705*5331Samw } 1706*5331Samw } 1707*5331Samw if (error == 0 && rval) 1708*5331Samw *rval = value; 1709*5331Samw return (error); 1710*5331Samw } 1711*5331Samw 1712*5331Samw /* 1713*5331Samw * zfs_normalization_get 1714*5331Samw * 1715*5331Samw * Get the normalization flag value. If the properties have 1716*5331Samw * non-default values, make sure the pool version is recent enough to 1717*5331Samw * support these choices. 1718*5331Samw */ 1719*5331Samw static int 1720*5331Samw zfs_normalization_get(const char *dataset, nvlist_t *proplist, int *norm, 1721*5331Samw boolean_t update) 1722*5331Samw { 1723*5331Samw char parentname[MAXNAMELEN]; 1724*5331Samw char poolname[MAXNAMELEN]; 1725*5331Samw char *cp; 1726*5331Samw uint64_t value; 1727*5331Samw int check = 0; 1728*5331Samw int error; 1729*5331Samw 1730*5331Samw ASSERT(norm != NULL); 1731*5331Samw *norm = 0; 1732*5331Samw 1733*5331Samw (void) strncpy(parentname, dataset, sizeof (parentname)); 1734*5331Samw cp = strrchr(parentname, '@'); 1735*5331Samw if (cp != NULL) { 1736*5331Samw cp[0] = '\0'; 1737*5331Samw } else { 1738*5331Samw cp = strrchr(parentname, '/'); 1739*5331Samw if (cp == NULL) 1740*5331Samw return (ENOENT); 1741*5331Samw cp[0] = '\0'; 1742*5331Samw } 1743*5331Samw 1744*5331Samw (void) strncpy(poolname, dataset, sizeof (poolname)); 1745*5331Samw cp = strchr(poolname, '/'); 1746*5331Samw if (cp != NULL) 1747*5331Samw cp[0] = '\0'; 1748*5331Samw 1749*5331Samw error = zfs_prop_lookup(parentname, ZFS_PROP_UTF8ONLY, 1750*5331Samw proplist, &value, update); 1751*5331Samw if (error != 0) 1752*5331Samw return (error); 1753*5331Samw if (value != zfs_prop_default_numeric(ZFS_PROP_UTF8ONLY)) 1754*5331Samw check = 1; 1755*5331Samw 1756*5331Samw error = zfs_prop_lookup(parentname, ZFS_PROP_NORMALIZE, 1757*5331Samw proplist, &value, update); 1758*5331Samw if (error != 0) 1759*5331Samw return (error); 1760*5331Samw if (value != zfs_prop_default_numeric(ZFS_PROP_NORMALIZE)) { 1761*5331Samw check = 1; 1762*5331Samw switch ((int)value) { 1763*5331Samw case ZFS_NORMALIZE_NONE: 1764*5331Samw break; 1765*5331Samw case ZFS_NORMALIZE_C: 1766*5331Samw *norm |= U8_TEXTPREP_NFC; 1767*5331Samw break; 1768*5331Samw case ZFS_NORMALIZE_D: 1769*5331Samw *norm |= U8_TEXTPREP_NFD; 1770*5331Samw break; 1771*5331Samw case ZFS_NORMALIZE_KC: 1772*5331Samw *norm |= U8_TEXTPREP_NFKC; 1773*5331Samw break; 1774*5331Samw case ZFS_NORMALIZE_KD: 1775*5331Samw *norm |= U8_TEXTPREP_NFKD; 1776*5331Samw break; 1777*5331Samw default: 1778*5331Samw ASSERT((int)value >= ZFS_NORMALIZE_NONE); 1779*5331Samw ASSERT((int)value <= ZFS_NORMALIZE_KD); 1780*5331Samw break; 1781*5331Samw } 1782*5331Samw } 1783*5331Samw 1784*5331Samw error = zfs_prop_lookup(parentname, ZFS_PROP_CASE, 1785*5331Samw proplist, &value, update); 1786*5331Samw if (error != 0) 1787*5331Samw return (error); 1788*5331Samw if (value != zfs_prop_default_numeric(ZFS_PROP_CASE)) { 1789*5331Samw check = 1; 1790*5331Samw switch ((int)value) { 1791*5331Samw case ZFS_CASE_SENSITIVE: 1792*5331Samw break; 1793*5331Samw case ZFS_CASE_INSENSITIVE: 1794*5331Samw *norm |= U8_TEXTPREP_TOUPPER; 1795*5331Samw break; 1796*5331Samw case ZFS_CASE_MIXED: 1797*5331Samw *norm |= U8_TEXTPREP_TOUPPER; 1798*5331Samw break; 1799*5331Samw default: 1800*5331Samw ASSERT((int)value >= ZFS_CASE_SENSITIVE); 1801*5331Samw ASSERT((int)value <= ZFS_CASE_MIXED); 1802*5331Samw break; 1803*5331Samw } 1804*5331Samw } 1805*5331Samw 1806*5331Samw if (check == 1) 1807*5331Samw if (zfs_check_version(poolname, SPA_VERSION_NORMALIZATION)) 1808*5331Samw return (ENOTSUP); 1809*5331Samw return (0); 1810789Sahrens } 1811789Sahrens 1812789Sahrens static int 1813789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1814789Sahrens { 1815789Sahrens objset_t *clone; 1816789Sahrens int error = 0; 1817*5331Samw zfs_creat_t zct; 18184543Smarks nvlist_t *nvprops = NULL; 18194543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1820789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1821789Sahrens 1822789Sahrens switch (type) { 1823789Sahrens 1824789Sahrens case DMU_OST_ZFS: 1825789Sahrens cbfunc = zfs_create_cb; 1826789Sahrens break; 1827789Sahrens 1828789Sahrens case DMU_OST_ZVOL: 1829789Sahrens cbfunc = zvol_create_cb; 1830789Sahrens break; 1831789Sahrens 1832789Sahrens default: 18332199Sahrens cbfunc = NULL; 18342199Sahrens } 18355326Sek110237 if (strchr(zc->zc_name, '@') || 18365326Sek110237 strchr(zc->zc_name, '%')) 1837789Sahrens return (EINVAL); 1838789Sahrens 18392676Seschrock if (zc->zc_nvlist_src != NULL && 18405094Slling (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 18415094Slling &nvprops)) != 0) 18422676Seschrock return (error); 18432676Seschrock 1844*5331Samw zct.zct_norm = 0; 1845*5331Samw zct.zct_props = nvprops; 1846*5331Samw 18472676Seschrock if (zc->zc_value[0] != '\0') { 1848789Sahrens /* 1849789Sahrens * We're creating a clone of an existing snapshot. 1850789Sahrens */ 18512676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 18522676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 18534543Smarks nvlist_free(nvprops); 1854789Sahrens return (EINVAL); 18552676Seschrock } 1856789Sahrens 18572676Seschrock error = dmu_objset_open(zc->zc_value, type, 1858789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 18592676Seschrock if (error) { 18604543Smarks nvlist_free(nvprops); 1861789Sahrens return (error); 18622676Seschrock } 1863789Sahrens error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); 1864*5331Samw if (error) { 1865*5331Samw dmu_objset_close(clone); 1866*5331Samw nvlist_free(nvprops); 1867*5331Samw return (error); 1868*5331Samw } 1869*5331Samw /* 1870*5331Samw * If caller did not provide any properties, allocate 1871*5331Samw * an nvlist for properties, as we will be adding our set-once 1872*5331Samw * properties to it. This carries the choices made on the 1873*5331Samw * original file system into the clone. 1874*5331Samw */ 1875*5331Samw if (nvprops == NULL) 1876*5331Samw VERIFY(nvlist_alloc(&nvprops, 1877*5331Samw NV_UNIQUE_NAME, KM_SLEEP) == 0); 1878*5331Samw 1879*5331Samw /* 1880*5331Samw * We have to have normalization and case-folding 1881*5331Samw * flags correct when we do the file system creation, 1882*5331Samw * so go figure them out now. All we really care about 1883*5331Samw * here is getting these values into the property list. 1884*5331Samw */ 1885*5331Samw error = zfs_normalization_get(zc->zc_value, nvprops, 1886*5331Samw &zct.zct_norm, B_TRUE); 1887*5331Samw if (error != 0) { 1888*5331Samw dmu_objset_close(clone); 1889*5331Samw nvlist_free(nvprops); 1890*5331Samw return (error); 1891*5331Samw } 1892789Sahrens dmu_objset_close(clone); 1893789Sahrens } else { 18942676Seschrock if (cbfunc == NULL) { 18954543Smarks nvlist_free(nvprops); 18962199Sahrens return (EINVAL); 18972676Seschrock } 18982676Seschrock 1899789Sahrens if (type == DMU_OST_ZVOL) { 19002676Seschrock uint64_t volsize, volblocksize; 19012676Seschrock 19024543Smarks if (nvprops == NULL || 19034543Smarks nvlist_lookup_uint64(nvprops, 19042676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 19052676Seschrock &volsize) != 0) { 19064543Smarks nvlist_free(nvprops); 19072676Seschrock return (EINVAL); 19082676Seschrock } 19092676Seschrock 19104543Smarks if ((error = nvlist_lookup_uint64(nvprops, 19112676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 19122676Seschrock &volblocksize)) != 0 && error != ENOENT) { 19134543Smarks nvlist_free(nvprops); 19142676Seschrock return (EINVAL); 19152676Seschrock } 19161133Seschrock 19172676Seschrock if (error != 0) 19182676Seschrock volblocksize = zfs_prop_default_numeric( 19192676Seschrock ZFS_PROP_VOLBLOCKSIZE); 19202676Seschrock 19212676Seschrock if ((error = zvol_check_volblocksize( 19222676Seschrock volblocksize)) != 0 || 19232676Seschrock (error = zvol_check_volsize(volsize, 19242676Seschrock volblocksize)) != 0) { 19254543Smarks nvlist_free(nvprops); 1926789Sahrens return (error); 19272676Seschrock } 19284577Sahrens } else if (type == DMU_OST_ZFS) { 19294577Sahrens uint64_t version; 1930*5331Samw int error; 1931*5331Samw 1932*5331Samw error = nvlist_lookup_uint64(nvprops, 1933*5331Samw zfs_prop_to_name(ZFS_PROP_VERSION), &version); 1934*5331Samw 1935*5331Samw if (error == 0 && (version < ZPL_VERSION_INITIAL || 19364577Sahrens version > ZPL_VERSION)) { 19374577Sahrens nvlist_free(nvprops); 1938*5331Samw return (ENOTSUP); 1939*5331Samw } else if (error == 0 && version >= ZPL_VERSION_FUID && 1940*5331Samw zfs_check_version(zc->zc_name, SPA_VERSION_FUID)) { 1941*5331Samw nvlist_free(nvprops); 1942*5331Samw return (ENOTSUP); 1943*5331Samw } 1944*5331Samw 1945*5331Samw /* 1946*5331Samw * We have to have normalization and 1947*5331Samw * case-folding flags correct when we do the 1948*5331Samw * file system creation, so go figure them out 1949*5331Samw * now. The final argument to zfs_normalization_get() 1950*5331Samw * tells that routine not to update the nvprops 1951*5331Samw * list. 1952*5331Samw */ 1953*5331Samw error = zfs_normalization_get(zc->zc_name, nvprops, 1954*5331Samw &zct.zct_norm, B_FALSE); 1955*5331Samw if (error != 0) { 1956*5331Samw nvlist_free(nvprops); 1957*5331Samw return (error); 19584577Sahrens } 19592676Seschrock } 19602676Seschrock error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, 1961*5331Samw &zct); 1962789Sahrens } 19632676Seschrock 19642676Seschrock /* 19652676Seschrock * It would be nice to do this atomically. 19662676Seschrock */ 19672676Seschrock if (error == 0) { 19684787Sahrens if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) 19692676Seschrock (void) dmu_objset_destroy(zc->zc_name); 19702676Seschrock } 19712676Seschrock 19724543Smarks nvlist_free(nvprops); 1973789Sahrens return (error); 1974789Sahrens } 1975789Sahrens 1976789Sahrens static int 19772199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 19782199Sahrens { 19792676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 19802199Sahrens return (EINVAL); 19812199Sahrens return (dmu_objset_snapshot(zc->zc_name, 19822676Seschrock zc->zc_value, zc->zc_cookie)); 19832199Sahrens } 19842199Sahrens 19854007Smmusante int 19862199Sahrens zfs_unmount_snap(char *name, void *arg) 1987789Sahrens { 19882199Sahrens char *snapname = arg; 19892199Sahrens char *cp; 19902417Sahrens vfs_t *vfsp = NULL; 19912199Sahrens 19922199Sahrens /* 19932199Sahrens * Snapshots (which are under .zfs control) must be unmounted 19942199Sahrens * before they can be destroyed. 19952199Sahrens */ 19962199Sahrens 19972199Sahrens if (snapname) { 19982199Sahrens (void) strcat(name, "@"); 19992199Sahrens (void) strcat(name, snapname); 20002199Sahrens vfsp = zfs_get_vfs(name); 20012199Sahrens cp = strchr(name, '@'); 20022199Sahrens *cp = '\0'; 20032417Sahrens } else if (strchr(name, '@')) { 20042199Sahrens vfsp = zfs_get_vfs(name); 20052199Sahrens } 20062199Sahrens 20072199Sahrens if (vfsp) { 20082199Sahrens /* 20092199Sahrens * Always force the unmount for snapshots. 20102199Sahrens */ 20112199Sahrens int flag = MS_FORCE; 2012789Sahrens int err; 2013789Sahrens 20142199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 20152199Sahrens VFS_RELE(vfsp); 20162199Sahrens return (err); 20172199Sahrens } 20182199Sahrens VFS_RELE(vfsp); 20192199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 20202199Sahrens return (err); 20212199Sahrens } 20222199Sahrens return (0); 20232199Sahrens } 20242199Sahrens 20252199Sahrens static int 20262199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 20272199Sahrens { 20282199Sahrens int err; 2029789Sahrens 20302676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 20312199Sahrens return (EINVAL); 20322199Sahrens err = dmu_objset_find(zc->zc_name, 20332676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 20342199Sahrens if (err) 20352199Sahrens return (err); 20362676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 20372199Sahrens } 20382199Sahrens 20392199Sahrens static int 20402199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 20412199Sahrens { 20422199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 20432199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 20442199Sahrens if (err) 20452199Sahrens return (err); 2046789Sahrens } 2047789Sahrens 2048789Sahrens return (dmu_objset_destroy(zc->zc_name)); 2049789Sahrens } 2050789Sahrens 2051789Sahrens static int 2052789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 2053789Sahrens { 2054789Sahrens return (dmu_objset_rollback(zc->zc_name)); 2055789Sahrens } 2056789Sahrens 2057789Sahrens static int 2058789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 2059789Sahrens { 20604490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 20614007Smmusante 20622676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 20635326Sek110237 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 20645326Sek110237 strchr(zc->zc_value, '%')) 2065789Sahrens return (EINVAL); 2066789Sahrens 20674007Smmusante /* 20684007Smmusante * Unmount snapshot unless we're doing a recursive rename, 20694007Smmusante * in which case the dataset code figures out which snapshots 20704007Smmusante * to unmount. 20714007Smmusante */ 20724007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 2073789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 20742199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 20752199Sahrens if (err) 20762199Sahrens return (err); 2077789Sahrens } 2078789Sahrens 20794007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 2080789Sahrens } 2081789Sahrens 2082789Sahrens static int 2083789Sahrens zfs_ioc_recvbackup(zfs_cmd_t *zc) 2084789Sahrens { 2085789Sahrens file_t *fp; 20865326Sek110237 offset_t new_off; 20875326Sek110237 objset_t *os; 20885326Sek110237 zfsvfs_t *zfsvfs = NULL; 20895326Sek110237 char *cp; 20905326Sek110237 char cosname[MAXNAMELEN]; 20915326Sek110237 boolean_t force = (boolean_t)zc->zc_guid; 2092789Sahrens int error, fd; 2093789Sahrens 20943265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 20955326Sek110237 strchr(zc->zc_value, '@') == NULL || 20965326Sek110237 strchr(zc->zc_value, '%')) 20973265Sahrens return (EINVAL); 20983265Sahrens 2099789Sahrens fd = zc->zc_cookie; 2100789Sahrens fp = getf(fd); 2101789Sahrens if (fp == NULL) 2102789Sahrens return (EBADF); 21035326Sek110237 21045326Sek110237 /* 21055326Sek110237 * Get the zfsvfs for the receiving objset. There 21065326Sek110237 * won't be one if we're operating on a zvol, if the 21075326Sek110237 * objset doesn't exist yet, or is not mounted. 21085326Sek110237 */ 21095326Sek110237 cp = strchr(zc->zc_value, '@'); 21105326Sek110237 *cp = '\0'; 21115326Sek110237 error = dmu_objset_open(zc->zc_value, DMU_OST_ANY, 21125326Sek110237 DS_MODE_STANDARD | DS_MODE_READONLY, &os); 21135326Sek110237 *cp = '@'; 21145326Sek110237 if (!error) { 21155326Sek110237 if (dmu_objset_type(os) == DMU_OST_ZFS) { 21165326Sek110237 mutex_enter(&os->os->os_user_ptr_lock); 21175326Sek110237 zfsvfs = dmu_objset_get_user(os); 21185326Sek110237 if (zfsvfs != NULL) 21195326Sek110237 VFS_HOLD(zfsvfs->z_vfs); 21205326Sek110237 mutex_exit(&os->os->os_user_ptr_lock); 21215326Sek110237 } 21225326Sek110237 dmu_objset_close(os); 21235326Sek110237 } 21245326Sek110237 21252676Seschrock error = dmu_recvbackup(zc->zc_value, &zc->zc_begin_record, 21265326Sek110237 &zc->zc_cookie, force, zfsvfs != NULL, fp->f_vnode, 21275326Sek110237 fp->f_offset, cosname); 21285326Sek110237 21295326Sek110237 /* 21305326Sek110237 * For incremental snapshots where we created a 21315326Sek110237 * temporary clone, we now swap zfsvfs::z_os with 21325326Sek110237 * the newly created and received "cosname". 21335326Sek110237 */ 21345326Sek110237 if (!error && zfsvfs != NULL) { 21355326Sek110237 char osname[MAXNAMELEN]; 21365326Sek110237 int mode; 21375326Sek110237 21385326Sek110237 error = zfs_suspend_fs(zfsvfs, osname, &mode); 21395326Sek110237 if (!error) { 21405326Sek110237 int swap_err; 21415326Sek110237 int snap_err = 0; 21422885Sahrens 21435326Sek110237 swap_err = dsl_dataset_clone_swap(cosname, force); 21445326Sek110237 if (!swap_err) { 21455326Sek110237 char *cp = strrchr(zc->zc_value, '@'); 21465326Sek110237 21475326Sek110237 *cp = '\0'; 21485326Sek110237 snap_err = dmu_replay_end_snapshot(zc->zc_value, 21495326Sek110237 &zc->zc_begin_record); 21505326Sek110237 *cp = '@'; 21515326Sek110237 } 21525326Sek110237 error = zfs_resume_fs(zfsvfs, osname, mode); 21535326Sek110237 if (!error) 21545326Sek110237 error = swap_err; 21555326Sek110237 if (!error) 21565326Sek110237 error = snap_err; 21575326Sek110237 } 21585326Sek110237 21595326Sek110237 /* destroy the clone we created */ 21605326Sek110237 (void) dmu_objset_destroy(cosname); 21615326Sek110237 } 21625326Sek110237 if (zfsvfs != NULL) 21635326Sek110237 VFS_RELE(zfsvfs->z_vfs); 21642885Sahrens new_off = fp->f_offset + zc->zc_cookie; 2165*5331Samw if (VOP_SEEK(fp->f_vnode, fp->f_offset, &new_off, NULL) == 0) 21662885Sahrens fp->f_offset = new_off; 21672885Sahrens 2168789Sahrens releasef(fd); 2169789Sahrens return (error); 2170789Sahrens } 2171789Sahrens 2172789Sahrens static int 2173789Sahrens zfs_ioc_sendbackup(zfs_cmd_t *zc) 2174789Sahrens { 2175789Sahrens objset_t *fromsnap = NULL; 2176789Sahrens objset_t *tosnap; 2177789Sahrens file_t *fp; 2178789Sahrens int error; 2179789Sahrens 2180789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 2181789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); 2182789Sahrens if (error) 2183789Sahrens return (error); 2184789Sahrens 21852676Seschrock if (zc->zc_value[0] != '\0') { 21862885Sahrens char buf[MAXPATHLEN]; 21872885Sahrens char *cp; 21882885Sahrens 21892885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 21902885Sahrens cp = strchr(buf, '@'); 21912885Sahrens if (cp) 21922885Sahrens *(cp+1) = 0; 21932885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 21942885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 2195789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); 2196789Sahrens if (error) { 2197789Sahrens dmu_objset_close(tosnap); 2198789Sahrens return (error); 2199789Sahrens } 2200789Sahrens } 2201789Sahrens 2202789Sahrens fp = getf(zc->zc_cookie); 2203789Sahrens if (fp == NULL) { 2204789Sahrens dmu_objset_close(tosnap); 2205789Sahrens if (fromsnap) 2206789Sahrens dmu_objset_close(fromsnap); 2207789Sahrens return (EBADF); 2208789Sahrens } 2209789Sahrens 2210789Sahrens error = dmu_sendbackup(tosnap, fromsnap, fp->f_vnode); 2211789Sahrens 2212789Sahrens releasef(zc->zc_cookie); 2213789Sahrens if (fromsnap) 2214789Sahrens dmu_objset_close(fromsnap); 2215789Sahrens dmu_objset_close(tosnap); 2216789Sahrens return (error); 2217789Sahrens } 2218789Sahrens 22191544Seschrock static int 22201544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 22211544Seschrock { 22221544Seschrock int id, error; 22231544Seschrock 22241544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 22251544Seschrock &zc->zc_inject_record); 22261544Seschrock 22271544Seschrock if (error == 0) 22281544Seschrock zc->zc_guid = (uint64_t)id; 22291544Seschrock 22301544Seschrock return (error); 22311544Seschrock } 22321544Seschrock 22331544Seschrock static int 22341544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 22351544Seschrock { 22361544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 22371544Seschrock } 22381544Seschrock 22391544Seschrock static int 22401544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 22411544Seschrock { 22421544Seschrock int id = (int)zc->zc_guid; 22431544Seschrock int error; 22441544Seschrock 22451544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 22461544Seschrock &zc->zc_inject_record); 22471544Seschrock 22481544Seschrock zc->zc_guid = id; 22491544Seschrock 22501544Seschrock return (error); 22511544Seschrock } 22521544Seschrock 22531544Seschrock static int 22541544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 22551544Seschrock { 22561544Seschrock spa_t *spa; 22571544Seschrock int error; 22582676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 22591544Seschrock 22601544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 22611544Seschrock return (error); 22621544Seschrock 22632676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 22641544Seschrock &count); 22651544Seschrock if (error == 0) 22662676Seschrock zc->zc_nvlist_dst_size = count; 22671544Seschrock else 22682676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 22691544Seschrock 22701544Seschrock spa_close(spa, FTAG); 22711544Seschrock 22721544Seschrock return (error); 22731544Seschrock } 22741544Seschrock 22751544Seschrock static int 22761544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 22771544Seschrock { 22781544Seschrock spa_t *spa; 22791544Seschrock vdev_t *vd; 22804808Sek110237 uint64_t txg; 22811544Seschrock int error; 22821544Seschrock 22831544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 22841544Seschrock return (error); 22851544Seschrock 22865329Sgw25295 /* 22875329Sgw25295 * Try to resume any I/Os which may have been suspended 22885329Sgw25295 * as a result of a complete pool failure. 22895329Sgw25295 */ 22905329Sgw25295 if (!list_is_empty(&spa->spa_zio_list)) { 22915329Sgw25295 if (zio_vdev_resume_io(spa) != 0) { 22925329Sgw25295 spa_close(spa, FTAG); 22935329Sgw25295 return (EIO); 22945329Sgw25295 } 22955329Sgw25295 } 22965329Sgw25295 22974451Seschrock txg = spa_vdev_enter(spa); 22981544Seschrock 22992676Seschrock if (zc->zc_guid == 0) { 23001544Seschrock vd = NULL; 23012676Seschrock } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { 23024451Seschrock (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 23031544Seschrock spa_close(spa, FTAG); 23041544Seschrock return (ENODEV); 23051544Seschrock } 23061544Seschrock 23075329Sgw25295 vdev_clear(spa, vd, B_TRUE); 23081544Seschrock 23094451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 23101544Seschrock 23111544Seschrock spa_close(spa, FTAG); 23121544Seschrock 23131544Seschrock return (0); 23141544Seschrock } 23151544Seschrock 23161544Seschrock static int 23172082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 23182082Seschrock { 23192417Sahrens char *cp; 23202417Sahrens 23212417Sahrens /* 23222417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 23232417Sahrens * it's easier. 23242417Sahrens */ 23252676Seschrock cp = strchr(zc->zc_value, '@'); 23262417Sahrens if (cp) 23272417Sahrens *cp = '\0'; 23282676Seschrock (void) dmu_objset_find(zc->zc_value, 23292417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 23302082Seschrock return (dsl_dataset_promote(zc->zc_name)); 23312082Seschrock } 23322082Seschrock 23334543Smarks /* 23344543Smarks * We don't want to have a hard dependency 23354543Smarks * against some special symbols in sharefs 2336*5331Samw * nfs, and smbsrv. Determine them if needed when 23374543Smarks * the first file system is shared. 2338*5331Samw * Neither sharefs, nfs or smbsrv are unloadable modules. 23394543Smarks */ 2340*5331Samw int (*znfsexport_fs)(void *arg); 23414543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 2342*5331Samw int (*zsmbexport_fs)(void *arg, boolean_t add_share); 2343*5331Samw 2344*5331Samw int zfs_nfsshare_inited; 2345*5331Samw int zfs_smbshare_inited; 2346*5331Samw 23474543Smarks ddi_modhandle_t nfs_mod; 23484543Smarks ddi_modhandle_t sharefs_mod; 2349*5331Samw ddi_modhandle_t smbsrv_mod; 23504543Smarks kmutex_t zfs_share_lock; 23514543Smarks 23524543Smarks static int 2353*5331Samw zfs_init_sharefs() 2354*5331Samw { 2355*5331Samw int error; 2356*5331Samw 2357*5331Samw ASSERT(MUTEX_HELD(&zfs_share_lock)); 2358*5331Samw /* Both NFS and SMB shares also require sharetab support. */ 2359*5331Samw if (sharefs_mod == NULL && ((sharefs_mod = 2360*5331Samw ddi_modopen("fs/sharefs", 2361*5331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 2362*5331Samw return (ENOSYS); 2363*5331Samw } 2364*5331Samw if (zshare_fs == NULL && ((zshare_fs = 2365*5331Samw (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 2366*5331Samw ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 2367*5331Samw return (ENOSYS); 2368*5331Samw } 2369*5331Samw return (0); 2370*5331Samw } 2371*5331Samw 2372*5331Samw static int 23734543Smarks zfs_ioc_share(zfs_cmd_t *zc) 23744543Smarks { 23754543Smarks int error; 23764543Smarks int opcode; 23774543Smarks 2378*5331Samw switch (zc->zc_share.z_sharetype) { 2379*5331Samw case ZFS_SHARE_NFS: 2380*5331Samw case ZFS_UNSHARE_NFS: 2381*5331Samw if (zfs_nfsshare_inited == 0) { 2382*5331Samw mutex_enter(&zfs_share_lock); 2383*5331Samw if (nfs_mod == NULL && ((nfs_mod = ddi_modopen("fs/nfs", 2384*5331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 2385*5331Samw mutex_exit(&zfs_share_lock); 2386*5331Samw return (ENOSYS); 2387*5331Samw } 2388*5331Samw if (znfsexport_fs == NULL && 2389*5331Samw ((znfsexport_fs = (int (*)(void *)) 2390*5331Samw ddi_modsym(nfs_mod, 2391*5331Samw "nfs_export", &error)) == NULL)) { 2392*5331Samw mutex_exit(&zfs_share_lock); 2393*5331Samw return (ENOSYS); 2394*5331Samw } 2395*5331Samw error = zfs_init_sharefs(); 2396*5331Samw if (error) { 2397*5331Samw mutex_exit(&zfs_share_lock); 2398*5331Samw return (ENOSYS); 2399*5331Samw } 2400*5331Samw zfs_nfsshare_inited = 1; 24014543Smarks mutex_exit(&zfs_share_lock); 24024543Smarks } 2403*5331Samw break; 2404*5331Samw case ZFS_SHARE_SMB: 2405*5331Samw case ZFS_UNSHARE_SMB: 2406*5331Samw if (zfs_smbshare_inited == 0) { 2407*5331Samw mutex_enter(&zfs_share_lock); 2408*5331Samw if (smbsrv_mod == NULL && ((smbsrv_mod = 2409*5331Samw ddi_modopen("drv/smbsrv", 2410*5331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 2411*5331Samw mutex_exit(&zfs_share_lock); 2412*5331Samw return (ENOSYS); 2413*5331Samw } 2414*5331Samw if (zsmbexport_fs == NULL && ((zsmbexport_fs = 2415*5331Samw (int (*)(void *, boolean_t))ddi_modsym(smbsrv_mod, 2416*5331Samw "lmshrd_share_upcall", &error)) == NULL)) { 2417*5331Samw mutex_exit(&zfs_share_lock); 2418*5331Samw return (ENOSYS); 2419*5331Samw } 2420*5331Samw error = zfs_init_sharefs(); 2421*5331Samw if (error) { 2422*5331Samw mutex_exit(&zfs_share_lock); 2423*5331Samw return (ENOSYS); 2424*5331Samw } 2425*5331Samw zfs_smbshare_inited = 1; 24264543Smarks mutex_exit(&zfs_share_lock); 24274543Smarks } 2428*5331Samw break; 2429*5331Samw default: 2430*5331Samw return (EINVAL); 24314543Smarks } 24324543Smarks 2433*5331Samw switch (zc->zc_share.z_sharetype) { 2434*5331Samw case ZFS_SHARE_NFS: 2435*5331Samw case ZFS_UNSHARE_NFS: 2436*5331Samw if (error = 2437*5331Samw znfsexport_fs((void *) 2438*5331Samw (uintptr_t)zc->zc_share.z_exportdata)) 2439*5331Samw return (error); 2440*5331Samw break; 2441*5331Samw case ZFS_SHARE_SMB: 2442*5331Samw case ZFS_UNSHARE_SMB: 2443*5331Samw if (error = zsmbexport_fs((void *) 2444*5331Samw (uintptr_t)zc->zc_share.z_exportdata, 2445*5331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB ? 2446*5331Samw B_TRUE : B_FALSE)) { 2447*5331Samw return (error); 2448*5331Samw } 2449*5331Samw break; 2450*5331Samw } 2451*5331Samw 2452*5331Samw opcode = (zc->zc_share.z_sharetype == ZFS_SHARE_NFS || 2453*5331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB) ? 24544543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 24554543Smarks 2456*5331Samw /* 2457*5331Samw * Add or remove share from sharetab 2458*5331Samw */ 24594543Smarks error = zshare_fs(opcode, 24604543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 24614543Smarks zc->zc_share.z_sharemax); 24624543Smarks 24634543Smarks return (error); 24644543Smarks 24654543Smarks } 24664543Smarks 24674543Smarks /* 24684988Sek110237 * pool create, destroy, and export don't log the history as part of 24694988Sek110237 * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export 24704988Sek110237 * do the logging of those commands. 24714543Smarks */ 2472789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 24734715Sek110237 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 24744577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 24754577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 24764577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 24774577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 24784577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 24794577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 24804577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 24814577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 24824577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 24834577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 24844577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 24854577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 24864577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 24874577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 24884577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 24894577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 24904577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 24915147Srm160521 { zfs_ioc_objset_version, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 24924543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 24934577Sahrens DATASET_NAME, B_FALSE }, 24944543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 24954577Sahrens DATASET_NAME, B_FALSE }, 24964577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 24974577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 24984577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 24994577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 25004577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 25014577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 25024577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 25034577Sahrens { zfs_ioc_recvbackup, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 25044577Sahrens { zfs_ioc_sendbackup, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 25054577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 25064577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 25074577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 25084577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 25094577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 25104577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 25114577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 25124577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 25134577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 25144577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 25154577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 25164577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 25174577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 25184577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 25194543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 25204577Sahrens DATASET_NAME, B_FALSE }, 25214849Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }, 25224849Sahrens { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE }, 2523789Sahrens }; 2524789Sahrens 2525789Sahrens static int 2526789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2527789Sahrens { 2528789Sahrens zfs_cmd_t *zc; 2529789Sahrens uint_t vec; 25302199Sahrens int error, rc; 2531789Sahrens 2532789Sahrens if (getminor(dev) != 0) 2533789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2534789Sahrens 2535789Sahrens vec = cmd - ZFS_IOC; 25364787Sahrens ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); 2537789Sahrens 2538789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2539789Sahrens return (EINVAL); 2540789Sahrens 2541789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2542789Sahrens 2543789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2544789Sahrens 25454787Sahrens if (error == 0) 25464543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2547789Sahrens 2548789Sahrens /* 2549789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2550789Sahrens * the lower layers. 2551789Sahrens */ 2552789Sahrens if (error == 0) { 2553789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2554789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 25554577Sahrens case POOL_NAME: 2556789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2557789Sahrens error = EINVAL; 2558789Sahrens break; 2559789Sahrens 25604577Sahrens case DATASET_NAME: 2561789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2562789Sahrens error = EINVAL; 2563789Sahrens break; 25642856Snd150628 25654577Sahrens case NO_NAME: 25662856Snd150628 break; 2567789Sahrens } 2568789Sahrens } 2569789Sahrens 2570789Sahrens if (error == 0) 2571789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2572789Sahrens 25732199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 25744543Smarks if (error == 0) { 25752199Sahrens error = rc; 25764543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 25774543Smarks zfs_log_history(zc); 25784543Smarks } 2579789Sahrens 2580789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2581789Sahrens return (error); 2582789Sahrens } 2583789Sahrens 2584789Sahrens static int 2585789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2586789Sahrens { 2587789Sahrens if (cmd != DDI_ATTACH) 2588789Sahrens return (DDI_FAILURE); 2589789Sahrens 2590789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2591789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2592789Sahrens return (DDI_FAILURE); 2593789Sahrens 2594789Sahrens zfs_dip = dip; 2595789Sahrens 2596789Sahrens ddi_report_dev(dip); 2597789Sahrens 2598789Sahrens return (DDI_SUCCESS); 2599789Sahrens } 2600789Sahrens 2601789Sahrens static int 2602789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2603789Sahrens { 2604789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2605789Sahrens return (DDI_FAILURE); 2606789Sahrens 2607789Sahrens if (cmd != DDI_DETACH) 2608789Sahrens return (DDI_FAILURE); 2609789Sahrens 2610789Sahrens zfs_dip = NULL; 2611789Sahrens 2612789Sahrens ddi_prop_remove_all(dip); 2613789Sahrens ddi_remove_minor_node(dip, NULL); 2614789Sahrens 2615789Sahrens return (DDI_SUCCESS); 2616789Sahrens } 2617789Sahrens 2618789Sahrens /*ARGSUSED*/ 2619789Sahrens static int 2620789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2621789Sahrens { 2622789Sahrens switch (infocmd) { 2623789Sahrens case DDI_INFO_DEVT2DEVINFO: 2624789Sahrens *result = zfs_dip; 2625789Sahrens return (DDI_SUCCESS); 2626789Sahrens 2627789Sahrens case DDI_INFO_DEVT2INSTANCE: 2628849Sbonwick *result = (void *)0; 2629789Sahrens return (DDI_SUCCESS); 2630789Sahrens } 2631789Sahrens 2632789Sahrens return (DDI_FAILURE); 2633789Sahrens } 2634789Sahrens 2635789Sahrens /* 2636789Sahrens * OK, so this is a little weird. 2637789Sahrens * 2638789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2639789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2640789Sahrens * 2641789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2642789Sahrens * so most of the standard driver entry points are in zvol.c. 2643789Sahrens */ 2644789Sahrens static struct cb_ops zfs_cb_ops = { 2645789Sahrens zvol_open, /* open */ 2646789Sahrens zvol_close, /* close */ 2647789Sahrens zvol_strategy, /* strategy */ 2648789Sahrens nodev, /* print */ 2649789Sahrens nodev, /* dump */ 2650789Sahrens zvol_read, /* read */ 2651789Sahrens zvol_write, /* write */ 2652789Sahrens zfsdev_ioctl, /* ioctl */ 2653789Sahrens nodev, /* devmap */ 2654789Sahrens nodev, /* mmap */ 2655789Sahrens nodev, /* segmap */ 2656789Sahrens nochpoll, /* poll */ 2657789Sahrens ddi_prop_op, /* prop_op */ 2658789Sahrens NULL, /* streamtab */ 2659789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2660789Sahrens CB_REV, /* version */ 26613638Sbillm nodev, /* async read */ 26623638Sbillm nodev, /* async write */ 2663789Sahrens }; 2664789Sahrens 2665789Sahrens static struct dev_ops zfs_dev_ops = { 2666789Sahrens DEVO_REV, /* version */ 2667789Sahrens 0, /* refcnt */ 2668789Sahrens zfs_info, /* info */ 2669789Sahrens nulldev, /* identify */ 2670789Sahrens nulldev, /* probe */ 2671789Sahrens zfs_attach, /* attach */ 2672789Sahrens zfs_detach, /* detach */ 2673789Sahrens nodev, /* reset */ 2674789Sahrens &zfs_cb_ops, /* driver operations */ 2675789Sahrens NULL /* no bus operations */ 2676789Sahrens }; 2677789Sahrens 2678789Sahrens static struct modldrv zfs_modldrv = { 26794577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 26802676Seschrock &zfs_dev_ops 2681789Sahrens }; 2682789Sahrens 2683789Sahrens static struct modlinkage modlinkage = { 2684789Sahrens MODREV_1, 2685789Sahrens (void *)&zfs_modlfs, 2686789Sahrens (void *)&zfs_modldrv, 2687789Sahrens NULL 2688789Sahrens }; 2689789Sahrens 26904720Sfr157268 26914720Sfr157268 uint_t zfs_fsyncer_key; 26925326Sek110237 extern uint_t rrw_tsd_key; 26934720Sfr157268 2694789Sahrens int 2695789Sahrens _init(void) 2696789Sahrens { 2697789Sahrens int error; 2698789Sahrens 2699849Sbonwick spa_init(FREAD | FWRITE); 2700849Sbonwick zfs_init(); 2701849Sbonwick zvol_init(); 2702849Sbonwick 2703849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 2704849Sbonwick zvol_fini(); 2705849Sbonwick zfs_fini(); 2706849Sbonwick spa_fini(); 2707789Sahrens return (error); 2708849Sbonwick } 2709789Sahrens 27104720Sfr157268 tsd_create(&zfs_fsyncer_key, NULL); 27115326Sek110237 tsd_create(&rrw_tsd_key, NULL); 27124720Sfr157268 2713789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 2714789Sahrens ASSERT(error == 0); 27154543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 2716789Sahrens 2717789Sahrens return (0); 2718789Sahrens } 2719789Sahrens 2720789Sahrens int 2721789Sahrens _fini(void) 2722789Sahrens { 2723789Sahrens int error; 2724789Sahrens 27251544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 2726789Sahrens return (EBUSY); 2727789Sahrens 2728789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 2729789Sahrens return (error); 2730789Sahrens 2731789Sahrens zvol_fini(); 2732789Sahrens zfs_fini(); 2733789Sahrens spa_fini(); 2734*5331Samw if (zfs_nfsshare_inited) 27354543Smarks (void) ddi_modclose(nfs_mod); 2736*5331Samw if (zfs_smbshare_inited) 2737*5331Samw (void) ddi_modclose(smbsrv_mod); 2738*5331Samw if (zfs_nfsshare_inited || zfs_smbshare_inited) 27394543Smarks (void) ddi_modclose(sharefs_mod); 2740789Sahrens 27414720Sfr157268 tsd_destroy(&zfs_fsyncer_key); 2742789Sahrens ldi_ident_release(zfs_li); 2743789Sahrens zfs_li = NULL; 27444543Smarks mutex_destroy(&zfs_share_lock); 2745789Sahrens 2746789Sahrens return (error); 2747789Sahrens } 2748789Sahrens 2749789Sahrens int 2750789Sahrens _info(struct modinfo *modinfop) 2751789Sahrens { 2752789Sahrens return (mod_info(&modlinkage, modinfop)); 2753789Sahrens } 2754