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 95789Sahrens /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */ 96789Sahrens void 97789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 98789Sahrens { 99789Sahrens const char *newfile; 100789Sahrens char buf[256]; 101789Sahrens va_list adx; 102789Sahrens 103789Sahrens /* 104789Sahrens * Get rid of annoying "../common/" prefix to filename. 105789Sahrens */ 106789Sahrens newfile = strrchr(file, '/'); 107789Sahrens if (newfile != NULL) { 108789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 109789Sahrens } else { 110789Sahrens newfile = file; 111789Sahrens } 112789Sahrens 113789Sahrens va_start(adx, fmt); 114789Sahrens (void) vsnprintf(buf, sizeof (buf), fmt, adx); 115789Sahrens va_end(adx); 116789Sahrens 117789Sahrens /* 118789Sahrens * To get this data, use the zfs-dprintf probe as so: 119789Sahrens * dtrace -q -n 'zfs-dprintf \ 120789Sahrens * /stringof(arg0) == "dbuf.c"/ \ 121789Sahrens * {printf("%s: %s", stringof(arg1), stringof(arg3))}' 122789Sahrens * arg0 = file name 123789Sahrens * arg1 = function name 124789Sahrens * arg2 = line number 125789Sahrens * arg3 = message 126789Sahrens */ 127789Sahrens DTRACE_PROBE4(zfs__dprintf, 128789Sahrens char *, newfile, char *, func, int, line, char *, buf); 129789Sahrens } 130789Sahrens 1314543Smarks static void 1324715Sek110237 history_str_free(char *buf) 1334715Sek110237 { 1344715Sek110237 kmem_free(buf, HIS_MAX_RECORD_LEN); 1354715Sek110237 } 1364715Sek110237 1374715Sek110237 static char * 1384715Sek110237 history_str_get(zfs_cmd_t *zc) 1394715Sek110237 { 1404715Sek110237 char *buf; 1414715Sek110237 1424715Sek110237 if (zc->zc_history == NULL) 1434715Sek110237 return (NULL); 1444715Sek110237 1454715Sek110237 buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP); 1464715Sek110237 if (copyinstr((void *)(uintptr_t)zc->zc_history, 1474715Sek110237 buf, HIS_MAX_RECORD_LEN, NULL) != 0) { 1484715Sek110237 history_str_free(buf); 1494715Sek110237 return (NULL); 1504715Sek110237 } 1514715Sek110237 1524715Sek110237 buf[HIS_MAX_RECORD_LEN -1] = '\0'; 1534715Sek110237 1544715Sek110237 return (buf); 1554715Sek110237 } 1564715Sek110237 1575375Stimh /* 1587042Sgw25295 * Check to see if the named dataset is currently defined as bootable 1597042Sgw25295 */ 1607042Sgw25295 static boolean_t 1617042Sgw25295 zfs_is_bootfs(const char *name) 1627042Sgw25295 { 1637042Sgw25295 spa_t *spa; 1647042Sgw25295 boolean_t ret = B_FALSE; 1657042Sgw25295 1667042Sgw25295 if (spa_open(name, &spa, FTAG) == 0) { 1677042Sgw25295 if (spa->spa_bootfs) { 1687042Sgw25295 objset_t *os; 1697042Sgw25295 1707042Sgw25295 if (dmu_objset_open(name, DMU_OST_ZFS, 1717042Sgw25295 DS_MODE_USER | DS_MODE_READONLY, &os) == 0) { 1727042Sgw25295 ret = (dmu_objset_id(os) == spa->spa_bootfs); 1737042Sgw25295 dmu_objset_close(os); 1747042Sgw25295 } 1757042Sgw25295 } 1767042Sgw25295 spa_close(spa, FTAG); 1777042Sgw25295 } 1787042Sgw25295 return (ret); 1797042Sgw25295 } 1807042Sgw25295 1817042Sgw25295 /* 1825375Stimh * zfs_check_version 1835375Stimh * 1845375Stimh * Return non-zero if the spa version is less than requested version. 1855375Stimh */ 1865331Samw static int 1875331Samw zfs_check_version(const char *name, int version) 1885331Samw { 1895331Samw 1905331Samw spa_t *spa; 1915331Samw 1925331Samw if (spa_open(name, &spa, FTAG) == 0) { 1935331Samw if (spa_version(spa) < version) { 1945331Samw spa_close(spa, FTAG); 1955331Samw return (1); 1965331Samw } 1975331Samw spa_close(spa, FTAG); 1985331Samw } 1995331Samw return (0); 2005331Samw } 2015331Samw 2025977Smarks /* 2036689Smaybee * zpl_earlier_version 2045977Smarks * 2056689Smaybee * Return TRUE if the ZPL version is less than requested version. 2065977Smarks */ 2076689Smaybee static boolean_t 2086689Smaybee zpl_earlier_version(const char *name, int version) 2095977Smarks { 2105977Smarks objset_t *os; 2116689Smaybee boolean_t rc = B_TRUE; 2125977Smarks 2135977Smarks if (dmu_objset_open(name, DMU_OST_ANY, 2146689Smaybee DS_MODE_USER | DS_MODE_READONLY, &os) == 0) { 2156689Smaybee uint64_t zplversion; 2166689Smaybee 2176689Smaybee if (zfs_get_zplprop(os, ZFS_PROP_VERSION, &zplversion) == 0) 2186689Smaybee rc = zplversion < version; 2195977Smarks dmu_objset_close(os); 2205977Smarks } 2215977Smarks return (rc); 2225977Smarks } 2235977Smarks 2244715Sek110237 static void 2254543Smarks zfs_log_history(zfs_cmd_t *zc) 2264543Smarks { 2274543Smarks spa_t *spa; 2284603Sahrens char *buf; 2294543Smarks 2304715Sek110237 if ((buf = history_str_get(zc)) == NULL) 2314577Sahrens return; 2324577Sahrens 2334715Sek110237 if (spa_open(zc->zc_name, &spa, FTAG) == 0) { 2344715Sek110237 if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY) 2354715Sek110237 (void) spa_history_log(spa, buf, LOG_CMD_NORMAL); 2364715Sek110237 spa_close(spa, FTAG); 2374543Smarks } 2384715Sek110237 history_str_free(buf); 2394543Smarks } 2404543Smarks 241789Sahrens /* 242789Sahrens * Policy for top-level read operations (list pools). Requires no privileges, 243789Sahrens * and can be used in the local zone, as there is no associated dataset. 244789Sahrens */ 245789Sahrens /* ARGSUSED */ 246789Sahrens static int 2474543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) 248789Sahrens { 249789Sahrens return (0); 250789Sahrens } 251789Sahrens 252789Sahrens /* 253789Sahrens * Policy for dataset read operations (list children, get statistics). Requires 254789Sahrens * no privileges, but must be visible in the local zone. 255789Sahrens */ 256789Sahrens /* ARGSUSED */ 257789Sahrens static int 2584543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) 259789Sahrens { 260789Sahrens if (INGLOBALZONE(curproc) || 2614543Smarks zone_dataset_visible(zc->zc_name, NULL)) 262789Sahrens return (0); 263789Sahrens 264789Sahrens return (ENOENT); 265789Sahrens } 266789Sahrens 267789Sahrens static int 268789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr) 269789Sahrens { 270789Sahrens uint64_t zoned; 271789Sahrens int writable = 1; 272789Sahrens 273789Sahrens /* 274789Sahrens * The dataset must be visible by this zone -- check this first 275789Sahrens * so they don't see EPERM on something they shouldn't know about. 276789Sahrens */ 277789Sahrens if (!INGLOBALZONE(curproc) && 278789Sahrens !zone_dataset_visible(dataset, &writable)) 279789Sahrens return (ENOENT); 280789Sahrens 281789Sahrens if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) 282789Sahrens return (ENOENT); 283789Sahrens 284789Sahrens if (INGLOBALZONE(curproc)) { 285789Sahrens /* 286789Sahrens * If the fs is zoned, only root can access it from the 287789Sahrens * global zone. 288789Sahrens */ 289789Sahrens if (secpolicy_zfs(cr) && zoned) 290789Sahrens return (EPERM); 291789Sahrens } else { 292789Sahrens /* 293789Sahrens * If we are in a local zone, the 'zoned' property must be set. 294789Sahrens */ 295789Sahrens if (!zoned) 296789Sahrens return (EPERM); 297789Sahrens 298789Sahrens /* must be writable by this zone */ 299789Sahrens if (!writable) 300789Sahrens return (EPERM); 301789Sahrens } 302789Sahrens return (0); 303789Sahrens } 304789Sahrens 305789Sahrens int 3064543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) 307789Sahrens { 308789Sahrens int error; 309789Sahrens 3104543Smarks error = zfs_dozonecheck(name, cr); 3114543Smarks if (error == 0) { 3124543Smarks error = secpolicy_zfs(cr); 3134670Sahrens if (error) 3144543Smarks error = dsl_deleg_access(name, perm, cr); 3154543Smarks } 3164543Smarks return (error); 3174543Smarks } 3184543Smarks 3194543Smarks static int 3204543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) 3214543Smarks { 3224543Smarks /* 3234543Smarks * Check permissions for special properties. 3244543Smarks */ 3254543Smarks switch (prop) { 3264543Smarks case ZFS_PROP_ZONED: 3274543Smarks /* 3284543Smarks * Disallow setting of 'zoned' from within a local zone. 3294543Smarks */ 3304543Smarks if (!INGLOBALZONE(curproc)) 3314543Smarks return (EPERM); 3324543Smarks break; 333789Sahrens 3344543Smarks case ZFS_PROP_QUOTA: 3354543Smarks if (!INGLOBALZONE(curproc)) { 3364543Smarks uint64_t zoned; 3374543Smarks char setpoint[MAXNAMELEN]; 3384543Smarks /* 3394543Smarks * Unprivileged users are allowed to modify the 3404543Smarks * quota on things *under* (ie. contained by) 3414543Smarks * the thing they own. 3424543Smarks */ 3434543Smarks if (dsl_prop_get_integer(name, "zoned", &zoned, 3444543Smarks setpoint)) 3454543Smarks return (EPERM); 3464670Sahrens if (!zoned || strlen(name) <= strlen(setpoint)) 3474543Smarks return (EPERM); 3484543Smarks } 3494670Sahrens break; 3504543Smarks } 3514543Smarks 3524787Sahrens return (zfs_secpolicy_write_perms(name, zfs_prop_to_name(prop), cr)); 353789Sahrens } 354789Sahrens 3554543Smarks int 3564543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) 3574543Smarks { 3584543Smarks int error; 3594543Smarks 3604543Smarks error = zfs_dozonecheck(zc->zc_name, cr); 3614543Smarks if (error) 3624543Smarks return (error); 3634543Smarks 3644543Smarks /* 3654543Smarks * permission to set permissions will be evaluated later in 3664543Smarks * dsl_deleg_can_allow() 3674543Smarks */ 3684543Smarks return (0); 3694543Smarks } 3704543Smarks 3714543Smarks int 3724543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) 3734543Smarks { 3744543Smarks int error; 3754543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3764543Smarks ZFS_DELEG_PERM_ROLLBACK, cr); 3774543Smarks if (error == 0) 3784543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3794543Smarks ZFS_DELEG_PERM_MOUNT, cr); 3804543Smarks return (error); 3814543Smarks } 3824543Smarks 3834543Smarks int 3844543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) 3854543Smarks { 3864543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 3874543Smarks ZFS_DELEG_PERM_SEND, cr)); 3884543Smarks } 3894543Smarks 3904543Smarks int 3914543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) 3924543Smarks { 3934543Smarks if (!INGLOBALZONE(curproc)) 3944543Smarks return (EPERM); 3954543Smarks 3965367Sahrens if (secpolicy_nfs(cr) == 0) { 3974543Smarks return (0); 3984543Smarks } else { 3994543Smarks vnode_t *vp; 4004543Smarks int error; 4014543Smarks 4024543Smarks if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, 4034543Smarks NO_FOLLOW, NULL, &vp)) != 0) 4044543Smarks return (error); 4054543Smarks 4064543Smarks /* Now make sure mntpnt and dataset are ZFS */ 4074543Smarks 4084543Smarks if (vp->v_vfsp->vfs_fstype != zfsfstype || 4094543Smarks (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), 4104543Smarks zc->zc_name) != 0)) { 4114543Smarks VN_RELE(vp); 4124543Smarks return (EPERM); 4134543Smarks } 4144543Smarks 4154543Smarks VN_RELE(vp); 4164543Smarks return (dsl_deleg_access(zc->zc_name, 4174543Smarks ZFS_DELEG_PERM_SHARE, cr)); 4184543Smarks } 4194543Smarks } 4204543Smarks 421789Sahrens static int 4224543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize) 423789Sahrens { 424789Sahrens char *cp; 425789Sahrens 426789Sahrens /* 427789Sahrens * Remove the @bla or /bla from the end of the name to get the parent. 428789Sahrens */ 4294543Smarks (void) strncpy(parent, datasetname, parentsize); 4304543Smarks cp = strrchr(parent, '@'); 431789Sahrens if (cp != NULL) { 432789Sahrens cp[0] = '\0'; 433789Sahrens } else { 4344543Smarks cp = strrchr(parent, '/'); 435789Sahrens if (cp == NULL) 436789Sahrens return (ENOENT); 437789Sahrens cp[0] = '\0'; 438789Sahrens } 439789Sahrens 4404543Smarks return (0); 4414543Smarks } 4424543Smarks 4434543Smarks int 4444543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 4454543Smarks { 4464543Smarks int error; 4474543Smarks 4484543Smarks if ((error = zfs_secpolicy_write_perms(name, 4494543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4504543Smarks return (error); 4514543Smarks 4524543Smarks return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); 4534543Smarks } 4544543Smarks 4554543Smarks static int 4564543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) 4574543Smarks { 4584543Smarks return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); 4594543Smarks } 4604543Smarks 4614543Smarks /* 4624543Smarks * Must have sys_config privilege to check the iscsi permission 4634543Smarks */ 4644543Smarks /* ARGSUSED */ 4654543Smarks static int 4664543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) 4674543Smarks { 4684543Smarks return (secpolicy_zfs(cr)); 4694543Smarks } 4704543Smarks 4714543Smarks int 4724543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 4734543Smarks { 4744543Smarks char parentname[MAXNAMELEN]; 4754543Smarks int error; 4764543Smarks 4774543Smarks if ((error = zfs_secpolicy_write_perms(from, 4784543Smarks ZFS_DELEG_PERM_RENAME, cr)) != 0) 4794543Smarks return (error); 4804543Smarks 4814543Smarks if ((error = zfs_secpolicy_write_perms(from, 4824543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4834543Smarks return (error); 4844543Smarks 4854543Smarks if ((error = zfs_get_parent(to, parentname, 4864543Smarks sizeof (parentname))) != 0) 4874543Smarks return (error); 4884543Smarks 4894543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4904543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 4914543Smarks return (error); 4924543Smarks 4934543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4944543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4954543Smarks return (error); 4964543Smarks 4974543Smarks return (error); 4984543Smarks } 4994543Smarks 5004543Smarks static int 5014543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) 5024543Smarks { 5034543Smarks return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); 5044543Smarks } 5054543Smarks 5064543Smarks static int 5074543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) 5084543Smarks { 5094543Smarks char parentname[MAXNAMELEN]; 5104543Smarks objset_t *clone; 5114543Smarks int error; 5124543Smarks 5134543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 5144543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 5154543Smarks if (error) 5164543Smarks return (error); 5174543Smarks 5184543Smarks error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 5196689Smaybee DS_MODE_USER | DS_MODE_READONLY, &clone); 5204543Smarks 5214543Smarks if (error == 0) { 5224543Smarks dsl_dataset_t *pclone = NULL; 5234543Smarks dsl_dir_t *dd; 5244543Smarks dd = clone->os->os_dsl_dataset->ds_dir; 5254543Smarks 5264543Smarks rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 5276689Smaybee error = dsl_dataset_hold_obj(dd->dd_pool, 5286689Smaybee dd->dd_phys->dd_origin_obj, FTAG, &pclone); 5294543Smarks rw_exit(&dd->dd_pool->dp_config_rwlock); 5304543Smarks if (error) { 5314543Smarks dmu_objset_close(clone); 5324543Smarks return (error); 5334543Smarks } 5344543Smarks 5354543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 5364543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5374543Smarks 5384543Smarks dsl_dataset_name(pclone, parentname); 5394543Smarks dmu_objset_close(clone); 5406689Smaybee dsl_dataset_rele(pclone, FTAG); 5414543Smarks if (error == 0) 5424543Smarks error = zfs_secpolicy_write_perms(parentname, 5434543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 5444543Smarks } 5454543Smarks return (error); 5464543Smarks } 5474543Smarks 5484543Smarks static int 5494543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) 5504543Smarks { 5514543Smarks int error; 5524543Smarks 5534543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5544543Smarks ZFS_DELEG_PERM_RECEIVE, cr)) != 0) 5554543Smarks return (error); 5564543Smarks 5574543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5584543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 5594543Smarks return (error); 5604543Smarks 5614543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 5624543Smarks ZFS_DELEG_PERM_CREATE, cr)); 5634543Smarks } 5644543Smarks 5654543Smarks int 5664543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 5674543Smarks { 5684543Smarks int error; 5694543Smarks 5704543Smarks if ((error = zfs_secpolicy_write_perms(name, 5714543Smarks ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) 5724543Smarks return (error); 5734543Smarks 5744543Smarks error = zfs_secpolicy_write_perms(name, 5754543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5764543Smarks 5774543Smarks return (error); 5784543Smarks } 5794543Smarks 5804543Smarks static int 5814543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) 5824543Smarks { 5834543Smarks 5844543Smarks return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); 5854543Smarks } 5864543Smarks 5874543Smarks static int 5884543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) 5894543Smarks { 5904543Smarks char parentname[MAXNAMELEN]; 5914543Smarks int error; 5924543Smarks 5934543Smarks if ((error = zfs_get_parent(zc->zc_name, parentname, 5944543Smarks sizeof (parentname))) != 0) 5954543Smarks return (error); 5964543Smarks 5974543Smarks if (zc->zc_value[0] != '\0') { 5984543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_value, 5994543Smarks ZFS_DELEG_PERM_CLONE, cr)) != 0) 6004543Smarks return (error); 6014543Smarks } 6024543Smarks 6034543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 6044543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 6054543Smarks return (error); 6064543Smarks 6074543Smarks error = zfs_secpolicy_write_perms(parentname, 6084543Smarks ZFS_DELEG_PERM_MOUNT, cr); 6094543Smarks 6104543Smarks return (error); 6114543Smarks } 6124543Smarks 6134543Smarks static int 6144543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) 6154543Smarks { 6164543Smarks int error; 6174543Smarks 6184543Smarks error = secpolicy_fs_unmount(cr, NULL); 6194543Smarks if (error) { 6204543Smarks error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); 6214543Smarks } 6224543Smarks return (error); 623789Sahrens } 624789Sahrens 625789Sahrens /* 626789Sahrens * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires 627789Sahrens * SYS_CONFIG privilege, which is not available in a local zone. 628789Sahrens */ 629789Sahrens /* ARGSUSED */ 630789Sahrens static int 6314543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) 632789Sahrens { 633789Sahrens if (secpolicy_sys_config(cr, B_FALSE) != 0) 634789Sahrens return (EPERM); 635789Sahrens 636789Sahrens return (0); 637789Sahrens } 638789Sahrens 639789Sahrens /* 6404543Smarks * Just like zfs_secpolicy_config, except that we will check for 6414543Smarks * mount permission on the dataset for permission to create/remove 6424543Smarks * the minor nodes. 6434543Smarks */ 6444543Smarks static int 6454543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) 6464543Smarks { 6474543Smarks if (secpolicy_sys_config(cr, B_FALSE) != 0) { 6484543Smarks return (dsl_deleg_access(zc->zc_name, 6494543Smarks ZFS_DELEG_PERM_MOUNT, cr)); 6504543Smarks } 6514543Smarks 6524543Smarks return (0); 6534543Smarks } 6544543Smarks 6554543Smarks /* 6561544Seschrock * Policy for fault injection. Requires all privileges. 6571544Seschrock */ 6581544Seschrock /* ARGSUSED */ 6591544Seschrock static int 6604543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) 6611544Seschrock { 6621544Seschrock return (secpolicy_zinject(cr)); 6631544Seschrock } 6641544Seschrock 6654849Sahrens static int 6664849Sahrens zfs_secpolicy_inherit(zfs_cmd_t *zc, cred_t *cr) 6674849Sahrens { 6684849Sahrens zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); 6694849Sahrens 6705094Slling if (prop == ZPROP_INVAL) { 6714849Sahrens if (!zfs_prop_user(zc->zc_value)) 6724849Sahrens return (EINVAL); 6734849Sahrens return (zfs_secpolicy_write_perms(zc->zc_name, 6744849Sahrens ZFS_DELEG_PERM_USERPROP, cr)); 6754849Sahrens } else { 6764849Sahrens if (!zfs_prop_inheritable(prop)) 6774849Sahrens return (EINVAL); 6784849Sahrens return (zfs_secpolicy_setprop(zc->zc_name, prop, cr)); 6794849Sahrens } 6804849Sahrens } 6814849Sahrens 6821544Seschrock /* 683789Sahrens * Returns the nvlist as specified by the user in the zfs_cmd_t. 684789Sahrens */ 685789Sahrens static int 6865094Slling get_nvlist(uint64_t nvl, uint64_t size, nvlist_t **nvp) 687789Sahrens { 688789Sahrens char *packed; 689789Sahrens int error; 6905094Slling nvlist_t *list = NULL; 691789Sahrens 692789Sahrens /* 6932676Seschrock * Read in and unpack the user-supplied nvlist. 694789Sahrens */ 6955094Slling if (size == 0) 696789Sahrens return (EINVAL); 697789Sahrens 698789Sahrens packed = kmem_alloc(size, KM_SLEEP); 699789Sahrens 7005094Slling if ((error = xcopyin((void *)(uintptr_t)nvl, packed, size)) != 0) { 701789Sahrens kmem_free(packed, size); 702789Sahrens return (error); 703789Sahrens } 704789Sahrens 7055094Slling if ((error = nvlist_unpack(packed, size, &list, 0)) != 0) { 706789Sahrens kmem_free(packed, size); 707789Sahrens return (error); 708789Sahrens } 709789Sahrens 710789Sahrens kmem_free(packed, size); 711789Sahrens 7125094Slling *nvp = list; 713789Sahrens return (0); 714789Sahrens } 715789Sahrens 716789Sahrens static int 7172676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 7182676Seschrock { 7192676Seschrock char *packed = NULL; 7202676Seschrock size_t size; 7212676Seschrock int error; 7222676Seschrock 7232676Seschrock VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 7242676Seschrock 7252676Seschrock if (size > zc->zc_nvlist_dst_size) { 7262676Seschrock error = ENOMEM; 7272676Seschrock } else { 7284611Smarks packed = kmem_alloc(size, KM_SLEEP); 7292676Seschrock VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 7302676Seschrock KM_SLEEP) == 0); 7312676Seschrock error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 7322676Seschrock size); 7332676Seschrock kmem_free(packed, size); 7342676Seschrock } 7352676Seschrock 7362676Seschrock zc->zc_nvlist_dst_size = size; 7372676Seschrock return (error); 7382676Seschrock } 7392676Seschrock 7402676Seschrock static int 741789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc) 742789Sahrens { 743789Sahrens int error; 7445094Slling nvlist_t *config, *props = NULL; 7454715Sek110237 char *buf; 746789Sahrens 7475094Slling if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7485094Slling &config)) 7494988Sek110237 return (error); 7504715Sek110237 7515094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7525094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7535094Slling nvlist_free(config); 7545094Slling return (error); 7555094Slling } 7565094Slling 7574988Sek110237 buf = history_str_get(zc); 758789Sahrens 7595094Slling error = spa_create(zc->zc_name, config, props, buf); 760789Sahrens 7614988Sek110237 if (buf != NULL) 7624988Sek110237 history_str_free(buf); 7635094Slling 764789Sahrens nvlist_free(config); 765789Sahrens 7665094Slling if (props) 7675094Slling nvlist_free(props); 7685094Slling 769789Sahrens return (error); 770789Sahrens } 771789Sahrens 772789Sahrens static int 773789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc) 774789Sahrens { 7754543Smarks int error; 7764543Smarks zfs_log_history(zc); 7774543Smarks error = spa_destroy(zc->zc_name); 7784543Smarks return (error); 779789Sahrens } 780789Sahrens 781789Sahrens static int 782789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc) 783789Sahrens { 784789Sahrens int error; 7855094Slling nvlist_t *config, *props = NULL; 786789Sahrens uint64_t guid; 787789Sahrens 7885094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7895094Slling &config)) != 0) 790789Sahrens return (error); 791789Sahrens 7925094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7935094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7945094Slling nvlist_free(config); 7955094Slling return (error); 7965094Slling } 7975094Slling 798789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 7991544Seschrock guid != zc->zc_guid) 800789Sahrens error = EINVAL; 8016643Seschrock else if (zc->zc_cookie) 8026643Seschrock error = spa_import_faulted(zc->zc_name, config, 8036643Seschrock props); 804789Sahrens else 8055094Slling error = spa_import(zc->zc_name, config, props); 806789Sahrens 807789Sahrens nvlist_free(config); 808789Sahrens 8095094Slling if (props) 8105094Slling nvlist_free(props); 8115094Slling 812789Sahrens return (error); 813789Sahrens } 814789Sahrens 815789Sahrens static int 816789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc) 817789Sahrens { 8184543Smarks int error; 8194543Smarks zfs_log_history(zc); 8204543Smarks error = spa_export(zc->zc_name, NULL); 8214543Smarks return (error); 822789Sahrens } 823789Sahrens 824789Sahrens static int 825789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc) 826789Sahrens { 827789Sahrens nvlist_t *configs; 828789Sahrens int error; 829789Sahrens 830789Sahrens if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 831789Sahrens return (EEXIST); 832789Sahrens 8332676Seschrock error = put_nvlist(zc, configs); 834789Sahrens 835789Sahrens nvlist_free(configs); 836789Sahrens 837789Sahrens return (error); 838789Sahrens } 839789Sahrens 840789Sahrens static int 841789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc) 842789Sahrens { 843789Sahrens nvlist_t *config; 844789Sahrens int error; 8451544Seschrock int ret = 0; 846789Sahrens 8472676Seschrock error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 8482676Seschrock sizeof (zc->zc_value)); 849789Sahrens 850789Sahrens if (config != NULL) { 8512676Seschrock ret = put_nvlist(zc, config); 852789Sahrens nvlist_free(config); 8531544Seschrock 8541544Seschrock /* 8551544Seschrock * The config may be present even if 'error' is non-zero. 8561544Seschrock * In this case we return success, and preserve the real errno 8571544Seschrock * in 'zc_cookie'. 8581544Seschrock */ 8591544Seschrock zc->zc_cookie = error; 860789Sahrens } else { 8611544Seschrock ret = error; 862789Sahrens } 863789Sahrens 8641544Seschrock return (ret); 865789Sahrens } 866789Sahrens 867789Sahrens /* 868789Sahrens * Try to import the given pool, returning pool stats as appropriate so that 869789Sahrens * user land knows which devices are available and overall pool health. 870789Sahrens */ 871789Sahrens static int 872789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 873789Sahrens { 874789Sahrens nvlist_t *tryconfig, *config; 875789Sahrens int error; 876789Sahrens 8775094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 8785094Slling &tryconfig)) != 0) 879789Sahrens return (error); 880789Sahrens 881789Sahrens config = spa_tryimport(tryconfig); 882789Sahrens 883789Sahrens nvlist_free(tryconfig); 884789Sahrens 885789Sahrens if (config == NULL) 886789Sahrens return (EINVAL); 887789Sahrens 8882676Seschrock error = put_nvlist(zc, config); 889789Sahrens nvlist_free(config); 890789Sahrens 891789Sahrens return (error); 892789Sahrens } 893789Sahrens 894789Sahrens static int 895789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc) 896789Sahrens { 897789Sahrens spa_t *spa; 898789Sahrens int error; 899789Sahrens 9002926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9012926Sek110237 return (error); 9022926Sek110237 903*7046Sahrens error = spa_scrub(spa, zc->zc_cookie); 9042926Sek110237 9052926Sek110237 spa_close(spa, FTAG); 9062926Sek110237 907789Sahrens return (error); 908789Sahrens } 909789Sahrens 910789Sahrens static int 911789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 912789Sahrens { 913789Sahrens spa_t *spa; 914789Sahrens int error; 915789Sahrens 916789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 917789Sahrens if (error == 0) { 918789Sahrens spa_freeze(spa); 919789Sahrens spa_close(spa, FTAG); 920789Sahrens } 921789Sahrens return (error); 922789Sahrens } 923789Sahrens 924789Sahrens static int 9251760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 9261760Seschrock { 9271760Seschrock spa_t *spa; 9281760Seschrock int error; 9291760Seschrock 9302926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9312926Sek110237 return (error); 9322926Sek110237 9335118Slling if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) { 9345118Slling spa_close(spa, FTAG); 9355118Slling return (EINVAL); 9365118Slling } 9375118Slling 9385094Slling spa_upgrade(spa, zc->zc_cookie); 9392926Sek110237 spa_close(spa, FTAG); 9402926Sek110237 9412926Sek110237 return (error); 9422926Sek110237 } 9432926Sek110237 9442926Sek110237 static int 9452926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 9462926Sek110237 { 9472926Sek110237 spa_t *spa; 9482926Sek110237 char *hist_buf; 9492926Sek110237 uint64_t size; 9502926Sek110237 int error; 9512926Sek110237 9522926Sek110237 if ((size = zc->zc_history_len) == 0) 9532926Sek110237 return (EINVAL); 9542926Sek110237 9552926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9562926Sek110237 return (error); 9572926Sek110237 9584577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 9593863Sek110237 spa_close(spa, FTAG); 9603863Sek110237 return (ENOTSUP); 9613863Sek110237 } 9623863Sek110237 9632926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 9642926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 9652926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 9664543Smarks error = xcopyout(hist_buf, 9674543Smarks (char *)(uintptr_t)zc->zc_history, 9682926Sek110237 zc->zc_history_len); 9692926Sek110237 } 9702926Sek110237 9712926Sek110237 spa_close(spa, FTAG); 9722926Sek110237 kmem_free(hist_buf, size); 9732926Sek110237 return (error); 9742926Sek110237 } 9752926Sek110237 9762926Sek110237 static int 9773444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 9783444Sek110237 { 9793444Sek110237 int error; 9803444Sek110237 9813912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 9823444Sek110237 return (error); 9833444Sek110237 9843444Sek110237 return (0); 9853444Sek110237 } 9863444Sek110237 9873444Sek110237 static int 9883444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 9893444Sek110237 { 9903444Sek110237 objset_t *osp; 9913444Sek110237 int error; 9923444Sek110237 9933444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 9946689Smaybee DS_MODE_USER | DS_MODE_READONLY, &osp)) != 0) 9953444Sek110237 return (error); 9963444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 9973444Sek110237 sizeof (zc->zc_value)); 9983444Sek110237 dmu_objset_close(osp); 9993444Sek110237 10003444Sek110237 return (error); 10013444Sek110237 } 10023444Sek110237 10033444Sek110237 static int 1004789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 1005789Sahrens { 1006789Sahrens spa_t *spa; 1007789Sahrens int error; 10086423Sgw25295 nvlist_t *config, **l2cache, **spares; 10096423Sgw25295 uint_t nl2cache = 0, nspares = 0; 1010789Sahrens 1011789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 1012789Sahrens if (error != 0) 1013789Sahrens return (error); 1014789Sahrens 10155450Sbrendan error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 10165450Sbrendan &config); 10175450Sbrendan (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_L2CACHE, 10185450Sbrendan &l2cache, &nl2cache); 10195450Sbrendan 10206423Sgw25295 (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_SPARES, 10216423Sgw25295 &spares, &nspares); 10226423Sgw25295 10233912Slling /* 10243912Slling * A root pool with concatenated devices is not supported. 10256423Sgw25295 * Thus, can not add a device to a root pool. 10266423Sgw25295 * 10276423Sgw25295 * Intent log device can not be added to a rootpool because 10286423Sgw25295 * during mountroot, zil is replayed, a seperated log device 10296423Sgw25295 * can not be accessed during the mountroot time. 10306423Sgw25295 * 10316423Sgw25295 * l2cache and spare devices are ok to be added to a rootpool. 10323912Slling */ 10336423Sgw25295 if (spa->spa_bootfs != 0 && nl2cache == 0 && nspares == 0) { 10343912Slling spa_close(spa, FTAG); 10353912Slling return (EDOM); 10363912Slling } 10373912Slling 10385450Sbrendan if (error == 0) { 1039789Sahrens error = spa_vdev_add(spa, config); 1040789Sahrens nvlist_free(config); 1041789Sahrens } 1042789Sahrens spa_close(spa, FTAG); 1043789Sahrens return (error); 1044789Sahrens } 1045789Sahrens 1046789Sahrens static int 1047789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 1048789Sahrens { 10492082Seschrock spa_t *spa; 10502082Seschrock int error; 10512082Seschrock 10522082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10532082Seschrock if (error != 0) 10542082Seschrock return (error); 10552082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 10562082Seschrock spa_close(spa, FTAG); 10572082Seschrock return (error); 1058789Sahrens } 1059789Sahrens 1060789Sahrens static int 10614451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 1062789Sahrens { 1063789Sahrens spa_t *spa; 1064789Sahrens int error; 10654451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 1066789Sahrens 10672926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1068789Sahrens return (error); 10694451Seschrock switch (zc->zc_cookie) { 10704451Seschrock case VDEV_STATE_ONLINE: 10714451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 10724451Seschrock break; 10734451Seschrock 10744451Seschrock case VDEV_STATE_OFFLINE: 10754451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 10764451Seschrock break; 1077789Sahrens 10784451Seschrock case VDEV_STATE_FAULTED: 10794451Seschrock error = vdev_fault(spa, zc->zc_guid); 10804451Seschrock break; 1081789Sahrens 10824451Seschrock case VDEV_STATE_DEGRADED: 10834451Seschrock error = vdev_degrade(spa, zc->zc_guid); 10844451Seschrock break; 10854451Seschrock 10864451Seschrock default: 10874451Seschrock error = EINVAL; 10884451Seschrock } 10894451Seschrock zc->zc_cookie = newstate; 1090789Sahrens spa_close(spa, FTAG); 1091789Sahrens return (error); 1092789Sahrens } 1093789Sahrens 1094789Sahrens static int 1095789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 1096789Sahrens { 1097789Sahrens spa_t *spa; 1098789Sahrens int replacing = zc->zc_cookie; 1099789Sahrens nvlist_t *config; 1100789Sahrens int error; 1101789Sahrens 11022926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1103789Sahrens return (error); 1104789Sahrens 11055094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 11065094Slling &config)) == 0) { 11071544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 1108789Sahrens nvlist_free(config); 1109789Sahrens } 1110789Sahrens 1111789Sahrens spa_close(spa, FTAG); 1112789Sahrens return (error); 1113789Sahrens } 1114789Sahrens 1115789Sahrens static int 1116789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 1117789Sahrens { 1118789Sahrens spa_t *spa; 1119789Sahrens int error; 1120789Sahrens 11212926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1122789Sahrens return (error); 1123789Sahrens 11241544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1125789Sahrens 1126789Sahrens spa_close(spa, FTAG); 1127789Sahrens return (error); 1128789Sahrens } 1129789Sahrens 1130789Sahrens static int 11311354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 11321354Seschrock { 11331354Seschrock spa_t *spa; 11342676Seschrock char *path = zc->zc_value; 11351544Seschrock uint64_t guid = zc->zc_guid; 11361354Seschrock int error; 11371354Seschrock 11381354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 11391354Seschrock if (error != 0) 11401354Seschrock return (error); 11411354Seschrock 11421354Seschrock error = spa_vdev_setpath(spa, guid, path); 11431354Seschrock spa_close(spa, FTAG); 11441354Seschrock return (error); 11451354Seschrock } 11461354Seschrock 11475367Sahrens /* 11485367Sahrens * inputs: 11495367Sahrens * zc_name name of filesystem 11505367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 11515367Sahrens * 11525367Sahrens * outputs: 11535367Sahrens * zc_objset_stats stats 11545367Sahrens * zc_nvlist_dst property nvlist 11555367Sahrens * zc_nvlist_dst_size size of property nvlist 11565367Sahrens */ 11571354Seschrock static int 1158789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1159789Sahrens { 1160789Sahrens objset_t *os = NULL; 1161789Sahrens int error; 11621356Seschrock nvlist_t *nv; 1163789Sahrens 11646689Smaybee if (error = dmu_objset_open(zc->zc_name, 11656689Smaybee DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os)) 1166789Sahrens return (error); 1167789Sahrens 11682885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1169789Sahrens 11702856Snd150628 if (zc->zc_nvlist_dst != 0 && 11716689Smaybee (error = dsl_prop_get_all(os, &nv, FALSE)) == 0) { 11722885Sahrens dmu_objset_stats(os, nv); 11733087Sahrens /* 11745147Srm160521 * NB: zvol_get_stats() will read the objset contents, 11753087Sahrens * which we aren't supposed to do with a 11766689Smaybee * DS_MODE_USER hold, because it could be 11773087Sahrens * inconsistent. So this is a bit of a workaround... 11783087Sahrens */ 11794577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 11804577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 11814577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 11824577Sahrens } 11832676Seschrock error = put_nvlist(zc, nv); 11841356Seschrock nvlist_free(nv); 11851356Seschrock } 1186789Sahrens 1187789Sahrens dmu_objset_close(os); 1188789Sahrens return (error); 1189789Sahrens } 1190789Sahrens 11915498Stimh static int 11925498Stimh nvl_add_zplprop(objset_t *os, nvlist_t *props, zfs_prop_t prop) 11935498Stimh { 11945498Stimh uint64_t value; 11955498Stimh int error; 11965498Stimh 11975498Stimh /* 11985498Stimh * zfs_get_zplprop() will either find a value or give us 11995498Stimh * the default value (if there is one). 12005498Stimh */ 12015498Stimh if ((error = zfs_get_zplprop(os, prop, &value)) != 0) 12025498Stimh return (error); 12035498Stimh VERIFY(nvlist_add_uint64(props, zfs_prop_to_name(prop), value) == 0); 12045498Stimh return (0); 12055498Stimh } 12065498Stimh 12075498Stimh /* 12085498Stimh * inputs: 12095498Stimh * zc_name name of filesystem 12105498Stimh * zc_nvlist_dst_size size of buffer for zpl property nvlist 12115498Stimh * 12125498Stimh * outputs: 12135498Stimh * zc_nvlist_dst zpl property nvlist 12145498Stimh * zc_nvlist_dst_size size of zpl property nvlist 12155498Stimh */ 12165498Stimh static int 12175498Stimh zfs_ioc_objset_zplprops(zfs_cmd_t *zc) 12185498Stimh { 12195498Stimh objset_t *os; 12205498Stimh int err; 12215498Stimh 12226689Smaybee if (err = dmu_objset_open(zc->zc_name, 12236689Smaybee DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os)) 12245498Stimh return (err); 12255498Stimh 12265498Stimh dmu_objset_fast_stat(os, &zc->zc_objset_stats); 12275498Stimh 12285498Stimh /* 12295498Stimh * NB: nvl_add_zplprop() will read the objset contents, 12306689Smaybee * which we aren't supposed to do with a DS_MODE_USER 12316689Smaybee * hold, because it could be inconsistent. 12325498Stimh */ 12335498Stimh if (zc->zc_nvlist_dst != NULL && 12345498Stimh !zc->zc_objset_stats.dds_inconsistent && 12355498Stimh dmu_objset_type(os) == DMU_OST_ZFS) { 12365498Stimh nvlist_t *nv; 12375498Stimh 12385498Stimh VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) == 0); 12395498Stimh if ((err = nvl_add_zplprop(os, nv, ZFS_PROP_VERSION)) == 0 && 12405498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_NORMALIZE)) == 0 && 12415498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_UTF8ONLY)) == 0 && 12425498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_CASE)) == 0) 12435498Stimh err = put_nvlist(zc, nv); 12445498Stimh nvlist_free(nv); 12455498Stimh } else { 12465498Stimh err = ENOENT; 12475498Stimh } 12485498Stimh dmu_objset_close(os); 12495498Stimh return (err); 12505498Stimh } 12515498Stimh 12525367Sahrens /* 12535367Sahrens * inputs: 12545367Sahrens * zc_name name of filesystem 12555367Sahrens * zc_cookie zap cursor 12565367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 12575367Sahrens * 12585367Sahrens * outputs: 12595367Sahrens * zc_name name of next filesystem 12605367Sahrens * zc_objset_stats stats 12615367Sahrens * zc_nvlist_dst property nvlist 12625367Sahrens * zc_nvlist_dst_size size of property nvlist 12635367Sahrens */ 1264789Sahrens static int 1265789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1266789Sahrens { 1267885Sahrens objset_t *os; 1268789Sahrens int error; 1269789Sahrens char *p; 1270789Sahrens 12716689Smaybee if (error = dmu_objset_open(zc->zc_name, 12726689Smaybee DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os)) { 1273885Sahrens if (error == ENOENT) 1274885Sahrens error = ESRCH; 1275885Sahrens return (error); 1276789Sahrens } 1277789Sahrens 1278789Sahrens p = strrchr(zc->zc_name, '/'); 1279789Sahrens if (p == NULL || p[1] != '\0') 1280789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1281789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1282789Sahrens 1283789Sahrens do { 1284885Sahrens error = dmu_dir_list_next(os, 1285885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1286885Sahrens NULL, &zc->zc_cookie); 1287789Sahrens if (error == ENOENT) 1288789Sahrens error = ESRCH; 1289885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1290789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 12916689Smaybee dmu_objset_close(os); 1292789Sahrens 1293885Sahrens /* 1294885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1295885Sahrens * try to get stats for it. Userland will skip over it. 1296885Sahrens */ 1297885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1298885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1299789Sahrens 1300789Sahrens return (error); 1301789Sahrens } 1302789Sahrens 13035367Sahrens /* 13045367Sahrens * inputs: 13055367Sahrens * zc_name name of filesystem 13065367Sahrens * zc_cookie zap cursor 13075367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 13085367Sahrens * 13095367Sahrens * outputs: 13105367Sahrens * zc_name name of next snapshot 13115367Sahrens * zc_objset_stats stats 13125367Sahrens * zc_nvlist_dst property nvlist 13135367Sahrens * zc_nvlist_dst_size size of property nvlist 13145367Sahrens */ 1315789Sahrens static int 1316789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1317789Sahrens { 1318885Sahrens objset_t *os; 1319789Sahrens int error; 1320789Sahrens 13216689Smaybee error = dmu_objset_open(zc->zc_name, 13226689Smaybee DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os); 13236689Smaybee if (error) 13246689Smaybee return (error == ENOENT ? ESRCH : error); 1325789Sahrens 13261003Slling /* 13271003Slling * A dataset name of maximum length cannot have any snapshots, 13281003Slling * so exit immediately. 13291003Slling */ 13301003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1331885Sahrens dmu_objset_close(os); 13321003Slling return (ESRCH); 1333789Sahrens } 1334789Sahrens 1335885Sahrens error = dmu_snapshot_list_next(os, 1336885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 13375663Sck153898 zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie, NULL); 13386689Smaybee dmu_objset_close(os); 1339885Sahrens if (error == 0) 1340885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 13416689Smaybee else if (error == ENOENT) 13426689Smaybee error = ESRCH; 1343789Sahrens 13445367Sahrens /* if we failed, undo the @ that we tacked on to zc_name */ 13456689Smaybee if (error) 13465367Sahrens *strchr(zc->zc_name, '@') = '\0'; 1347789Sahrens return (error); 1348789Sahrens } 1349789Sahrens 13506423Sgw25295 int 13514787Sahrens zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) 1352789Sahrens { 13532676Seschrock nvpair_t *elem; 13542676Seschrock int error; 13552676Seschrock uint64_t intval; 13562676Seschrock char *strval; 13572676Seschrock 13584543Smarks /* 13594543Smarks * First validate permission to set all of the properties 13604543Smarks */ 13612676Seschrock elem = NULL; 13622676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 13634670Sahrens const char *propname = nvpair_name(elem); 13644670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 13652676Seschrock 13665094Slling if (prop == ZPROP_INVAL) { 13672676Seschrock /* 13682676Seschrock * If this is a user-defined property, it must be a 13692676Seschrock * string, and there is no further validation to do. 13702676Seschrock */ 13712676Seschrock if (!zfs_prop_user(propname) || 13722676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 13732676Seschrock return (EINVAL); 13742676Seschrock 13755331Samw if (error = zfs_secpolicy_write_perms(name, 13765331Samw ZFS_DELEG_PERM_USERPROP, CRED())) 13774670Sahrens return (error); 13784543Smarks continue; 13792676Seschrock } 13802676Seschrock 13814787Sahrens if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 13824670Sahrens return (error); 13832676Seschrock 13844670Sahrens /* 13854670Sahrens * Check that this value is valid for this pool version 13864670Sahrens */ 13874670Sahrens switch (prop) { 13883886Sahl case ZFS_PROP_COMPRESSION: 13893886Sahl /* 13903886Sahl * If the user specified gzip compression, make sure 13913886Sahl * the SPA supports it. We ignore any errors here since 13923886Sahl * we'll catch them later. 13933886Sahl */ 13943886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 13957042Sgw25295 nvpair_value_uint64(elem, &intval) == 0) { 13967042Sgw25295 if (intval >= ZIO_COMPRESS_GZIP_1 && 13977042Sgw25295 intval <= ZIO_COMPRESS_GZIP_9 && 13987042Sgw25295 zfs_check_version(name, 13995331Samw SPA_VERSION_GZIP_COMPRESSION)) 14005331Samw return (ENOTSUP); 14017042Sgw25295 14027042Sgw25295 /* 14037042Sgw25295 * If this is a bootable dataset then 14047042Sgw25295 * verify that the compression algorithm 14057042Sgw25295 * is supported for booting. We must return 14067042Sgw25295 * something other than ENOTSUP since it 14077042Sgw25295 * implies a downrev pool version. 14087042Sgw25295 */ 14097042Sgw25295 if (zfs_is_bootfs(name) && 14107042Sgw25295 !BOOTFS_COMPRESS_VALID(intval)) 14117042Sgw25295 return (ERANGE); 14123886Sahl } 14133886Sahl break; 14144603Sahrens 14154603Sahrens case ZFS_PROP_COPIES: 14165331Samw if (zfs_check_version(name, SPA_VERSION_DITTO_BLOCKS)) 14175331Samw return (ENOTSUP); 14184603Sahrens break; 14195977Smarks 14205977Smarks case ZFS_PROP_SHARESMB: 14216689Smaybee if (zpl_earlier_version(name, ZPL_VERSION_FUID)) 14225977Smarks return (ENOTSUP); 14235977Smarks break; 14244603Sahrens } 14255331Samw if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 14265331Samw return (error); 14274543Smarks } 14284543Smarks 14294543Smarks elem = NULL; 14304543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 14314670Sahrens const char *propname = nvpair_name(elem); 14324670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 14334543Smarks 14345094Slling if (prop == ZPROP_INVAL) { 14354543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 14364543Smarks error = dsl_prop_set(name, propname, 1, 14374543Smarks strlen(strval) + 1, strval); 14384543Smarks if (error == 0) 14394543Smarks continue; 14404543Smarks else 14414543Smarks return (error); 14424543Smarks } 14432676Seschrock 14442676Seschrock switch (prop) { 14452676Seschrock case ZFS_PROP_QUOTA: 14462676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14474577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 14482676Seschrock return (error); 14492676Seschrock break; 14502676Seschrock 14515378Sck153898 case ZFS_PROP_REFQUOTA: 14525378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14535378Sck153898 (error = dsl_dataset_set_quota(name, intval)) != 0) 14545378Sck153898 return (error); 14555378Sck153898 break; 14565378Sck153898 14572676Seschrock case ZFS_PROP_RESERVATION: 14582676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14592676Seschrock (error = dsl_dir_set_reservation(name, 14602676Seschrock intval)) != 0) 14612676Seschrock return (error); 14622676Seschrock break; 1463789Sahrens 14645378Sck153898 case ZFS_PROP_REFRESERVATION: 14655378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14665378Sck153898 (error = dsl_dataset_set_reservation(name, 14675378Sck153898 intval)) != 0) 14685378Sck153898 return (error); 14695378Sck153898 break; 14705378Sck153898 14712676Seschrock case ZFS_PROP_VOLSIZE: 14722676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14734787Sahrens (error = zvol_set_volsize(name, 14744787Sahrens ddi_driver_major(zfs_dip), intval)) != 0) 14752676Seschrock return (error); 14762676Seschrock break; 14772676Seschrock 14782676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 14792676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14804577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 14814577Sahrens return (error); 14824577Sahrens break; 14834577Sahrens 14844577Sahrens case ZFS_PROP_VERSION: 14854577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14864577Sahrens (error = zfs_set_version(name, intval)) != 0) 14872676Seschrock return (error); 14882676Seschrock break; 14892676Seschrock 14902676Seschrock default: 14912676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 14922676Seschrock if (zfs_prop_get_type(prop) != 14934787Sahrens PROP_TYPE_STRING) 14942676Seschrock return (EINVAL); 14952717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 14962717Seschrock if ((error = dsl_prop_set(name, 14972676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 14982717Seschrock strval)) != 0) 14992717Seschrock return (error); 15002676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 15012885Sahrens const char *unused; 15022885Sahrens 15032717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 15042676Seschrock 15052676Seschrock switch (zfs_prop_get_type(prop)) { 15064787Sahrens case PROP_TYPE_NUMBER: 15072676Seschrock break; 15084787Sahrens case PROP_TYPE_STRING: 15092717Seschrock return (EINVAL); 15104787Sahrens case PROP_TYPE_INDEX: 15112717Seschrock if (zfs_prop_index_to_string(prop, 15122717Seschrock intval, &unused) != 0) 15132717Seschrock return (EINVAL); 15142676Seschrock break; 15152676Seschrock default: 15164577Sahrens cmn_err(CE_PANIC, 15174577Sahrens "unknown property type"); 15182676Seschrock break; 15192676Seschrock } 15202676Seschrock 15212717Seschrock if ((error = dsl_prop_set(name, propname, 15222717Seschrock 8, 1, &intval)) != 0) 15232717Seschrock return (error); 15242676Seschrock } else { 15252676Seschrock return (EINVAL); 15262676Seschrock } 15272676Seschrock break; 15282676Seschrock } 15292676Seschrock } 15302676Seschrock 15312676Seschrock return (0); 1532789Sahrens } 1533789Sahrens 15345367Sahrens /* 15355367Sahrens * inputs: 15365367Sahrens * zc_name name of filesystem 15375367Sahrens * zc_value name of property to inherit 15385367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 15395367Sahrens * 15405367Sahrens * outputs: none 15415367Sahrens */ 1542789Sahrens static int 15432676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1544789Sahrens { 15452676Seschrock nvlist_t *nvl; 15462676Seschrock int error; 1547789Sahrens 15485094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15495094Slling &nvl)) != 0) 15502676Seschrock return (error); 15512676Seschrock 15524787Sahrens error = zfs_set_prop_nvlist(zc->zc_name, nvl); 15534543Smarks 15542676Seschrock nvlist_free(nvl); 15552676Seschrock return (error); 1556789Sahrens } 1557789Sahrens 15585367Sahrens /* 15595367Sahrens * inputs: 15605367Sahrens * zc_name name of filesystem 15615367Sahrens * zc_value name of property to inherit 15625367Sahrens * 15635367Sahrens * outputs: none 15645367Sahrens */ 1565789Sahrens static int 15664849Sahrens zfs_ioc_inherit_prop(zfs_cmd_t *zc) 15674849Sahrens { 15684849Sahrens /* the property name has been validated by zfs_secpolicy_inherit() */ 15694849Sahrens return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 15704849Sahrens } 15714849Sahrens 15724849Sahrens static int 15734098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 15743912Slling { 15755094Slling nvlist_t *props; 15763912Slling spa_t *spa; 15775094Slling int error; 15783912Slling 15795094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15805094Slling &props))) 15813912Slling return (error); 15823912Slling 15833912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 15845094Slling nvlist_free(props); 15853912Slling return (error); 15863912Slling } 15873912Slling 15885094Slling error = spa_prop_set(spa, props); 15893912Slling 15905094Slling nvlist_free(props); 15913912Slling spa_close(spa, FTAG); 15923912Slling 15933912Slling return (error); 15943912Slling } 15953912Slling 15963912Slling static int 15974098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 15983912Slling { 15993912Slling spa_t *spa; 16003912Slling int error; 16013912Slling nvlist_t *nvp = NULL; 16023912Slling 16033912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 16043912Slling return (error); 16053912Slling 16065094Slling error = spa_prop_get(spa, &nvp); 16073912Slling 16083912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 16093912Slling error = put_nvlist(zc, nvp); 16103912Slling else 16113912Slling error = EFAULT; 16123912Slling 16133912Slling spa_close(spa, FTAG); 16143912Slling 16153912Slling if (nvp) 16163912Slling nvlist_free(nvp); 16173912Slling return (error); 16183912Slling } 16193912Slling 16203912Slling static int 16214543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 16224543Smarks { 16234543Smarks nvlist_t *nvp; 16244543Smarks int error; 16254543Smarks uint32_t uid; 16264543Smarks uint32_t gid; 16274543Smarks uint32_t *groups; 16284543Smarks uint_t group_cnt; 16294543Smarks cred_t *usercred; 16304543Smarks 16315094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16325094Slling &nvp)) != 0) { 16334543Smarks return (error); 16344543Smarks } 16354543Smarks 16364543Smarks if ((error = nvlist_lookup_uint32(nvp, 16374543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 16384543Smarks nvlist_free(nvp); 16394543Smarks return (EPERM); 16404543Smarks } 16414543Smarks 16424543Smarks if ((error = nvlist_lookup_uint32(nvp, 16434543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 16444543Smarks nvlist_free(nvp); 16454543Smarks return (EPERM); 16464543Smarks } 16474543Smarks 16484543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 16494543Smarks &groups, &group_cnt)) != 0) { 16504543Smarks nvlist_free(nvp); 16514543Smarks return (EPERM); 16524543Smarks } 16534543Smarks usercred = cralloc(); 16544543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 16554543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 16564543Smarks nvlist_free(nvp); 16574543Smarks crfree(usercred); 16584543Smarks return (EPERM); 16594543Smarks } 16604543Smarks nvlist_free(nvp); 16614543Smarks error = dsl_deleg_access(zc->zc_name, 16624787Sahrens zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); 16634543Smarks crfree(usercred); 16644543Smarks return (error); 16654543Smarks } 16664543Smarks 16675367Sahrens /* 16685367Sahrens * inputs: 16695367Sahrens * zc_name name of filesystem 16705367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 16715367Sahrens * zc_perm_action allow/unallow flag 16725367Sahrens * 16735367Sahrens * outputs: none 16745367Sahrens */ 16754543Smarks static int 16764543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 16774543Smarks { 16784543Smarks int error; 16794543Smarks nvlist_t *fsaclnv = NULL; 16804543Smarks 16815094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16825094Slling &fsaclnv)) != 0) 16834543Smarks return (error); 16844543Smarks 16854543Smarks /* 16864543Smarks * Verify nvlist is constructed correctly 16874543Smarks */ 16884543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 16894543Smarks nvlist_free(fsaclnv); 16904543Smarks return (EINVAL); 16914543Smarks } 16924543Smarks 16934543Smarks /* 16944543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 16954543Smarks * that user is allowed to hand out each permission in 16964543Smarks * the nvlist(s) 16974543Smarks */ 16984543Smarks 16994787Sahrens error = secpolicy_zfs(CRED()); 17004543Smarks if (error) { 17014787Sahrens if (zc->zc_perm_action == B_FALSE) { 17024787Sahrens error = dsl_deleg_can_allow(zc->zc_name, 17034787Sahrens fsaclnv, CRED()); 17044787Sahrens } else { 17054787Sahrens error = dsl_deleg_can_unallow(zc->zc_name, 17064787Sahrens fsaclnv, CRED()); 17074787Sahrens } 17084543Smarks } 17094543Smarks 17104543Smarks if (error == 0) 17114543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 17124543Smarks 17134543Smarks nvlist_free(fsaclnv); 17144543Smarks return (error); 17154543Smarks } 17164543Smarks 17175367Sahrens /* 17185367Sahrens * inputs: 17195367Sahrens * zc_name name of filesystem 17205367Sahrens * 17215367Sahrens * outputs: 17225367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 17235367Sahrens */ 17244543Smarks static int 17254543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 17264543Smarks { 17274543Smarks nvlist_t *nvp; 17284543Smarks int error; 17294543Smarks 17304543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 17314543Smarks error = put_nvlist(zc, nvp); 17324543Smarks nvlist_free(nvp); 17334543Smarks } 17344543Smarks 17354543Smarks return (error); 17364543Smarks } 17374543Smarks 17385367Sahrens /* 17395367Sahrens * inputs: 17405367Sahrens * zc_name name of volume 17415367Sahrens * 17425367Sahrens * outputs: none 17435367Sahrens */ 17444543Smarks static int 1745789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1746789Sahrens { 17474787Sahrens return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); 1748789Sahrens } 1749789Sahrens 17505367Sahrens /* 17515367Sahrens * inputs: 17525367Sahrens * zc_name name of volume 17535367Sahrens * 17545367Sahrens * outputs: none 17555367Sahrens */ 1756789Sahrens static int 1757789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1758789Sahrens { 17592676Seschrock return (zvol_remove_minor(zc->zc_name)); 1760789Sahrens } 1761789Sahrens 1762789Sahrens /* 1763789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1764789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1765789Sahrens * is responsible for releasing the returned vfs pointer. 1766789Sahrens */ 1767789Sahrens static vfs_t * 1768789Sahrens zfs_get_vfs(const char *resource) 1769789Sahrens { 1770789Sahrens struct vfs *vfsp; 1771789Sahrens struct vfs *vfs_found = NULL; 1772789Sahrens 1773789Sahrens vfs_list_read_lock(); 1774789Sahrens vfsp = rootvfs; 1775789Sahrens do { 1776789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1777789Sahrens VFS_HOLD(vfsp); 1778789Sahrens vfs_found = vfsp; 1779789Sahrens break; 1780789Sahrens } 1781789Sahrens vfsp = vfsp->vfs_next; 1782789Sahrens } while (vfsp != rootvfs); 1783789Sahrens vfs_list_unlock(); 1784789Sahrens return (vfs_found); 1785789Sahrens } 1786789Sahrens 17874543Smarks /* ARGSUSED */ 1788789Sahrens static void 17894543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1790789Sahrens { 17915331Samw zfs_creat_t *zct = arg; 17925498Stimh 17935498Stimh zfs_create_fs(os, cr, zct->zct_zplprops, tx); 17945331Samw } 17955331Samw 17965498Stimh #define ZFS_PROP_UNDEFINED ((uint64_t)-1) 17975498Stimh 17985331Samw /* 17995498Stimh * inputs: 18005498Stimh * createprops list of properties requested by creator 18015498Stimh * dataset name of dataset we are creating 18025331Samw * 18035498Stimh * outputs: 18045498Stimh * zplprops values for the zplprops we attach to the master node object 18055331Samw * 18065498Stimh * Determine the settings for utf8only, normalization and 18075498Stimh * casesensitivity. Specific values may have been requested by the 18085498Stimh * creator and/or we can inherit values from the parent dataset. If 18095498Stimh * the file system is of too early a vintage, a creator can not 18105498Stimh * request settings for these properties, even if the requested 18115498Stimh * setting is the default value. We don't actually want to create dsl 18125498Stimh * properties for these, so remove them from the source nvlist after 18135498Stimh * processing. 18145331Samw */ 18155331Samw static int 18165498Stimh zfs_fill_zplprops(const char *dataset, nvlist_t *createprops, 18176492Stimh nvlist_t *zplprops, uint64_t zplver, boolean_t *is_ci) 18185331Samw { 18195498Stimh objset_t *os; 18205331Samw char parentname[MAXNAMELEN]; 18215331Samw char *cp; 18225498Stimh uint64_t sense = ZFS_PROP_UNDEFINED; 18235498Stimh uint64_t norm = ZFS_PROP_UNDEFINED; 18245498Stimh uint64_t u8 = ZFS_PROP_UNDEFINED; 18255498Stimh int error = 0; 18265498Stimh 18275498Stimh ASSERT(zplprops != NULL); 18285498Stimh 18295498Stimh (void) strlcpy(parentname, dataset, sizeof (parentname)); 18305498Stimh cp = strrchr(parentname, '/'); 18315498Stimh ASSERT(cp != NULL); 18325498Stimh cp[0] = '\0'; 18335331Samw 18345375Stimh /* 18355498Stimh * Pull out creator prop choices, if any. 18365375Stimh */ 18375498Stimh if (createprops) { 18385498Stimh (void) nvlist_lookup_uint64(createprops, 18395498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE), &norm); 18405498Stimh (void) nvlist_remove_all(createprops, 18415498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE)); 18425498Stimh (void) nvlist_lookup_uint64(createprops, 18435498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY), &u8); 18445498Stimh (void) nvlist_remove_all(createprops, 18455498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY)); 18465498Stimh (void) nvlist_lookup_uint64(createprops, 18475498Stimh zfs_prop_to_name(ZFS_PROP_CASE), &sense); 18485498Stimh (void) nvlist_remove_all(createprops, 18495498Stimh zfs_prop_to_name(ZFS_PROP_CASE)); 18505331Samw } 18515331Samw 18525375Stimh /* 18535498Stimh * If the file system or pool is version is too "young" to 18545498Stimh * support normalization and the creator tried to set a value 18555498Stimh * for one of the props, error out. We only need check the 18565498Stimh * ZPL version because we've already checked by now that the 18575498Stimh * SPA version is compatible with the selected ZPL version. 18585498Stimh */ 18595498Stimh if (zplver < ZPL_VERSION_NORMALIZATION && 18605498Stimh (norm != ZFS_PROP_UNDEFINED || u8 != ZFS_PROP_UNDEFINED || 18615498Stimh sense != ZFS_PROP_UNDEFINED)) 18625498Stimh return (ENOTSUP); 18635498Stimh 18645498Stimh /* 18655498Stimh * Put the version in the zplprops 18665498Stimh */ 18675498Stimh VERIFY(nvlist_add_uint64(zplprops, 18685498Stimh zfs_prop_to_name(ZFS_PROP_VERSION), zplver) == 0); 18695498Stimh 18705498Stimh /* 18715498Stimh * Open parent object set so we can inherit zplprop values if 18725498Stimh * necessary. 18735375Stimh */ 18746689Smaybee if (error = dmu_objset_open(parentname, 18756689Smaybee DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os)) 18765498Stimh return (error); 18775498Stimh 18785498Stimh if (norm == ZFS_PROP_UNDEFINED) 18795498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &norm) == 0); 18805498Stimh VERIFY(nvlist_add_uint64(zplprops, 18815498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE), norm) == 0); 18825498Stimh 18835498Stimh /* 18845498Stimh * If we're normalizing, names must always be valid UTF-8 strings. 18855498Stimh */ 18865498Stimh if (norm) 18875498Stimh u8 = 1; 18885498Stimh if (u8 == ZFS_PROP_UNDEFINED) 18895498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &u8) == 0); 18905498Stimh VERIFY(nvlist_add_uint64(zplprops, 18915498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY), u8) == 0); 18925498Stimh 18935498Stimh if (sense == ZFS_PROP_UNDEFINED) 18945498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_CASE, &sense) == 0); 18955498Stimh VERIFY(nvlist_add_uint64(zplprops, 18965498Stimh zfs_prop_to_name(ZFS_PROP_CASE), sense) == 0); 18975498Stimh 18986492Stimh if (is_ci) 18996492Stimh *is_ci = (sense == ZFS_CASE_INSENSITIVE); 19006492Stimh 19015498Stimh dmu_objset_close(os); 19025331Samw return (0); 1903789Sahrens } 1904789Sahrens 19055367Sahrens /* 19065367Sahrens * inputs: 19075367Sahrens * zc_objset_type type of objset to create (fs vs zvol) 19085367Sahrens * zc_name name of new objset 19095367Sahrens * zc_value name of snapshot to clone from (may be empty) 19105367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 19115367Sahrens * 19125498Stimh * outputs: none 19135367Sahrens */ 1914789Sahrens static int 1915789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1916789Sahrens { 1917789Sahrens objset_t *clone; 1918789Sahrens int error = 0; 19195331Samw zfs_creat_t zct; 19204543Smarks nvlist_t *nvprops = NULL; 19214543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1922789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1923789Sahrens 1924789Sahrens switch (type) { 1925789Sahrens 1926789Sahrens case DMU_OST_ZFS: 1927789Sahrens cbfunc = zfs_create_cb; 1928789Sahrens break; 1929789Sahrens 1930789Sahrens case DMU_OST_ZVOL: 1931789Sahrens cbfunc = zvol_create_cb; 1932789Sahrens break; 1933789Sahrens 1934789Sahrens default: 19352199Sahrens cbfunc = NULL; 19366423Sgw25295 break; 19372199Sahrens } 19385326Sek110237 if (strchr(zc->zc_name, '@') || 19395326Sek110237 strchr(zc->zc_name, '%')) 1940789Sahrens return (EINVAL); 1941789Sahrens 19422676Seschrock if (zc->zc_nvlist_src != NULL && 19435094Slling (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 19445094Slling &nvprops)) != 0) 19452676Seschrock return (error); 19462676Seschrock 19475498Stimh zct.zct_zplprops = NULL; 19485331Samw zct.zct_props = nvprops; 19495331Samw 19502676Seschrock if (zc->zc_value[0] != '\0') { 1951789Sahrens /* 1952789Sahrens * We're creating a clone of an existing snapshot. 1953789Sahrens */ 19542676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 19552676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 19564543Smarks nvlist_free(nvprops); 1957789Sahrens return (EINVAL); 19582676Seschrock } 1959789Sahrens 19602676Seschrock error = dmu_objset_open(zc->zc_value, type, 19616689Smaybee DS_MODE_USER | DS_MODE_READONLY, &clone); 19622676Seschrock if (error) { 19634543Smarks nvlist_free(nvprops); 1964789Sahrens return (error); 19652676Seschrock } 19666492Stimh 19676492Stimh error = dmu_objset_create(zc->zc_name, type, clone, 0, 19686492Stimh NULL, NULL); 19695331Samw if (error) { 19705331Samw dmu_objset_close(clone); 19715331Samw nvlist_free(nvprops); 19725331Samw return (error); 19735331Samw } 1974789Sahrens dmu_objset_close(clone); 1975789Sahrens } else { 19766492Stimh boolean_t is_insensitive = B_FALSE; 19776492Stimh 19782676Seschrock if (cbfunc == NULL) { 19794543Smarks nvlist_free(nvprops); 19802199Sahrens return (EINVAL); 19812676Seschrock } 19822676Seschrock 1983789Sahrens if (type == DMU_OST_ZVOL) { 19842676Seschrock uint64_t volsize, volblocksize; 19852676Seschrock 19864543Smarks if (nvprops == NULL || 19874543Smarks nvlist_lookup_uint64(nvprops, 19882676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 19892676Seschrock &volsize) != 0) { 19904543Smarks nvlist_free(nvprops); 19912676Seschrock return (EINVAL); 19922676Seschrock } 19932676Seschrock 19944543Smarks if ((error = nvlist_lookup_uint64(nvprops, 19952676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 19962676Seschrock &volblocksize)) != 0 && error != ENOENT) { 19974543Smarks nvlist_free(nvprops); 19982676Seschrock return (EINVAL); 19992676Seschrock } 20001133Seschrock 20012676Seschrock if (error != 0) 20022676Seschrock volblocksize = zfs_prop_default_numeric( 20032676Seschrock ZFS_PROP_VOLBLOCKSIZE); 20042676Seschrock 20052676Seschrock if ((error = zvol_check_volblocksize( 20062676Seschrock volblocksize)) != 0 || 20072676Seschrock (error = zvol_check_volsize(volsize, 20082676Seschrock volblocksize)) != 0) { 20094543Smarks nvlist_free(nvprops); 2010789Sahrens return (error); 20112676Seschrock } 20124577Sahrens } else if (type == DMU_OST_ZFS) { 20134577Sahrens uint64_t version; 20145331Samw int error; 20155331Samw 20165498Stimh /* 20175498Stimh * Default ZPL version to non-FUID capable if the 20185498Stimh * pool is not upgraded to support FUIDs. 20195498Stimh */ 20205498Stimh if (zfs_check_version(zc->zc_name, SPA_VERSION_FUID)) 20215498Stimh version = ZPL_VERSION_FUID - 1; 20225498Stimh else 20235498Stimh version = ZPL_VERSION; 20245498Stimh 20255498Stimh /* 20265498Stimh * Potentially override default ZPL version based 20275498Stimh * on creator's request. 20285498Stimh */ 20295498Stimh (void) nvlist_lookup_uint64(nvprops, 20305331Samw zfs_prop_to_name(ZFS_PROP_VERSION), &version); 20315331Samw 20325498Stimh /* 20335498Stimh * Make sure version we ended up with is kosher 20345498Stimh */ 20355498Stimh if ((version < ZPL_VERSION_INITIAL || 20365498Stimh version > ZPL_VERSION) || 20375498Stimh (version >= ZPL_VERSION_FUID && 20385498Stimh zfs_check_version(zc->zc_name, SPA_VERSION_FUID))) { 20395331Samw nvlist_free(nvprops); 20405331Samw return (ENOTSUP); 20415331Samw } 20425331Samw 20435331Samw /* 20445331Samw * We have to have normalization and 20455331Samw * case-folding flags correct when we do the 20465331Samw * file system creation, so go figure them out 20475498Stimh * now. 20485331Samw */ 20495498Stimh VERIFY(nvlist_alloc(&zct.zct_zplprops, 20505498Stimh NV_UNIQUE_NAME, KM_SLEEP) == 0); 20515498Stimh error = zfs_fill_zplprops(zc->zc_name, nvprops, 20526492Stimh zct.zct_zplprops, version, &is_insensitive); 20535331Samw if (error != 0) { 20545331Samw nvlist_free(nvprops); 20555498Stimh nvlist_free(zct.zct_zplprops); 20565331Samw return (error); 20574577Sahrens } 20582676Seschrock } 20596492Stimh error = dmu_objset_create(zc->zc_name, type, NULL, 20606492Stimh is_insensitive ? DS_FLAG_CI_DATASET : 0, cbfunc, &zct); 20615498Stimh nvlist_free(zct.zct_zplprops); 2062789Sahrens } 20632676Seschrock 20642676Seschrock /* 20652676Seschrock * It would be nice to do this atomically. 20662676Seschrock */ 20672676Seschrock if (error == 0) { 20684787Sahrens if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) 20692676Seschrock (void) dmu_objset_destroy(zc->zc_name); 20702676Seschrock } 20714543Smarks nvlist_free(nvprops); 2072789Sahrens return (error); 2073789Sahrens } 2074789Sahrens 20755367Sahrens /* 20765367Sahrens * inputs: 20775367Sahrens * zc_name name of filesystem 20785367Sahrens * zc_value short name of snapshot 20795367Sahrens * zc_cookie recursive flag 20805367Sahrens * 20815367Sahrens * outputs: none 20825367Sahrens */ 2083789Sahrens static int 20842199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 20852199Sahrens { 20862676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 20872199Sahrens return (EINVAL); 20882199Sahrens return (dmu_objset_snapshot(zc->zc_name, 20892676Seschrock zc->zc_value, zc->zc_cookie)); 20902199Sahrens } 20912199Sahrens 20924007Smmusante int 20932199Sahrens zfs_unmount_snap(char *name, void *arg) 2094789Sahrens { 20952417Sahrens vfs_t *vfsp = NULL; 20962199Sahrens 20976689Smaybee if (arg) { 20986689Smaybee char *snapname = arg; 20996689Smaybee int len = strlen(name) + strlen(snapname) + 2; 21006689Smaybee char *buf = kmem_alloc(len, KM_SLEEP); 21016689Smaybee 21026689Smaybee (void) strcpy(buf, name); 21036689Smaybee (void) strcat(buf, "@"); 21046689Smaybee (void) strcat(buf, snapname); 21056689Smaybee vfsp = zfs_get_vfs(buf); 21066689Smaybee kmem_free(buf, len); 21072417Sahrens } else if (strchr(name, '@')) { 21082199Sahrens vfsp = zfs_get_vfs(name); 21092199Sahrens } 21102199Sahrens 21112199Sahrens if (vfsp) { 21122199Sahrens /* 21132199Sahrens * Always force the unmount for snapshots. 21142199Sahrens */ 21152199Sahrens int flag = MS_FORCE; 2116789Sahrens int err; 2117789Sahrens 21182199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 21192199Sahrens VFS_RELE(vfsp); 21202199Sahrens return (err); 21212199Sahrens } 21222199Sahrens VFS_RELE(vfsp); 21232199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 21242199Sahrens return (err); 21252199Sahrens } 21262199Sahrens return (0); 21272199Sahrens } 21282199Sahrens 21295367Sahrens /* 21305367Sahrens * inputs: 21315367Sahrens * zc_name name of filesystem 21325367Sahrens * zc_value short name of snapshot 21335367Sahrens * 21345367Sahrens * outputs: none 21355367Sahrens */ 21362199Sahrens static int 21372199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 21382199Sahrens { 21392199Sahrens int err; 2140789Sahrens 21412676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 21422199Sahrens return (EINVAL); 21432199Sahrens err = dmu_objset_find(zc->zc_name, 21442676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 21452199Sahrens if (err) 21462199Sahrens return (err); 21472676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 21482199Sahrens } 21492199Sahrens 21505367Sahrens /* 21515367Sahrens * inputs: 21525367Sahrens * zc_name name of dataset to destroy 21535367Sahrens * zc_objset_type type of objset 21545367Sahrens * 21555367Sahrens * outputs: none 21565367Sahrens */ 21572199Sahrens static int 21582199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 21592199Sahrens { 21602199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 21612199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 21622199Sahrens if (err) 21632199Sahrens return (err); 2164789Sahrens } 2165789Sahrens 2166789Sahrens return (dmu_objset_destroy(zc->zc_name)); 2167789Sahrens } 2168789Sahrens 21695367Sahrens /* 21705367Sahrens * inputs: 21715446Sahrens * zc_name name of dataset to rollback (to most recent snapshot) 21725367Sahrens * 21735367Sahrens * outputs: none 21745367Sahrens */ 2175789Sahrens static int 2176789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 2177789Sahrens { 21785446Sahrens objset_t *os; 21795446Sahrens int error; 21805446Sahrens zfsvfs_t *zfsvfs = NULL; 21815446Sahrens 21825446Sahrens /* 21835446Sahrens * Get the zfsvfs for the receiving objset. There 21845446Sahrens * won't be one if we're operating on a zvol, if the 21855446Sahrens * objset doesn't exist yet, or is not mounted. 21865446Sahrens */ 21876689Smaybee error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, DS_MODE_USER, &os); 21885446Sahrens if (error) 21895446Sahrens return (error); 21905446Sahrens 21915446Sahrens if (dmu_objset_type(os) == DMU_OST_ZFS) { 21925446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 21935446Sahrens zfsvfs = dmu_objset_get_user(os); 21945446Sahrens if (zfsvfs != NULL) 21955446Sahrens VFS_HOLD(zfsvfs->z_vfs); 21965446Sahrens mutex_exit(&os->os->os_user_ptr_lock); 21975446Sahrens } 21985446Sahrens 21995446Sahrens if (zfsvfs != NULL) { 22005446Sahrens char osname[MAXNAMELEN]; 22015446Sahrens int mode; 22025446Sahrens 22036083Sek110237 error = zfs_suspend_fs(zfsvfs, osname, &mode); 22046083Sek110237 if (error == 0) { 22056083Sek110237 int resume_err; 22066083Sek110237 22076083Sek110237 ASSERT(strcmp(osname, zc->zc_name) == 0); 22086083Sek110237 error = dmu_objset_rollback(os); 22096083Sek110237 resume_err = zfs_resume_fs(zfsvfs, osname, mode); 22106083Sek110237 error = error ? error : resume_err; 22116083Sek110237 } else { 22126083Sek110237 dmu_objset_close(os); 22136083Sek110237 } 22145446Sahrens VFS_RELE(zfsvfs->z_vfs); 22155446Sahrens } else { 22165446Sahrens error = dmu_objset_rollback(os); 22175446Sahrens } 22186689Smaybee /* Note, the dmu_objset_rollback() releases the objset for us. */ 22195446Sahrens 22205446Sahrens return (error); 2221789Sahrens } 2222789Sahrens 22235367Sahrens /* 22245367Sahrens * inputs: 22255367Sahrens * zc_name old name of dataset 22265367Sahrens * zc_value new name of dataset 22275367Sahrens * zc_cookie recursive flag (only valid for snapshots) 22285367Sahrens * 22295367Sahrens * outputs: none 22305367Sahrens */ 2231789Sahrens static int 2232789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 2233789Sahrens { 22344490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 22354007Smmusante 22362676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 22375326Sek110237 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 22385326Sek110237 strchr(zc->zc_value, '%')) 2239789Sahrens return (EINVAL); 2240789Sahrens 22414007Smmusante /* 22424007Smmusante * Unmount snapshot unless we're doing a recursive rename, 22434007Smmusante * in which case the dataset code figures out which snapshots 22444007Smmusante * to unmount. 22454007Smmusante */ 22464007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 2247789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 22482199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 22492199Sahrens if (err) 22502199Sahrens return (err); 2251789Sahrens } 22524007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 2253789Sahrens } 2254789Sahrens 22556689Smaybee static void 22566689Smaybee clear_props(char *dataset, nvlist_t *props) 22576689Smaybee { 22586689Smaybee zfs_cmd_t *zc; 22596689Smaybee nvpair_t *prop; 22606689Smaybee 22616689Smaybee if (props == NULL) 22626689Smaybee return; 22636689Smaybee zc = kmem_alloc(sizeof (zfs_cmd_t), KM_SLEEP); 22646689Smaybee (void) strcpy(zc->zc_name, dataset); 22656689Smaybee for (prop = nvlist_next_nvpair(props, NULL); prop; 22666689Smaybee prop = nvlist_next_nvpair(props, prop)) { 22676689Smaybee (void) strcpy(zc->zc_value, nvpair_name(prop)); 22686689Smaybee if (zfs_secpolicy_inherit(zc, CRED()) == 0) 22696689Smaybee (void) zfs_ioc_inherit_prop(zc); 22706689Smaybee } 22716689Smaybee kmem_free(zc, sizeof (zfs_cmd_t)); 22726689Smaybee } 22736689Smaybee 22745367Sahrens /* 22755367Sahrens * inputs: 22765367Sahrens * zc_name name of containing filesystem 22775367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 22785367Sahrens * zc_value name of snapshot to create 22795367Sahrens * zc_string name of clone origin (if DRR_FLAG_CLONE) 22805367Sahrens * zc_cookie file descriptor to recv from 22815367Sahrens * zc_begin_record the BEGIN record of the stream (not byteswapped) 22825367Sahrens * zc_guid force flag 22835367Sahrens * 22845367Sahrens * outputs: 22855367Sahrens * zc_cookie number of bytes read 22865367Sahrens */ 2287789Sahrens static int 22885367Sahrens zfs_ioc_recv(zfs_cmd_t *zc) 2289789Sahrens { 2290789Sahrens file_t *fp; 22915326Sek110237 objset_t *os; 22925367Sahrens dmu_recv_cookie_t drc; 22935326Sek110237 zfsvfs_t *zfsvfs = NULL; 22945326Sek110237 boolean_t force = (boolean_t)zc->zc_guid; 2295789Sahrens int error, fd; 22965367Sahrens offset_t off; 22975367Sahrens nvlist_t *props = NULL; 22986689Smaybee nvlist_t *origprops = NULL; 22995367Sahrens objset_t *origin = NULL; 23005367Sahrens char *tosnap; 23015367Sahrens char tofs[ZFS_MAXNAMELEN]; 2302789Sahrens 23033265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 23045326Sek110237 strchr(zc->zc_value, '@') == NULL || 23055326Sek110237 strchr(zc->zc_value, '%')) 23063265Sahrens return (EINVAL); 23073265Sahrens 23085367Sahrens (void) strcpy(tofs, zc->zc_value); 23095367Sahrens tosnap = strchr(tofs, '@'); 23105367Sahrens *tosnap = '\0'; 23115367Sahrens tosnap++; 23125367Sahrens 23135367Sahrens if (zc->zc_nvlist_src != NULL && 23145367Sahrens (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 23155367Sahrens &props)) != 0) 23165367Sahrens return (error); 23175367Sahrens 2318789Sahrens fd = zc->zc_cookie; 2319789Sahrens fp = getf(fd); 23205367Sahrens if (fp == NULL) { 23215367Sahrens nvlist_free(props); 2322789Sahrens return (EBADF); 23235367Sahrens } 23245326Sek110237 23256689Smaybee if (dmu_objset_open(tofs, DMU_OST_ANY, 23266689Smaybee DS_MODE_USER | DS_MODE_READONLY, &os) == 0) { 23276689Smaybee /* 23286689Smaybee * Try to get the zfsvfs for the receiving objset. 23296689Smaybee * There won't be one if we're operating on a zvol, 23306689Smaybee * if the objset doesn't exist yet, or is not mounted. 23316689Smaybee */ 23325446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 23336689Smaybee if (zfsvfs = dmu_objset_get_user(os)) { 23346083Sek110237 if (!mutex_tryenter(&zfsvfs->z_online_recv_lock)) { 23356689Smaybee mutex_exit(&os->os->os_user_ptr_lock); 23366083Sek110237 dmu_objset_close(os); 23376689Smaybee zfsvfs = NULL; 23386689Smaybee error = EBUSY; 23396689Smaybee goto out; 23406083Sek110237 } 23416689Smaybee VFS_HOLD(zfsvfs->z_vfs); 23426083Sek110237 } 23436689Smaybee mutex_exit(&os->os->os_user_ptr_lock); 23446689Smaybee 23456689Smaybee /* 23466689Smaybee * If new properties are supplied, they are to completely 23476689Smaybee * replace the existing ones, so stash away the existing ones. 23486689Smaybee */ 23496689Smaybee if (props) 23506689Smaybee (void) dsl_prop_get_all(os, &origprops, TRUE); 23516689Smaybee 23525326Sek110237 dmu_objset_close(os); 23535326Sek110237 } 23545326Sek110237 23555367Sahrens if (zc->zc_string[0]) { 23565367Sahrens error = dmu_objset_open(zc->zc_string, DMU_OST_ANY, 23576689Smaybee DS_MODE_USER | DS_MODE_READONLY, &origin); 23586689Smaybee if (error) 23596689Smaybee goto out; 23605367Sahrens } 23615367Sahrens 23625367Sahrens error = dmu_recv_begin(tofs, tosnap, &zc->zc_begin_record, 23635367Sahrens force, origin, zfsvfs != NULL, &drc); 23645367Sahrens if (origin) 23655367Sahrens dmu_objset_close(origin); 23666689Smaybee if (error) 23676689Smaybee goto out; 23685326Sek110237 23695326Sek110237 /* 23706689Smaybee * Reset properties. We do this before we receive the stream 23716689Smaybee * so that the properties are applied to the new data. 23725326Sek110237 */ 23735367Sahrens if (props) { 23746689Smaybee clear_props(tofs, origprops); 23756689Smaybee /* 23766689Smaybee * XXX - Note, this is all-or-nothing; should be best-effort. 23776689Smaybee */ 23786689Smaybee (void) zfs_set_prop_nvlist(tofs, props); 23795367Sahrens } 23805367Sahrens 23815367Sahrens off = fp->f_offset; 23825367Sahrens error = dmu_recv_stream(&drc, fp->f_vnode, &off); 23835367Sahrens 23846689Smaybee if (error == 0 && zfsvfs) { 23856689Smaybee char osname[MAXNAMELEN]; 23866689Smaybee int mode; 23876689Smaybee 23886689Smaybee /* online recv */ 23896689Smaybee error = zfs_suspend_fs(zfsvfs, osname, &mode); 23906689Smaybee if (error == 0) { 23916689Smaybee int resume_err; 23926689Smaybee 23936689Smaybee error = dmu_recv_end(&drc); 23946689Smaybee resume_err = zfs_resume_fs(zfsvfs, osname, mode); 23956689Smaybee error = error ? error : resume_err; 23965367Sahrens } else { 23976689Smaybee dmu_recv_abort_cleanup(&drc); 23985367Sahrens } 23996689Smaybee } else if (error == 0) { 24006689Smaybee error = dmu_recv_end(&drc); 24016083Sek110237 } 24025367Sahrens 24035367Sahrens zc->zc_cookie = off - fp->f_offset; 24045367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 24055367Sahrens fp->f_offset = off; 24062885Sahrens 24076689Smaybee /* 24086689Smaybee * On error, restore the original props. 24096689Smaybee */ 24106689Smaybee if (error && props) { 24116689Smaybee clear_props(tofs, props); 24126689Smaybee (void) zfs_set_prop_nvlist(tofs, origprops); 24136689Smaybee } 24146689Smaybee out: 24156689Smaybee if (zfsvfs) { 24166689Smaybee mutex_exit(&zfsvfs->z_online_recv_lock); 24176689Smaybee VFS_RELE(zfsvfs->z_vfs); 24186689Smaybee } 24196689Smaybee nvlist_free(props); 24206689Smaybee nvlist_free(origprops); 2421789Sahrens releasef(fd); 2422789Sahrens return (error); 2423789Sahrens } 2424789Sahrens 24255367Sahrens /* 24265367Sahrens * inputs: 24275367Sahrens * zc_name name of snapshot to send 24285367Sahrens * zc_value short name of incremental fromsnap (may be empty) 24295367Sahrens * zc_cookie file descriptor to send stream to 24305367Sahrens * zc_obj fromorigin flag (mutually exclusive with zc_value) 24315367Sahrens * 24325367Sahrens * outputs: none 24335367Sahrens */ 2434789Sahrens static int 24355367Sahrens zfs_ioc_send(zfs_cmd_t *zc) 2436789Sahrens { 2437789Sahrens objset_t *fromsnap = NULL; 2438789Sahrens objset_t *tosnap; 2439789Sahrens file_t *fp; 2440789Sahrens int error; 24415367Sahrens offset_t off; 2442789Sahrens 2443789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 24446689Smaybee DS_MODE_USER | DS_MODE_READONLY, &tosnap); 2445789Sahrens if (error) 2446789Sahrens return (error); 2447789Sahrens 24482676Seschrock if (zc->zc_value[0] != '\0') { 24492885Sahrens char buf[MAXPATHLEN]; 24502885Sahrens char *cp; 24512885Sahrens 24522885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 24532885Sahrens cp = strchr(buf, '@'); 24542885Sahrens if (cp) 24552885Sahrens *(cp+1) = 0; 24562885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 24572885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 24586689Smaybee DS_MODE_USER | DS_MODE_READONLY, &fromsnap); 2459789Sahrens if (error) { 2460789Sahrens dmu_objset_close(tosnap); 2461789Sahrens return (error); 2462789Sahrens } 2463789Sahrens } 2464789Sahrens 2465789Sahrens fp = getf(zc->zc_cookie); 2466789Sahrens if (fp == NULL) { 2467789Sahrens dmu_objset_close(tosnap); 2468789Sahrens if (fromsnap) 2469789Sahrens dmu_objset_close(fromsnap); 2470789Sahrens return (EBADF); 2471789Sahrens } 2472789Sahrens 24735367Sahrens off = fp->f_offset; 24745367Sahrens error = dmu_sendbackup(tosnap, fromsnap, zc->zc_obj, fp->f_vnode, &off); 24755367Sahrens 24765367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 24775367Sahrens fp->f_offset = off; 2478789Sahrens releasef(zc->zc_cookie); 2479789Sahrens if (fromsnap) 2480789Sahrens dmu_objset_close(fromsnap); 2481789Sahrens dmu_objset_close(tosnap); 2482789Sahrens return (error); 2483789Sahrens } 2484789Sahrens 24851544Seschrock static int 24861544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 24871544Seschrock { 24881544Seschrock int id, error; 24891544Seschrock 24901544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 24911544Seschrock &zc->zc_inject_record); 24921544Seschrock 24931544Seschrock if (error == 0) 24941544Seschrock zc->zc_guid = (uint64_t)id; 24951544Seschrock 24961544Seschrock return (error); 24971544Seschrock } 24981544Seschrock 24991544Seschrock static int 25001544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 25011544Seschrock { 25021544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 25031544Seschrock } 25041544Seschrock 25051544Seschrock static int 25061544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 25071544Seschrock { 25081544Seschrock int id = (int)zc->zc_guid; 25091544Seschrock int error; 25101544Seschrock 25111544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 25121544Seschrock &zc->zc_inject_record); 25131544Seschrock 25141544Seschrock zc->zc_guid = id; 25151544Seschrock 25161544Seschrock return (error); 25171544Seschrock } 25181544Seschrock 25191544Seschrock static int 25201544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 25211544Seschrock { 25221544Seschrock spa_t *spa; 25231544Seschrock int error; 25242676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 25251544Seschrock 25261544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 25271544Seschrock return (error); 25281544Seschrock 25292676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 25301544Seschrock &count); 25311544Seschrock if (error == 0) 25322676Seschrock zc->zc_nvlist_dst_size = count; 25331544Seschrock else 25342676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 25351544Seschrock 25361544Seschrock spa_close(spa, FTAG); 25371544Seschrock 25381544Seschrock return (error); 25391544Seschrock } 25401544Seschrock 25411544Seschrock static int 25421544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 25431544Seschrock { 25441544Seschrock spa_t *spa; 25451544Seschrock vdev_t *vd; 25464808Sek110237 uint64_t txg; 25471544Seschrock int error; 25481544Seschrock 25491544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 25501544Seschrock return (error); 25511544Seschrock 25525329Sgw25295 /* 25535329Sgw25295 * Try to resume any I/Os which may have been suspended 25545329Sgw25295 * as a result of a complete pool failure. 25555329Sgw25295 */ 25565329Sgw25295 if (!list_is_empty(&spa->spa_zio_list)) { 25575329Sgw25295 if (zio_vdev_resume_io(spa) != 0) { 25585329Sgw25295 spa_close(spa, FTAG); 25595329Sgw25295 return (EIO); 25605329Sgw25295 } 25615329Sgw25295 } 25625329Sgw25295 25634451Seschrock txg = spa_vdev_enter(spa); 25641544Seschrock 25652676Seschrock if (zc->zc_guid == 0) { 25661544Seschrock vd = NULL; 25676643Seschrock } else { 25686643Seschrock vd = spa_lookup_by_guid(spa, zc->zc_guid, B_TRUE); 25695450Sbrendan if (vd == NULL) { 25705450Sbrendan (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 25715450Sbrendan spa_close(spa, FTAG); 25725450Sbrendan return (ENODEV); 25735450Sbrendan } 25741544Seschrock } 25751544Seschrock 25765329Sgw25295 vdev_clear(spa, vd, B_TRUE); 25771544Seschrock 25784451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 25791544Seschrock 25801544Seschrock spa_close(spa, FTAG); 25811544Seschrock 25821544Seschrock return (0); 25831544Seschrock } 25841544Seschrock 25855367Sahrens /* 25865367Sahrens * inputs: 25875367Sahrens * zc_name name of filesystem 25885367Sahrens * zc_value name of origin snapshot 25895367Sahrens * 25905367Sahrens * outputs: none 25915367Sahrens */ 25921544Seschrock static int 25932082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 25942082Seschrock { 25952417Sahrens char *cp; 25962417Sahrens 25972417Sahrens /* 25982417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 25992417Sahrens * it's easier. 26002417Sahrens */ 26012676Seschrock cp = strchr(zc->zc_value, '@'); 26022417Sahrens if (cp) 26032417Sahrens *cp = '\0'; 26042676Seschrock (void) dmu_objset_find(zc->zc_value, 26052417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 26062082Seschrock return (dsl_dataset_promote(zc->zc_name)); 26072082Seschrock } 26082082Seschrock 26094543Smarks /* 26104543Smarks * We don't want to have a hard dependency 26114543Smarks * against some special symbols in sharefs 26125331Samw * nfs, and smbsrv. Determine them if needed when 26134543Smarks * the first file system is shared. 26145331Samw * Neither sharefs, nfs or smbsrv are unloadable modules. 26154543Smarks */ 26165331Samw int (*znfsexport_fs)(void *arg); 26174543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 26185331Samw int (*zsmbexport_fs)(void *arg, boolean_t add_share); 26195331Samw 26205331Samw int zfs_nfsshare_inited; 26215331Samw int zfs_smbshare_inited; 26225331Samw 26234543Smarks ddi_modhandle_t nfs_mod; 26244543Smarks ddi_modhandle_t sharefs_mod; 26255331Samw ddi_modhandle_t smbsrv_mod; 26264543Smarks kmutex_t zfs_share_lock; 26274543Smarks 26284543Smarks static int 26295331Samw zfs_init_sharefs() 26305331Samw { 26315331Samw int error; 26325331Samw 26335331Samw ASSERT(MUTEX_HELD(&zfs_share_lock)); 26345331Samw /* Both NFS and SMB shares also require sharetab support. */ 26355331Samw if (sharefs_mod == NULL && ((sharefs_mod = 26365331Samw ddi_modopen("fs/sharefs", 26375331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26385331Samw return (ENOSYS); 26395331Samw } 26405331Samw if (zshare_fs == NULL && ((zshare_fs = 26415331Samw (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 26425331Samw ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 26435331Samw return (ENOSYS); 26445331Samw } 26455331Samw return (0); 26465331Samw } 26475331Samw 26485331Samw static int 26494543Smarks zfs_ioc_share(zfs_cmd_t *zc) 26504543Smarks { 26514543Smarks int error; 26524543Smarks int opcode; 26534543Smarks 26545331Samw switch (zc->zc_share.z_sharetype) { 26555331Samw case ZFS_SHARE_NFS: 26565331Samw case ZFS_UNSHARE_NFS: 26575331Samw if (zfs_nfsshare_inited == 0) { 26585331Samw mutex_enter(&zfs_share_lock); 26595331Samw if (nfs_mod == NULL && ((nfs_mod = ddi_modopen("fs/nfs", 26605331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26615331Samw mutex_exit(&zfs_share_lock); 26625331Samw return (ENOSYS); 26635331Samw } 26645331Samw if (znfsexport_fs == NULL && 26655331Samw ((znfsexport_fs = (int (*)(void *)) 26665331Samw ddi_modsym(nfs_mod, 26675331Samw "nfs_export", &error)) == NULL)) { 26685331Samw mutex_exit(&zfs_share_lock); 26695331Samw return (ENOSYS); 26705331Samw } 26715331Samw error = zfs_init_sharefs(); 26725331Samw if (error) { 26735331Samw mutex_exit(&zfs_share_lock); 26745331Samw return (ENOSYS); 26755331Samw } 26765331Samw zfs_nfsshare_inited = 1; 26774543Smarks mutex_exit(&zfs_share_lock); 26784543Smarks } 26795331Samw break; 26805331Samw case ZFS_SHARE_SMB: 26815331Samw case ZFS_UNSHARE_SMB: 26825331Samw if (zfs_smbshare_inited == 0) { 26835331Samw mutex_enter(&zfs_share_lock); 26845331Samw if (smbsrv_mod == NULL && ((smbsrv_mod = 26855331Samw ddi_modopen("drv/smbsrv", 26865331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26875331Samw mutex_exit(&zfs_share_lock); 26885331Samw return (ENOSYS); 26895331Samw } 26905331Samw if (zsmbexport_fs == NULL && ((zsmbexport_fs = 26915331Samw (int (*)(void *, boolean_t))ddi_modsym(smbsrv_mod, 26926139Sjb150015 "smb_server_share", &error)) == NULL)) { 26935331Samw mutex_exit(&zfs_share_lock); 26945331Samw return (ENOSYS); 26955331Samw } 26965331Samw error = zfs_init_sharefs(); 26975331Samw if (error) { 26985331Samw mutex_exit(&zfs_share_lock); 26995331Samw return (ENOSYS); 27005331Samw } 27015331Samw zfs_smbshare_inited = 1; 27024543Smarks mutex_exit(&zfs_share_lock); 27034543Smarks } 27045331Samw break; 27055331Samw default: 27065331Samw return (EINVAL); 27074543Smarks } 27084543Smarks 27095331Samw switch (zc->zc_share.z_sharetype) { 27105331Samw case ZFS_SHARE_NFS: 27115331Samw case ZFS_UNSHARE_NFS: 27125331Samw if (error = 27135331Samw znfsexport_fs((void *) 27145331Samw (uintptr_t)zc->zc_share.z_exportdata)) 27155331Samw return (error); 27165331Samw break; 27175331Samw case ZFS_SHARE_SMB: 27185331Samw case ZFS_UNSHARE_SMB: 27195331Samw if (error = zsmbexport_fs((void *) 27205331Samw (uintptr_t)zc->zc_share.z_exportdata, 27215331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB ? 27225331Samw B_TRUE : B_FALSE)) { 27235331Samw return (error); 27245331Samw } 27255331Samw break; 27265331Samw } 27275331Samw 27285331Samw opcode = (zc->zc_share.z_sharetype == ZFS_SHARE_NFS || 27295331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB) ? 27304543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 27314543Smarks 27325331Samw /* 27335331Samw * Add or remove share from sharetab 27345331Samw */ 27354543Smarks error = zshare_fs(opcode, 27364543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 27374543Smarks zc->zc_share.z_sharemax); 27384543Smarks 27394543Smarks return (error); 27404543Smarks 27414543Smarks } 27424543Smarks 27434543Smarks /* 27444988Sek110237 * pool create, destroy, and export don't log the history as part of 27454988Sek110237 * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export 27464988Sek110237 * do the logging of those commands. 27474543Smarks */ 2748789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 27494715Sek110237 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27504577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27514577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27524577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27534577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 27544577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 27554577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27564577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27574577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27584577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27594577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27604577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27614577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27624577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27634577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27644577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27654577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27664577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27675498Stimh { zfs_ioc_objset_zplprops, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27684543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 27694577Sahrens DATASET_NAME, B_FALSE }, 27704543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 27714577Sahrens DATASET_NAME, B_FALSE }, 27724577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 27734577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 27744577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 27754577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 27764577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 27774577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 27784577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 27795367Sahrens { zfs_ioc_recv, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 27805367Sahrens { zfs_ioc_send, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 27814577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 27824577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 27834577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 27844577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 27854577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27864577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 27874577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 27884577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 27894577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27904577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27914577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27924577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 27934577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 27944577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27954543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 27964577Sahrens DATASET_NAME, B_FALSE }, 27974849Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }, 27984849Sahrens { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE }, 2799789Sahrens }; 2800789Sahrens 2801789Sahrens static int 2802789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2803789Sahrens { 2804789Sahrens zfs_cmd_t *zc; 2805789Sahrens uint_t vec; 28062199Sahrens int error, rc; 2807789Sahrens 2808789Sahrens if (getminor(dev) != 0) 2809789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2810789Sahrens 2811789Sahrens vec = cmd - ZFS_IOC; 28124787Sahrens ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); 2813789Sahrens 2814789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2815789Sahrens return (EINVAL); 2816789Sahrens 2817789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2818789Sahrens 2819789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2820789Sahrens 28214787Sahrens if (error == 0) 28224543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2823789Sahrens 2824789Sahrens /* 2825789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2826789Sahrens * the lower layers. 2827789Sahrens */ 2828789Sahrens if (error == 0) { 2829789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2830789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 28314577Sahrens case POOL_NAME: 2832789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2833789Sahrens error = EINVAL; 2834789Sahrens break; 2835789Sahrens 28364577Sahrens case DATASET_NAME: 2837789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2838789Sahrens error = EINVAL; 2839789Sahrens break; 28402856Snd150628 28414577Sahrens case NO_NAME: 28422856Snd150628 break; 2843789Sahrens } 2844789Sahrens } 2845789Sahrens 2846789Sahrens if (error == 0) 2847789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2848789Sahrens 28492199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 28504543Smarks if (error == 0) { 28512199Sahrens error = rc; 28524543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 28534543Smarks zfs_log_history(zc); 28544543Smarks } 2855789Sahrens 2856789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2857789Sahrens return (error); 2858789Sahrens } 2859789Sahrens 2860789Sahrens static int 2861789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2862789Sahrens { 2863789Sahrens if (cmd != DDI_ATTACH) 2864789Sahrens return (DDI_FAILURE); 2865789Sahrens 2866789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2867789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2868789Sahrens return (DDI_FAILURE); 2869789Sahrens 2870789Sahrens zfs_dip = dip; 2871789Sahrens 2872789Sahrens ddi_report_dev(dip); 2873789Sahrens 2874789Sahrens return (DDI_SUCCESS); 2875789Sahrens } 2876789Sahrens 2877789Sahrens static int 2878789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2879789Sahrens { 2880789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2881789Sahrens return (DDI_FAILURE); 2882789Sahrens 2883789Sahrens if (cmd != DDI_DETACH) 2884789Sahrens return (DDI_FAILURE); 2885789Sahrens 2886789Sahrens zfs_dip = NULL; 2887789Sahrens 2888789Sahrens ddi_prop_remove_all(dip); 2889789Sahrens ddi_remove_minor_node(dip, NULL); 2890789Sahrens 2891789Sahrens return (DDI_SUCCESS); 2892789Sahrens } 2893789Sahrens 2894789Sahrens /*ARGSUSED*/ 2895789Sahrens static int 2896789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2897789Sahrens { 2898789Sahrens switch (infocmd) { 2899789Sahrens case DDI_INFO_DEVT2DEVINFO: 2900789Sahrens *result = zfs_dip; 2901789Sahrens return (DDI_SUCCESS); 2902789Sahrens 2903789Sahrens case DDI_INFO_DEVT2INSTANCE: 2904849Sbonwick *result = (void *)0; 2905789Sahrens return (DDI_SUCCESS); 2906789Sahrens } 2907789Sahrens 2908789Sahrens return (DDI_FAILURE); 2909789Sahrens } 2910789Sahrens 2911789Sahrens /* 2912789Sahrens * OK, so this is a little weird. 2913789Sahrens * 2914789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2915789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2916789Sahrens * 2917789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2918789Sahrens * so most of the standard driver entry points are in zvol.c. 2919789Sahrens */ 2920789Sahrens static struct cb_ops zfs_cb_ops = { 2921789Sahrens zvol_open, /* open */ 2922789Sahrens zvol_close, /* close */ 2923789Sahrens zvol_strategy, /* strategy */ 2924789Sahrens nodev, /* print */ 29256423Sgw25295 zvol_dump, /* dump */ 2926789Sahrens zvol_read, /* read */ 2927789Sahrens zvol_write, /* write */ 2928789Sahrens zfsdev_ioctl, /* ioctl */ 2929789Sahrens nodev, /* devmap */ 2930789Sahrens nodev, /* mmap */ 2931789Sahrens nodev, /* segmap */ 2932789Sahrens nochpoll, /* poll */ 2933789Sahrens ddi_prop_op, /* prop_op */ 2934789Sahrens NULL, /* streamtab */ 2935789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2936789Sahrens CB_REV, /* version */ 29373638Sbillm nodev, /* async read */ 29383638Sbillm nodev, /* async write */ 2939789Sahrens }; 2940789Sahrens 2941789Sahrens static struct dev_ops zfs_dev_ops = { 2942789Sahrens DEVO_REV, /* version */ 2943789Sahrens 0, /* refcnt */ 2944789Sahrens zfs_info, /* info */ 2945789Sahrens nulldev, /* identify */ 2946789Sahrens nulldev, /* probe */ 2947789Sahrens zfs_attach, /* attach */ 2948789Sahrens zfs_detach, /* detach */ 2949789Sahrens nodev, /* reset */ 2950789Sahrens &zfs_cb_ops, /* driver operations */ 2951789Sahrens NULL /* no bus operations */ 2952789Sahrens }; 2953789Sahrens 2954789Sahrens static struct modldrv zfs_modldrv = { 29554577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 29562676Seschrock &zfs_dev_ops 2957789Sahrens }; 2958789Sahrens 2959789Sahrens static struct modlinkage modlinkage = { 2960789Sahrens MODREV_1, 2961789Sahrens (void *)&zfs_modlfs, 2962789Sahrens (void *)&zfs_modldrv, 2963789Sahrens NULL 2964789Sahrens }; 2965789Sahrens 29664720Sfr157268 29674720Sfr157268 uint_t zfs_fsyncer_key; 29685326Sek110237 extern uint_t rrw_tsd_key; 29694720Sfr157268 2970789Sahrens int 2971789Sahrens _init(void) 2972789Sahrens { 2973789Sahrens int error; 2974789Sahrens 2975849Sbonwick spa_init(FREAD | FWRITE); 2976849Sbonwick zfs_init(); 2977849Sbonwick zvol_init(); 2978849Sbonwick 2979849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 2980849Sbonwick zvol_fini(); 2981849Sbonwick zfs_fini(); 2982849Sbonwick spa_fini(); 2983789Sahrens return (error); 2984849Sbonwick } 2985789Sahrens 29864720Sfr157268 tsd_create(&zfs_fsyncer_key, NULL); 29875326Sek110237 tsd_create(&rrw_tsd_key, NULL); 29884720Sfr157268 2989789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 2990789Sahrens ASSERT(error == 0); 29914543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 2992789Sahrens 2993789Sahrens return (0); 2994789Sahrens } 2995789Sahrens 2996789Sahrens int 2997789Sahrens _fini(void) 2998789Sahrens { 2999789Sahrens int error; 3000789Sahrens 30011544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 3002789Sahrens return (EBUSY); 3003789Sahrens 3004789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 3005789Sahrens return (error); 3006789Sahrens 3007789Sahrens zvol_fini(); 3008789Sahrens zfs_fini(); 3009789Sahrens spa_fini(); 30105331Samw if (zfs_nfsshare_inited) 30114543Smarks (void) ddi_modclose(nfs_mod); 30125331Samw if (zfs_smbshare_inited) 30135331Samw (void) ddi_modclose(smbsrv_mod); 30145331Samw if (zfs_nfsshare_inited || zfs_smbshare_inited) 30154543Smarks (void) ddi_modclose(sharefs_mod); 3016789Sahrens 30174720Sfr157268 tsd_destroy(&zfs_fsyncer_key); 3018789Sahrens ldi_ident_release(zfs_li); 3019789Sahrens zfs_li = NULL; 30204543Smarks mutex_destroy(&zfs_share_lock); 3021789Sahrens 3022789Sahrens return (error); 3023789Sahrens } 3024789Sahrens 3025789Sahrens int 3026789Sahrens _info(struct modinfo *modinfop) 3027789Sahrens { 3028789Sahrens return (mod_info(&modlinkage, modinfop)); 3029789Sahrens } 3030