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 /* 225977Smarks * Copyright 2008 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> 415331Samw #include <sys/zfs_znode.h> 42789Sahrens #include <sys/zap.h> 43789Sahrens #include <sys/spa.h> 443912Slling #include <sys/spa_impl.h> 45789Sahrens #include <sys/vdev.h> 463912Slling #include <sys/vdev_impl.h> 47789Sahrens #include <sys/dmu.h> 48789Sahrens #include <sys/dsl_dir.h> 49789Sahrens #include <sys/dsl_dataset.h> 50789Sahrens #include <sys/dsl_prop.h> 514543Smarks #include <sys/dsl_deleg.h> 524543Smarks #include <sys/dmu_objset.h> 53789Sahrens #include <sys/ddi.h> 54789Sahrens #include <sys/sunddi.h> 55789Sahrens #include <sys/sunldi.h> 56789Sahrens #include <sys/policy.h> 57789Sahrens #include <sys/zone.h> 58789Sahrens #include <sys/nvpair.h> 59789Sahrens #include <sys/pathname.h> 60789Sahrens #include <sys/mount.h> 61789Sahrens #include <sys/sdt.h> 62789Sahrens #include <sys/fs/zfs.h> 63789Sahrens #include <sys/zfs_ctldir.h> 645331Samw #include <sys/zfs_dir.h> 652885Sahrens #include <sys/zvol.h> 664543Smarks #include <sharefs/share.h> 675326Sek110237 #include <sys/dmu_objset.h> 68789Sahrens 69789Sahrens #include "zfs_namecheck.h" 702676Seschrock #include "zfs_prop.h" 714543Smarks #include "zfs_deleg.h" 72789Sahrens 73789Sahrens extern struct modlfs zfs_modlfs; 74789Sahrens 75789Sahrens extern void zfs_init(void); 76789Sahrens extern void zfs_fini(void); 77789Sahrens 78789Sahrens ldi_ident_t zfs_li = NULL; 79789Sahrens dev_info_t *zfs_dip; 80789Sahrens 81789Sahrens typedef int zfs_ioc_func_t(zfs_cmd_t *); 824543Smarks typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *); 83789Sahrens 84789Sahrens typedef struct zfs_ioc_vec { 85789Sahrens zfs_ioc_func_t *zvec_func; 86789Sahrens zfs_secpolicy_func_t *zvec_secpolicy; 87789Sahrens enum { 884577Sahrens NO_NAME, 894577Sahrens POOL_NAME, 904577Sahrens DATASET_NAME 914543Smarks } zvec_namecheck; 924543Smarks boolean_t zvec_his_log; 93789Sahrens } zfs_ioc_vec_t; 94789Sahrens 95*7265Sahrens static void clear_props(char *dataset, nvlist_t *props); 967184Stimh static int zfs_fill_zplprops_root(uint64_t, nvlist_t *, nvlist_t *, 977184Stimh boolean_t *); 987184Stimh int zfs_set_prop_nvlist(const char *, nvlist_t *); 997184Stimh 100789Sahrens /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */ 101789Sahrens void 102789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 103789Sahrens { 104789Sahrens const char *newfile; 105789Sahrens char buf[256]; 106789Sahrens va_list adx; 107789Sahrens 108789Sahrens /* 109789Sahrens * Get rid of annoying "../common/" prefix to filename. 110789Sahrens */ 111789Sahrens newfile = strrchr(file, '/'); 112789Sahrens if (newfile != NULL) { 113789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 114789Sahrens } else { 115789Sahrens newfile = file; 116789Sahrens } 117789Sahrens 118789Sahrens va_start(adx, fmt); 119789Sahrens (void) vsnprintf(buf, sizeof (buf), fmt, adx); 120789Sahrens va_end(adx); 121789Sahrens 122789Sahrens /* 123789Sahrens * To get this data, use the zfs-dprintf probe as so: 124789Sahrens * dtrace -q -n 'zfs-dprintf \ 125789Sahrens * /stringof(arg0) == "dbuf.c"/ \ 126789Sahrens * {printf("%s: %s", stringof(arg1), stringof(arg3))}' 127789Sahrens * arg0 = file name 128789Sahrens * arg1 = function name 129789Sahrens * arg2 = line number 130789Sahrens * arg3 = message 131789Sahrens */ 132789Sahrens DTRACE_PROBE4(zfs__dprintf, 133789Sahrens char *, newfile, char *, func, int, line, char *, buf); 134789Sahrens } 135789Sahrens 1364543Smarks static void 1374715Sek110237 history_str_free(char *buf) 1384715Sek110237 { 1394715Sek110237 kmem_free(buf, HIS_MAX_RECORD_LEN); 1404715Sek110237 } 1414715Sek110237 1424715Sek110237 static char * 1434715Sek110237 history_str_get(zfs_cmd_t *zc) 1444715Sek110237 { 1454715Sek110237 char *buf; 1464715Sek110237 1474715Sek110237 if (zc->zc_history == NULL) 1484715Sek110237 return (NULL); 1494715Sek110237 1504715Sek110237 buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP); 1514715Sek110237 if (copyinstr((void *)(uintptr_t)zc->zc_history, 1524715Sek110237 buf, HIS_MAX_RECORD_LEN, NULL) != 0) { 1534715Sek110237 history_str_free(buf); 1544715Sek110237 return (NULL); 1554715Sek110237 } 1564715Sek110237 1574715Sek110237 buf[HIS_MAX_RECORD_LEN -1] = '\0'; 1584715Sek110237 1594715Sek110237 return (buf); 1604715Sek110237 } 1614715Sek110237 1625375Stimh /* 1637042Sgw25295 * Check to see if the named dataset is currently defined as bootable 1647042Sgw25295 */ 1657042Sgw25295 static boolean_t 1667042Sgw25295 zfs_is_bootfs(const char *name) 1677042Sgw25295 { 1687042Sgw25295 spa_t *spa; 1697042Sgw25295 boolean_t ret = B_FALSE; 1707042Sgw25295 1717042Sgw25295 if (spa_open(name, &spa, FTAG) == 0) { 1727042Sgw25295 if (spa->spa_bootfs) { 1737042Sgw25295 objset_t *os; 1747042Sgw25295 1757042Sgw25295 if (dmu_objset_open(name, DMU_OST_ZFS, 1767042Sgw25295 DS_MODE_USER | DS_MODE_READONLY, &os) == 0) { 1777042Sgw25295 ret = (dmu_objset_id(os) == spa->spa_bootfs); 1787042Sgw25295 dmu_objset_close(os); 1797042Sgw25295 } 1807042Sgw25295 } 1817042Sgw25295 spa_close(spa, FTAG); 1827042Sgw25295 } 1837042Sgw25295 return (ret); 1847042Sgw25295 } 1857042Sgw25295 1867042Sgw25295 /* 1877184Stimh * zfs_earlier_version 1885375Stimh * 1895375Stimh * Return non-zero if the spa version is less than requested version. 1905375Stimh */ 1915331Samw static int 1927184Stimh zfs_earlier_version(const char *name, int version) 1935331Samw { 1945331Samw spa_t *spa; 1955331Samw 1965331Samw if (spa_open(name, &spa, FTAG) == 0) { 1975331Samw if (spa_version(spa) < version) { 1985331Samw spa_close(spa, FTAG); 1995331Samw return (1); 2005331Samw } 2015331Samw spa_close(spa, FTAG); 2025331Samw } 2035331Samw return (0); 2045331Samw } 2055331Samw 2065977Smarks /* 2076689Smaybee * zpl_earlier_version 2085977Smarks * 2096689Smaybee * Return TRUE if the ZPL version is less than requested version. 2105977Smarks */ 2116689Smaybee static boolean_t 2126689Smaybee zpl_earlier_version(const char *name, int version) 2135977Smarks { 2145977Smarks objset_t *os; 2156689Smaybee boolean_t rc = B_TRUE; 2165977Smarks 2175977Smarks if (dmu_objset_open(name, DMU_OST_ANY, 2186689Smaybee DS_MODE_USER | DS_MODE_READONLY, &os) == 0) { 2196689Smaybee uint64_t zplversion; 2206689Smaybee 2216689Smaybee if (zfs_get_zplprop(os, ZFS_PROP_VERSION, &zplversion) == 0) 2226689Smaybee rc = zplversion < version; 2235977Smarks dmu_objset_close(os); 2245977Smarks } 2255977Smarks return (rc); 2265977Smarks } 2275977Smarks 2284715Sek110237 static void 2294543Smarks zfs_log_history(zfs_cmd_t *zc) 2304543Smarks { 2314543Smarks spa_t *spa; 2324603Sahrens char *buf; 2334543Smarks 2344715Sek110237 if ((buf = history_str_get(zc)) == NULL) 2354577Sahrens return; 2364577Sahrens 2374715Sek110237 if (spa_open(zc->zc_name, &spa, FTAG) == 0) { 2384715Sek110237 if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY) 2394715Sek110237 (void) spa_history_log(spa, buf, LOG_CMD_NORMAL); 2404715Sek110237 spa_close(spa, FTAG); 2414543Smarks } 2424715Sek110237 history_str_free(buf); 2434543Smarks } 2444543Smarks 245789Sahrens /* 246789Sahrens * Policy for top-level read operations (list pools). Requires no privileges, 247789Sahrens * and can be used in the local zone, as there is no associated dataset. 248789Sahrens */ 249789Sahrens /* ARGSUSED */ 250789Sahrens static int 2514543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) 252789Sahrens { 253789Sahrens return (0); 254789Sahrens } 255789Sahrens 256789Sahrens /* 257789Sahrens * Policy for dataset read operations (list children, get statistics). Requires 258789Sahrens * no privileges, but must be visible in the local zone. 259789Sahrens */ 260789Sahrens /* ARGSUSED */ 261789Sahrens static int 2624543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) 263789Sahrens { 264789Sahrens if (INGLOBALZONE(curproc) || 2654543Smarks zone_dataset_visible(zc->zc_name, NULL)) 266789Sahrens return (0); 267789Sahrens 268789Sahrens return (ENOENT); 269789Sahrens } 270789Sahrens 271789Sahrens static int 272789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr) 273789Sahrens { 274789Sahrens uint64_t zoned; 275789Sahrens int writable = 1; 276789Sahrens 277789Sahrens /* 278789Sahrens * The dataset must be visible by this zone -- check this first 279789Sahrens * so they don't see EPERM on something they shouldn't know about. 280789Sahrens */ 281789Sahrens if (!INGLOBALZONE(curproc) && 282789Sahrens !zone_dataset_visible(dataset, &writable)) 283789Sahrens return (ENOENT); 284789Sahrens 285789Sahrens if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) 286789Sahrens return (ENOENT); 287789Sahrens 288789Sahrens if (INGLOBALZONE(curproc)) { 289789Sahrens /* 290789Sahrens * If the fs is zoned, only root can access it from the 291789Sahrens * global zone. 292789Sahrens */ 293789Sahrens if (secpolicy_zfs(cr) && zoned) 294789Sahrens return (EPERM); 295789Sahrens } else { 296789Sahrens /* 297789Sahrens * If we are in a local zone, the 'zoned' property must be set. 298789Sahrens */ 299789Sahrens if (!zoned) 300789Sahrens return (EPERM); 301789Sahrens 302789Sahrens /* must be writable by this zone */ 303789Sahrens if (!writable) 304789Sahrens return (EPERM); 305789Sahrens } 306789Sahrens return (0); 307789Sahrens } 308789Sahrens 309789Sahrens int 3104543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) 311789Sahrens { 312789Sahrens int error; 313789Sahrens 3144543Smarks error = zfs_dozonecheck(name, cr); 3154543Smarks if (error == 0) { 3164543Smarks error = secpolicy_zfs(cr); 3174670Sahrens if (error) 3184543Smarks error = dsl_deleg_access(name, perm, cr); 3194543Smarks } 3204543Smarks return (error); 3214543Smarks } 3224543Smarks 3234543Smarks static int 3244543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) 3254543Smarks { 3264543Smarks /* 3274543Smarks * Check permissions for special properties. 3284543Smarks */ 3294543Smarks switch (prop) { 3304543Smarks case ZFS_PROP_ZONED: 3314543Smarks /* 3324543Smarks * Disallow setting of 'zoned' from within a local zone. 3334543Smarks */ 3344543Smarks if (!INGLOBALZONE(curproc)) 3354543Smarks return (EPERM); 3364543Smarks break; 337789Sahrens 3384543Smarks case ZFS_PROP_QUOTA: 3394543Smarks if (!INGLOBALZONE(curproc)) { 3404543Smarks uint64_t zoned; 3414543Smarks char setpoint[MAXNAMELEN]; 3424543Smarks /* 3434543Smarks * Unprivileged users are allowed to modify the 3444543Smarks * quota on things *under* (ie. contained by) 3454543Smarks * the thing they own. 3464543Smarks */ 3474543Smarks if (dsl_prop_get_integer(name, "zoned", &zoned, 3484543Smarks setpoint)) 3494543Smarks return (EPERM); 3504670Sahrens if (!zoned || strlen(name) <= strlen(setpoint)) 3514543Smarks return (EPERM); 3524543Smarks } 3534670Sahrens break; 3544543Smarks } 3554543Smarks 3564787Sahrens return (zfs_secpolicy_write_perms(name, zfs_prop_to_name(prop), cr)); 357789Sahrens } 358789Sahrens 3594543Smarks int 3604543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) 3614543Smarks { 3624543Smarks int error; 3634543Smarks 3644543Smarks error = zfs_dozonecheck(zc->zc_name, cr); 3654543Smarks if (error) 3664543Smarks return (error); 3674543Smarks 3684543Smarks /* 3694543Smarks * permission to set permissions will be evaluated later in 3704543Smarks * dsl_deleg_can_allow() 3714543Smarks */ 3724543Smarks return (0); 3734543Smarks } 3744543Smarks 3754543Smarks int 3764543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) 3774543Smarks { 3784543Smarks int error; 3794543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3804543Smarks ZFS_DELEG_PERM_ROLLBACK, cr); 3814543Smarks if (error == 0) 3824543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3834543Smarks ZFS_DELEG_PERM_MOUNT, cr); 3844543Smarks return (error); 3854543Smarks } 3864543Smarks 3874543Smarks int 3884543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) 3894543Smarks { 3904543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 3914543Smarks ZFS_DELEG_PERM_SEND, cr)); 3924543Smarks } 3934543Smarks 3944543Smarks int 3954543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) 3964543Smarks { 3974543Smarks if (!INGLOBALZONE(curproc)) 3984543Smarks return (EPERM); 3994543Smarks 4005367Sahrens if (secpolicy_nfs(cr) == 0) { 4014543Smarks return (0); 4024543Smarks } else { 4034543Smarks vnode_t *vp; 4044543Smarks int error; 4054543Smarks 4064543Smarks if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, 4074543Smarks NO_FOLLOW, NULL, &vp)) != 0) 4084543Smarks return (error); 4094543Smarks 4104543Smarks /* Now make sure mntpnt and dataset are ZFS */ 4114543Smarks 4124543Smarks if (vp->v_vfsp->vfs_fstype != zfsfstype || 4134543Smarks (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), 4144543Smarks zc->zc_name) != 0)) { 4154543Smarks VN_RELE(vp); 4164543Smarks return (EPERM); 4174543Smarks } 4184543Smarks 4194543Smarks VN_RELE(vp); 4204543Smarks return (dsl_deleg_access(zc->zc_name, 4214543Smarks ZFS_DELEG_PERM_SHARE, cr)); 4224543Smarks } 4234543Smarks } 4244543Smarks 425789Sahrens static int 4264543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize) 427789Sahrens { 428789Sahrens char *cp; 429789Sahrens 430789Sahrens /* 431789Sahrens * Remove the @bla or /bla from the end of the name to get the parent. 432789Sahrens */ 4334543Smarks (void) strncpy(parent, datasetname, parentsize); 4344543Smarks cp = strrchr(parent, '@'); 435789Sahrens if (cp != NULL) { 436789Sahrens cp[0] = '\0'; 437789Sahrens } else { 4384543Smarks cp = strrchr(parent, '/'); 439789Sahrens if (cp == NULL) 440789Sahrens return (ENOENT); 441789Sahrens cp[0] = '\0'; 442789Sahrens } 443789Sahrens 4444543Smarks return (0); 4454543Smarks } 4464543Smarks 4474543Smarks int 4484543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 4494543Smarks { 4504543Smarks int error; 4514543Smarks 4524543Smarks if ((error = zfs_secpolicy_write_perms(name, 4534543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4544543Smarks return (error); 4554543Smarks 4564543Smarks return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); 4574543Smarks } 4584543Smarks 4594543Smarks static int 4604543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) 4614543Smarks { 4624543Smarks return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); 4634543Smarks } 4644543Smarks 4654543Smarks /* 4664543Smarks * Must have sys_config privilege to check the iscsi permission 4674543Smarks */ 4684543Smarks /* ARGSUSED */ 4694543Smarks static int 4704543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) 4714543Smarks { 4724543Smarks return (secpolicy_zfs(cr)); 4734543Smarks } 4744543Smarks 4754543Smarks int 4764543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 4774543Smarks { 4784543Smarks char parentname[MAXNAMELEN]; 4794543Smarks int error; 4804543Smarks 4814543Smarks if ((error = zfs_secpolicy_write_perms(from, 4824543Smarks ZFS_DELEG_PERM_RENAME, cr)) != 0) 4834543Smarks return (error); 4844543Smarks 4854543Smarks if ((error = zfs_secpolicy_write_perms(from, 4864543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4874543Smarks return (error); 4884543Smarks 4894543Smarks if ((error = zfs_get_parent(to, parentname, 4904543Smarks sizeof (parentname))) != 0) 4914543Smarks return (error); 4924543Smarks 4934543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4944543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 4954543Smarks return (error); 4964543Smarks 4974543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4984543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4994543Smarks return (error); 5004543Smarks 5014543Smarks return (error); 5024543Smarks } 5034543Smarks 5044543Smarks static int 5054543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) 5064543Smarks { 5074543Smarks return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); 5084543Smarks } 5094543Smarks 5104543Smarks static int 5114543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) 5124543Smarks { 5134543Smarks char parentname[MAXNAMELEN]; 5144543Smarks objset_t *clone; 5154543Smarks int error; 5164543Smarks 5174543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 5184543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 5194543Smarks if (error) 5204543Smarks return (error); 5214543Smarks 5224543Smarks error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 5236689Smaybee DS_MODE_USER | DS_MODE_READONLY, &clone); 5244543Smarks 5254543Smarks if (error == 0) { 5264543Smarks dsl_dataset_t *pclone = NULL; 5274543Smarks dsl_dir_t *dd; 5284543Smarks dd = clone->os->os_dsl_dataset->ds_dir; 5294543Smarks 5304543Smarks rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 5316689Smaybee error = dsl_dataset_hold_obj(dd->dd_pool, 5326689Smaybee dd->dd_phys->dd_origin_obj, FTAG, &pclone); 5334543Smarks rw_exit(&dd->dd_pool->dp_config_rwlock); 5344543Smarks if (error) { 5354543Smarks dmu_objset_close(clone); 5364543Smarks return (error); 5374543Smarks } 5384543Smarks 5394543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 5404543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5414543Smarks 5424543Smarks dsl_dataset_name(pclone, parentname); 5434543Smarks dmu_objset_close(clone); 5446689Smaybee dsl_dataset_rele(pclone, FTAG); 5454543Smarks if (error == 0) 5464543Smarks error = zfs_secpolicy_write_perms(parentname, 5474543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 5484543Smarks } 5494543Smarks return (error); 5504543Smarks } 5514543Smarks 5524543Smarks static int 5534543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) 5544543Smarks { 5554543Smarks int error; 5564543Smarks 5574543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5584543Smarks ZFS_DELEG_PERM_RECEIVE, cr)) != 0) 5594543Smarks return (error); 5604543Smarks 5614543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5624543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 5634543Smarks return (error); 5644543Smarks 5654543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 5664543Smarks ZFS_DELEG_PERM_CREATE, cr)); 5674543Smarks } 5684543Smarks 5694543Smarks int 5704543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 5714543Smarks { 5724543Smarks int error; 5734543Smarks 5744543Smarks if ((error = zfs_secpolicy_write_perms(name, 5754543Smarks ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) 5764543Smarks return (error); 5774543Smarks 5784543Smarks error = zfs_secpolicy_write_perms(name, 5794543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5804543Smarks 5814543Smarks return (error); 5824543Smarks } 5834543Smarks 5844543Smarks static int 5854543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) 5864543Smarks { 5874543Smarks 5884543Smarks return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); 5894543Smarks } 5904543Smarks 5914543Smarks static int 5924543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) 5934543Smarks { 5944543Smarks char parentname[MAXNAMELEN]; 5954543Smarks int error; 5964543Smarks 5974543Smarks if ((error = zfs_get_parent(zc->zc_name, parentname, 5984543Smarks sizeof (parentname))) != 0) 5994543Smarks return (error); 6004543Smarks 6014543Smarks if (zc->zc_value[0] != '\0') { 6024543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_value, 6034543Smarks ZFS_DELEG_PERM_CLONE, cr)) != 0) 6044543Smarks return (error); 6054543Smarks } 6064543Smarks 6074543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 6084543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 6094543Smarks return (error); 6104543Smarks 6114543Smarks error = zfs_secpolicy_write_perms(parentname, 6124543Smarks ZFS_DELEG_PERM_MOUNT, cr); 6134543Smarks 6144543Smarks return (error); 6154543Smarks } 6164543Smarks 6174543Smarks static int 6184543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) 6194543Smarks { 6204543Smarks int error; 6214543Smarks 6224543Smarks error = secpolicy_fs_unmount(cr, NULL); 6234543Smarks if (error) { 6244543Smarks error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); 6254543Smarks } 6264543Smarks return (error); 627789Sahrens } 628789Sahrens 629789Sahrens /* 630789Sahrens * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires 631789Sahrens * SYS_CONFIG privilege, which is not available in a local zone. 632789Sahrens */ 633789Sahrens /* ARGSUSED */ 634789Sahrens static int 6354543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) 636789Sahrens { 637789Sahrens if (secpolicy_sys_config(cr, B_FALSE) != 0) 638789Sahrens return (EPERM); 639789Sahrens 640789Sahrens return (0); 641789Sahrens } 642789Sahrens 643789Sahrens /* 6444543Smarks * Just like zfs_secpolicy_config, except that we will check for 6454543Smarks * mount permission on the dataset for permission to create/remove 6464543Smarks * the minor nodes. 6474543Smarks */ 6484543Smarks static int 6494543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) 6504543Smarks { 6514543Smarks if (secpolicy_sys_config(cr, B_FALSE) != 0) { 6524543Smarks return (dsl_deleg_access(zc->zc_name, 6534543Smarks ZFS_DELEG_PERM_MOUNT, cr)); 6544543Smarks } 6554543Smarks 6564543Smarks return (0); 6574543Smarks } 6584543Smarks 6594543Smarks /* 6601544Seschrock * Policy for fault injection. Requires all privileges. 6611544Seschrock */ 6621544Seschrock /* ARGSUSED */ 6631544Seschrock static int 6644543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) 6651544Seschrock { 6661544Seschrock return (secpolicy_zinject(cr)); 6671544Seschrock } 6681544Seschrock 6694849Sahrens static int 6704849Sahrens zfs_secpolicy_inherit(zfs_cmd_t *zc, cred_t *cr) 6714849Sahrens { 6724849Sahrens zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); 6734849Sahrens 6745094Slling if (prop == ZPROP_INVAL) { 6754849Sahrens if (!zfs_prop_user(zc->zc_value)) 6764849Sahrens return (EINVAL); 6774849Sahrens return (zfs_secpolicy_write_perms(zc->zc_name, 6784849Sahrens ZFS_DELEG_PERM_USERPROP, cr)); 6794849Sahrens } else { 6804849Sahrens if (!zfs_prop_inheritable(prop)) 6814849Sahrens return (EINVAL); 6824849Sahrens return (zfs_secpolicy_setprop(zc->zc_name, prop, cr)); 6834849Sahrens } 6844849Sahrens } 6854849Sahrens 6861544Seschrock /* 687789Sahrens * Returns the nvlist as specified by the user in the zfs_cmd_t. 688789Sahrens */ 689789Sahrens static int 6905094Slling get_nvlist(uint64_t nvl, uint64_t size, nvlist_t **nvp) 691789Sahrens { 692789Sahrens char *packed; 693789Sahrens int error; 6945094Slling nvlist_t *list = NULL; 695789Sahrens 696789Sahrens /* 6972676Seschrock * Read in and unpack the user-supplied nvlist. 698789Sahrens */ 6995094Slling if (size == 0) 700789Sahrens return (EINVAL); 701789Sahrens 702789Sahrens packed = kmem_alloc(size, KM_SLEEP); 703789Sahrens 7045094Slling if ((error = xcopyin((void *)(uintptr_t)nvl, packed, size)) != 0) { 705789Sahrens kmem_free(packed, size); 706789Sahrens return (error); 707789Sahrens } 708789Sahrens 7095094Slling if ((error = nvlist_unpack(packed, size, &list, 0)) != 0) { 710789Sahrens kmem_free(packed, size); 711789Sahrens return (error); 712789Sahrens } 713789Sahrens 714789Sahrens kmem_free(packed, size); 715789Sahrens 7165094Slling *nvp = list; 717789Sahrens return (0); 718789Sahrens } 719789Sahrens 720789Sahrens static int 7212676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 7222676Seschrock { 7232676Seschrock char *packed = NULL; 7242676Seschrock size_t size; 7252676Seschrock int error; 7262676Seschrock 7272676Seschrock VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 7282676Seschrock 7292676Seschrock if (size > zc->zc_nvlist_dst_size) { 7302676Seschrock error = ENOMEM; 7312676Seschrock } else { 7324611Smarks packed = kmem_alloc(size, KM_SLEEP); 7332676Seschrock VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 7342676Seschrock KM_SLEEP) == 0); 7352676Seschrock error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 7362676Seschrock size); 7372676Seschrock kmem_free(packed, size); 7382676Seschrock } 7392676Seschrock 7402676Seschrock zc->zc_nvlist_dst_size = size; 7412676Seschrock return (error); 7422676Seschrock } 7432676Seschrock 7442676Seschrock static int 745789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc) 746789Sahrens { 747789Sahrens int error; 7485094Slling nvlist_t *config, *props = NULL; 7497184Stimh nvlist_t *rootprops = NULL; 7507184Stimh nvlist_t *zplprops = NULL; 7514715Sek110237 char *buf; 752789Sahrens 7535094Slling if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7545094Slling &config)) 7554988Sek110237 return (error); 7564715Sek110237 7575094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7585094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7595094Slling nvlist_free(config); 7605094Slling return (error); 7615094Slling } 7625094Slling 7637184Stimh if (props) { 7647184Stimh nvlist_t *nvl = NULL; 7657184Stimh uint64_t version = SPA_VERSION; 7667184Stimh 7677184Stimh (void) nvlist_lookup_uint64(props, 7687184Stimh zpool_prop_to_name(ZPOOL_PROP_VERSION), &version); 7697184Stimh if (version < SPA_VERSION_INITIAL || version > SPA_VERSION) { 7707184Stimh error = EINVAL; 7717184Stimh goto pool_props_bad; 7727184Stimh } 7737184Stimh (void) nvlist_lookup_nvlist(props, ZPOOL_ROOTFS_PROPS, &nvl); 7747184Stimh if (nvl) { 7757184Stimh error = nvlist_dup(nvl, &rootprops, KM_SLEEP); 7767184Stimh if (error != 0) { 7777184Stimh nvlist_free(config); 7787184Stimh nvlist_free(props); 7797184Stimh return (error); 7807184Stimh } 7817184Stimh (void) nvlist_remove_all(props, ZPOOL_ROOTFS_PROPS); 7827184Stimh } 7837184Stimh VERIFY(nvlist_alloc(&zplprops, NV_UNIQUE_NAME, KM_SLEEP) == 0); 7847184Stimh error = zfs_fill_zplprops_root(version, rootprops, 7857184Stimh zplprops, NULL); 7867184Stimh if (error) 7877184Stimh goto pool_props_bad; 7887184Stimh } 7897184Stimh 7904988Sek110237 buf = history_str_get(zc); 791789Sahrens 7927184Stimh error = spa_create(zc->zc_name, config, props, buf, zplprops); 7937184Stimh 7947184Stimh /* 7957184Stimh * Set the remaining root properties 7967184Stimh */ 7977184Stimh if (!error && 7987184Stimh (error = zfs_set_prop_nvlist(zc->zc_name, rootprops)) != 0) 7997184Stimh (void) spa_destroy(zc->zc_name); 800789Sahrens 8014988Sek110237 if (buf != NULL) 8024988Sek110237 history_str_free(buf); 8035094Slling 8047184Stimh pool_props_bad: 8057184Stimh nvlist_free(rootprops); 8067184Stimh nvlist_free(zplprops); 807789Sahrens nvlist_free(config); 8087184Stimh nvlist_free(props); 8095094Slling 810789Sahrens return (error); 811789Sahrens } 812789Sahrens 813789Sahrens static int 814789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc) 815789Sahrens { 8164543Smarks int error; 8174543Smarks zfs_log_history(zc); 8184543Smarks error = spa_destroy(zc->zc_name); 8194543Smarks return (error); 820789Sahrens } 821789Sahrens 822789Sahrens static int 823789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc) 824789Sahrens { 825789Sahrens int error; 8265094Slling nvlist_t *config, *props = NULL; 827789Sahrens uint64_t guid; 828789Sahrens 8295094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 8305094Slling &config)) != 0) 831789Sahrens return (error); 832789Sahrens 8335094Slling if (zc->zc_nvlist_src_size != 0 && (error = 8345094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 8355094Slling nvlist_free(config); 8365094Slling return (error); 8375094Slling } 8385094Slling 839789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 8401544Seschrock guid != zc->zc_guid) 841789Sahrens error = EINVAL; 8426643Seschrock else if (zc->zc_cookie) 8436643Seschrock error = spa_import_faulted(zc->zc_name, config, 8446643Seschrock props); 845789Sahrens else 8465094Slling error = spa_import(zc->zc_name, config, props); 847789Sahrens 848789Sahrens nvlist_free(config); 849789Sahrens 8505094Slling if (props) 8515094Slling nvlist_free(props); 8525094Slling 853789Sahrens return (error); 854789Sahrens } 855789Sahrens 856789Sahrens static int 857789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc) 858789Sahrens { 8594543Smarks int error; 8607214Slling boolean_t force = (boolean_t)zc->zc_cookie; 8617214Slling 8624543Smarks zfs_log_history(zc); 8637214Slling error = spa_export(zc->zc_name, NULL, force); 8644543Smarks return (error); 865789Sahrens } 866789Sahrens 867789Sahrens static int 868789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc) 869789Sahrens { 870789Sahrens nvlist_t *configs; 871789Sahrens int error; 872789Sahrens 873789Sahrens if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 874789Sahrens return (EEXIST); 875789Sahrens 8762676Seschrock error = put_nvlist(zc, configs); 877789Sahrens 878789Sahrens nvlist_free(configs); 879789Sahrens 880789Sahrens return (error); 881789Sahrens } 882789Sahrens 883789Sahrens static int 884789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc) 885789Sahrens { 886789Sahrens nvlist_t *config; 887789Sahrens int error; 8881544Seschrock int ret = 0; 889789Sahrens 8902676Seschrock error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 8912676Seschrock sizeof (zc->zc_value)); 892789Sahrens 893789Sahrens if (config != NULL) { 8942676Seschrock ret = put_nvlist(zc, config); 895789Sahrens nvlist_free(config); 8961544Seschrock 8971544Seschrock /* 8981544Seschrock * The config may be present even if 'error' is non-zero. 8991544Seschrock * In this case we return success, and preserve the real errno 9001544Seschrock * in 'zc_cookie'. 9011544Seschrock */ 9021544Seschrock zc->zc_cookie = error; 903789Sahrens } else { 9041544Seschrock ret = error; 905789Sahrens } 906789Sahrens 9071544Seschrock return (ret); 908789Sahrens } 909789Sahrens 910789Sahrens /* 911789Sahrens * Try to import the given pool, returning pool stats as appropriate so that 912789Sahrens * user land knows which devices are available and overall pool health. 913789Sahrens */ 914789Sahrens static int 915789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 916789Sahrens { 917789Sahrens nvlist_t *tryconfig, *config; 918789Sahrens int error; 919789Sahrens 9205094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 9215094Slling &tryconfig)) != 0) 922789Sahrens return (error); 923789Sahrens 924789Sahrens config = spa_tryimport(tryconfig); 925789Sahrens 926789Sahrens nvlist_free(tryconfig); 927789Sahrens 928789Sahrens if (config == NULL) 929789Sahrens return (EINVAL); 930789Sahrens 9312676Seschrock error = put_nvlist(zc, config); 932789Sahrens nvlist_free(config); 933789Sahrens 934789Sahrens return (error); 935789Sahrens } 936789Sahrens 937789Sahrens static int 938789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc) 939789Sahrens { 940789Sahrens spa_t *spa; 941789Sahrens int error; 942789Sahrens 9432926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9442926Sek110237 return (error); 9452926Sek110237 9467046Sahrens error = spa_scrub(spa, zc->zc_cookie); 9472926Sek110237 9482926Sek110237 spa_close(spa, FTAG); 9492926Sek110237 950789Sahrens return (error); 951789Sahrens } 952789Sahrens 953789Sahrens static int 954789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 955789Sahrens { 956789Sahrens spa_t *spa; 957789Sahrens int error; 958789Sahrens 959789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 960789Sahrens if (error == 0) { 961789Sahrens spa_freeze(spa); 962789Sahrens spa_close(spa, FTAG); 963789Sahrens } 964789Sahrens return (error); 965789Sahrens } 966789Sahrens 967789Sahrens static int 9681760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 9691760Seschrock { 9701760Seschrock spa_t *spa; 9711760Seschrock int error; 9721760Seschrock 9732926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9742926Sek110237 return (error); 9752926Sek110237 9765118Slling if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) { 9775118Slling spa_close(spa, FTAG); 9785118Slling return (EINVAL); 9795118Slling } 9805118Slling 9815094Slling spa_upgrade(spa, zc->zc_cookie); 9822926Sek110237 spa_close(spa, FTAG); 9832926Sek110237 9842926Sek110237 return (error); 9852926Sek110237 } 9862926Sek110237 9872926Sek110237 static int 9882926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 9892926Sek110237 { 9902926Sek110237 spa_t *spa; 9912926Sek110237 char *hist_buf; 9922926Sek110237 uint64_t size; 9932926Sek110237 int error; 9942926Sek110237 9952926Sek110237 if ((size = zc->zc_history_len) == 0) 9962926Sek110237 return (EINVAL); 9972926Sek110237 9982926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9992926Sek110237 return (error); 10002926Sek110237 10014577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 10023863Sek110237 spa_close(spa, FTAG); 10033863Sek110237 return (ENOTSUP); 10043863Sek110237 } 10053863Sek110237 10062926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 10072926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 10082926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 10094543Smarks error = xcopyout(hist_buf, 10104543Smarks (char *)(uintptr_t)zc->zc_history, 10112926Sek110237 zc->zc_history_len); 10122926Sek110237 } 10132926Sek110237 10142926Sek110237 spa_close(spa, FTAG); 10152926Sek110237 kmem_free(hist_buf, size); 10162926Sek110237 return (error); 10172926Sek110237 } 10182926Sek110237 10192926Sek110237 static int 10203444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 10213444Sek110237 { 10223444Sek110237 int error; 10233444Sek110237 10243912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 10253444Sek110237 return (error); 10263444Sek110237 10273444Sek110237 return (0); 10283444Sek110237 } 10293444Sek110237 10303444Sek110237 static int 10313444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 10323444Sek110237 { 10333444Sek110237 objset_t *osp; 10343444Sek110237 int error; 10353444Sek110237 10363444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 10376689Smaybee DS_MODE_USER | DS_MODE_READONLY, &osp)) != 0) 10383444Sek110237 return (error); 10393444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 10403444Sek110237 sizeof (zc->zc_value)); 10413444Sek110237 dmu_objset_close(osp); 10423444Sek110237 10433444Sek110237 return (error); 10443444Sek110237 } 10453444Sek110237 10463444Sek110237 static int 1047789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 1048789Sahrens { 1049789Sahrens spa_t *spa; 1050789Sahrens int error; 10516423Sgw25295 nvlist_t *config, **l2cache, **spares; 10526423Sgw25295 uint_t nl2cache = 0, nspares = 0; 1053789Sahrens 1054789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 1055789Sahrens if (error != 0) 1056789Sahrens return (error); 1057789Sahrens 10585450Sbrendan error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 10595450Sbrendan &config); 10605450Sbrendan (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_L2CACHE, 10615450Sbrendan &l2cache, &nl2cache); 10625450Sbrendan 10636423Sgw25295 (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_SPARES, 10646423Sgw25295 &spares, &nspares); 10656423Sgw25295 10663912Slling /* 10673912Slling * A root pool with concatenated devices is not supported. 10686423Sgw25295 * Thus, can not add a device to a root pool. 10696423Sgw25295 * 10706423Sgw25295 * Intent log device can not be added to a rootpool because 10716423Sgw25295 * during mountroot, zil is replayed, a seperated log device 10726423Sgw25295 * can not be accessed during the mountroot time. 10736423Sgw25295 * 10746423Sgw25295 * l2cache and spare devices are ok to be added to a rootpool. 10753912Slling */ 10766423Sgw25295 if (spa->spa_bootfs != 0 && nl2cache == 0 && nspares == 0) { 10773912Slling spa_close(spa, FTAG); 10783912Slling return (EDOM); 10793912Slling } 10803912Slling 10815450Sbrendan if (error == 0) { 1082789Sahrens error = spa_vdev_add(spa, config); 1083789Sahrens nvlist_free(config); 1084789Sahrens } 1085789Sahrens spa_close(spa, FTAG); 1086789Sahrens return (error); 1087789Sahrens } 1088789Sahrens 1089789Sahrens static int 1090789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 1091789Sahrens { 10922082Seschrock spa_t *spa; 10932082Seschrock int error; 10942082Seschrock 10952082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10962082Seschrock if (error != 0) 10972082Seschrock return (error); 10982082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 10992082Seschrock spa_close(spa, FTAG); 11002082Seschrock return (error); 1101789Sahrens } 1102789Sahrens 1103789Sahrens static int 11044451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 1105789Sahrens { 1106789Sahrens spa_t *spa; 1107789Sahrens int error; 11084451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 1109789Sahrens 11102926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1111789Sahrens return (error); 11124451Seschrock switch (zc->zc_cookie) { 11134451Seschrock case VDEV_STATE_ONLINE: 11144451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 11154451Seschrock break; 11164451Seschrock 11174451Seschrock case VDEV_STATE_OFFLINE: 11184451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 11194451Seschrock break; 1120789Sahrens 11214451Seschrock case VDEV_STATE_FAULTED: 11224451Seschrock error = vdev_fault(spa, zc->zc_guid); 11234451Seschrock break; 1124789Sahrens 11254451Seschrock case VDEV_STATE_DEGRADED: 11264451Seschrock error = vdev_degrade(spa, zc->zc_guid); 11274451Seschrock break; 11284451Seschrock 11294451Seschrock default: 11304451Seschrock error = EINVAL; 11314451Seschrock } 11324451Seschrock zc->zc_cookie = newstate; 1133789Sahrens spa_close(spa, FTAG); 1134789Sahrens return (error); 1135789Sahrens } 1136789Sahrens 1137789Sahrens static int 1138789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 1139789Sahrens { 1140789Sahrens spa_t *spa; 1141789Sahrens int replacing = zc->zc_cookie; 1142789Sahrens nvlist_t *config; 1143789Sahrens int error; 1144789Sahrens 11452926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1146789Sahrens return (error); 1147789Sahrens 11485094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 11495094Slling &config)) == 0) { 11501544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 1151789Sahrens nvlist_free(config); 1152789Sahrens } 1153789Sahrens 1154789Sahrens spa_close(spa, FTAG); 1155789Sahrens return (error); 1156789Sahrens } 1157789Sahrens 1158789Sahrens static int 1159789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 1160789Sahrens { 1161789Sahrens spa_t *spa; 1162789Sahrens int error; 1163789Sahrens 11642926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1165789Sahrens return (error); 1166789Sahrens 11671544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1168789Sahrens 1169789Sahrens spa_close(spa, FTAG); 1170789Sahrens return (error); 1171789Sahrens } 1172789Sahrens 1173789Sahrens static int 11741354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 11751354Seschrock { 11761354Seschrock spa_t *spa; 11772676Seschrock char *path = zc->zc_value; 11781544Seschrock uint64_t guid = zc->zc_guid; 11791354Seschrock int error; 11801354Seschrock 11811354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 11821354Seschrock if (error != 0) 11831354Seschrock return (error); 11841354Seschrock 11851354Seschrock error = spa_vdev_setpath(spa, guid, path); 11861354Seschrock spa_close(spa, FTAG); 11871354Seschrock return (error); 11881354Seschrock } 11891354Seschrock 11905367Sahrens /* 11915367Sahrens * inputs: 11925367Sahrens * zc_name name of filesystem 11935367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 11945367Sahrens * 11955367Sahrens * outputs: 11965367Sahrens * zc_objset_stats stats 11975367Sahrens * zc_nvlist_dst property nvlist 11985367Sahrens * zc_nvlist_dst_size size of property nvlist 11995367Sahrens */ 12001354Seschrock static int 1201789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1202789Sahrens { 1203789Sahrens objset_t *os = NULL; 1204789Sahrens int error; 12051356Seschrock nvlist_t *nv; 1206789Sahrens 12076689Smaybee if (error = dmu_objset_open(zc->zc_name, 12086689Smaybee DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os)) 1209789Sahrens return (error); 1210789Sahrens 12112885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1212789Sahrens 12132856Snd150628 if (zc->zc_nvlist_dst != 0 && 12146689Smaybee (error = dsl_prop_get_all(os, &nv, FALSE)) == 0) { 12152885Sahrens dmu_objset_stats(os, nv); 12163087Sahrens /* 12175147Srm160521 * NB: zvol_get_stats() will read the objset contents, 12183087Sahrens * which we aren't supposed to do with a 12196689Smaybee * DS_MODE_USER hold, because it could be 12203087Sahrens * inconsistent. So this is a bit of a workaround... 12213087Sahrens */ 12224577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 12234577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 12244577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 12254577Sahrens } 12262676Seschrock error = put_nvlist(zc, nv); 12271356Seschrock nvlist_free(nv); 12281356Seschrock } 1229789Sahrens 1230789Sahrens dmu_objset_close(os); 1231789Sahrens return (error); 1232789Sahrens } 1233789Sahrens 12345498Stimh static int 12355498Stimh nvl_add_zplprop(objset_t *os, nvlist_t *props, zfs_prop_t prop) 12365498Stimh { 12375498Stimh uint64_t value; 12385498Stimh int error; 12395498Stimh 12405498Stimh /* 12415498Stimh * zfs_get_zplprop() will either find a value or give us 12425498Stimh * the default value (if there is one). 12435498Stimh */ 12445498Stimh if ((error = zfs_get_zplprop(os, prop, &value)) != 0) 12455498Stimh return (error); 12465498Stimh VERIFY(nvlist_add_uint64(props, zfs_prop_to_name(prop), value) == 0); 12475498Stimh return (0); 12485498Stimh } 12495498Stimh 12505498Stimh /* 12515498Stimh * inputs: 12525498Stimh * zc_name name of filesystem 12535498Stimh * zc_nvlist_dst_size size of buffer for zpl property nvlist 12545498Stimh * 12555498Stimh * outputs: 12565498Stimh * zc_nvlist_dst zpl property nvlist 12575498Stimh * zc_nvlist_dst_size size of zpl property nvlist 12585498Stimh */ 12595498Stimh static int 12605498Stimh zfs_ioc_objset_zplprops(zfs_cmd_t *zc) 12615498Stimh { 12625498Stimh objset_t *os; 12635498Stimh int err; 12645498Stimh 12656689Smaybee if (err = dmu_objset_open(zc->zc_name, 12666689Smaybee DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os)) 12675498Stimh return (err); 12685498Stimh 12695498Stimh dmu_objset_fast_stat(os, &zc->zc_objset_stats); 12705498Stimh 12715498Stimh /* 12725498Stimh * NB: nvl_add_zplprop() will read the objset contents, 12736689Smaybee * which we aren't supposed to do with a DS_MODE_USER 12746689Smaybee * hold, because it could be inconsistent. 12755498Stimh */ 12765498Stimh if (zc->zc_nvlist_dst != NULL && 12775498Stimh !zc->zc_objset_stats.dds_inconsistent && 12785498Stimh dmu_objset_type(os) == DMU_OST_ZFS) { 12795498Stimh nvlist_t *nv; 12805498Stimh 12815498Stimh VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) == 0); 12825498Stimh if ((err = nvl_add_zplprop(os, nv, ZFS_PROP_VERSION)) == 0 && 12835498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_NORMALIZE)) == 0 && 12845498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_UTF8ONLY)) == 0 && 12855498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_CASE)) == 0) 12865498Stimh err = put_nvlist(zc, nv); 12875498Stimh nvlist_free(nv); 12885498Stimh } else { 12895498Stimh err = ENOENT; 12905498Stimh } 12915498Stimh dmu_objset_close(os); 12925498Stimh return (err); 12935498Stimh } 12945498Stimh 12955367Sahrens /* 12965367Sahrens * inputs: 12975367Sahrens * zc_name name of filesystem 12985367Sahrens * zc_cookie zap cursor 12995367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 13005367Sahrens * 13015367Sahrens * outputs: 13025367Sahrens * zc_name name of next filesystem 13035367Sahrens * zc_objset_stats stats 13045367Sahrens * zc_nvlist_dst property nvlist 13055367Sahrens * zc_nvlist_dst_size size of property nvlist 13065367Sahrens */ 1307789Sahrens static int 1308789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1309789Sahrens { 1310885Sahrens objset_t *os; 1311789Sahrens int error; 1312789Sahrens char *p; 1313789Sahrens 13146689Smaybee if (error = dmu_objset_open(zc->zc_name, 13156689Smaybee DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os)) { 1316885Sahrens if (error == ENOENT) 1317885Sahrens error = ESRCH; 1318885Sahrens return (error); 1319789Sahrens } 1320789Sahrens 1321789Sahrens p = strrchr(zc->zc_name, '/'); 1322789Sahrens if (p == NULL || p[1] != '\0') 1323789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1324789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1325789Sahrens 1326789Sahrens do { 1327885Sahrens error = dmu_dir_list_next(os, 1328885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1329885Sahrens NULL, &zc->zc_cookie); 1330789Sahrens if (error == ENOENT) 1331789Sahrens error = ESRCH; 1332885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1333789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 13346689Smaybee dmu_objset_close(os); 1335789Sahrens 1336885Sahrens /* 1337885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1338885Sahrens * try to get stats for it. Userland will skip over it. 1339885Sahrens */ 1340885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1341885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1342789Sahrens 1343789Sahrens return (error); 1344789Sahrens } 1345789Sahrens 13465367Sahrens /* 13475367Sahrens * inputs: 13485367Sahrens * zc_name name of filesystem 13495367Sahrens * zc_cookie zap cursor 13505367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 13515367Sahrens * 13525367Sahrens * outputs: 13535367Sahrens * zc_name name of next snapshot 13545367Sahrens * zc_objset_stats stats 13555367Sahrens * zc_nvlist_dst property nvlist 13565367Sahrens * zc_nvlist_dst_size size of property nvlist 13575367Sahrens */ 1358789Sahrens static int 1359789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1360789Sahrens { 1361885Sahrens objset_t *os; 1362789Sahrens int error; 1363789Sahrens 13646689Smaybee error = dmu_objset_open(zc->zc_name, 13656689Smaybee DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os); 13666689Smaybee if (error) 13676689Smaybee return (error == ENOENT ? ESRCH : error); 1368789Sahrens 13691003Slling /* 13701003Slling * A dataset name of maximum length cannot have any snapshots, 13711003Slling * so exit immediately. 13721003Slling */ 13731003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1374885Sahrens dmu_objset_close(os); 13751003Slling return (ESRCH); 1376789Sahrens } 1377789Sahrens 1378885Sahrens error = dmu_snapshot_list_next(os, 1379885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 13805663Sck153898 zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie, NULL); 13816689Smaybee dmu_objset_close(os); 1382885Sahrens if (error == 0) 1383885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 13846689Smaybee else if (error == ENOENT) 13856689Smaybee error = ESRCH; 1386789Sahrens 13875367Sahrens /* if we failed, undo the @ that we tacked on to zc_name */ 13886689Smaybee if (error) 13895367Sahrens *strchr(zc->zc_name, '@') = '\0'; 1390789Sahrens return (error); 1391789Sahrens } 1392789Sahrens 13936423Sgw25295 int 13944787Sahrens zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) 1395789Sahrens { 13962676Seschrock nvpair_t *elem; 13972676Seschrock int error; 13982676Seschrock uint64_t intval; 13992676Seschrock char *strval; 14002676Seschrock 14014543Smarks /* 14024543Smarks * First validate permission to set all of the properties 14034543Smarks */ 14042676Seschrock elem = NULL; 14052676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 14064670Sahrens const char *propname = nvpair_name(elem); 14074670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 14082676Seschrock 14095094Slling if (prop == ZPROP_INVAL) { 14102676Seschrock /* 14112676Seschrock * If this is a user-defined property, it must be a 14122676Seschrock * string, and there is no further validation to do. 14132676Seschrock */ 14142676Seschrock if (!zfs_prop_user(propname) || 14152676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 14162676Seschrock return (EINVAL); 14172676Seschrock 14185331Samw if (error = zfs_secpolicy_write_perms(name, 14195331Samw ZFS_DELEG_PERM_USERPROP, CRED())) 14204670Sahrens return (error); 14214543Smarks continue; 14222676Seschrock } 14232676Seschrock 14244787Sahrens if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 14254670Sahrens return (error); 14262676Seschrock 14274670Sahrens /* 14284670Sahrens * Check that this value is valid for this pool version 14294670Sahrens */ 14304670Sahrens switch (prop) { 14313886Sahl case ZFS_PROP_COMPRESSION: 14323886Sahl /* 14333886Sahl * If the user specified gzip compression, make sure 14343886Sahl * the SPA supports it. We ignore any errors here since 14353886Sahl * we'll catch them later. 14363886Sahl */ 14373886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 14387042Sgw25295 nvpair_value_uint64(elem, &intval) == 0) { 14397042Sgw25295 if (intval >= ZIO_COMPRESS_GZIP_1 && 14407042Sgw25295 intval <= ZIO_COMPRESS_GZIP_9 && 14417184Stimh zfs_earlier_version(name, 14425331Samw SPA_VERSION_GZIP_COMPRESSION)) 14435331Samw return (ENOTSUP); 14447042Sgw25295 14457042Sgw25295 /* 14467042Sgw25295 * If this is a bootable dataset then 14477042Sgw25295 * verify that the compression algorithm 14487042Sgw25295 * is supported for booting. We must return 14497042Sgw25295 * something other than ENOTSUP since it 14507042Sgw25295 * implies a downrev pool version. 14517042Sgw25295 */ 14527042Sgw25295 if (zfs_is_bootfs(name) && 14537042Sgw25295 !BOOTFS_COMPRESS_VALID(intval)) 14547042Sgw25295 return (ERANGE); 14553886Sahl } 14563886Sahl break; 14574603Sahrens 14584603Sahrens case ZFS_PROP_COPIES: 14597184Stimh if (zfs_earlier_version(name, 14607184Stimh SPA_VERSION_DITTO_BLOCKS)) 14615331Samw return (ENOTSUP); 14624603Sahrens break; 14635977Smarks 14645977Smarks case ZFS_PROP_SHARESMB: 14656689Smaybee if (zpl_earlier_version(name, ZPL_VERSION_FUID)) 14665977Smarks return (ENOTSUP); 14675977Smarks break; 14684603Sahrens } 14694543Smarks } 14704543Smarks 14714543Smarks elem = NULL; 14724543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 14734670Sahrens const char *propname = nvpair_name(elem); 14744670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 14754543Smarks 14765094Slling if (prop == ZPROP_INVAL) { 14774543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 14784543Smarks error = dsl_prop_set(name, propname, 1, 14794543Smarks strlen(strval) + 1, strval); 14804543Smarks if (error == 0) 14814543Smarks continue; 14824543Smarks else 14834543Smarks return (error); 14844543Smarks } 14852676Seschrock 14862676Seschrock switch (prop) { 14872676Seschrock case ZFS_PROP_QUOTA: 14882676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14894577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 14902676Seschrock return (error); 14912676Seschrock break; 14922676Seschrock 14935378Sck153898 case ZFS_PROP_REFQUOTA: 14945378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14955378Sck153898 (error = dsl_dataset_set_quota(name, intval)) != 0) 14965378Sck153898 return (error); 14975378Sck153898 break; 14985378Sck153898 14992676Seschrock case ZFS_PROP_RESERVATION: 15002676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 15012676Seschrock (error = dsl_dir_set_reservation(name, 15022676Seschrock intval)) != 0) 15032676Seschrock return (error); 15042676Seschrock break; 1505789Sahrens 15065378Sck153898 case ZFS_PROP_REFRESERVATION: 15075378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 15085378Sck153898 (error = dsl_dataset_set_reservation(name, 15095378Sck153898 intval)) != 0) 15105378Sck153898 return (error); 15115378Sck153898 break; 15125378Sck153898 15132676Seschrock case ZFS_PROP_VOLSIZE: 15142676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 15154787Sahrens (error = zvol_set_volsize(name, 15164787Sahrens ddi_driver_major(zfs_dip), intval)) != 0) 15172676Seschrock return (error); 15182676Seschrock break; 15192676Seschrock 15202676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 15212676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 15224577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 15234577Sahrens return (error); 15244577Sahrens break; 15254577Sahrens 15264577Sahrens case ZFS_PROP_VERSION: 15274577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 15284577Sahrens (error = zfs_set_version(name, intval)) != 0) 15292676Seschrock return (error); 15302676Seschrock break; 15312676Seschrock 15322676Seschrock default: 15332676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 15342676Seschrock if (zfs_prop_get_type(prop) != 15354787Sahrens PROP_TYPE_STRING) 15362676Seschrock return (EINVAL); 15372717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 15382717Seschrock if ((error = dsl_prop_set(name, 15392676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 15402717Seschrock strval)) != 0) 15412717Seschrock return (error); 15422676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 15432885Sahrens const char *unused; 15442885Sahrens 15452717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 15462676Seschrock 15472676Seschrock switch (zfs_prop_get_type(prop)) { 15484787Sahrens case PROP_TYPE_NUMBER: 15492676Seschrock break; 15504787Sahrens case PROP_TYPE_STRING: 15512717Seschrock return (EINVAL); 15524787Sahrens case PROP_TYPE_INDEX: 15532717Seschrock if (zfs_prop_index_to_string(prop, 15542717Seschrock intval, &unused) != 0) 15552717Seschrock return (EINVAL); 15562676Seschrock break; 15572676Seschrock default: 15584577Sahrens cmn_err(CE_PANIC, 15594577Sahrens "unknown property type"); 15602676Seschrock break; 15612676Seschrock } 15622676Seschrock 15632717Seschrock if ((error = dsl_prop_set(name, propname, 15642717Seschrock 8, 1, &intval)) != 0) 15652717Seschrock return (error); 15662676Seschrock } else { 15672676Seschrock return (EINVAL); 15682676Seschrock } 15692676Seschrock break; 15702676Seschrock } 15712676Seschrock } 15722676Seschrock 15732676Seschrock return (0); 1574789Sahrens } 1575789Sahrens 15765367Sahrens /* 15775367Sahrens * inputs: 15785367Sahrens * zc_name name of filesystem 15795367Sahrens * zc_value name of property to inherit 15805367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 1581*7265Sahrens * zc_cookie clear existing local props? 15825367Sahrens * 15835367Sahrens * outputs: none 15845367Sahrens */ 1585789Sahrens static int 15862676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1587789Sahrens { 15882676Seschrock nvlist_t *nvl; 15892676Seschrock int error; 1590789Sahrens 15915094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15925094Slling &nvl)) != 0) 15932676Seschrock return (error); 15942676Seschrock 1595*7265Sahrens if (zc->zc_cookie) { 1596*7265Sahrens nvlist_t *origprops; 1597*7265Sahrens objset_t *os; 1598*7265Sahrens 1599*7265Sahrens if (dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1600*7265Sahrens DS_MODE_USER | DS_MODE_READONLY, &os) == 0) { 1601*7265Sahrens if (dsl_prop_get_all(os, &origprops, TRUE) == 0) { 1602*7265Sahrens clear_props(zc->zc_name, origprops); 1603*7265Sahrens nvlist_free(origprops); 1604*7265Sahrens } 1605*7265Sahrens dmu_objset_close(os); 1606*7265Sahrens } 1607*7265Sahrens 1608*7265Sahrens } 1609*7265Sahrens 16104787Sahrens error = zfs_set_prop_nvlist(zc->zc_name, nvl); 16114543Smarks 16122676Seschrock nvlist_free(nvl); 16132676Seschrock return (error); 1614789Sahrens } 1615789Sahrens 16165367Sahrens /* 16175367Sahrens * inputs: 16185367Sahrens * zc_name name of filesystem 16195367Sahrens * zc_value name of property to inherit 16205367Sahrens * 16215367Sahrens * outputs: none 16225367Sahrens */ 1623789Sahrens static int 16244849Sahrens zfs_ioc_inherit_prop(zfs_cmd_t *zc) 16254849Sahrens { 16264849Sahrens /* the property name has been validated by zfs_secpolicy_inherit() */ 16274849Sahrens return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 16284849Sahrens } 16294849Sahrens 16304849Sahrens static int 16314098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 16323912Slling { 16335094Slling nvlist_t *props; 16343912Slling spa_t *spa; 16355094Slling int error; 16363912Slling 16375094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16385094Slling &props))) 16393912Slling return (error); 16403912Slling 16413912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 16425094Slling nvlist_free(props); 16433912Slling return (error); 16443912Slling } 16453912Slling 16465094Slling error = spa_prop_set(spa, props); 16473912Slling 16485094Slling nvlist_free(props); 16493912Slling spa_close(spa, FTAG); 16503912Slling 16513912Slling return (error); 16523912Slling } 16533912Slling 16543912Slling static int 16554098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 16563912Slling { 16573912Slling spa_t *spa; 16583912Slling int error; 16593912Slling nvlist_t *nvp = NULL; 16603912Slling 16613912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 16623912Slling return (error); 16633912Slling 16645094Slling error = spa_prop_get(spa, &nvp); 16653912Slling 16663912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 16673912Slling error = put_nvlist(zc, nvp); 16683912Slling else 16693912Slling error = EFAULT; 16703912Slling 16713912Slling spa_close(spa, FTAG); 16723912Slling 16733912Slling if (nvp) 16743912Slling nvlist_free(nvp); 16753912Slling return (error); 16763912Slling } 16773912Slling 16783912Slling static int 16794543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 16804543Smarks { 16814543Smarks nvlist_t *nvp; 16824543Smarks int error; 16834543Smarks uint32_t uid; 16844543Smarks uint32_t gid; 16854543Smarks uint32_t *groups; 16864543Smarks uint_t group_cnt; 16874543Smarks cred_t *usercred; 16884543Smarks 16895094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16905094Slling &nvp)) != 0) { 16914543Smarks return (error); 16924543Smarks } 16934543Smarks 16944543Smarks if ((error = nvlist_lookup_uint32(nvp, 16954543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 16964543Smarks nvlist_free(nvp); 16974543Smarks return (EPERM); 16984543Smarks } 16994543Smarks 17004543Smarks if ((error = nvlist_lookup_uint32(nvp, 17014543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 17024543Smarks nvlist_free(nvp); 17034543Smarks return (EPERM); 17044543Smarks } 17054543Smarks 17064543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 17074543Smarks &groups, &group_cnt)) != 0) { 17084543Smarks nvlist_free(nvp); 17094543Smarks return (EPERM); 17104543Smarks } 17114543Smarks usercred = cralloc(); 17124543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 17134543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 17144543Smarks nvlist_free(nvp); 17154543Smarks crfree(usercred); 17164543Smarks return (EPERM); 17174543Smarks } 17184543Smarks nvlist_free(nvp); 17194543Smarks error = dsl_deleg_access(zc->zc_name, 17204787Sahrens zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); 17214543Smarks crfree(usercred); 17224543Smarks return (error); 17234543Smarks } 17244543Smarks 17255367Sahrens /* 17265367Sahrens * inputs: 17275367Sahrens * zc_name name of filesystem 17285367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 17295367Sahrens * zc_perm_action allow/unallow flag 17305367Sahrens * 17315367Sahrens * outputs: none 17325367Sahrens */ 17334543Smarks static int 17344543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 17354543Smarks { 17364543Smarks int error; 17374543Smarks nvlist_t *fsaclnv = NULL; 17384543Smarks 17395094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 17405094Slling &fsaclnv)) != 0) 17414543Smarks return (error); 17424543Smarks 17434543Smarks /* 17444543Smarks * Verify nvlist is constructed correctly 17454543Smarks */ 17464543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 17474543Smarks nvlist_free(fsaclnv); 17484543Smarks return (EINVAL); 17494543Smarks } 17504543Smarks 17514543Smarks /* 17524543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 17534543Smarks * that user is allowed to hand out each permission in 17544543Smarks * the nvlist(s) 17554543Smarks */ 17564543Smarks 17574787Sahrens error = secpolicy_zfs(CRED()); 17584543Smarks if (error) { 17594787Sahrens if (zc->zc_perm_action == B_FALSE) { 17604787Sahrens error = dsl_deleg_can_allow(zc->zc_name, 17614787Sahrens fsaclnv, CRED()); 17624787Sahrens } else { 17634787Sahrens error = dsl_deleg_can_unallow(zc->zc_name, 17644787Sahrens fsaclnv, CRED()); 17654787Sahrens } 17664543Smarks } 17674543Smarks 17684543Smarks if (error == 0) 17694543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 17704543Smarks 17714543Smarks nvlist_free(fsaclnv); 17724543Smarks return (error); 17734543Smarks } 17744543Smarks 17755367Sahrens /* 17765367Sahrens * inputs: 17775367Sahrens * zc_name name of filesystem 17785367Sahrens * 17795367Sahrens * outputs: 17805367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 17815367Sahrens */ 17824543Smarks static int 17834543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 17844543Smarks { 17854543Smarks nvlist_t *nvp; 17864543Smarks int error; 17874543Smarks 17884543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 17894543Smarks error = put_nvlist(zc, nvp); 17904543Smarks nvlist_free(nvp); 17914543Smarks } 17924543Smarks 17934543Smarks return (error); 17944543Smarks } 17954543Smarks 17965367Sahrens /* 17975367Sahrens * inputs: 17985367Sahrens * zc_name name of volume 17995367Sahrens * 18005367Sahrens * outputs: none 18015367Sahrens */ 18024543Smarks static int 1803789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1804789Sahrens { 18054787Sahrens return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); 1806789Sahrens } 1807789Sahrens 18085367Sahrens /* 18095367Sahrens * inputs: 18105367Sahrens * zc_name name of volume 18115367Sahrens * 18125367Sahrens * outputs: none 18135367Sahrens */ 1814789Sahrens static int 1815789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1816789Sahrens { 18172676Seschrock return (zvol_remove_minor(zc->zc_name)); 1818789Sahrens } 1819789Sahrens 1820789Sahrens /* 1821789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1822789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1823789Sahrens * is responsible for releasing the returned vfs pointer. 1824789Sahrens */ 1825789Sahrens static vfs_t * 1826789Sahrens zfs_get_vfs(const char *resource) 1827789Sahrens { 1828789Sahrens struct vfs *vfsp; 1829789Sahrens struct vfs *vfs_found = NULL; 1830789Sahrens 1831789Sahrens vfs_list_read_lock(); 1832789Sahrens vfsp = rootvfs; 1833789Sahrens do { 1834789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1835789Sahrens VFS_HOLD(vfsp); 1836789Sahrens vfs_found = vfsp; 1837789Sahrens break; 1838789Sahrens } 1839789Sahrens vfsp = vfsp->vfs_next; 1840789Sahrens } while (vfsp != rootvfs); 1841789Sahrens vfs_list_unlock(); 1842789Sahrens return (vfs_found); 1843789Sahrens } 1844789Sahrens 18454543Smarks /* ARGSUSED */ 1846789Sahrens static void 18474543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1848789Sahrens { 18495331Samw zfs_creat_t *zct = arg; 18505498Stimh 18515498Stimh zfs_create_fs(os, cr, zct->zct_zplprops, tx); 18525331Samw } 18535331Samw 18545498Stimh #define ZFS_PROP_UNDEFINED ((uint64_t)-1) 18555498Stimh 18565331Samw /* 18575498Stimh * inputs: 18587184Stimh * createprops list of properties requested by creator 18597184Stimh * default_zplver zpl version to use if unspecified in createprops 18607184Stimh * fuids_ok fuids allowed in this version of the spa? 18617184Stimh * os parent objset pointer (NULL if root fs) 18625331Samw * 18635498Stimh * outputs: 18645498Stimh * zplprops values for the zplprops we attach to the master node object 18657184Stimh * is_ci true if requested file system will be purely case-insensitive 18665331Samw * 18675498Stimh * Determine the settings for utf8only, normalization and 18685498Stimh * casesensitivity. Specific values may have been requested by the 18695498Stimh * creator and/or we can inherit values from the parent dataset. If 18705498Stimh * the file system is of too early a vintage, a creator can not 18715498Stimh * request settings for these properties, even if the requested 18725498Stimh * setting is the default value. We don't actually want to create dsl 18735498Stimh * properties for these, so remove them from the source nvlist after 18745498Stimh * processing. 18755331Samw */ 18765331Samw static int 18777184Stimh zfs_fill_zplprops_impl(objset_t *os, uint64_t default_zplver, 18787184Stimh boolean_t fuids_ok, nvlist_t *createprops, nvlist_t *zplprops, 18797184Stimh boolean_t *is_ci) 18805331Samw { 18817184Stimh uint64_t zplver = default_zplver; 18825498Stimh uint64_t sense = ZFS_PROP_UNDEFINED; 18835498Stimh uint64_t norm = ZFS_PROP_UNDEFINED; 18845498Stimh uint64_t u8 = ZFS_PROP_UNDEFINED; 18855498Stimh 18865498Stimh ASSERT(zplprops != NULL); 18875498Stimh 18885375Stimh /* 18895498Stimh * Pull out creator prop choices, if any. 18905375Stimh */ 18915498Stimh if (createprops) { 18925498Stimh (void) nvlist_lookup_uint64(createprops, 18937184Stimh zfs_prop_to_name(ZFS_PROP_VERSION), &zplver); 18947184Stimh (void) nvlist_lookup_uint64(createprops, 18955498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE), &norm); 18965498Stimh (void) nvlist_remove_all(createprops, 18975498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE)); 18985498Stimh (void) nvlist_lookup_uint64(createprops, 18995498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY), &u8); 19005498Stimh (void) nvlist_remove_all(createprops, 19015498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY)); 19025498Stimh (void) nvlist_lookup_uint64(createprops, 19035498Stimh zfs_prop_to_name(ZFS_PROP_CASE), &sense); 19045498Stimh (void) nvlist_remove_all(createprops, 19055498Stimh zfs_prop_to_name(ZFS_PROP_CASE)); 19065331Samw } 19075331Samw 19085375Stimh /* 19097184Stimh * If the zpl version requested is whacky or the file system 19107184Stimh * or pool is version is too "young" to support normalization 19117184Stimh * and the creator tried to set a value for one of the props, 19127184Stimh * error out. 19135498Stimh */ 19147184Stimh if ((zplver < ZPL_VERSION_INITIAL || zplver > ZPL_VERSION) || 19157184Stimh (zplver >= ZPL_VERSION_FUID && !fuids_ok) || 19167184Stimh (zplver < ZPL_VERSION_NORMALIZATION && 19175498Stimh (norm != ZFS_PROP_UNDEFINED || u8 != ZFS_PROP_UNDEFINED || 19187184Stimh sense != ZFS_PROP_UNDEFINED))) 19195498Stimh return (ENOTSUP); 19205498Stimh 19215498Stimh /* 19225498Stimh * Put the version in the zplprops 19235498Stimh */ 19245498Stimh VERIFY(nvlist_add_uint64(zplprops, 19255498Stimh zfs_prop_to_name(ZFS_PROP_VERSION), zplver) == 0); 19265498Stimh 19275498Stimh if (norm == ZFS_PROP_UNDEFINED) 19285498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &norm) == 0); 19295498Stimh VERIFY(nvlist_add_uint64(zplprops, 19305498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE), norm) == 0); 19315498Stimh 19325498Stimh /* 19335498Stimh * If we're normalizing, names must always be valid UTF-8 strings. 19345498Stimh */ 19355498Stimh if (norm) 19365498Stimh u8 = 1; 19375498Stimh if (u8 == ZFS_PROP_UNDEFINED) 19385498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &u8) == 0); 19395498Stimh VERIFY(nvlist_add_uint64(zplprops, 19405498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY), u8) == 0); 19415498Stimh 19425498Stimh if (sense == ZFS_PROP_UNDEFINED) 19435498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_CASE, &sense) == 0); 19445498Stimh VERIFY(nvlist_add_uint64(zplprops, 19455498Stimh zfs_prop_to_name(ZFS_PROP_CASE), sense) == 0); 19465498Stimh 19476492Stimh if (is_ci) 19486492Stimh *is_ci = (sense == ZFS_CASE_INSENSITIVE); 19496492Stimh 19507184Stimh return (0); 19517184Stimh } 19527184Stimh 19537184Stimh static int 19547184Stimh zfs_fill_zplprops(const char *dataset, nvlist_t *createprops, 19557184Stimh nvlist_t *zplprops, boolean_t *is_ci) 19567184Stimh { 19577184Stimh boolean_t fuids_ok = B_TRUE; 19587184Stimh uint64_t zplver = ZPL_VERSION; 19597184Stimh objset_t *os = NULL; 19607184Stimh char parentname[MAXNAMELEN]; 19617184Stimh char *cp; 19627184Stimh int error; 19637184Stimh 19647184Stimh (void) strlcpy(parentname, dataset, sizeof (parentname)); 19657184Stimh cp = strrchr(parentname, '/'); 19667184Stimh ASSERT(cp != NULL); 19677184Stimh cp[0] = '\0'; 19687184Stimh 19697184Stimh if (zfs_earlier_version(dataset, SPA_VERSION_FUID)) { 19707184Stimh zplver = ZPL_VERSION_FUID - 1; 19717184Stimh fuids_ok = B_FALSE; 19727184Stimh } 19737184Stimh 19747184Stimh /* 19757184Stimh * Open parent object set so we can inherit zplprop values. 19767184Stimh */ 19777184Stimh if ((error = dmu_objset_open(parentname, DMU_OST_ANY, 19787184Stimh DS_MODE_USER | DS_MODE_READONLY, &os)) != 0) 19797184Stimh return (error); 19807184Stimh 19817184Stimh error = zfs_fill_zplprops_impl(os, zplver, fuids_ok, createprops, 19827184Stimh zplprops, is_ci); 19835498Stimh dmu_objset_close(os); 19847184Stimh return (error); 19857184Stimh } 19867184Stimh 19877184Stimh static int 19887184Stimh zfs_fill_zplprops_root(uint64_t spa_vers, nvlist_t *createprops, 19897184Stimh nvlist_t *zplprops, boolean_t *is_ci) 19907184Stimh { 19917184Stimh boolean_t fuids_ok = B_TRUE; 19927184Stimh uint64_t zplver = ZPL_VERSION; 19937184Stimh int error; 19947184Stimh 19957184Stimh if (spa_vers < SPA_VERSION_FUID) { 19967184Stimh zplver = ZPL_VERSION_FUID - 1; 19977184Stimh fuids_ok = B_FALSE; 19987184Stimh } 19997184Stimh 20007184Stimh error = zfs_fill_zplprops_impl(NULL, zplver, fuids_ok, createprops, 20017184Stimh zplprops, is_ci); 20027184Stimh return (error); 2003789Sahrens } 2004789Sahrens 20055367Sahrens /* 20065367Sahrens * inputs: 20075367Sahrens * zc_objset_type type of objset to create (fs vs zvol) 20085367Sahrens * zc_name name of new objset 20095367Sahrens * zc_value name of snapshot to clone from (may be empty) 20105367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 20115367Sahrens * 20125498Stimh * outputs: none 20135367Sahrens */ 2014789Sahrens static int 2015789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 2016789Sahrens { 2017789Sahrens objset_t *clone; 2018789Sahrens int error = 0; 20195331Samw zfs_creat_t zct; 20204543Smarks nvlist_t *nvprops = NULL; 20214543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 2022789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 2023789Sahrens 2024789Sahrens switch (type) { 2025789Sahrens 2026789Sahrens case DMU_OST_ZFS: 2027789Sahrens cbfunc = zfs_create_cb; 2028789Sahrens break; 2029789Sahrens 2030789Sahrens case DMU_OST_ZVOL: 2031789Sahrens cbfunc = zvol_create_cb; 2032789Sahrens break; 2033789Sahrens 2034789Sahrens default: 20352199Sahrens cbfunc = NULL; 20366423Sgw25295 break; 20372199Sahrens } 20385326Sek110237 if (strchr(zc->zc_name, '@') || 20395326Sek110237 strchr(zc->zc_name, '%')) 2040789Sahrens return (EINVAL); 2041789Sahrens 20422676Seschrock if (zc->zc_nvlist_src != NULL && 20435094Slling (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 20445094Slling &nvprops)) != 0) 20452676Seschrock return (error); 20462676Seschrock 20475498Stimh zct.zct_zplprops = NULL; 20485331Samw zct.zct_props = nvprops; 20495331Samw 20502676Seschrock if (zc->zc_value[0] != '\0') { 2051789Sahrens /* 2052789Sahrens * We're creating a clone of an existing snapshot. 2053789Sahrens */ 20542676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 20552676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 20564543Smarks nvlist_free(nvprops); 2057789Sahrens return (EINVAL); 20582676Seschrock } 2059789Sahrens 20602676Seschrock error = dmu_objset_open(zc->zc_value, type, 20616689Smaybee DS_MODE_USER | DS_MODE_READONLY, &clone); 20622676Seschrock if (error) { 20634543Smarks nvlist_free(nvprops); 2064789Sahrens return (error); 20652676Seschrock } 20666492Stimh 20676492Stimh error = dmu_objset_create(zc->zc_name, type, clone, 0, 20686492Stimh NULL, NULL); 20695331Samw if (error) { 20705331Samw dmu_objset_close(clone); 20715331Samw nvlist_free(nvprops); 20725331Samw return (error); 20735331Samw } 2074789Sahrens dmu_objset_close(clone); 2075789Sahrens } else { 20766492Stimh boolean_t is_insensitive = B_FALSE; 20776492Stimh 20782676Seschrock if (cbfunc == NULL) { 20794543Smarks nvlist_free(nvprops); 20802199Sahrens return (EINVAL); 20812676Seschrock } 20822676Seschrock 2083789Sahrens if (type == DMU_OST_ZVOL) { 20842676Seschrock uint64_t volsize, volblocksize; 20852676Seschrock 20864543Smarks if (nvprops == NULL || 20874543Smarks nvlist_lookup_uint64(nvprops, 20882676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 20892676Seschrock &volsize) != 0) { 20904543Smarks nvlist_free(nvprops); 20912676Seschrock return (EINVAL); 20922676Seschrock } 20932676Seschrock 20944543Smarks if ((error = nvlist_lookup_uint64(nvprops, 20952676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 20962676Seschrock &volblocksize)) != 0 && error != ENOENT) { 20974543Smarks nvlist_free(nvprops); 20982676Seschrock return (EINVAL); 20992676Seschrock } 21001133Seschrock 21012676Seschrock if (error != 0) 21022676Seschrock volblocksize = zfs_prop_default_numeric( 21032676Seschrock ZFS_PROP_VOLBLOCKSIZE); 21042676Seschrock 21052676Seschrock if ((error = zvol_check_volblocksize( 21062676Seschrock volblocksize)) != 0 || 21072676Seschrock (error = zvol_check_volsize(volsize, 21082676Seschrock volblocksize)) != 0) { 21094543Smarks nvlist_free(nvprops); 2110789Sahrens return (error); 21112676Seschrock } 21124577Sahrens } else if (type == DMU_OST_ZFS) { 21135331Samw int error; 21145331Samw 21155498Stimh /* 21165331Samw * We have to have normalization and 21175331Samw * case-folding flags correct when we do the 21185331Samw * file system creation, so go figure them out 21195498Stimh * now. 21205331Samw */ 21215498Stimh VERIFY(nvlist_alloc(&zct.zct_zplprops, 21225498Stimh NV_UNIQUE_NAME, KM_SLEEP) == 0); 21235498Stimh error = zfs_fill_zplprops(zc->zc_name, nvprops, 21247184Stimh zct.zct_zplprops, &is_insensitive); 21255331Samw if (error != 0) { 21265331Samw nvlist_free(nvprops); 21275498Stimh nvlist_free(zct.zct_zplprops); 21285331Samw return (error); 21294577Sahrens } 21302676Seschrock } 21316492Stimh error = dmu_objset_create(zc->zc_name, type, NULL, 21326492Stimh is_insensitive ? DS_FLAG_CI_DATASET : 0, cbfunc, &zct); 21335498Stimh nvlist_free(zct.zct_zplprops); 2134789Sahrens } 21352676Seschrock 21362676Seschrock /* 21372676Seschrock * It would be nice to do this atomically. 21382676Seschrock */ 21392676Seschrock if (error == 0) { 21404787Sahrens if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) 21412676Seschrock (void) dmu_objset_destroy(zc->zc_name); 21422676Seschrock } 21434543Smarks nvlist_free(nvprops); 2144789Sahrens return (error); 2145789Sahrens } 2146789Sahrens 2147*7265Sahrens struct snap_prop_arg { 2148*7265Sahrens nvlist_t *nvprops; 2149*7265Sahrens const char *snapname; 2150*7265Sahrens }; 2151*7265Sahrens 2152*7265Sahrens static int 2153*7265Sahrens set_snap_props(char *name, void *arg) 2154*7265Sahrens { 2155*7265Sahrens struct snap_prop_arg *snpa = arg; 2156*7265Sahrens int len = strlen(name) + strlen(snpa->snapname) + 2; 2157*7265Sahrens char *buf = kmem_alloc(len, KM_SLEEP); 2158*7265Sahrens int err; 2159*7265Sahrens 2160*7265Sahrens (void) snprintf(buf, len, "%s@%s", name, snpa->snapname); 2161*7265Sahrens err = zfs_set_prop_nvlist(buf, snpa->nvprops); 2162*7265Sahrens if (err) 2163*7265Sahrens (void) dmu_objset_destroy(buf); 2164*7265Sahrens kmem_free(buf, len); 2165*7265Sahrens return (err); 2166*7265Sahrens } 2167*7265Sahrens 21685367Sahrens /* 21695367Sahrens * inputs: 21705367Sahrens * zc_name name of filesystem 21715367Sahrens * zc_value short name of snapshot 21725367Sahrens * zc_cookie recursive flag 21735367Sahrens * 21745367Sahrens * outputs: none 21755367Sahrens */ 2176789Sahrens static int 21772199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 21782199Sahrens { 2179*7265Sahrens nvlist_t *nvprops = NULL; 2180*7265Sahrens int error; 2181*7265Sahrens boolean_t recursive = zc->zc_cookie; 2182*7265Sahrens 21832676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 21842199Sahrens return (EINVAL); 2185*7265Sahrens 2186*7265Sahrens if (zc->zc_nvlist_src != NULL && 2187*7265Sahrens (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 2188*7265Sahrens &nvprops)) != 0) 2189*7265Sahrens return (error); 2190*7265Sahrens 2191*7265Sahrens error = dmu_objset_snapshot(zc->zc_name, zc->zc_value, recursive); 2192*7265Sahrens 2193*7265Sahrens /* 2194*7265Sahrens * It would be nice to do this atomically. 2195*7265Sahrens */ 2196*7265Sahrens if (error == 0) { 2197*7265Sahrens struct snap_prop_arg snpa; 2198*7265Sahrens snpa.nvprops = nvprops; 2199*7265Sahrens snpa.snapname = zc->zc_value; 2200*7265Sahrens if (recursive) { 2201*7265Sahrens error = dmu_objset_find(zc->zc_name, 2202*7265Sahrens set_snap_props, &snpa, DS_FIND_CHILDREN); 2203*7265Sahrens if (error) { 2204*7265Sahrens (void) dmu_snapshots_destroy(zc->zc_name, 2205*7265Sahrens zc->zc_value); 2206*7265Sahrens } 2207*7265Sahrens } else { 2208*7265Sahrens error = set_snap_props(zc->zc_name, &snpa); 2209*7265Sahrens } 2210*7265Sahrens } 2211*7265Sahrens nvlist_free(nvprops); 2212*7265Sahrens return (error); 22132199Sahrens } 22142199Sahrens 22154007Smmusante int 22162199Sahrens zfs_unmount_snap(char *name, void *arg) 2217789Sahrens { 22182417Sahrens vfs_t *vfsp = NULL; 22192199Sahrens 22206689Smaybee if (arg) { 22216689Smaybee char *snapname = arg; 22226689Smaybee int len = strlen(name) + strlen(snapname) + 2; 22236689Smaybee char *buf = kmem_alloc(len, KM_SLEEP); 22246689Smaybee 22256689Smaybee (void) strcpy(buf, name); 22266689Smaybee (void) strcat(buf, "@"); 22276689Smaybee (void) strcat(buf, snapname); 22286689Smaybee vfsp = zfs_get_vfs(buf); 22296689Smaybee kmem_free(buf, len); 22302417Sahrens } else if (strchr(name, '@')) { 22312199Sahrens vfsp = zfs_get_vfs(name); 22322199Sahrens } 22332199Sahrens 22342199Sahrens if (vfsp) { 22352199Sahrens /* 22362199Sahrens * Always force the unmount for snapshots. 22372199Sahrens */ 22382199Sahrens int flag = MS_FORCE; 2239789Sahrens int err; 2240789Sahrens 22412199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 22422199Sahrens VFS_RELE(vfsp); 22432199Sahrens return (err); 22442199Sahrens } 22452199Sahrens VFS_RELE(vfsp); 22462199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 22472199Sahrens return (err); 22482199Sahrens } 22492199Sahrens return (0); 22502199Sahrens } 22512199Sahrens 22525367Sahrens /* 22535367Sahrens * inputs: 22545367Sahrens * zc_name name of filesystem 22555367Sahrens * zc_value short name of snapshot 22565367Sahrens * 22575367Sahrens * outputs: none 22585367Sahrens */ 22592199Sahrens static int 22602199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 22612199Sahrens { 22622199Sahrens int err; 2263789Sahrens 22642676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 22652199Sahrens return (EINVAL); 22662199Sahrens err = dmu_objset_find(zc->zc_name, 22672676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 22682199Sahrens if (err) 22692199Sahrens return (err); 22702676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 22712199Sahrens } 22722199Sahrens 22735367Sahrens /* 22745367Sahrens * inputs: 22755367Sahrens * zc_name name of dataset to destroy 22765367Sahrens * zc_objset_type type of objset 22775367Sahrens * 22785367Sahrens * outputs: none 22795367Sahrens */ 22802199Sahrens static int 22812199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 22822199Sahrens { 22832199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 22842199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 22852199Sahrens if (err) 22862199Sahrens return (err); 2287789Sahrens } 2288789Sahrens 2289789Sahrens return (dmu_objset_destroy(zc->zc_name)); 2290789Sahrens } 2291789Sahrens 22925367Sahrens /* 22935367Sahrens * inputs: 22945446Sahrens * zc_name name of dataset to rollback (to most recent snapshot) 22955367Sahrens * 22965367Sahrens * outputs: none 22975367Sahrens */ 2298789Sahrens static int 2299789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 2300789Sahrens { 23015446Sahrens objset_t *os; 23025446Sahrens int error; 23035446Sahrens zfsvfs_t *zfsvfs = NULL; 23045446Sahrens 23055446Sahrens /* 23065446Sahrens * Get the zfsvfs for the receiving objset. There 23075446Sahrens * won't be one if we're operating on a zvol, if the 23085446Sahrens * objset doesn't exist yet, or is not mounted. 23095446Sahrens */ 23106689Smaybee error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, DS_MODE_USER, &os); 23115446Sahrens if (error) 23125446Sahrens return (error); 23135446Sahrens 23145446Sahrens if (dmu_objset_type(os) == DMU_OST_ZFS) { 23155446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 23165446Sahrens zfsvfs = dmu_objset_get_user(os); 23175446Sahrens if (zfsvfs != NULL) 23185446Sahrens VFS_HOLD(zfsvfs->z_vfs); 23195446Sahrens mutex_exit(&os->os->os_user_ptr_lock); 23205446Sahrens } 23215446Sahrens 23225446Sahrens if (zfsvfs != NULL) { 23235446Sahrens char osname[MAXNAMELEN]; 23245446Sahrens int mode; 23255446Sahrens 23266083Sek110237 error = zfs_suspend_fs(zfsvfs, osname, &mode); 23276083Sek110237 if (error == 0) { 23286083Sek110237 int resume_err; 23296083Sek110237 23306083Sek110237 ASSERT(strcmp(osname, zc->zc_name) == 0); 23316083Sek110237 error = dmu_objset_rollback(os); 23326083Sek110237 resume_err = zfs_resume_fs(zfsvfs, osname, mode); 23336083Sek110237 error = error ? error : resume_err; 23346083Sek110237 } else { 23356083Sek110237 dmu_objset_close(os); 23366083Sek110237 } 23375446Sahrens VFS_RELE(zfsvfs->z_vfs); 23385446Sahrens } else { 23395446Sahrens error = dmu_objset_rollback(os); 23405446Sahrens } 23416689Smaybee /* Note, the dmu_objset_rollback() releases the objset for us. */ 23425446Sahrens 23435446Sahrens return (error); 2344789Sahrens } 2345789Sahrens 23465367Sahrens /* 23475367Sahrens * inputs: 23485367Sahrens * zc_name old name of dataset 23495367Sahrens * zc_value new name of dataset 23505367Sahrens * zc_cookie recursive flag (only valid for snapshots) 23515367Sahrens * 23525367Sahrens * outputs: none 23535367Sahrens */ 2354789Sahrens static int 2355789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 2356789Sahrens { 23574490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 23584007Smmusante 23592676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 23605326Sek110237 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 23615326Sek110237 strchr(zc->zc_value, '%')) 2362789Sahrens return (EINVAL); 2363789Sahrens 23644007Smmusante /* 23654007Smmusante * Unmount snapshot unless we're doing a recursive rename, 23664007Smmusante * in which case the dataset code figures out which snapshots 23674007Smmusante * to unmount. 23684007Smmusante */ 23694007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 2370789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 23712199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 23722199Sahrens if (err) 23732199Sahrens return (err); 2374789Sahrens } 23754007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 2376789Sahrens } 2377789Sahrens 23786689Smaybee static void 23796689Smaybee clear_props(char *dataset, nvlist_t *props) 23806689Smaybee { 23816689Smaybee zfs_cmd_t *zc; 23826689Smaybee nvpair_t *prop; 23836689Smaybee 23846689Smaybee if (props == NULL) 23856689Smaybee return; 23866689Smaybee zc = kmem_alloc(sizeof (zfs_cmd_t), KM_SLEEP); 23876689Smaybee (void) strcpy(zc->zc_name, dataset); 23886689Smaybee for (prop = nvlist_next_nvpair(props, NULL); prop; 23896689Smaybee prop = nvlist_next_nvpair(props, prop)) { 23906689Smaybee (void) strcpy(zc->zc_value, nvpair_name(prop)); 23916689Smaybee if (zfs_secpolicy_inherit(zc, CRED()) == 0) 23926689Smaybee (void) zfs_ioc_inherit_prop(zc); 23936689Smaybee } 23946689Smaybee kmem_free(zc, sizeof (zfs_cmd_t)); 23956689Smaybee } 23966689Smaybee 23975367Sahrens /* 23985367Sahrens * inputs: 23995367Sahrens * zc_name name of containing filesystem 24005367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 24015367Sahrens * zc_value name of snapshot to create 24025367Sahrens * zc_string name of clone origin (if DRR_FLAG_CLONE) 24035367Sahrens * zc_cookie file descriptor to recv from 24045367Sahrens * zc_begin_record the BEGIN record of the stream (not byteswapped) 24055367Sahrens * zc_guid force flag 24065367Sahrens * 24075367Sahrens * outputs: 24085367Sahrens * zc_cookie number of bytes read 24095367Sahrens */ 2410789Sahrens static int 24115367Sahrens zfs_ioc_recv(zfs_cmd_t *zc) 2412789Sahrens { 2413789Sahrens file_t *fp; 24145326Sek110237 objset_t *os; 24155367Sahrens dmu_recv_cookie_t drc; 24165326Sek110237 zfsvfs_t *zfsvfs = NULL; 24175326Sek110237 boolean_t force = (boolean_t)zc->zc_guid; 2418789Sahrens int error, fd; 24195367Sahrens offset_t off; 24205367Sahrens nvlist_t *props = NULL; 24216689Smaybee nvlist_t *origprops = NULL; 24225367Sahrens objset_t *origin = NULL; 24235367Sahrens char *tosnap; 24245367Sahrens char tofs[ZFS_MAXNAMELEN]; 2425789Sahrens 24263265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 24275326Sek110237 strchr(zc->zc_value, '@') == NULL || 24285326Sek110237 strchr(zc->zc_value, '%')) 24293265Sahrens return (EINVAL); 24303265Sahrens 24315367Sahrens (void) strcpy(tofs, zc->zc_value); 24325367Sahrens tosnap = strchr(tofs, '@'); 24335367Sahrens *tosnap = '\0'; 24345367Sahrens tosnap++; 24355367Sahrens 24365367Sahrens if (zc->zc_nvlist_src != NULL && 24375367Sahrens (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 24385367Sahrens &props)) != 0) 24395367Sahrens return (error); 24405367Sahrens 2441789Sahrens fd = zc->zc_cookie; 2442789Sahrens fp = getf(fd); 24435367Sahrens if (fp == NULL) { 24445367Sahrens nvlist_free(props); 2445789Sahrens return (EBADF); 24465367Sahrens } 24475326Sek110237 24486689Smaybee if (dmu_objset_open(tofs, DMU_OST_ANY, 24496689Smaybee DS_MODE_USER | DS_MODE_READONLY, &os) == 0) { 24506689Smaybee /* 24516689Smaybee * Try to get the zfsvfs for the receiving objset. 24526689Smaybee * There won't be one if we're operating on a zvol, 24536689Smaybee * if the objset doesn't exist yet, or is not mounted. 24546689Smaybee */ 24555446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 24566689Smaybee if (zfsvfs = dmu_objset_get_user(os)) { 24576083Sek110237 if (!mutex_tryenter(&zfsvfs->z_online_recv_lock)) { 24586689Smaybee mutex_exit(&os->os->os_user_ptr_lock); 24596083Sek110237 dmu_objset_close(os); 24606689Smaybee zfsvfs = NULL; 24616689Smaybee error = EBUSY; 24626689Smaybee goto out; 24636083Sek110237 } 24646689Smaybee VFS_HOLD(zfsvfs->z_vfs); 24656083Sek110237 } 24666689Smaybee mutex_exit(&os->os->os_user_ptr_lock); 24676689Smaybee 24686689Smaybee /* 24696689Smaybee * If new properties are supplied, they are to completely 24706689Smaybee * replace the existing ones, so stash away the existing ones. 24716689Smaybee */ 24726689Smaybee if (props) 24736689Smaybee (void) dsl_prop_get_all(os, &origprops, TRUE); 24746689Smaybee 24755326Sek110237 dmu_objset_close(os); 24765326Sek110237 } 24775326Sek110237 24785367Sahrens if (zc->zc_string[0]) { 24795367Sahrens error = dmu_objset_open(zc->zc_string, DMU_OST_ANY, 24806689Smaybee DS_MODE_USER | DS_MODE_READONLY, &origin); 24816689Smaybee if (error) 24826689Smaybee goto out; 24835367Sahrens } 24845367Sahrens 24855367Sahrens error = dmu_recv_begin(tofs, tosnap, &zc->zc_begin_record, 24865367Sahrens force, origin, zfsvfs != NULL, &drc); 24875367Sahrens if (origin) 24885367Sahrens dmu_objset_close(origin); 24896689Smaybee if (error) 24906689Smaybee goto out; 24915326Sek110237 24925326Sek110237 /* 24936689Smaybee * Reset properties. We do this before we receive the stream 24946689Smaybee * so that the properties are applied to the new data. 24955326Sek110237 */ 24965367Sahrens if (props) { 24976689Smaybee clear_props(tofs, origprops); 24986689Smaybee /* 24996689Smaybee * XXX - Note, this is all-or-nothing; should be best-effort. 25006689Smaybee */ 25016689Smaybee (void) zfs_set_prop_nvlist(tofs, props); 25025367Sahrens } 25035367Sahrens 25045367Sahrens off = fp->f_offset; 25055367Sahrens error = dmu_recv_stream(&drc, fp->f_vnode, &off); 25065367Sahrens 25076689Smaybee if (error == 0 && zfsvfs) { 25086689Smaybee char osname[MAXNAMELEN]; 25096689Smaybee int mode; 25106689Smaybee 25116689Smaybee /* online recv */ 25126689Smaybee error = zfs_suspend_fs(zfsvfs, osname, &mode); 25136689Smaybee if (error == 0) { 25146689Smaybee int resume_err; 25156689Smaybee 25166689Smaybee error = dmu_recv_end(&drc); 25176689Smaybee resume_err = zfs_resume_fs(zfsvfs, osname, mode); 25186689Smaybee error = error ? error : resume_err; 25195367Sahrens } else { 25206689Smaybee dmu_recv_abort_cleanup(&drc); 25215367Sahrens } 25226689Smaybee } else if (error == 0) { 25236689Smaybee error = dmu_recv_end(&drc); 25246083Sek110237 } 25255367Sahrens 25265367Sahrens zc->zc_cookie = off - fp->f_offset; 25275367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 25285367Sahrens fp->f_offset = off; 25292885Sahrens 25306689Smaybee /* 25316689Smaybee * On error, restore the original props. 25326689Smaybee */ 25336689Smaybee if (error && props) { 25346689Smaybee clear_props(tofs, props); 25356689Smaybee (void) zfs_set_prop_nvlist(tofs, origprops); 25366689Smaybee } 25376689Smaybee out: 25386689Smaybee if (zfsvfs) { 25396689Smaybee mutex_exit(&zfsvfs->z_online_recv_lock); 25406689Smaybee VFS_RELE(zfsvfs->z_vfs); 25416689Smaybee } 25426689Smaybee nvlist_free(props); 25436689Smaybee nvlist_free(origprops); 2544789Sahrens releasef(fd); 2545789Sahrens return (error); 2546789Sahrens } 2547789Sahrens 25485367Sahrens /* 25495367Sahrens * inputs: 25505367Sahrens * zc_name name of snapshot to send 25515367Sahrens * zc_value short name of incremental fromsnap (may be empty) 25525367Sahrens * zc_cookie file descriptor to send stream to 25535367Sahrens * zc_obj fromorigin flag (mutually exclusive with zc_value) 25545367Sahrens * 25555367Sahrens * outputs: none 25565367Sahrens */ 2557789Sahrens static int 25585367Sahrens zfs_ioc_send(zfs_cmd_t *zc) 2559789Sahrens { 2560789Sahrens objset_t *fromsnap = NULL; 2561789Sahrens objset_t *tosnap; 2562789Sahrens file_t *fp; 2563789Sahrens int error; 25645367Sahrens offset_t off; 2565789Sahrens 2566789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 25676689Smaybee DS_MODE_USER | DS_MODE_READONLY, &tosnap); 2568789Sahrens if (error) 2569789Sahrens return (error); 2570789Sahrens 25712676Seschrock if (zc->zc_value[0] != '\0') { 25722885Sahrens char buf[MAXPATHLEN]; 25732885Sahrens char *cp; 25742885Sahrens 25752885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 25762885Sahrens cp = strchr(buf, '@'); 25772885Sahrens if (cp) 25782885Sahrens *(cp+1) = 0; 25792885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 25802885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 25816689Smaybee DS_MODE_USER | DS_MODE_READONLY, &fromsnap); 2582789Sahrens if (error) { 2583789Sahrens dmu_objset_close(tosnap); 2584789Sahrens return (error); 2585789Sahrens } 2586789Sahrens } 2587789Sahrens 2588789Sahrens fp = getf(zc->zc_cookie); 2589789Sahrens if (fp == NULL) { 2590789Sahrens dmu_objset_close(tosnap); 2591789Sahrens if (fromsnap) 2592789Sahrens dmu_objset_close(fromsnap); 2593789Sahrens return (EBADF); 2594789Sahrens } 2595789Sahrens 25965367Sahrens off = fp->f_offset; 25975367Sahrens error = dmu_sendbackup(tosnap, fromsnap, zc->zc_obj, fp->f_vnode, &off); 25985367Sahrens 25995367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 26005367Sahrens fp->f_offset = off; 2601789Sahrens releasef(zc->zc_cookie); 2602789Sahrens if (fromsnap) 2603789Sahrens dmu_objset_close(fromsnap); 2604789Sahrens dmu_objset_close(tosnap); 2605789Sahrens return (error); 2606789Sahrens } 2607789Sahrens 26081544Seschrock static int 26091544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 26101544Seschrock { 26111544Seschrock int id, error; 26121544Seschrock 26131544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 26141544Seschrock &zc->zc_inject_record); 26151544Seschrock 26161544Seschrock if (error == 0) 26171544Seschrock zc->zc_guid = (uint64_t)id; 26181544Seschrock 26191544Seschrock return (error); 26201544Seschrock } 26211544Seschrock 26221544Seschrock static int 26231544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 26241544Seschrock { 26251544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 26261544Seschrock } 26271544Seschrock 26281544Seschrock static int 26291544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 26301544Seschrock { 26311544Seschrock int id = (int)zc->zc_guid; 26321544Seschrock int error; 26331544Seschrock 26341544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 26351544Seschrock &zc->zc_inject_record); 26361544Seschrock 26371544Seschrock zc->zc_guid = id; 26381544Seschrock 26391544Seschrock return (error); 26401544Seschrock } 26411544Seschrock 26421544Seschrock static int 26431544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 26441544Seschrock { 26451544Seschrock spa_t *spa; 26461544Seschrock int error; 26472676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 26481544Seschrock 26491544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 26501544Seschrock return (error); 26511544Seschrock 26522676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 26531544Seschrock &count); 26541544Seschrock if (error == 0) 26552676Seschrock zc->zc_nvlist_dst_size = count; 26561544Seschrock else 26572676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 26581544Seschrock 26591544Seschrock spa_close(spa, FTAG); 26601544Seschrock 26611544Seschrock return (error); 26621544Seschrock } 26631544Seschrock 26641544Seschrock static int 26651544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 26661544Seschrock { 26671544Seschrock spa_t *spa; 26681544Seschrock vdev_t *vd; 26694808Sek110237 uint64_t txg; 26701544Seschrock int error; 26711544Seschrock 26721544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 26731544Seschrock return (error); 26741544Seschrock 26755329Sgw25295 /* 26765329Sgw25295 * Try to resume any I/Os which may have been suspended 26775329Sgw25295 * as a result of a complete pool failure. 26785329Sgw25295 */ 26795329Sgw25295 if (!list_is_empty(&spa->spa_zio_list)) { 26805329Sgw25295 if (zio_vdev_resume_io(spa) != 0) { 26815329Sgw25295 spa_close(spa, FTAG); 26825329Sgw25295 return (EIO); 26835329Sgw25295 } 26845329Sgw25295 } 26855329Sgw25295 26864451Seschrock txg = spa_vdev_enter(spa); 26871544Seschrock 26882676Seschrock if (zc->zc_guid == 0) { 26891544Seschrock vd = NULL; 26906643Seschrock } else { 26916643Seschrock vd = spa_lookup_by_guid(spa, zc->zc_guid, B_TRUE); 26925450Sbrendan if (vd == NULL) { 26935450Sbrendan (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 26945450Sbrendan spa_close(spa, FTAG); 26955450Sbrendan return (ENODEV); 26965450Sbrendan } 26971544Seschrock } 26981544Seschrock 26995329Sgw25295 vdev_clear(spa, vd, B_TRUE); 27001544Seschrock 27014451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 27021544Seschrock 27031544Seschrock spa_close(spa, FTAG); 27041544Seschrock 27051544Seschrock return (0); 27061544Seschrock } 27071544Seschrock 27085367Sahrens /* 27095367Sahrens * inputs: 27105367Sahrens * zc_name name of filesystem 27115367Sahrens * zc_value name of origin snapshot 27125367Sahrens * 27135367Sahrens * outputs: none 27145367Sahrens */ 27151544Seschrock static int 27162082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 27172082Seschrock { 27182417Sahrens char *cp; 27192417Sahrens 27202417Sahrens /* 27212417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 27222417Sahrens * it's easier. 27232417Sahrens */ 27242676Seschrock cp = strchr(zc->zc_value, '@'); 27252417Sahrens if (cp) 27262417Sahrens *cp = '\0'; 27272676Seschrock (void) dmu_objset_find(zc->zc_value, 27282417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 27292082Seschrock return (dsl_dataset_promote(zc->zc_name)); 27302082Seschrock } 27312082Seschrock 27324543Smarks /* 27334543Smarks * We don't want to have a hard dependency 27344543Smarks * against some special symbols in sharefs 27355331Samw * nfs, and smbsrv. Determine them if needed when 27364543Smarks * the first file system is shared. 27375331Samw * Neither sharefs, nfs or smbsrv are unloadable modules. 27384543Smarks */ 27395331Samw int (*znfsexport_fs)(void *arg); 27404543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 27415331Samw int (*zsmbexport_fs)(void *arg, boolean_t add_share); 27425331Samw 27435331Samw int zfs_nfsshare_inited; 27445331Samw int zfs_smbshare_inited; 27455331Samw 27464543Smarks ddi_modhandle_t nfs_mod; 27474543Smarks ddi_modhandle_t sharefs_mod; 27485331Samw ddi_modhandle_t smbsrv_mod; 27494543Smarks kmutex_t zfs_share_lock; 27504543Smarks 27514543Smarks static int 27525331Samw zfs_init_sharefs() 27535331Samw { 27545331Samw int error; 27555331Samw 27565331Samw ASSERT(MUTEX_HELD(&zfs_share_lock)); 27575331Samw /* Both NFS and SMB shares also require sharetab support. */ 27585331Samw if (sharefs_mod == NULL && ((sharefs_mod = 27595331Samw ddi_modopen("fs/sharefs", 27605331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 27615331Samw return (ENOSYS); 27625331Samw } 27635331Samw if (zshare_fs == NULL && ((zshare_fs = 27645331Samw (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 27655331Samw ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 27665331Samw return (ENOSYS); 27675331Samw } 27685331Samw return (0); 27695331Samw } 27705331Samw 27715331Samw static int 27724543Smarks zfs_ioc_share(zfs_cmd_t *zc) 27734543Smarks { 27744543Smarks int error; 27754543Smarks int opcode; 27764543Smarks 27775331Samw switch (zc->zc_share.z_sharetype) { 27785331Samw case ZFS_SHARE_NFS: 27795331Samw case ZFS_UNSHARE_NFS: 27805331Samw if (zfs_nfsshare_inited == 0) { 27815331Samw mutex_enter(&zfs_share_lock); 27825331Samw if (nfs_mod == NULL && ((nfs_mod = ddi_modopen("fs/nfs", 27835331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 27845331Samw mutex_exit(&zfs_share_lock); 27855331Samw return (ENOSYS); 27865331Samw } 27875331Samw if (znfsexport_fs == NULL && 27885331Samw ((znfsexport_fs = (int (*)(void *)) 27895331Samw ddi_modsym(nfs_mod, 27905331Samw "nfs_export", &error)) == NULL)) { 27915331Samw mutex_exit(&zfs_share_lock); 27925331Samw return (ENOSYS); 27935331Samw } 27945331Samw error = zfs_init_sharefs(); 27955331Samw if (error) { 27965331Samw mutex_exit(&zfs_share_lock); 27975331Samw return (ENOSYS); 27985331Samw } 27995331Samw zfs_nfsshare_inited = 1; 28004543Smarks mutex_exit(&zfs_share_lock); 28014543Smarks } 28025331Samw break; 28035331Samw case ZFS_SHARE_SMB: 28045331Samw case ZFS_UNSHARE_SMB: 28055331Samw if (zfs_smbshare_inited == 0) { 28065331Samw mutex_enter(&zfs_share_lock); 28075331Samw if (smbsrv_mod == NULL && ((smbsrv_mod = 28085331Samw ddi_modopen("drv/smbsrv", 28095331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 28105331Samw mutex_exit(&zfs_share_lock); 28115331Samw return (ENOSYS); 28125331Samw } 28135331Samw if (zsmbexport_fs == NULL && ((zsmbexport_fs = 28145331Samw (int (*)(void *, boolean_t))ddi_modsym(smbsrv_mod, 28156139Sjb150015 "smb_server_share", &error)) == NULL)) { 28165331Samw mutex_exit(&zfs_share_lock); 28175331Samw return (ENOSYS); 28185331Samw } 28195331Samw error = zfs_init_sharefs(); 28205331Samw if (error) { 28215331Samw mutex_exit(&zfs_share_lock); 28225331Samw return (ENOSYS); 28235331Samw } 28245331Samw zfs_smbshare_inited = 1; 28254543Smarks mutex_exit(&zfs_share_lock); 28264543Smarks } 28275331Samw break; 28285331Samw default: 28295331Samw return (EINVAL); 28304543Smarks } 28314543Smarks 28325331Samw switch (zc->zc_share.z_sharetype) { 28335331Samw case ZFS_SHARE_NFS: 28345331Samw case ZFS_UNSHARE_NFS: 28355331Samw if (error = 28365331Samw znfsexport_fs((void *) 28375331Samw (uintptr_t)zc->zc_share.z_exportdata)) 28385331Samw return (error); 28395331Samw break; 28405331Samw case ZFS_SHARE_SMB: 28415331Samw case ZFS_UNSHARE_SMB: 28425331Samw if (error = zsmbexport_fs((void *) 28435331Samw (uintptr_t)zc->zc_share.z_exportdata, 28445331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB ? 28455331Samw B_TRUE : B_FALSE)) { 28465331Samw return (error); 28475331Samw } 28485331Samw break; 28495331Samw } 28505331Samw 28515331Samw opcode = (zc->zc_share.z_sharetype == ZFS_SHARE_NFS || 28525331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB) ? 28534543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 28544543Smarks 28555331Samw /* 28565331Samw * Add or remove share from sharetab 28575331Samw */ 28584543Smarks error = zshare_fs(opcode, 28594543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 28604543Smarks zc->zc_share.z_sharemax); 28614543Smarks 28624543Smarks return (error); 28634543Smarks 28644543Smarks } 28654543Smarks 28664543Smarks /* 28674988Sek110237 * pool create, destroy, and export don't log the history as part of 28684988Sek110237 * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export 28694988Sek110237 * do the logging of those commands. 28704543Smarks */ 2871789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 28724715Sek110237 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 28734577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 28744577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 28754577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 28764577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 28774577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 28784577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 28794577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 28804577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 28814577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 28824577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 28834577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 28844577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 28854577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 28864577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 28874577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 28884577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 28894577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 28905498Stimh { zfs_ioc_objset_zplprops, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 28914543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 28924577Sahrens DATASET_NAME, B_FALSE }, 28934543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 28944577Sahrens DATASET_NAME, B_FALSE }, 28954577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 28964577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 28974577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 28984577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 28994577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 29004577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 29014577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 29025367Sahrens { zfs_ioc_recv, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 29035367Sahrens { zfs_ioc_send, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 29044577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 29054577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 29064577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 29074577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 29084577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 29094577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 29104577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 29114577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 29124577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 29134577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 29144577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 29154577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 29164577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 29174577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 29184543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 29194577Sahrens DATASET_NAME, B_FALSE }, 29204849Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }, 29214849Sahrens { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE }, 2922789Sahrens }; 2923789Sahrens 2924789Sahrens static int 2925789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2926789Sahrens { 2927789Sahrens zfs_cmd_t *zc; 2928789Sahrens uint_t vec; 29292199Sahrens int error, rc; 2930789Sahrens 2931789Sahrens if (getminor(dev) != 0) 2932789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2933789Sahrens 2934789Sahrens vec = cmd - ZFS_IOC; 29354787Sahrens ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); 2936789Sahrens 2937789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2938789Sahrens return (EINVAL); 2939789Sahrens 2940789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2941789Sahrens 2942789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2943789Sahrens 29444787Sahrens if (error == 0) 29454543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2946789Sahrens 2947789Sahrens /* 2948789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2949789Sahrens * the lower layers. 2950789Sahrens */ 2951789Sahrens if (error == 0) { 2952789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2953789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 29544577Sahrens case POOL_NAME: 2955789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2956789Sahrens error = EINVAL; 2957789Sahrens break; 2958789Sahrens 29594577Sahrens case DATASET_NAME: 2960789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2961789Sahrens error = EINVAL; 2962789Sahrens break; 29632856Snd150628 29644577Sahrens case NO_NAME: 29652856Snd150628 break; 2966789Sahrens } 2967789Sahrens } 2968789Sahrens 2969789Sahrens if (error == 0) 2970789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2971789Sahrens 29722199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 29734543Smarks if (error == 0) { 29742199Sahrens error = rc; 29754543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 29764543Smarks zfs_log_history(zc); 29774543Smarks } 2978789Sahrens 2979789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2980789Sahrens return (error); 2981789Sahrens } 2982789Sahrens 2983789Sahrens static int 2984789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2985789Sahrens { 2986789Sahrens if (cmd != DDI_ATTACH) 2987789Sahrens return (DDI_FAILURE); 2988789Sahrens 2989789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2990789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2991789Sahrens return (DDI_FAILURE); 2992789Sahrens 2993789Sahrens zfs_dip = dip; 2994789Sahrens 2995789Sahrens ddi_report_dev(dip); 2996789Sahrens 2997789Sahrens return (DDI_SUCCESS); 2998789Sahrens } 2999789Sahrens 3000789Sahrens static int 3001789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 3002789Sahrens { 3003789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 3004789Sahrens return (DDI_FAILURE); 3005789Sahrens 3006789Sahrens if (cmd != DDI_DETACH) 3007789Sahrens return (DDI_FAILURE); 3008789Sahrens 3009789Sahrens zfs_dip = NULL; 3010789Sahrens 3011789Sahrens ddi_prop_remove_all(dip); 3012789Sahrens ddi_remove_minor_node(dip, NULL); 3013789Sahrens 3014789Sahrens return (DDI_SUCCESS); 3015789Sahrens } 3016789Sahrens 3017789Sahrens /*ARGSUSED*/ 3018789Sahrens static int 3019789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 3020789Sahrens { 3021789Sahrens switch (infocmd) { 3022789Sahrens case DDI_INFO_DEVT2DEVINFO: 3023789Sahrens *result = zfs_dip; 3024789Sahrens return (DDI_SUCCESS); 3025789Sahrens 3026789Sahrens case DDI_INFO_DEVT2INSTANCE: 3027849Sbonwick *result = (void *)0; 3028789Sahrens return (DDI_SUCCESS); 3029789Sahrens } 3030789Sahrens 3031789Sahrens return (DDI_FAILURE); 3032789Sahrens } 3033789Sahrens 3034789Sahrens /* 3035789Sahrens * OK, so this is a little weird. 3036789Sahrens * 3037789Sahrens * /dev/zfs is the control node, i.e. minor 0. 3038789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 3039789Sahrens * 3040789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 3041789Sahrens * so most of the standard driver entry points are in zvol.c. 3042789Sahrens */ 3043789Sahrens static struct cb_ops zfs_cb_ops = { 3044789Sahrens zvol_open, /* open */ 3045789Sahrens zvol_close, /* close */ 3046789Sahrens zvol_strategy, /* strategy */ 3047789Sahrens nodev, /* print */ 30486423Sgw25295 zvol_dump, /* dump */ 3049789Sahrens zvol_read, /* read */ 3050789Sahrens zvol_write, /* write */ 3051789Sahrens zfsdev_ioctl, /* ioctl */ 3052789Sahrens nodev, /* devmap */ 3053789Sahrens nodev, /* mmap */ 3054789Sahrens nodev, /* segmap */ 3055789Sahrens nochpoll, /* poll */ 3056789Sahrens ddi_prop_op, /* prop_op */ 3057789Sahrens NULL, /* streamtab */ 3058789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 3059789Sahrens CB_REV, /* version */ 30603638Sbillm nodev, /* async read */ 30613638Sbillm nodev, /* async write */ 3062789Sahrens }; 3063789Sahrens 3064789Sahrens static struct dev_ops zfs_dev_ops = { 3065789Sahrens DEVO_REV, /* version */ 3066789Sahrens 0, /* refcnt */ 3067789Sahrens zfs_info, /* info */ 3068789Sahrens nulldev, /* identify */ 3069789Sahrens nulldev, /* probe */ 3070789Sahrens zfs_attach, /* attach */ 3071789Sahrens zfs_detach, /* detach */ 3072789Sahrens nodev, /* reset */ 3073789Sahrens &zfs_cb_ops, /* driver operations */ 3074789Sahrens NULL /* no bus operations */ 3075789Sahrens }; 3076789Sahrens 3077789Sahrens static struct modldrv zfs_modldrv = { 30784577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 30792676Seschrock &zfs_dev_ops 3080789Sahrens }; 3081789Sahrens 3082789Sahrens static struct modlinkage modlinkage = { 3083789Sahrens MODREV_1, 3084789Sahrens (void *)&zfs_modlfs, 3085789Sahrens (void *)&zfs_modldrv, 3086789Sahrens NULL 3087789Sahrens }; 3088789Sahrens 30894720Sfr157268 30904720Sfr157268 uint_t zfs_fsyncer_key; 30915326Sek110237 extern uint_t rrw_tsd_key; 30924720Sfr157268 3093789Sahrens int 3094789Sahrens _init(void) 3095789Sahrens { 3096789Sahrens int error; 3097789Sahrens 3098849Sbonwick spa_init(FREAD | FWRITE); 3099849Sbonwick zfs_init(); 3100849Sbonwick zvol_init(); 3101849Sbonwick 3102849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 3103849Sbonwick zvol_fini(); 3104849Sbonwick zfs_fini(); 3105849Sbonwick spa_fini(); 3106789Sahrens return (error); 3107849Sbonwick } 3108789Sahrens 31094720Sfr157268 tsd_create(&zfs_fsyncer_key, NULL); 31105326Sek110237 tsd_create(&rrw_tsd_key, NULL); 31114720Sfr157268 3112789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 3113789Sahrens ASSERT(error == 0); 31144543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 3115789Sahrens 3116789Sahrens return (0); 3117789Sahrens } 3118789Sahrens 3119789Sahrens int 3120789Sahrens _fini(void) 3121789Sahrens { 3122789Sahrens int error; 3123789Sahrens 31241544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 3125789Sahrens return (EBUSY); 3126789Sahrens 3127789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 3128789Sahrens return (error); 3129789Sahrens 3130789Sahrens zvol_fini(); 3131789Sahrens zfs_fini(); 3132789Sahrens spa_fini(); 31335331Samw if (zfs_nfsshare_inited) 31344543Smarks (void) ddi_modclose(nfs_mod); 31355331Samw if (zfs_smbshare_inited) 31365331Samw (void) ddi_modclose(smbsrv_mod); 31375331Samw if (zfs_nfsshare_inited || zfs_smbshare_inited) 31384543Smarks (void) ddi_modclose(sharefs_mod); 3139789Sahrens 31404720Sfr157268 tsd_destroy(&zfs_fsyncer_key); 3141789Sahrens ldi_ident_release(zfs_li); 3142789Sahrens zfs_li = NULL; 31434543Smarks mutex_destroy(&zfs_share_lock); 3144789Sahrens 3145789Sahrens return (error); 3146789Sahrens } 3147789Sahrens 3148789Sahrens int 3149789Sahrens _info(struct modinfo *modinfop) 3150789Sahrens { 3151789Sahrens return (mod_info(&modlinkage, modinfop)); 3152789Sahrens } 3153