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 /* 158*7042Sgw25295 * Check to see if the named dataset is currently defined as bootable 159*7042Sgw25295 */ 160*7042Sgw25295 static boolean_t 161*7042Sgw25295 zfs_is_bootfs(const char *name) 162*7042Sgw25295 { 163*7042Sgw25295 spa_t *spa; 164*7042Sgw25295 boolean_t ret = B_FALSE; 165*7042Sgw25295 166*7042Sgw25295 if (spa_open(name, &spa, FTAG) == 0) { 167*7042Sgw25295 if (spa->spa_bootfs) { 168*7042Sgw25295 objset_t *os; 169*7042Sgw25295 170*7042Sgw25295 if (dmu_objset_open(name, DMU_OST_ZFS, 171*7042Sgw25295 DS_MODE_USER | DS_MODE_READONLY, &os) == 0) { 172*7042Sgw25295 ret = (dmu_objset_id(os) == spa->spa_bootfs); 173*7042Sgw25295 dmu_objset_close(os); 174*7042Sgw25295 } 175*7042Sgw25295 } 176*7042Sgw25295 spa_close(spa, FTAG); 177*7042Sgw25295 } 178*7042Sgw25295 return (ret); 179*7042Sgw25295 } 180*7042Sgw25295 181*7042Sgw25295 /* 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 9034808Sek110237 mutex_enter(&spa_namespace_lock); 9042926Sek110237 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); 9054808Sek110237 mutex_exit(&spa_namespace_lock); 9062926Sek110237 9072926Sek110237 spa_close(spa, FTAG); 9082926Sek110237 909789Sahrens return (error); 910789Sahrens } 911789Sahrens 912789Sahrens static int 913789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 914789Sahrens { 915789Sahrens spa_t *spa; 916789Sahrens int error; 917789Sahrens 918789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 919789Sahrens if (error == 0) { 920789Sahrens spa_freeze(spa); 921789Sahrens spa_close(spa, FTAG); 922789Sahrens } 923789Sahrens return (error); 924789Sahrens } 925789Sahrens 926789Sahrens static int 9271760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 9281760Seschrock { 9291760Seschrock spa_t *spa; 9301760Seschrock int error; 9311760Seschrock 9322926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9332926Sek110237 return (error); 9342926Sek110237 9355118Slling if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) { 9365118Slling spa_close(spa, FTAG); 9375118Slling return (EINVAL); 9385118Slling } 9395118Slling 9405094Slling spa_upgrade(spa, zc->zc_cookie); 9412926Sek110237 spa_close(spa, FTAG); 9422926Sek110237 9432926Sek110237 return (error); 9442926Sek110237 } 9452926Sek110237 9462926Sek110237 static int 9472926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 9482926Sek110237 { 9492926Sek110237 spa_t *spa; 9502926Sek110237 char *hist_buf; 9512926Sek110237 uint64_t size; 9522926Sek110237 int error; 9532926Sek110237 9542926Sek110237 if ((size = zc->zc_history_len) == 0) 9552926Sek110237 return (EINVAL); 9562926Sek110237 9572926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9582926Sek110237 return (error); 9592926Sek110237 9604577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 9613863Sek110237 spa_close(spa, FTAG); 9623863Sek110237 return (ENOTSUP); 9633863Sek110237 } 9643863Sek110237 9652926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 9662926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 9672926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 9684543Smarks error = xcopyout(hist_buf, 9694543Smarks (char *)(uintptr_t)zc->zc_history, 9702926Sek110237 zc->zc_history_len); 9712926Sek110237 } 9722926Sek110237 9732926Sek110237 spa_close(spa, FTAG); 9742926Sek110237 kmem_free(hist_buf, size); 9752926Sek110237 return (error); 9762926Sek110237 } 9772926Sek110237 9782926Sek110237 static int 9793444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 9803444Sek110237 { 9813444Sek110237 int error; 9823444Sek110237 9833912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 9843444Sek110237 return (error); 9853444Sek110237 9863444Sek110237 return (0); 9873444Sek110237 } 9883444Sek110237 9893444Sek110237 static int 9903444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 9913444Sek110237 { 9923444Sek110237 objset_t *osp; 9933444Sek110237 int error; 9943444Sek110237 9953444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 9966689Smaybee DS_MODE_USER | DS_MODE_READONLY, &osp)) != 0) 9973444Sek110237 return (error); 9983444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 9993444Sek110237 sizeof (zc->zc_value)); 10003444Sek110237 dmu_objset_close(osp); 10013444Sek110237 10023444Sek110237 return (error); 10033444Sek110237 } 10043444Sek110237 10053444Sek110237 static int 1006789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 1007789Sahrens { 1008789Sahrens spa_t *spa; 1009789Sahrens int error; 10106423Sgw25295 nvlist_t *config, **l2cache, **spares; 10116423Sgw25295 uint_t nl2cache = 0, nspares = 0; 1012789Sahrens 1013789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 1014789Sahrens if (error != 0) 1015789Sahrens return (error); 1016789Sahrens 10175450Sbrendan error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 10185450Sbrendan &config); 10195450Sbrendan (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_L2CACHE, 10205450Sbrendan &l2cache, &nl2cache); 10215450Sbrendan 10226423Sgw25295 (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_SPARES, 10236423Sgw25295 &spares, &nspares); 10246423Sgw25295 10253912Slling /* 10263912Slling * A root pool with concatenated devices is not supported. 10276423Sgw25295 * Thus, can not add a device to a root pool. 10286423Sgw25295 * 10296423Sgw25295 * Intent log device can not be added to a rootpool because 10306423Sgw25295 * during mountroot, zil is replayed, a seperated log device 10316423Sgw25295 * can not be accessed during the mountroot time. 10326423Sgw25295 * 10336423Sgw25295 * l2cache and spare devices are ok to be added to a rootpool. 10343912Slling */ 10356423Sgw25295 if (spa->spa_bootfs != 0 && nl2cache == 0 && nspares == 0) { 10363912Slling spa_close(spa, FTAG); 10373912Slling return (EDOM); 10383912Slling } 10393912Slling 10405450Sbrendan if (error == 0) { 1041789Sahrens error = spa_vdev_add(spa, config); 1042789Sahrens nvlist_free(config); 1043789Sahrens } 1044789Sahrens spa_close(spa, FTAG); 1045789Sahrens return (error); 1046789Sahrens } 1047789Sahrens 1048789Sahrens static int 1049789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 1050789Sahrens { 10512082Seschrock spa_t *spa; 10522082Seschrock int error; 10532082Seschrock 10542082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10552082Seschrock if (error != 0) 10562082Seschrock return (error); 10572082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 10582082Seschrock spa_close(spa, FTAG); 10592082Seschrock return (error); 1060789Sahrens } 1061789Sahrens 1062789Sahrens static int 10634451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 1064789Sahrens { 1065789Sahrens spa_t *spa; 1066789Sahrens int error; 10674451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 1068789Sahrens 10692926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1070789Sahrens return (error); 10714451Seschrock switch (zc->zc_cookie) { 10724451Seschrock case VDEV_STATE_ONLINE: 10734451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 10744451Seschrock break; 10754451Seschrock 10764451Seschrock case VDEV_STATE_OFFLINE: 10774451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 10784451Seschrock break; 1079789Sahrens 10804451Seschrock case VDEV_STATE_FAULTED: 10814451Seschrock error = vdev_fault(spa, zc->zc_guid); 10824451Seschrock break; 1083789Sahrens 10844451Seschrock case VDEV_STATE_DEGRADED: 10854451Seschrock error = vdev_degrade(spa, zc->zc_guid); 10864451Seschrock break; 10874451Seschrock 10884451Seschrock default: 10894451Seschrock error = EINVAL; 10904451Seschrock } 10914451Seschrock zc->zc_cookie = newstate; 1092789Sahrens spa_close(spa, FTAG); 1093789Sahrens return (error); 1094789Sahrens } 1095789Sahrens 1096789Sahrens static int 1097789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 1098789Sahrens { 1099789Sahrens spa_t *spa; 1100789Sahrens int replacing = zc->zc_cookie; 1101789Sahrens nvlist_t *config; 1102789Sahrens int error; 1103789Sahrens 11042926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1105789Sahrens return (error); 1106789Sahrens 11075094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 11085094Slling &config)) == 0) { 11091544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 1110789Sahrens nvlist_free(config); 1111789Sahrens } 1112789Sahrens 1113789Sahrens spa_close(spa, FTAG); 1114789Sahrens return (error); 1115789Sahrens } 1116789Sahrens 1117789Sahrens static int 1118789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 1119789Sahrens { 1120789Sahrens spa_t *spa; 1121789Sahrens int error; 1122789Sahrens 11232926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1124789Sahrens return (error); 1125789Sahrens 11261544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1127789Sahrens 1128789Sahrens spa_close(spa, FTAG); 1129789Sahrens return (error); 1130789Sahrens } 1131789Sahrens 1132789Sahrens static int 11331354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 11341354Seschrock { 11351354Seschrock spa_t *spa; 11362676Seschrock char *path = zc->zc_value; 11371544Seschrock uint64_t guid = zc->zc_guid; 11381354Seschrock int error; 11391354Seschrock 11401354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 11411354Seschrock if (error != 0) 11421354Seschrock return (error); 11431354Seschrock 11441354Seschrock error = spa_vdev_setpath(spa, guid, path); 11451354Seschrock spa_close(spa, FTAG); 11461354Seschrock return (error); 11471354Seschrock } 11481354Seschrock 11495367Sahrens /* 11505367Sahrens * inputs: 11515367Sahrens * zc_name name of filesystem 11525367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 11535367Sahrens * 11545367Sahrens * outputs: 11555367Sahrens * zc_objset_stats stats 11565367Sahrens * zc_nvlist_dst property nvlist 11575367Sahrens * zc_nvlist_dst_size size of property nvlist 11585367Sahrens */ 11591354Seschrock static int 1160789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1161789Sahrens { 1162789Sahrens objset_t *os = NULL; 1163789Sahrens int error; 11641356Seschrock nvlist_t *nv; 1165789Sahrens 11666689Smaybee if (error = dmu_objset_open(zc->zc_name, 11676689Smaybee DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os)) 1168789Sahrens return (error); 1169789Sahrens 11702885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1171789Sahrens 11722856Snd150628 if (zc->zc_nvlist_dst != 0 && 11736689Smaybee (error = dsl_prop_get_all(os, &nv, FALSE)) == 0) { 11742885Sahrens dmu_objset_stats(os, nv); 11753087Sahrens /* 11765147Srm160521 * NB: zvol_get_stats() will read the objset contents, 11773087Sahrens * which we aren't supposed to do with a 11786689Smaybee * DS_MODE_USER hold, because it could be 11793087Sahrens * inconsistent. So this is a bit of a workaround... 11803087Sahrens */ 11814577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 11824577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 11834577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 11844577Sahrens } 11852676Seschrock error = put_nvlist(zc, nv); 11861356Seschrock nvlist_free(nv); 11871356Seschrock } 1188789Sahrens 1189789Sahrens dmu_objset_close(os); 1190789Sahrens return (error); 1191789Sahrens } 1192789Sahrens 11935498Stimh static int 11945498Stimh nvl_add_zplprop(objset_t *os, nvlist_t *props, zfs_prop_t prop) 11955498Stimh { 11965498Stimh uint64_t value; 11975498Stimh int error; 11985498Stimh 11995498Stimh /* 12005498Stimh * zfs_get_zplprop() will either find a value or give us 12015498Stimh * the default value (if there is one). 12025498Stimh */ 12035498Stimh if ((error = zfs_get_zplprop(os, prop, &value)) != 0) 12045498Stimh return (error); 12055498Stimh VERIFY(nvlist_add_uint64(props, zfs_prop_to_name(prop), value) == 0); 12065498Stimh return (0); 12075498Stimh } 12085498Stimh 12095498Stimh /* 12105498Stimh * inputs: 12115498Stimh * zc_name name of filesystem 12125498Stimh * zc_nvlist_dst_size size of buffer for zpl property nvlist 12135498Stimh * 12145498Stimh * outputs: 12155498Stimh * zc_nvlist_dst zpl property nvlist 12165498Stimh * zc_nvlist_dst_size size of zpl property nvlist 12175498Stimh */ 12185498Stimh static int 12195498Stimh zfs_ioc_objset_zplprops(zfs_cmd_t *zc) 12205498Stimh { 12215498Stimh objset_t *os; 12225498Stimh int err; 12235498Stimh 12246689Smaybee if (err = dmu_objset_open(zc->zc_name, 12256689Smaybee DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os)) 12265498Stimh return (err); 12275498Stimh 12285498Stimh dmu_objset_fast_stat(os, &zc->zc_objset_stats); 12295498Stimh 12305498Stimh /* 12315498Stimh * NB: nvl_add_zplprop() will read the objset contents, 12326689Smaybee * which we aren't supposed to do with a DS_MODE_USER 12336689Smaybee * hold, because it could be inconsistent. 12345498Stimh */ 12355498Stimh if (zc->zc_nvlist_dst != NULL && 12365498Stimh !zc->zc_objset_stats.dds_inconsistent && 12375498Stimh dmu_objset_type(os) == DMU_OST_ZFS) { 12385498Stimh nvlist_t *nv; 12395498Stimh 12405498Stimh VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) == 0); 12415498Stimh if ((err = nvl_add_zplprop(os, nv, ZFS_PROP_VERSION)) == 0 && 12425498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_NORMALIZE)) == 0 && 12435498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_UTF8ONLY)) == 0 && 12445498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_CASE)) == 0) 12455498Stimh err = put_nvlist(zc, nv); 12465498Stimh nvlist_free(nv); 12475498Stimh } else { 12485498Stimh err = ENOENT; 12495498Stimh } 12505498Stimh dmu_objset_close(os); 12515498Stimh return (err); 12525498Stimh } 12535498Stimh 12545367Sahrens /* 12555367Sahrens * inputs: 12565367Sahrens * zc_name name of filesystem 12575367Sahrens * zc_cookie zap cursor 12585367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 12595367Sahrens * 12605367Sahrens * outputs: 12615367Sahrens * zc_name name of next filesystem 12625367Sahrens * zc_objset_stats stats 12635367Sahrens * zc_nvlist_dst property nvlist 12645367Sahrens * zc_nvlist_dst_size size of property nvlist 12655367Sahrens */ 1266789Sahrens static int 1267789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1268789Sahrens { 1269885Sahrens objset_t *os; 1270789Sahrens int error; 1271789Sahrens char *p; 1272789Sahrens 12736689Smaybee if (error = dmu_objset_open(zc->zc_name, 12746689Smaybee DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os)) { 1275885Sahrens if (error == ENOENT) 1276885Sahrens error = ESRCH; 1277885Sahrens return (error); 1278789Sahrens } 1279789Sahrens 1280789Sahrens p = strrchr(zc->zc_name, '/'); 1281789Sahrens if (p == NULL || p[1] != '\0') 1282789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1283789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1284789Sahrens 1285789Sahrens do { 1286885Sahrens error = dmu_dir_list_next(os, 1287885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1288885Sahrens NULL, &zc->zc_cookie); 1289789Sahrens if (error == ENOENT) 1290789Sahrens error = ESRCH; 1291885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1292789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 12936689Smaybee dmu_objset_close(os); 1294789Sahrens 1295885Sahrens /* 1296885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1297885Sahrens * try to get stats for it. Userland will skip over it. 1298885Sahrens */ 1299885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1300885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1301789Sahrens 1302789Sahrens return (error); 1303789Sahrens } 1304789Sahrens 13055367Sahrens /* 13065367Sahrens * inputs: 13075367Sahrens * zc_name name of filesystem 13085367Sahrens * zc_cookie zap cursor 13095367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 13105367Sahrens * 13115367Sahrens * outputs: 13125367Sahrens * zc_name name of next snapshot 13135367Sahrens * zc_objset_stats stats 13145367Sahrens * zc_nvlist_dst property nvlist 13155367Sahrens * zc_nvlist_dst_size size of property nvlist 13165367Sahrens */ 1317789Sahrens static int 1318789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1319789Sahrens { 1320885Sahrens objset_t *os; 1321789Sahrens int error; 1322789Sahrens 13236689Smaybee error = dmu_objset_open(zc->zc_name, 13246689Smaybee DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os); 13256689Smaybee if (error) 13266689Smaybee return (error == ENOENT ? ESRCH : error); 1327789Sahrens 13281003Slling /* 13291003Slling * A dataset name of maximum length cannot have any snapshots, 13301003Slling * so exit immediately. 13311003Slling */ 13321003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1333885Sahrens dmu_objset_close(os); 13341003Slling return (ESRCH); 1335789Sahrens } 1336789Sahrens 1337885Sahrens error = dmu_snapshot_list_next(os, 1338885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 13395663Sck153898 zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie, NULL); 13406689Smaybee dmu_objset_close(os); 1341885Sahrens if (error == 0) 1342885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 13436689Smaybee else if (error == ENOENT) 13446689Smaybee error = ESRCH; 1345789Sahrens 13465367Sahrens /* if we failed, undo the @ that we tacked on to zc_name */ 13476689Smaybee if (error) 13485367Sahrens *strchr(zc->zc_name, '@') = '\0'; 1349789Sahrens return (error); 1350789Sahrens } 1351789Sahrens 13526423Sgw25295 int 13534787Sahrens zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) 1354789Sahrens { 13552676Seschrock nvpair_t *elem; 13562676Seschrock int error; 13572676Seschrock uint64_t intval; 13582676Seschrock char *strval; 13592676Seschrock 13604543Smarks /* 13614543Smarks * First validate permission to set all of the properties 13624543Smarks */ 13632676Seschrock elem = NULL; 13642676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 13654670Sahrens const char *propname = nvpair_name(elem); 13664670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 13672676Seschrock 13685094Slling if (prop == ZPROP_INVAL) { 13692676Seschrock /* 13702676Seschrock * If this is a user-defined property, it must be a 13712676Seschrock * string, and there is no further validation to do. 13722676Seschrock */ 13732676Seschrock if (!zfs_prop_user(propname) || 13742676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 13752676Seschrock return (EINVAL); 13762676Seschrock 13775331Samw if (error = zfs_secpolicy_write_perms(name, 13785331Samw ZFS_DELEG_PERM_USERPROP, CRED())) 13794670Sahrens return (error); 13804543Smarks continue; 13812676Seschrock } 13822676Seschrock 13834787Sahrens if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 13844670Sahrens return (error); 13852676Seschrock 13864670Sahrens /* 13874670Sahrens * Check that this value is valid for this pool version 13884670Sahrens */ 13894670Sahrens switch (prop) { 13903886Sahl case ZFS_PROP_COMPRESSION: 13913886Sahl /* 13923886Sahl * If the user specified gzip compression, make sure 13933886Sahl * the SPA supports it. We ignore any errors here since 13943886Sahl * we'll catch them later. 13953886Sahl */ 13963886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 1397*7042Sgw25295 nvpair_value_uint64(elem, &intval) == 0) { 1398*7042Sgw25295 if (intval >= ZIO_COMPRESS_GZIP_1 && 1399*7042Sgw25295 intval <= ZIO_COMPRESS_GZIP_9 && 1400*7042Sgw25295 zfs_check_version(name, 14015331Samw SPA_VERSION_GZIP_COMPRESSION)) 14025331Samw return (ENOTSUP); 1403*7042Sgw25295 1404*7042Sgw25295 /* 1405*7042Sgw25295 * If this is a bootable dataset then 1406*7042Sgw25295 * verify that the compression algorithm 1407*7042Sgw25295 * is supported for booting. We must return 1408*7042Sgw25295 * something other than ENOTSUP since it 1409*7042Sgw25295 * implies a downrev pool version. 1410*7042Sgw25295 */ 1411*7042Sgw25295 if (zfs_is_bootfs(name) && 1412*7042Sgw25295 !BOOTFS_COMPRESS_VALID(intval)) 1413*7042Sgw25295 return (ERANGE); 14143886Sahl } 14153886Sahl break; 14164603Sahrens 14174603Sahrens case ZFS_PROP_COPIES: 14185331Samw if (zfs_check_version(name, SPA_VERSION_DITTO_BLOCKS)) 14195331Samw return (ENOTSUP); 14204603Sahrens break; 14215977Smarks 14225977Smarks case ZFS_PROP_SHARESMB: 14236689Smaybee if (zpl_earlier_version(name, ZPL_VERSION_FUID)) 14245977Smarks return (ENOTSUP); 14255977Smarks break; 14264603Sahrens } 14275331Samw if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 14285331Samw return (error); 14294543Smarks } 14304543Smarks 14314543Smarks elem = NULL; 14324543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 14334670Sahrens const char *propname = nvpair_name(elem); 14344670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 14354543Smarks 14365094Slling if (prop == ZPROP_INVAL) { 14374543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 14384543Smarks error = dsl_prop_set(name, propname, 1, 14394543Smarks strlen(strval) + 1, strval); 14404543Smarks if (error == 0) 14414543Smarks continue; 14424543Smarks else 14434543Smarks return (error); 14444543Smarks } 14452676Seschrock 14462676Seschrock switch (prop) { 14472676Seschrock case ZFS_PROP_QUOTA: 14482676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14494577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 14502676Seschrock return (error); 14512676Seschrock break; 14522676Seschrock 14535378Sck153898 case ZFS_PROP_REFQUOTA: 14545378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14555378Sck153898 (error = dsl_dataset_set_quota(name, intval)) != 0) 14565378Sck153898 return (error); 14575378Sck153898 break; 14585378Sck153898 14592676Seschrock case ZFS_PROP_RESERVATION: 14602676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14612676Seschrock (error = dsl_dir_set_reservation(name, 14622676Seschrock intval)) != 0) 14632676Seschrock return (error); 14642676Seschrock break; 1465789Sahrens 14665378Sck153898 case ZFS_PROP_REFRESERVATION: 14675378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14685378Sck153898 (error = dsl_dataset_set_reservation(name, 14695378Sck153898 intval)) != 0) 14705378Sck153898 return (error); 14715378Sck153898 break; 14725378Sck153898 14732676Seschrock case ZFS_PROP_VOLSIZE: 14742676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14754787Sahrens (error = zvol_set_volsize(name, 14764787Sahrens ddi_driver_major(zfs_dip), intval)) != 0) 14772676Seschrock return (error); 14782676Seschrock break; 14792676Seschrock 14802676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 14812676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14824577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 14834577Sahrens return (error); 14844577Sahrens break; 14854577Sahrens 14864577Sahrens case ZFS_PROP_VERSION: 14874577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14884577Sahrens (error = zfs_set_version(name, intval)) != 0) 14892676Seschrock return (error); 14902676Seschrock break; 14912676Seschrock 14922676Seschrock default: 14932676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 14942676Seschrock if (zfs_prop_get_type(prop) != 14954787Sahrens PROP_TYPE_STRING) 14962676Seschrock return (EINVAL); 14972717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 14982717Seschrock if ((error = dsl_prop_set(name, 14992676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 15002717Seschrock strval)) != 0) 15012717Seschrock return (error); 15022676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 15032885Sahrens const char *unused; 15042885Sahrens 15052717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 15062676Seschrock 15072676Seschrock switch (zfs_prop_get_type(prop)) { 15084787Sahrens case PROP_TYPE_NUMBER: 15092676Seschrock break; 15104787Sahrens case PROP_TYPE_STRING: 15112717Seschrock return (EINVAL); 15124787Sahrens case PROP_TYPE_INDEX: 15132717Seschrock if (zfs_prop_index_to_string(prop, 15142717Seschrock intval, &unused) != 0) 15152717Seschrock return (EINVAL); 15162676Seschrock break; 15172676Seschrock default: 15184577Sahrens cmn_err(CE_PANIC, 15194577Sahrens "unknown property type"); 15202676Seschrock break; 15212676Seschrock } 15222676Seschrock 15232717Seschrock if ((error = dsl_prop_set(name, propname, 15242717Seschrock 8, 1, &intval)) != 0) 15252717Seschrock return (error); 15262676Seschrock } else { 15272676Seschrock return (EINVAL); 15282676Seschrock } 15292676Seschrock break; 15302676Seschrock } 15312676Seschrock } 15322676Seschrock 15332676Seschrock return (0); 1534789Sahrens } 1535789Sahrens 15365367Sahrens /* 15375367Sahrens * inputs: 15385367Sahrens * zc_name name of filesystem 15395367Sahrens * zc_value name of property to inherit 15405367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 15415367Sahrens * 15425367Sahrens * outputs: none 15435367Sahrens */ 1544789Sahrens static int 15452676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1546789Sahrens { 15472676Seschrock nvlist_t *nvl; 15482676Seschrock int error; 1549789Sahrens 15505094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15515094Slling &nvl)) != 0) 15522676Seschrock return (error); 15532676Seschrock 15544787Sahrens error = zfs_set_prop_nvlist(zc->zc_name, nvl); 15554543Smarks 15562676Seschrock nvlist_free(nvl); 15572676Seschrock return (error); 1558789Sahrens } 1559789Sahrens 15605367Sahrens /* 15615367Sahrens * inputs: 15625367Sahrens * zc_name name of filesystem 15635367Sahrens * zc_value name of property to inherit 15645367Sahrens * 15655367Sahrens * outputs: none 15665367Sahrens */ 1567789Sahrens static int 15684849Sahrens zfs_ioc_inherit_prop(zfs_cmd_t *zc) 15694849Sahrens { 15704849Sahrens /* the property name has been validated by zfs_secpolicy_inherit() */ 15714849Sahrens return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 15724849Sahrens } 15734849Sahrens 15744849Sahrens static int 15754098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 15763912Slling { 15775094Slling nvlist_t *props; 15783912Slling spa_t *spa; 15795094Slling int error; 15803912Slling 15815094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15825094Slling &props))) 15833912Slling return (error); 15843912Slling 15853912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 15865094Slling nvlist_free(props); 15873912Slling return (error); 15883912Slling } 15893912Slling 15905094Slling error = spa_prop_set(spa, props); 15913912Slling 15925094Slling nvlist_free(props); 15933912Slling spa_close(spa, FTAG); 15943912Slling 15953912Slling return (error); 15963912Slling } 15973912Slling 15983912Slling static int 15994098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 16003912Slling { 16013912Slling spa_t *spa; 16023912Slling int error; 16033912Slling nvlist_t *nvp = NULL; 16043912Slling 16053912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 16063912Slling return (error); 16073912Slling 16085094Slling error = spa_prop_get(spa, &nvp); 16093912Slling 16103912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 16113912Slling error = put_nvlist(zc, nvp); 16123912Slling else 16133912Slling error = EFAULT; 16143912Slling 16153912Slling spa_close(spa, FTAG); 16163912Slling 16173912Slling if (nvp) 16183912Slling nvlist_free(nvp); 16193912Slling return (error); 16203912Slling } 16213912Slling 16223912Slling static int 16234543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 16244543Smarks { 16254543Smarks nvlist_t *nvp; 16264543Smarks int error; 16274543Smarks uint32_t uid; 16284543Smarks uint32_t gid; 16294543Smarks uint32_t *groups; 16304543Smarks uint_t group_cnt; 16314543Smarks cred_t *usercred; 16324543Smarks 16335094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16345094Slling &nvp)) != 0) { 16354543Smarks return (error); 16364543Smarks } 16374543Smarks 16384543Smarks if ((error = nvlist_lookup_uint32(nvp, 16394543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 16404543Smarks nvlist_free(nvp); 16414543Smarks return (EPERM); 16424543Smarks } 16434543Smarks 16444543Smarks if ((error = nvlist_lookup_uint32(nvp, 16454543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 16464543Smarks nvlist_free(nvp); 16474543Smarks return (EPERM); 16484543Smarks } 16494543Smarks 16504543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 16514543Smarks &groups, &group_cnt)) != 0) { 16524543Smarks nvlist_free(nvp); 16534543Smarks return (EPERM); 16544543Smarks } 16554543Smarks usercred = cralloc(); 16564543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 16574543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 16584543Smarks nvlist_free(nvp); 16594543Smarks crfree(usercred); 16604543Smarks return (EPERM); 16614543Smarks } 16624543Smarks nvlist_free(nvp); 16634543Smarks error = dsl_deleg_access(zc->zc_name, 16644787Sahrens zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); 16654543Smarks crfree(usercred); 16664543Smarks return (error); 16674543Smarks } 16684543Smarks 16695367Sahrens /* 16705367Sahrens * inputs: 16715367Sahrens * zc_name name of filesystem 16725367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 16735367Sahrens * zc_perm_action allow/unallow flag 16745367Sahrens * 16755367Sahrens * outputs: none 16765367Sahrens */ 16774543Smarks static int 16784543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 16794543Smarks { 16804543Smarks int error; 16814543Smarks nvlist_t *fsaclnv = NULL; 16824543Smarks 16835094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16845094Slling &fsaclnv)) != 0) 16854543Smarks return (error); 16864543Smarks 16874543Smarks /* 16884543Smarks * Verify nvlist is constructed correctly 16894543Smarks */ 16904543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 16914543Smarks nvlist_free(fsaclnv); 16924543Smarks return (EINVAL); 16934543Smarks } 16944543Smarks 16954543Smarks /* 16964543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 16974543Smarks * that user is allowed to hand out each permission in 16984543Smarks * the nvlist(s) 16994543Smarks */ 17004543Smarks 17014787Sahrens error = secpolicy_zfs(CRED()); 17024543Smarks if (error) { 17034787Sahrens if (zc->zc_perm_action == B_FALSE) { 17044787Sahrens error = dsl_deleg_can_allow(zc->zc_name, 17054787Sahrens fsaclnv, CRED()); 17064787Sahrens } else { 17074787Sahrens error = dsl_deleg_can_unallow(zc->zc_name, 17084787Sahrens fsaclnv, CRED()); 17094787Sahrens } 17104543Smarks } 17114543Smarks 17124543Smarks if (error == 0) 17134543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 17144543Smarks 17154543Smarks nvlist_free(fsaclnv); 17164543Smarks return (error); 17174543Smarks } 17184543Smarks 17195367Sahrens /* 17205367Sahrens * inputs: 17215367Sahrens * zc_name name of filesystem 17225367Sahrens * 17235367Sahrens * outputs: 17245367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 17255367Sahrens */ 17264543Smarks static int 17274543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 17284543Smarks { 17294543Smarks nvlist_t *nvp; 17304543Smarks int error; 17314543Smarks 17324543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 17334543Smarks error = put_nvlist(zc, nvp); 17344543Smarks nvlist_free(nvp); 17354543Smarks } 17364543Smarks 17374543Smarks return (error); 17384543Smarks } 17394543Smarks 17405367Sahrens /* 17415367Sahrens * inputs: 17425367Sahrens * zc_name name of volume 17435367Sahrens * 17445367Sahrens * outputs: none 17455367Sahrens */ 17464543Smarks static int 1747789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1748789Sahrens { 17494787Sahrens return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); 1750789Sahrens } 1751789Sahrens 17525367Sahrens /* 17535367Sahrens * inputs: 17545367Sahrens * zc_name name of volume 17555367Sahrens * 17565367Sahrens * outputs: none 17575367Sahrens */ 1758789Sahrens static int 1759789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1760789Sahrens { 17612676Seschrock return (zvol_remove_minor(zc->zc_name)); 1762789Sahrens } 1763789Sahrens 1764789Sahrens /* 1765789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1766789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1767789Sahrens * is responsible for releasing the returned vfs pointer. 1768789Sahrens */ 1769789Sahrens static vfs_t * 1770789Sahrens zfs_get_vfs(const char *resource) 1771789Sahrens { 1772789Sahrens struct vfs *vfsp; 1773789Sahrens struct vfs *vfs_found = NULL; 1774789Sahrens 1775789Sahrens vfs_list_read_lock(); 1776789Sahrens vfsp = rootvfs; 1777789Sahrens do { 1778789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1779789Sahrens VFS_HOLD(vfsp); 1780789Sahrens vfs_found = vfsp; 1781789Sahrens break; 1782789Sahrens } 1783789Sahrens vfsp = vfsp->vfs_next; 1784789Sahrens } while (vfsp != rootvfs); 1785789Sahrens vfs_list_unlock(); 1786789Sahrens return (vfs_found); 1787789Sahrens } 1788789Sahrens 17894543Smarks /* ARGSUSED */ 1790789Sahrens static void 17914543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1792789Sahrens { 17935331Samw zfs_creat_t *zct = arg; 17945498Stimh 17955498Stimh zfs_create_fs(os, cr, zct->zct_zplprops, tx); 17965331Samw } 17975331Samw 17985498Stimh #define ZFS_PROP_UNDEFINED ((uint64_t)-1) 17995498Stimh 18005331Samw /* 18015498Stimh * inputs: 18025498Stimh * createprops list of properties requested by creator 18035498Stimh * dataset name of dataset we are creating 18045331Samw * 18055498Stimh * outputs: 18065498Stimh * zplprops values for the zplprops we attach to the master node object 18075331Samw * 18085498Stimh * Determine the settings for utf8only, normalization and 18095498Stimh * casesensitivity. Specific values may have been requested by the 18105498Stimh * creator and/or we can inherit values from the parent dataset. If 18115498Stimh * the file system is of too early a vintage, a creator can not 18125498Stimh * request settings for these properties, even if the requested 18135498Stimh * setting is the default value. We don't actually want to create dsl 18145498Stimh * properties for these, so remove them from the source nvlist after 18155498Stimh * processing. 18165331Samw */ 18175331Samw static int 18185498Stimh zfs_fill_zplprops(const char *dataset, nvlist_t *createprops, 18196492Stimh nvlist_t *zplprops, uint64_t zplver, boolean_t *is_ci) 18205331Samw { 18215498Stimh objset_t *os; 18225331Samw char parentname[MAXNAMELEN]; 18235331Samw char *cp; 18245498Stimh uint64_t sense = ZFS_PROP_UNDEFINED; 18255498Stimh uint64_t norm = ZFS_PROP_UNDEFINED; 18265498Stimh uint64_t u8 = ZFS_PROP_UNDEFINED; 18275498Stimh int error = 0; 18285498Stimh 18295498Stimh ASSERT(zplprops != NULL); 18305498Stimh 18315498Stimh (void) strlcpy(parentname, dataset, sizeof (parentname)); 18325498Stimh cp = strrchr(parentname, '/'); 18335498Stimh ASSERT(cp != NULL); 18345498Stimh cp[0] = '\0'; 18355331Samw 18365375Stimh /* 18375498Stimh * Pull out creator prop choices, if any. 18385375Stimh */ 18395498Stimh if (createprops) { 18405498Stimh (void) nvlist_lookup_uint64(createprops, 18415498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE), &norm); 18425498Stimh (void) nvlist_remove_all(createprops, 18435498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE)); 18445498Stimh (void) nvlist_lookup_uint64(createprops, 18455498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY), &u8); 18465498Stimh (void) nvlist_remove_all(createprops, 18475498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY)); 18485498Stimh (void) nvlist_lookup_uint64(createprops, 18495498Stimh zfs_prop_to_name(ZFS_PROP_CASE), &sense); 18505498Stimh (void) nvlist_remove_all(createprops, 18515498Stimh zfs_prop_to_name(ZFS_PROP_CASE)); 18525331Samw } 18535331Samw 18545375Stimh /* 18555498Stimh * If the file system or pool is version is too "young" to 18565498Stimh * support normalization and the creator tried to set a value 18575498Stimh * for one of the props, error out. We only need check the 18585498Stimh * ZPL version because we've already checked by now that the 18595498Stimh * SPA version is compatible with the selected ZPL version. 18605498Stimh */ 18615498Stimh if (zplver < ZPL_VERSION_NORMALIZATION && 18625498Stimh (norm != ZFS_PROP_UNDEFINED || u8 != ZFS_PROP_UNDEFINED || 18635498Stimh sense != ZFS_PROP_UNDEFINED)) 18645498Stimh return (ENOTSUP); 18655498Stimh 18665498Stimh /* 18675498Stimh * Put the version in the zplprops 18685498Stimh */ 18695498Stimh VERIFY(nvlist_add_uint64(zplprops, 18705498Stimh zfs_prop_to_name(ZFS_PROP_VERSION), zplver) == 0); 18715498Stimh 18725498Stimh /* 18735498Stimh * Open parent object set so we can inherit zplprop values if 18745498Stimh * necessary. 18755375Stimh */ 18766689Smaybee if (error = dmu_objset_open(parentname, 18776689Smaybee DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os)) 18785498Stimh return (error); 18795498Stimh 18805498Stimh if (norm == ZFS_PROP_UNDEFINED) 18815498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &norm) == 0); 18825498Stimh VERIFY(nvlist_add_uint64(zplprops, 18835498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE), norm) == 0); 18845498Stimh 18855498Stimh /* 18865498Stimh * If we're normalizing, names must always be valid UTF-8 strings. 18875498Stimh */ 18885498Stimh if (norm) 18895498Stimh u8 = 1; 18905498Stimh if (u8 == ZFS_PROP_UNDEFINED) 18915498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &u8) == 0); 18925498Stimh VERIFY(nvlist_add_uint64(zplprops, 18935498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY), u8) == 0); 18945498Stimh 18955498Stimh if (sense == ZFS_PROP_UNDEFINED) 18965498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_CASE, &sense) == 0); 18975498Stimh VERIFY(nvlist_add_uint64(zplprops, 18985498Stimh zfs_prop_to_name(ZFS_PROP_CASE), sense) == 0); 18995498Stimh 19006492Stimh if (is_ci) 19016492Stimh *is_ci = (sense == ZFS_CASE_INSENSITIVE); 19026492Stimh 19035498Stimh dmu_objset_close(os); 19045331Samw return (0); 1905789Sahrens } 1906789Sahrens 19075367Sahrens /* 19085367Sahrens * inputs: 19095367Sahrens * zc_objset_type type of objset to create (fs vs zvol) 19105367Sahrens * zc_name name of new objset 19115367Sahrens * zc_value name of snapshot to clone from (may be empty) 19125367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 19135367Sahrens * 19145498Stimh * outputs: none 19155367Sahrens */ 1916789Sahrens static int 1917789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1918789Sahrens { 1919789Sahrens objset_t *clone; 1920789Sahrens int error = 0; 19215331Samw zfs_creat_t zct; 19224543Smarks nvlist_t *nvprops = NULL; 19234543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1924789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1925789Sahrens 1926789Sahrens switch (type) { 1927789Sahrens 1928789Sahrens case DMU_OST_ZFS: 1929789Sahrens cbfunc = zfs_create_cb; 1930789Sahrens break; 1931789Sahrens 1932789Sahrens case DMU_OST_ZVOL: 1933789Sahrens cbfunc = zvol_create_cb; 1934789Sahrens break; 1935789Sahrens 1936789Sahrens default: 19372199Sahrens cbfunc = NULL; 19386423Sgw25295 break; 19392199Sahrens } 19405326Sek110237 if (strchr(zc->zc_name, '@') || 19415326Sek110237 strchr(zc->zc_name, '%')) 1942789Sahrens return (EINVAL); 1943789Sahrens 19442676Seschrock if (zc->zc_nvlist_src != NULL && 19455094Slling (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 19465094Slling &nvprops)) != 0) 19472676Seschrock return (error); 19482676Seschrock 19495498Stimh zct.zct_zplprops = NULL; 19505331Samw zct.zct_props = nvprops; 19515331Samw 19522676Seschrock if (zc->zc_value[0] != '\0') { 1953789Sahrens /* 1954789Sahrens * We're creating a clone of an existing snapshot. 1955789Sahrens */ 19562676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 19572676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 19584543Smarks nvlist_free(nvprops); 1959789Sahrens return (EINVAL); 19602676Seschrock } 1961789Sahrens 19622676Seschrock error = dmu_objset_open(zc->zc_value, type, 19636689Smaybee DS_MODE_USER | DS_MODE_READONLY, &clone); 19642676Seschrock if (error) { 19654543Smarks nvlist_free(nvprops); 1966789Sahrens return (error); 19672676Seschrock } 19686492Stimh 19696492Stimh error = dmu_objset_create(zc->zc_name, type, clone, 0, 19706492Stimh NULL, NULL); 19715331Samw if (error) { 19725331Samw dmu_objset_close(clone); 19735331Samw nvlist_free(nvprops); 19745331Samw return (error); 19755331Samw } 1976789Sahrens dmu_objset_close(clone); 1977789Sahrens } else { 19786492Stimh boolean_t is_insensitive = B_FALSE; 19796492Stimh 19802676Seschrock if (cbfunc == NULL) { 19814543Smarks nvlist_free(nvprops); 19822199Sahrens return (EINVAL); 19832676Seschrock } 19842676Seschrock 1985789Sahrens if (type == DMU_OST_ZVOL) { 19862676Seschrock uint64_t volsize, volblocksize; 19872676Seschrock 19884543Smarks if (nvprops == NULL || 19894543Smarks nvlist_lookup_uint64(nvprops, 19902676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 19912676Seschrock &volsize) != 0) { 19924543Smarks nvlist_free(nvprops); 19932676Seschrock return (EINVAL); 19942676Seschrock } 19952676Seschrock 19964543Smarks if ((error = nvlist_lookup_uint64(nvprops, 19972676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 19982676Seschrock &volblocksize)) != 0 && error != ENOENT) { 19994543Smarks nvlist_free(nvprops); 20002676Seschrock return (EINVAL); 20012676Seschrock } 20021133Seschrock 20032676Seschrock if (error != 0) 20042676Seschrock volblocksize = zfs_prop_default_numeric( 20052676Seschrock ZFS_PROP_VOLBLOCKSIZE); 20062676Seschrock 20072676Seschrock if ((error = zvol_check_volblocksize( 20082676Seschrock volblocksize)) != 0 || 20092676Seschrock (error = zvol_check_volsize(volsize, 20102676Seschrock volblocksize)) != 0) { 20114543Smarks nvlist_free(nvprops); 2012789Sahrens return (error); 20132676Seschrock } 20144577Sahrens } else if (type == DMU_OST_ZFS) { 20154577Sahrens uint64_t version; 20165331Samw int error; 20175331Samw 20185498Stimh /* 20195498Stimh * Default ZPL version to non-FUID capable if the 20205498Stimh * pool is not upgraded to support FUIDs. 20215498Stimh */ 20225498Stimh if (zfs_check_version(zc->zc_name, SPA_VERSION_FUID)) 20235498Stimh version = ZPL_VERSION_FUID - 1; 20245498Stimh else 20255498Stimh version = ZPL_VERSION; 20265498Stimh 20275498Stimh /* 20285498Stimh * Potentially override default ZPL version based 20295498Stimh * on creator's request. 20305498Stimh */ 20315498Stimh (void) nvlist_lookup_uint64(nvprops, 20325331Samw zfs_prop_to_name(ZFS_PROP_VERSION), &version); 20335331Samw 20345498Stimh /* 20355498Stimh * Make sure version we ended up with is kosher 20365498Stimh */ 20375498Stimh if ((version < ZPL_VERSION_INITIAL || 20385498Stimh version > ZPL_VERSION) || 20395498Stimh (version >= ZPL_VERSION_FUID && 20405498Stimh zfs_check_version(zc->zc_name, SPA_VERSION_FUID))) { 20415331Samw nvlist_free(nvprops); 20425331Samw return (ENOTSUP); 20435331Samw } 20445331Samw 20455331Samw /* 20465331Samw * We have to have normalization and 20475331Samw * case-folding flags correct when we do the 20485331Samw * file system creation, so go figure them out 20495498Stimh * now. 20505331Samw */ 20515498Stimh VERIFY(nvlist_alloc(&zct.zct_zplprops, 20525498Stimh NV_UNIQUE_NAME, KM_SLEEP) == 0); 20535498Stimh error = zfs_fill_zplprops(zc->zc_name, nvprops, 20546492Stimh zct.zct_zplprops, version, &is_insensitive); 20555331Samw if (error != 0) { 20565331Samw nvlist_free(nvprops); 20575498Stimh nvlist_free(zct.zct_zplprops); 20585331Samw return (error); 20594577Sahrens } 20602676Seschrock } 20616492Stimh error = dmu_objset_create(zc->zc_name, type, NULL, 20626492Stimh is_insensitive ? DS_FLAG_CI_DATASET : 0, cbfunc, &zct); 20635498Stimh nvlist_free(zct.zct_zplprops); 2064789Sahrens } 20652676Seschrock 20662676Seschrock /* 20672676Seschrock * It would be nice to do this atomically. 20682676Seschrock */ 20692676Seschrock if (error == 0) { 20704787Sahrens if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) 20712676Seschrock (void) dmu_objset_destroy(zc->zc_name); 20722676Seschrock } 20734543Smarks nvlist_free(nvprops); 2074789Sahrens return (error); 2075789Sahrens } 2076789Sahrens 20775367Sahrens /* 20785367Sahrens * inputs: 20795367Sahrens * zc_name name of filesystem 20805367Sahrens * zc_value short name of snapshot 20815367Sahrens * zc_cookie recursive flag 20825367Sahrens * 20835367Sahrens * outputs: none 20845367Sahrens */ 2085789Sahrens static int 20862199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 20872199Sahrens { 20882676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 20892199Sahrens return (EINVAL); 20902199Sahrens return (dmu_objset_snapshot(zc->zc_name, 20912676Seschrock zc->zc_value, zc->zc_cookie)); 20922199Sahrens } 20932199Sahrens 20944007Smmusante int 20952199Sahrens zfs_unmount_snap(char *name, void *arg) 2096789Sahrens { 20972417Sahrens vfs_t *vfsp = NULL; 20982199Sahrens 20996689Smaybee if (arg) { 21006689Smaybee char *snapname = arg; 21016689Smaybee int len = strlen(name) + strlen(snapname) + 2; 21026689Smaybee char *buf = kmem_alloc(len, KM_SLEEP); 21036689Smaybee 21046689Smaybee (void) strcpy(buf, name); 21056689Smaybee (void) strcat(buf, "@"); 21066689Smaybee (void) strcat(buf, snapname); 21076689Smaybee vfsp = zfs_get_vfs(buf); 21086689Smaybee kmem_free(buf, len); 21092417Sahrens } else if (strchr(name, '@')) { 21102199Sahrens vfsp = zfs_get_vfs(name); 21112199Sahrens } 21122199Sahrens 21132199Sahrens if (vfsp) { 21142199Sahrens /* 21152199Sahrens * Always force the unmount for snapshots. 21162199Sahrens */ 21172199Sahrens int flag = MS_FORCE; 2118789Sahrens int err; 2119789Sahrens 21202199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 21212199Sahrens VFS_RELE(vfsp); 21222199Sahrens return (err); 21232199Sahrens } 21242199Sahrens VFS_RELE(vfsp); 21252199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 21262199Sahrens return (err); 21272199Sahrens } 21282199Sahrens return (0); 21292199Sahrens } 21302199Sahrens 21315367Sahrens /* 21325367Sahrens * inputs: 21335367Sahrens * zc_name name of filesystem 21345367Sahrens * zc_value short name of snapshot 21355367Sahrens * 21365367Sahrens * outputs: none 21375367Sahrens */ 21382199Sahrens static int 21392199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 21402199Sahrens { 21412199Sahrens int err; 2142789Sahrens 21432676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 21442199Sahrens return (EINVAL); 21452199Sahrens err = dmu_objset_find(zc->zc_name, 21462676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 21472199Sahrens if (err) 21482199Sahrens return (err); 21492676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 21502199Sahrens } 21512199Sahrens 21525367Sahrens /* 21535367Sahrens * inputs: 21545367Sahrens * zc_name name of dataset to destroy 21555367Sahrens * zc_objset_type type of objset 21565367Sahrens * 21575367Sahrens * outputs: none 21585367Sahrens */ 21592199Sahrens static int 21602199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 21612199Sahrens { 21622199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 21632199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 21642199Sahrens if (err) 21652199Sahrens return (err); 2166789Sahrens } 2167789Sahrens 2168789Sahrens return (dmu_objset_destroy(zc->zc_name)); 2169789Sahrens } 2170789Sahrens 21715367Sahrens /* 21725367Sahrens * inputs: 21735446Sahrens * zc_name name of dataset to rollback (to most recent snapshot) 21745367Sahrens * 21755367Sahrens * outputs: none 21765367Sahrens */ 2177789Sahrens static int 2178789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 2179789Sahrens { 21805446Sahrens objset_t *os; 21815446Sahrens int error; 21825446Sahrens zfsvfs_t *zfsvfs = NULL; 21835446Sahrens 21845446Sahrens /* 21855446Sahrens * Get the zfsvfs for the receiving objset. There 21865446Sahrens * won't be one if we're operating on a zvol, if the 21875446Sahrens * objset doesn't exist yet, or is not mounted. 21885446Sahrens */ 21896689Smaybee error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, DS_MODE_USER, &os); 21905446Sahrens if (error) 21915446Sahrens return (error); 21925446Sahrens 21935446Sahrens if (dmu_objset_type(os) == DMU_OST_ZFS) { 21945446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 21955446Sahrens zfsvfs = dmu_objset_get_user(os); 21965446Sahrens if (zfsvfs != NULL) 21975446Sahrens VFS_HOLD(zfsvfs->z_vfs); 21985446Sahrens mutex_exit(&os->os->os_user_ptr_lock); 21995446Sahrens } 22005446Sahrens 22015446Sahrens if (zfsvfs != NULL) { 22025446Sahrens char osname[MAXNAMELEN]; 22035446Sahrens int mode; 22045446Sahrens 22056083Sek110237 error = zfs_suspend_fs(zfsvfs, osname, &mode); 22066083Sek110237 if (error == 0) { 22076083Sek110237 int resume_err; 22086083Sek110237 22096083Sek110237 ASSERT(strcmp(osname, zc->zc_name) == 0); 22106083Sek110237 error = dmu_objset_rollback(os); 22116083Sek110237 resume_err = zfs_resume_fs(zfsvfs, osname, mode); 22126083Sek110237 error = error ? error : resume_err; 22136083Sek110237 } else { 22146083Sek110237 dmu_objset_close(os); 22156083Sek110237 } 22165446Sahrens VFS_RELE(zfsvfs->z_vfs); 22175446Sahrens } else { 22185446Sahrens error = dmu_objset_rollback(os); 22195446Sahrens } 22206689Smaybee /* Note, the dmu_objset_rollback() releases the objset for us. */ 22215446Sahrens 22225446Sahrens return (error); 2223789Sahrens } 2224789Sahrens 22255367Sahrens /* 22265367Sahrens * inputs: 22275367Sahrens * zc_name old name of dataset 22285367Sahrens * zc_value new name of dataset 22295367Sahrens * zc_cookie recursive flag (only valid for snapshots) 22305367Sahrens * 22315367Sahrens * outputs: none 22325367Sahrens */ 2233789Sahrens static int 2234789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 2235789Sahrens { 22364490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 22374007Smmusante 22382676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 22395326Sek110237 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 22405326Sek110237 strchr(zc->zc_value, '%')) 2241789Sahrens return (EINVAL); 2242789Sahrens 22434007Smmusante /* 22444007Smmusante * Unmount snapshot unless we're doing a recursive rename, 22454007Smmusante * in which case the dataset code figures out which snapshots 22464007Smmusante * to unmount. 22474007Smmusante */ 22484007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 2249789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 22502199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 22512199Sahrens if (err) 22522199Sahrens return (err); 2253789Sahrens } 22544007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 2255789Sahrens } 2256789Sahrens 22576689Smaybee static void 22586689Smaybee clear_props(char *dataset, nvlist_t *props) 22596689Smaybee { 22606689Smaybee zfs_cmd_t *zc; 22616689Smaybee nvpair_t *prop; 22626689Smaybee 22636689Smaybee if (props == NULL) 22646689Smaybee return; 22656689Smaybee zc = kmem_alloc(sizeof (zfs_cmd_t), KM_SLEEP); 22666689Smaybee (void) strcpy(zc->zc_name, dataset); 22676689Smaybee for (prop = nvlist_next_nvpair(props, NULL); prop; 22686689Smaybee prop = nvlist_next_nvpair(props, prop)) { 22696689Smaybee (void) strcpy(zc->zc_value, nvpair_name(prop)); 22706689Smaybee if (zfs_secpolicy_inherit(zc, CRED()) == 0) 22716689Smaybee (void) zfs_ioc_inherit_prop(zc); 22726689Smaybee } 22736689Smaybee kmem_free(zc, sizeof (zfs_cmd_t)); 22746689Smaybee } 22756689Smaybee 22765367Sahrens /* 22775367Sahrens * inputs: 22785367Sahrens * zc_name name of containing filesystem 22795367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 22805367Sahrens * zc_value name of snapshot to create 22815367Sahrens * zc_string name of clone origin (if DRR_FLAG_CLONE) 22825367Sahrens * zc_cookie file descriptor to recv from 22835367Sahrens * zc_begin_record the BEGIN record of the stream (not byteswapped) 22845367Sahrens * zc_guid force flag 22855367Sahrens * 22865367Sahrens * outputs: 22875367Sahrens * zc_cookie number of bytes read 22885367Sahrens */ 2289789Sahrens static int 22905367Sahrens zfs_ioc_recv(zfs_cmd_t *zc) 2291789Sahrens { 2292789Sahrens file_t *fp; 22935326Sek110237 objset_t *os; 22945367Sahrens dmu_recv_cookie_t drc; 22955326Sek110237 zfsvfs_t *zfsvfs = NULL; 22965326Sek110237 boolean_t force = (boolean_t)zc->zc_guid; 2297789Sahrens int error, fd; 22985367Sahrens offset_t off; 22995367Sahrens nvlist_t *props = NULL; 23006689Smaybee nvlist_t *origprops = NULL; 23015367Sahrens objset_t *origin = NULL; 23025367Sahrens char *tosnap; 23035367Sahrens char tofs[ZFS_MAXNAMELEN]; 2304789Sahrens 23053265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 23065326Sek110237 strchr(zc->zc_value, '@') == NULL || 23075326Sek110237 strchr(zc->zc_value, '%')) 23083265Sahrens return (EINVAL); 23093265Sahrens 23105367Sahrens (void) strcpy(tofs, zc->zc_value); 23115367Sahrens tosnap = strchr(tofs, '@'); 23125367Sahrens *tosnap = '\0'; 23135367Sahrens tosnap++; 23145367Sahrens 23155367Sahrens if (zc->zc_nvlist_src != NULL && 23165367Sahrens (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 23175367Sahrens &props)) != 0) 23185367Sahrens return (error); 23195367Sahrens 2320789Sahrens fd = zc->zc_cookie; 2321789Sahrens fp = getf(fd); 23225367Sahrens if (fp == NULL) { 23235367Sahrens nvlist_free(props); 2324789Sahrens return (EBADF); 23255367Sahrens } 23265326Sek110237 23276689Smaybee if (dmu_objset_open(tofs, DMU_OST_ANY, 23286689Smaybee DS_MODE_USER | DS_MODE_READONLY, &os) == 0) { 23296689Smaybee /* 23306689Smaybee * Try to get the zfsvfs for the receiving objset. 23316689Smaybee * There won't be one if we're operating on a zvol, 23326689Smaybee * if the objset doesn't exist yet, or is not mounted. 23336689Smaybee */ 23345446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 23356689Smaybee if (zfsvfs = dmu_objset_get_user(os)) { 23366083Sek110237 if (!mutex_tryenter(&zfsvfs->z_online_recv_lock)) { 23376689Smaybee mutex_exit(&os->os->os_user_ptr_lock); 23386083Sek110237 dmu_objset_close(os); 23396689Smaybee zfsvfs = NULL; 23406689Smaybee error = EBUSY; 23416689Smaybee goto out; 23426083Sek110237 } 23436689Smaybee VFS_HOLD(zfsvfs->z_vfs); 23446083Sek110237 } 23456689Smaybee mutex_exit(&os->os->os_user_ptr_lock); 23466689Smaybee 23476689Smaybee /* 23486689Smaybee * If new properties are supplied, they are to completely 23496689Smaybee * replace the existing ones, so stash away the existing ones. 23506689Smaybee */ 23516689Smaybee if (props) 23526689Smaybee (void) dsl_prop_get_all(os, &origprops, TRUE); 23536689Smaybee 23545326Sek110237 dmu_objset_close(os); 23555326Sek110237 } 23565326Sek110237 23575367Sahrens if (zc->zc_string[0]) { 23585367Sahrens error = dmu_objset_open(zc->zc_string, DMU_OST_ANY, 23596689Smaybee DS_MODE_USER | DS_MODE_READONLY, &origin); 23606689Smaybee if (error) 23616689Smaybee goto out; 23625367Sahrens } 23635367Sahrens 23645367Sahrens error = dmu_recv_begin(tofs, tosnap, &zc->zc_begin_record, 23655367Sahrens force, origin, zfsvfs != NULL, &drc); 23665367Sahrens if (origin) 23675367Sahrens dmu_objset_close(origin); 23686689Smaybee if (error) 23696689Smaybee goto out; 23705326Sek110237 23715326Sek110237 /* 23726689Smaybee * Reset properties. We do this before we receive the stream 23736689Smaybee * so that the properties are applied to the new data. 23745326Sek110237 */ 23755367Sahrens if (props) { 23766689Smaybee clear_props(tofs, origprops); 23776689Smaybee /* 23786689Smaybee * XXX - Note, this is all-or-nothing; should be best-effort. 23796689Smaybee */ 23806689Smaybee (void) zfs_set_prop_nvlist(tofs, props); 23815367Sahrens } 23825367Sahrens 23835367Sahrens off = fp->f_offset; 23845367Sahrens error = dmu_recv_stream(&drc, fp->f_vnode, &off); 23855367Sahrens 23866689Smaybee if (error == 0 && zfsvfs) { 23876689Smaybee char osname[MAXNAMELEN]; 23886689Smaybee int mode; 23896689Smaybee 23906689Smaybee /* online recv */ 23916689Smaybee error = zfs_suspend_fs(zfsvfs, osname, &mode); 23926689Smaybee if (error == 0) { 23936689Smaybee int resume_err; 23946689Smaybee 23956689Smaybee error = dmu_recv_end(&drc); 23966689Smaybee resume_err = zfs_resume_fs(zfsvfs, osname, mode); 23976689Smaybee error = error ? error : resume_err; 23985367Sahrens } else { 23996689Smaybee dmu_recv_abort_cleanup(&drc); 24005367Sahrens } 24016689Smaybee } else if (error == 0) { 24026689Smaybee error = dmu_recv_end(&drc); 24036083Sek110237 } 24045367Sahrens 24055367Sahrens zc->zc_cookie = off - fp->f_offset; 24065367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 24075367Sahrens fp->f_offset = off; 24082885Sahrens 24096689Smaybee /* 24106689Smaybee * On error, restore the original props. 24116689Smaybee */ 24126689Smaybee if (error && props) { 24136689Smaybee clear_props(tofs, props); 24146689Smaybee (void) zfs_set_prop_nvlist(tofs, origprops); 24156689Smaybee } 24166689Smaybee out: 24176689Smaybee if (zfsvfs) { 24186689Smaybee mutex_exit(&zfsvfs->z_online_recv_lock); 24196689Smaybee VFS_RELE(zfsvfs->z_vfs); 24206689Smaybee } 24216689Smaybee nvlist_free(props); 24226689Smaybee nvlist_free(origprops); 2423789Sahrens releasef(fd); 2424789Sahrens return (error); 2425789Sahrens } 2426789Sahrens 24275367Sahrens /* 24285367Sahrens * inputs: 24295367Sahrens * zc_name name of snapshot to send 24305367Sahrens * zc_value short name of incremental fromsnap (may be empty) 24315367Sahrens * zc_cookie file descriptor to send stream to 24325367Sahrens * zc_obj fromorigin flag (mutually exclusive with zc_value) 24335367Sahrens * 24345367Sahrens * outputs: none 24355367Sahrens */ 2436789Sahrens static int 24375367Sahrens zfs_ioc_send(zfs_cmd_t *zc) 2438789Sahrens { 2439789Sahrens objset_t *fromsnap = NULL; 2440789Sahrens objset_t *tosnap; 2441789Sahrens file_t *fp; 2442789Sahrens int error; 24435367Sahrens offset_t off; 2444789Sahrens 2445789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 24466689Smaybee DS_MODE_USER | DS_MODE_READONLY, &tosnap); 2447789Sahrens if (error) 2448789Sahrens return (error); 2449789Sahrens 24502676Seschrock if (zc->zc_value[0] != '\0') { 24512885Sahrens char buf[MAXPATHLEN]; 24522885Sahrens char *cp; 24532885Sahrens 24542885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 24552885Sahrens cp = strchr(buf, '@'); 24562885Sahrens if (cp) 24572885Sahrens *(cp+1) = 0; 24582885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 24592885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 24606689Smaybee DS_MODE_USER | DS_MODE_READONLY, &fromsnap); 2461789Sahrens if (error) { 2462789Sahrens dmu_objset_close(tosnap); 2463789Sahrens return (error); 2464789Sahrens } 2465789Sahrens } 2466789Sahrens 2467789Sahrens fp = getf(zc->zc_cookie); 2468789Sahrens if (fp == NULL) { 2469789Sahrens dmu_objset_close(tosnap); 2470789Sahrens if (fromsnap) 2471789Sahrens dmu_objset_close(fromsnap); 2472789Sahrens return (EBADF); 2473789Sahrens } 2474789Sahrens 24755367Sahrens off = fp->f_offset; 24765367Sahrens error = dmu_sendbackup(tosnap, fromsnap, zc->zc_obj, fp->f_vnode, &off); 24775367Sahrens 24785367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 24795367Sahrens fp->f_offset = off; 2480789Sahrens releasef(zc->zc_cookie); 2481789Sahrens if (fromsnap) 2482789Sahrens dmu_objset_close(fromsnap); 2483789Sahrens dmu_objset_close(tosnap); 2484789Sahrens return (error); 2485789Sahrens } 2486789Sahrens 24871544Seschrock static int 24881544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 24891544Seschrock { 24901544Seschrock int id, error; 24911544Seschrock 24921544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 24931544Seschrock &zc->zc_inject_record); 24941544Seschrock 24951544Seschrock if (error == 0) 24961544Seschrock zc->zc_guid = (uint64_t)id; 24971544Seschrock 24981544Seschrock return (error); 24991544Seschrock } 25001544Seschrock 25011544Seschrock static int 25021544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 25031544Seschrock { 25041544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 25051544Seschrock } 25061544Seschrock 25071544Seschrock static int 25081544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 25091544Seschrock { 25101544Seschrock int id = (int)zc->zc_guid; 25111544Seschrock int error; 25121544Seschrock 25131544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 25141544Seschrock &zc->zc_inject_record); 25151544Seschrock 25161544Seschrock zc->zc_guid = id; 25171544Seschrock 25181544Seschrock return (error); 25191544Seschrock } 25201544Seschrock 25211544Seschrock static int 25221544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 25231544Seschrock { 25241544Seschrock spa_t *spa; 25251544Seschrock int error; 25262676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 25271544Seschrock 25281544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 25291544Seschrock return (error); 25301544Seschrock 25312676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 25321544Seschrock &count); 25331544Seschrock if (error == 0) 25342676Seschrock zc->zc_nvlist_dst_size = count; 25351544Seschrock else 25362676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 25371544Seschrock 25381544Seschrock spa_close(spa, FTAG); 25391544Seschrock 25401544Seschrock return (error); 25411544Seschrock } 25421544Seschrock 25431544Seschrock static int 25441544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 25451544Seschrock { 25461544Seschrock spa_t *spa; 25471544Seschrock vdev_t *vd; 25484808Sek110237 uint64_t txg; 25491544Seschrock int error; 25501544Seschrock 25511544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 25521544Seschrock return (error); 25531544Seschrock 25545329Sgw25295 /* 25555329Sgw25295 * Try to resume any I/Os which may have been suspended 25565329Sgw25295 * as a result of a complete pool failure. 25575329Sgw25295 */ 25585329Sgw25295 if (!list_is_empty(&spa->spa_zio_list)) { 25595329Sgw25295 if (zio_vdev_resume_io(spa) != 0) { 25605329Sgw25295 spa_close(spa, FTAG); 25615329Sgw25295 return (EIO); 25625329Sgw25295 } 25635329Sgw25295 } 25645329Sgw25295 25654451Seschrock txg = spa_vdev_enter(spa); 25661544Seschrock 25672676Seschrock if (zc->zc_guid == 0) { 25681544Seschrock vd = NULL; 25696643Seschrock } else { 25706643Seschrock vd = spa_lookup_by_guid(spa, zc->zc_guid, B_TRUE); 25715450Sbrendan if (vd == NULL) { 25725450Sbrendan (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 25735450Sbrendan spa_close(spa, FTAG); 25745450Sbrendan return (ENODEV); 25755450Sbrendan } 25761544Seschrock } 25771544Seschrock 25785329Sgw25295 vdev_clear(spa, vd, B_TRUE); 25791544Seschrock 25804451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 25811544Seschrock 25821544Seschrock spa_close(spa, FTAG); 25831544Seschrock 25841544Seschrock return (0); 25851544Seschrock } 25861544Seschrock 25875367Sahrens /* 25885367Sahrens * inputs: 25895367Sahrens * zc_name name of filesystem 25905367Sahrens * zc_value name of origin snapshot 25915367Sahrens * 25925367Sahrens * outputs: none 25935367Sahrens */ 25941544Seschrock static int 25952082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 25962082Seschrock { 25972417Sahrens char *cp; 25982417Sahrens 25992417Sahrens /* 26002417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 26012417Sahrens * it's easier. 26022417Sahrens */ 26032676Seschrock cp = strchr(zc->zc_value, '@'); 26042417Sahrens if (cp) 26052417Sahrens *cp = '\0'; 26062676Seschrock (void) dmu_objset_find(zc->zc_value, 26072417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 26082082Seschrock return (dsl_dataset_promote(zc->zc_name)); 26092082Seschrock } 26102082Seschrock 26114543Smarks /* 26124543Smarks * We don't want to have a hard dependency 26134543Smarks * against some special symbols in sharefs 26145331Samw * nfs, and smbsrv. Determine them if needed when 26154543Smarks * the first file system is shared. 26165331Samw * Neither sharefs, nfs or smbsrv are unloadable modules. 26174543Smarks */ 26185331Samw int (*znfsexport_fs)(void *arg); 26194543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 26205331Samw int (*zsmbexport_fs)(void *arg, boolean_t add_share); 26215331Samw 26225331Samw int zfs_nfsshare_inited; 26235331Samw int zfs_smbshare_inited; 26245331Samw 26254543Smarks ddi_modhandle_t nfs_mod; 26264543Smarks ddi_modhandle_t sharefs_mod; 26275331Samw ddi_modhandle_t smbsrv_mod; 26284543Smarks kmutex_t zfs_share_lock; 26294543Smarks 26304543Smarks static int 26315331Samw zfs_init_sharefs() 26325331Samw { 26335331Samw int error; 26345331Samw 26355331Samw ASSERT(MUTEX_HELD(&zfs_share_lock)); 26365331Samw /* Both NFS and SMB shares also require sharetab support. */ 26375331Samw if (sharefs_mod == NULL && ((sharefs_mod = 26385331Samw ddi_modopen("fs/sharefs", 26395331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26405331Samw return (ENOSYS); 26415331Samw } 26425331Samw if (zshare_fs == NULL && ((zshare_fs = 26435331Samw (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 26445331Samw ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 26455331Samw return (ENOSYS); 26465331Samw } 26475331Samw return (0); 26485331Samw } 26495331Samw 26505331Samw static int 26514543Smarks zfs_ioc_share(zfs_cmd_t *zc) 26524543Smarks { 26534543Smarks int error; 26544543Smarks int opcode; 26554543Smarks 26565331Samw switch (zc->zc_share.z_sharetype) { 26575331Samw case ZFS_SHARE_NFS: 26585331Samw case ZFS_UNSHARE_NFS: 26595331Samw if (zfs_nfsshare_inited == 0) { 26605331Samw mutex_enter(&zfs_share_lock); 26615331Samw if (nfs_mod == NULL && ((nfs_mod = ddi_modopen("fs/nfs", 26625331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26635331Samw mutex_exit(&zfs_share_lock); 26645331Samw return (ENOSYS); 26655331Samw } 26665331Samw if (znfsexport_fs == NULL && 26675331Samw ((znfsexport_fs = (int (*)(void *)) 26685331Samw ddi_modsym(nfs_mod, 26695331Samw "nfs_export", &error)) == NULL)) { 26705331Samw mutex_exit(&zfs_share_lock); 26715331Samw return (ENOSYS); 26725331Samw } 26735331Samw error = zfs_init_sharefs(); 26745331Samw if (error) { 26755331Samw mutex_exit(&zfs_share_lock); 26765331Samw return (ENOSYS); 26775331Samw } 26785331Samw zfs_nfsshare_inited = 1; 26794543Smarks mutex_exit(&zfs_share_lock); 26804543Smarks } 26815331Samw break; 26825331Samw case ZFS_SHARE_SMB: 26835331Samw case ZFS_UNSHARE_SMB: 26845331Samw if (zfs_smbshare_inited == 0) { 26855331Samw mutex_enter(&zfs_share_lock); 26865331Samw if (smbsrv_mod == NULL && ((smbsrv_mod = 26875331Samw ddi_modopen("drv/smbsrv", 26885331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26895331Samw mutex_exit(&zfs_share_lock); 26905331Samw return (ENOSYS); 26915331Samw } 26925331Samw if (zsmbexport_fs == NULL && ((zsmbexport_fs = 26935331Samw (int (*)(void *, boolean_t))ddi_modsym(smbsrv_mod, 26946139Sjb150015 "smb_server_share", &error)) == NULL)) { 26955331Samw mutex_exit(&zfs_share_lock); 26965331Samw return (ENOSYS); 26975331Samw } 26985331Samw error = zfs_init_sharefs(); 26995331Samw if (error) { 27005331Samw mutex_exit(&zfs_share_lock); 27015331Samw return (ENOSYS); 27025331Samw } 27035331Samw zfs_smbshare_inited = 1; 27044543Smarks mutex_exit(&zfs_share_lock); 27054543Smarks } 27065331Samw break; 27075331Samw default: 27085331Samw return (EINVAL); 27094543Smarks } 27104543Smarks 27115331Samw switch (zc->zc_share.z_sharetype) { 27125331Samw case ZFS_SHARE_NFS: 27135331Samw case ZFS_UNSHARE_NFS: 27145331Samw if (error = 27155331Samw znfsexport_fs((void *) 27165331Samw (uintptr_t)zc->zc_share.z_exportdata)) 27175331Samw return (error); 27185331Samw break; 27195331Samw case ZFS_SHARE_SMB: 27205331Samw case ZFS_UNSHARE_SMB: 27215331Samw if (error = zsmbexport_fs((void *) 27225331Samw (uintptr_t)zc->zc_share.z_exportdata, 27235331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB ? 27245331Samw B_TRUE : B_FALSE)) { 27255331Samw return (error); 27265331Samw } 27275331Samw break; 27285331Samw } 27295331Samw 27305331Samw opcode = (zc->zc_share.z_sharetype == ZFS_SHARE_NFS || 27315331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB) ? 27324543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 27334543Smarks 27345331Samw /* 27355331Samw * Add or remove share from sharetab 27365331Samw */ 27374543Smarks error = zshare_fs(opcode, 27384543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 27394543Smarks zc->zc_share.z_sharemax); 27404543Smarks 27414543Smarks return (error); 27424543Smarks 27434543Smarks } 27444543Smarks 27454543Smarks /* 27464988Sek110237 * pool create, destroy, and export don't log the history as part of 27474988Sek110237 * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export 27484988Sek110237 * do the logging of those commands. 27494543Smarks */ 2750789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 27514715Sek110237 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27524577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27534577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27544577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27554577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 27564577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 27574577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27584577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27594577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27604577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27614577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27624577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27634577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27644577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27654577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27664577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27674577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27684577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27695498Stimh { zfs_ioc_objset_zplprops, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27704543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 27714577Sahrens DATASET_NAME, B_FALSE }, 27724543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 27734577Sahrens DATASET_NAME, B_FALSE }, 27744577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 27754577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 27764577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 27774577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 27784577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 27794577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 27804577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 27815367Sahrens { zfs_ioc_recv, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 27825367Sahrens { zfs_ioc_send, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 27834577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 27844577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 27854577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 27864577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 27874577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27884577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 27894577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 27904577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 27914577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27924577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27934577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27944577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 27954577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 27964577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27974543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 27984577Sahrens DATASET_NAME, B_FALSE }, 27994849Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }, 28004849Sahrens { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE }, 2801789Sahrens }; 2802789Sahrens 2803789Sahrens static int 2804789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2805789Sahrens { 2806789Sahrens zfs_cmd_t *zc; 2807789Sahrens uint_t vec; 28082199Sahrens int error, rc; 2809789Sahrens 2810789Sahrens if (getminor(dev) != 0) 2811789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2812789Sahrens 2813789Sahrens vec = cmd - ZFS_IOC; 28144787Sahrens ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); 2815789Sahrens 2816789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2817789Sahrens return (EINVAL); 2818789Sahrens 2819789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2820789Sahrens 2821789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2822789Sahrens 28234787Sahrens if (error == 0) 28244543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2825789Sahrens 2826789Sahrens /* 2827789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2828789Sahrens * the lower layers. 2829789Sahrens */ 2830789Sahrens if (error == 0) { 2831789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2832789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 28334577Sahrens case POOL_NAME: 2834789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2835789Sahrens error = EINVAL; 2836789Sahrens break; 2837789Sahrens 28384577Sahrens case DATASET_NAME: 2839789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2840789Sahrens error = EINVAL; 2841789Sahrens break; 28422856Snd150628 28434577Sahrens case NO_NAME: 28442856Snd150628 break; 2845789Sahrens } 2846789Sahrens } 2847789Sahrens 2848789Sahrens if (error == 0) 2849789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2850789Sahrens 28512199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 28524543Smarks if (error == 0) { 28532199Sahrens error = rc; 28544543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 28554543Smarks zfs_log_history(zc); 28564543Smarks } 2857789Sahrens 2858789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2859789Sahrens return (error); 2860789Sahrens } 2861789Sahrens 2862789Sahrens static int 2863789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2864789Sahrens { 2865789Sahrens if (cmd != DDI_ATTACH) 2866789Sahrens return (DDI_FAILURE); 2867789Sahrens 2868789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2869789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2870789Sahrens return (DDI_FAILURE); 2871789Sahrens 2872789Sahrens zfs_dip = dip; 2873789Sahrens 2874789Sahrens ddi_report_dev(dip); 2875789Sahrens 2876789Sahrens return (DDI_SUCCESS); 2877789Sahrens } 2878789Sahrens 2879789Sahrens static int 2880789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2881789Sahrens { 2882789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2883789Sahrens return (DDI_FAILURE); 2884789Sahrens 2885789Sahrens if (cmd != DDI_DETACH) 2886789Sahrens return (DDI_FAILURE); 2887789Sahrens 2888789Sahrens zfs_dip = NULL; 2889789Sahrens 2890789Sahrens ddi_prop_remove_all(dip); 2891789Sahrens ddi_remove_minor_node(dip, NULL); 2892789Sahrens 2893789Sahrens return (DDI_SUCCESS); 2894789Sahrens } 2895789Sahrens 2896789Sahrens /*ARGSUSED*/ 2897789Sahrens static int 2898789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2899789Sahrens { 2900789Sahrens switch (infocmd) { 2901789Sahrens case DDI_INFO_DEVT2DEVINFO: 2902789Sahrens *result = zfs_dip; 2903789Sahrens return (DDI_SUCCESS); 2904789Sahrens 2905789Sahrens case DDI_INFO_DEVT2INSTANCE: 2906849Sbonwick *result = (void *)0; 2907789Sahrens return (DDI_SUCCESS); 2908789Sahrens } 2909789Sahrens 2910789Sahrens return (DDI_FAILURE); 2911789Sahrens } 2912789Sahrens 2913789Sahrens /* 2914789Sahrens * OK, so this is a little weird. 2915789Sahrens * 2916789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2917789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2918789Sahrens * 2919789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2920789Sahrens * so most of the standard driver entry points are in zvol.c. 2921789Sahrens */ 2922789Sahrens static struct cb_ops zfs_cb_ops = { 2923789Sahrens zvol_open, /* open */ 2924789Sahrens zvol_close, /* close */ 2925789Sahrens zvol_strategy, /* strategy */ 2926789Sahrens nodev, /* print */ 29276423Sgw25295 zvol_dump, /* dump */ 2928789Sahrens zvol_read, /* read */ 2929789Sahrens zvol_write, /* write */ 2930789Sahrens zfsdev_ioctl, /* ioctl */ 2931789Sahrens nodev, /* devmap */ 2932789Sahrens nodev, /* mmap */ 2933789Sahrens nodev, /* segmap */ 2934789Sahrens nochpoll, /* poll */ 2935789Sahrens ddi_prop_op, /* prop_op */ 2936789Sahrens NULL, /* streamtab */ 2937789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2938789Sahrens CB_REV, /* version */ 29393638Sbillm nodev, /* async read */ 29403638Sbillm nodev, /* async write */ 2941789Sahrens }; 2942789Sahrens 2943789Sahrens static struct dev_ops zfs_dev_ops = { 2944789Sahrens DEVO_REV, /* version */ 2945789Sahrens 0, /* refcnt */ 2946789Sahrens zfs_info, /* info */ 2947789Sahrens nulldev, /* identify */ 2948789Sahrens nulldev, /* probe */ 2949789Sahrens zfs_attach, /* attach */ 2950789Sahrens zfs_detach, /* detach */ 2951789Sahrens nodev, /* reset */ 2952789Sahrens &zfs_cb_ops, /* driver operations */ 2953789Sahrens NULL /* no bus operations */ 2954789Sahrens }; 2955789Sahrens 2956789Sahrens static struct modldrv zfs_modldrv = { 29574577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 29582676Seschrock &zfs_dev_ops 2959789Sahrens }; 2960789Sahrens 2961789Sahrens static struct modlinkage modlinkage = { 2962789Sahrens MODREV_1, 2963789Sahrens (void *)&zfs_modlfs, 2964789Sahrens (void *)&zfs_modldrv, 2965789Sahrens NULL 2966789Sahrens }; 2967789Sahrens 29684720Sfr157268 29694720Sfr157268 uint_t zfs_fsyncer_key; 29705326Sek110237 extern uint_t rrw_tsd_key; 29714720Sfr157268 2972789Sahrens int 2973789Sahrens _init(void) 2974789Sahrens { 2975789Sahrens int error; 2976789Sahrens 2977849Sbonwick spa_init(FREAD | FWRITE); 2978849Sbonwick zfs_init(); 2979849Sbonwick zvol_init(); 2980849Sbonwick 2981849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 2982849Sbonwick zvol_fini(); 2983849Sbonwick zfs_fini(); 2984849Sbonwick spa_fini(); 2985789Sahrens return (error); 2986849Sbonwick } 2987789Sahrens 29884720Sfr157268 tsd_create(&zfs_fsyncer_key, NULL); 29895326Sek110237 tsd_create(&rrw_tsd_key, NULL); 29904720Sfr157268 2991789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 2992789Sahrens ASSERT(error == 0); 29934543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 2994789Sahrens 2995789Sahrens return (0); 2996789Sahrens } 2997789Sahrens 2998789Sahrens int 2999789Sahrens _fini(void) 3000789Sahrens { 3001789Sahrens int error; 3002789Sahrens 30031544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 3004789Sahrens return (EBUSY); 3005789Sahrens 3006789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 3007789Sahrens return (error); 3008789Sahrens 3009789Sahrens zvol_fini(); 3010789Sahrens zfs_fini(); 3011789Sahrens spa_fini(); 30125331Samw if (zfs_nfsshare_inited) 30134543Smarks (void) ddi_modclose(nfs_mod); 30145331Samw if (zfs_smbshare_inited) 30155331Samw (void) ddi_modclose(smbsrv_mod); 30165331Samw if (zfs_nfsshare_inited || zfs_smbshare_inited) 30174543Smarks (void) ddi_modclose(sharefs_mod); 3018789Sahrens 30194720Sfr157268 tsd_destroy(&zfs_fsyncer_key); 3020789Sahrens ldi_ident_release(zfs_li); 3021789Sahrens zfs_li = NULL; 30224543Smarks mutex_destroy(&zfs_share_lock); 3023789Sahrens 3024789Sahrens return (error); 3025789Sahrens } 3026789Sahrens 3027789Sahrens int 3028789Sahrens _info(struct modinfo *modinfop) 3029789Sahrens { 3030789Sahrens return (mod_info(&modlinkage, modinfop)); 3031789Sahrens } 3032