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 /* 1585375Stimh * zfs_check_version 1595375Stimh * 1605375Stimh * Return non-zero if the spa version is less than requested version. 1615375Stimh */ 1625331Samw static int 1635331Samw zfs_check_version(const char *name, int version) 1645331Samw { 1655331Samw 1665331Samw spa_t *spa; 1675331Samw 1685331Samw if (spa_open(name, &spa, FTAG) == 0) { 1695331Samw if (spa_version(spa) < version) { 1705331Samw spa_close(spa, FTAG); 1715331Samw return (1); 1725331Samw } 1735331Samw spa_close(spa, FTAG); 1745331Samw } 1755331Samw return (0); 1765331Samw } 1775331Samw 1785977Smarks /* 1795977Smarks * zpl_check_version 1805977Smarks * 1815977Smarks * Return non-zero if the ZPL version is less than requested version. 1825977Smarks */ 1835977Smarks static int 1845977Smarks zpl_check_version(const char *name, int version) 1855977Smarks { 1865977Smarks objset_t *os; 1875977Smarks int rc = 1; 1885977Smarks 1895977Smarks if (dmu_objset_open(name, DMU_OST_ANY, 1905977Smarks DS_MODE_STANDARD | DS_MODE_READONLY, &os) == 0) { 1915977Smarks uint64_t propversion; 1925977Smarks 1935977Smarks if (zfs_get_zplprop(os, ZFS_PROP_VERSION, 1945977Smarks &propversion) == 0) { 1955977Smarks rc = !(propversion >= version); 1965977Smarks } 1975977Smarks dmu_objset_close(os); 1985977Smarks } 1995977Smarks return (rc); 2005977Smarks } 2015977Smarks 2024715Sek110237 static void 2034543Smarks zfs_log_history(zfs_cmd_t *zc) 2044543Smarks { 2054543Smarks spa_t *spa; 2064603Sahrens char *buf; 2074543Smarks 2084715Sek110237 if ((buf = history_str_get(zc)) == NULL) 2094577Sahrens return; 2104577Sahrens 2114715Sek110237 if (spa_open(zc->zc_name, &spa, FTAG) == 0) { 2124715Sek110237 if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY) 2134715Sek110237 (void) spa_history_log(spa, buf, LOG_CMD_NORMAL); 2144715Sek110237 spa_close(spa, FTAG); 2154543Smarks } 2164715Sek110237 history_str_free(buf); 2174543Smarks } 2184543Smarks 219789Sahrens /* 220789Sahrens * Policy for top-level read operations (list pools). Requires no privileges, 221789Sahrens * and can be used in the local zone, as there is no associated dataset. 222789Sahrens */ 223789Sahrens /* ARGSUSED */ 224789Sahrens static int 2254543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) 226789Sahrens { 227789Sahrens return (0); 228789Sahrens } 229789Sahrens 230789Sahrens /* 231789Sahrens * Policy for dataset read operations (list children, get statistics). Requires 232789Sahrens * no privileges, but must be visible in the local zone. 233789Sahrens */ 234789Sahrens /* ARGSUSED */ 235789Sahrens static int 2364543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) 237789Sahrens { 238789Sahrens if (INGLOBALZONE(curproc) || 2394543Smarks zone_dataset_visible(zc->zc_name, NULL)) 240789Sahrens return (0); 241789Sahrens 242789Sahrens return (ENOENT); 243789Sahrens } 244789Sahrens 245789Sahrens static int 246789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr) 247789Sahrens { 248789Sahrens uint64_t zoned; 249789Sahrens int writable = 1; 250789Sahrens 251789Sahrens /* 252789Sahrens * The dataset must be visible by this zone -- check this first 253789Sahrens * so they don't see EPERM on something they shouldn't know about. 254789Sahrens */ 255789Sahrens if (!INGLOBALZONE(curproc) && 256789Sahrens !zone_dataset_visible(dataset, &writable)) 257789Sahrens return (ENOENT); 258789Sahrens 259789Sahrens if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) 260789Sahrens return (ENOENT); 261789Sahrens 262789Sahrens if (INGLOBALZONE(curproc)) { 263789Sahrens /* 264789Sahrens * If the fs is zoned, only root can access it from the 265789Sahrens * global zone. 266789Sahrens */ 267789Sahrens if (secpolicy_zfs(cr) && zoned) 268789Sahrens return (EPERM); 269789Sahrens } else { 270789Sahrens /* 271789Sahrens * If we are in a local zone, the 'zoned' property must be set. 272789Sahrens */ 273789Sahrens if (!zoned) 274789Sahrens return (EPERM); 275789Sahrens 276789Sahrens /* must be writable by this zone */ 277789Sahrens if (!writable) 278789Sahrens return (EPERM); 279789Sahrens } 280789Sahrens return (0); 281789Sahrens } 282789Sahrens 283789Sahrens int 2844543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) 285789Sahrens { 286789Sahrens int error; 287789Sahrens 2884543Smarks error = zfs_dozonecheck(name, cr); 2894543Smarks if (error == 0) { 2904543Smarks error = secpolicy_zfs(cr); 2914670Sahrens if (error) 2924543Smarks error = dsl_deleg_access(name, perm, cr); 2934543Smarks } 2944543Smarks return (error); 2954543Smarks } 2964543Smarks 2974543Smarks static int 2984543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) 2994543Smarks { 3004543Smarks /* 3014543Smarks * Check permissions for special properties. 3024543Smarks */ 3034543Smarks switch (prop) { 3044543Smarks case ZFS_PROP_ZONED: 3054543Smarks /* 3064543Smarks * Disallow setting of 'zoned' from within a local zone. 3074543Smarks */ 3084543Smarks if (!INGLOBALZONE(curproc)) 3094543Smarks return (EPERM); 3104543Smarks break; 311789Sahrens 3124543Smarks case ZFS_PROP_QUOTA: 3134543Smarks if (!INGLOBALZONE(curproc)) { 3144543Smarks uint64_t zoned; 3154543Smarks char setpoint[MAXNAMELEN]; 3164543Smarks /* 3174543Smarks * Unprivileged users are allowed to modify the 3184543Smarks * quota on things *under* (ie. contained by) 3194543Smarks * the thing they own. 3204543Smarks */ 3214543Smarks if (dsl_prop_get_integer(name, "zoned", &zoned, 3224543Smarks setpoint)) 3234543Smarks return (EPERM); 3244670Sahrens if (!zoned || strlen(name) <= strlen(setpoint)) 3254543Smarks return (EPERM); 3264543Smarks } 3274670Sahrens break; 3284543Smarks } 3294543Smarks 3304787Sahrens return (zfs_secpolicy_write_perms(name, zfs_prop_to_name(prop), cr)); 331789Sahrens } 332789Sahrens 3334543Smarks int 3344543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) 3354543Smarks { 3364543Smarks int error; 3374543Smarks 3384543Smarks error = zfs_dozonecheck(zc->zc_name, cr); 3394543Smarks if (error) 3404543Smarks return (error); 3414543Smarks 3424543Smarks /* 3434543Smarks * permission to set permissions will be evaluated later in 3444543Smarks * dsl_deleg_can_allow() 3454543Smarks */ 3464543Smarks return (0); 3474543Smarks } 3484543Smarks 3494543Smarks int 3504543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) 3514543Smarks { 3524543Smarks int error; 3534543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3544543Smarks ZFS_DELEG_PERM_ROLLBACK, cr); 3554543Smarks if (error == 0) 3564543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3574543Smarks ZFS_DELEG_PERM_MOUNT, cr); 3584543Smarks return (error); 3594543Smarks } 3604543Smarks 3614543Smarks int 3624543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) 3634543Smarks { 3644543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 3654543Smarks ZFS_DELEG_PERM_SEND, cr)); 3664543Smarks } 3674543Smarks 3684543Smarks int 3694543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) 3704543Smarks { 3714543Smarks if (!INGLOBALZONE(curproc)) 3724543Smarks return (EPERM); 3734543Smarks 3745367Sahrens if (secpolicy_nfs(cr) == 0) { 3754543Smarks return (0); 3764543Smarks } else { 3774543Smarks vnode_t *vp; 3784543Smarks int error; 3794543Smarks 3804543Smarks if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, 3814543Smarks NO_FOLLOW, NULL, &vp)) != 0) 3824543Smarks return (error); 3834543Smarks 3844543Smarks /* Now make sure mntpnt and dataset are ZFS */ 3854543Smarks 3864543Smarks if (vp->v_vfsp->vfs_fstype != zfsfstype || 3874543Smarks (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), 3884543Smarks zc->zc_name) != 0)) { 3894543Smarks VN_RELE(vp); 3904543Smarks return (EPERM); 3914543Smarks } 3924543Smarks 3934543Smarks VN_RELE(vp); 3944543Smarks return (dsl_deleg_access(zc->zc_name, 3954543Smarks ZFS_DELEG_PERM_SHARE, cr)); 3964543Smarks } 3974543Smarks } 3984543Smarks 399789Sahrens static int 4004543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize) 401789Sahrens { 402789Sahrens char *cp; 403789Sahrens 404789Sahrens /* 405789Sahrens * Remove the @bla or /bla from the end of the name to get the parent. 406789Sahrens */ 4074543Smarks (void) strncpy(parent, datasetname, parentsize); 4084543Smarks cp = strrchr(parent, '@'); 409789Sahrens if (cp != NULL) { 410789Sahrens cp[0] = '\0'; 411789Sahrens } else { 4124543Smarks cp = strrchr(parent, '/'); 413789Sahrens if (cp == NULL) 414789Sahrens return (ENOENT); 415789Sahrens cp[0] = '\0'; 416789Sahrens } 417789Sahrens 4184543Smarks return (0); 4194543Smarks } 4204543Smarks 4214543Smarks int 4224543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 4234543Smarks { 4244543Smarks int error; 4254543Smarks 4264543Smarks if ((error = zfs_secpolicy_write_perms(name, 4274543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4284543Smarks return (error); 4294543Smarks 4304543Smarks return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); 4314543Smarks } 4324543Smarks 4334543Smarks static int 4344543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) 4354543Smarks { 4364543Smarks return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); 4374543Smarks } 4384543Smarks 4394543Smarks /* 4404543Smarks * Must have sys_config privilege to check the iscsi permission 4414543Smarks */ 4424543Smarks /* ARGSUSED */ 4434543Smarks static int 4444543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) 4454543Smarks { 4464543Smarks return (secpolicy_zfs(cr)); 4474543Smarks } 4484543Smarks 4494543Smarks int 4504543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 4514543Smarks { 4524543Smarks char parentname[MAXNAMELEN]; 4534543Smarks int error; 4544543Smarks 4554543Smarks if ((error = zfs_secpolicy_write_perms(from, 4564543Smarks ZFS_DELEG_PERM_RENAME, cr)) != 0) 4574543Smarks return (error); 4584543Smarks 4594543Smarks if ((error = zfs_secpolicy_write_perms(from, 4604543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4614543Smarks return (error); 4624543Smarks 4634543Smarks if ((error = zfs_get_parent(to, parentname, 4644543Smarks sizeof (parentname))) != 0) 4654543Smarks return (error); 4664543Smarks 4674543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4684543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 4694543Smarks return (error); 4704543Smarks 4714543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4724543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4734543Smarks return (error); 4744543Smarks 4754543Smarks return (error); 4764543Smarks } 4774543Smarks 4784543Smarks static int 4794543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) 4804543Smarks { 4814543Smarks return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); 4824543Smarks } 4834543Smarks 4844543Smarks static int 4854543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) 4864543Smarks { 4874543Smarks char parentname[MAXNAMELEN]; 4884543Smarks objset_t *clone; 4894543Smarks int error; 4904543Smarks 4914543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4924543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4934543Smarks if (error) 4944543Smarks return (error); 4954543Smarks 4964543Smarks error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 4974543Smarks DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 4984543Smarks 4994543Smarks if (error == 0) { 5004543Smarks dsl_dataset_t *pclone = NULL; 5014543Smarks dsl_dir_t *dd; 5024543Smarks dd = clone->os->os_dsl_dataset->ds_dir; 5034543Smarks 5044543Smarks rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 5054543Smarks error = dsl_dataset_open_obj(dd->dd_pool, 5065367Sahrens dd->dd_phys->dd_origin_obj, NULL, 5074543Smarks DS_MODE_NONE, FTAG, &pclone); 5084543Smarks rw_exit(&dd->dd_pool->dp_config_rwlock); 5094543Smarks if (error) { 5104543Smarks dmu_objset_close(clone); 5114543Smarks return (error); 5124543Smarks } 5134543Smarks 5144543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 5154543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5164543Smarks 5174543Smarks dsl_dataset_name(pclone, parentname); 5184543Smarks dmu_objset_close(clone); 5194543Smarks dsl_dataset_close(pclone, DS_MODE_NONE, FTAG); 5204543Smarks if (error == 0) 5214543Smarks error = zfs_secpolicy_write_perms(parentname, 5224543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 5234543Smarks } 5244543Smarks return (error); 5254543Smarks } 5264543Smarks 5274543Smarks static int 5284543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) 5294543Smarks { 5304543Smarks int error; 5314543Smarks 5324543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5334543Smarks ZFS_DELEG_PERM_RECEIVE, cr)) != 0) 5344543Smarks return (error); 5354543Smarks 5364543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5374543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 5384543Smarks return (error); 5394543Smarks 5404543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 5414543Smarks ZFS_DELEG_PERM_CREATE, cr)); 5424543Smarks } 5434543Smarks 5444543Smarks int 5454543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 5464543Smarks { 5474543Smarks int error; 5484543Smarks 5494543Smarks if ((error = zfs_secpolicy_write_perms(name, 5504543Smarks ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) 5514543Smarks return (error); 5524543Smarks 5534543Smarks error = zfs_secpolicy_write_perms(name, 5544543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5554543Smarks 5564543Smarks return (error); 5574543Smarks } 5584543Smarks 5594543Smarks static int 5604543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) 5614543Smarks { 5624543Smarks 5634543Smarks return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); 5644543Smarks } 5654543Smarks 5664543Smarks static int 5674543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) 5684543Smarks { 5694543Smarks char parentname[MAXNAMELEN]; 5704543Smarks int error; 5714543Smarks 5724543Smarks if ((error = zfs_get_parent(zc->zc_name, parentname, 5734543Smarks sizeof (parentname))) != 0) 5744543Smarks return (error); 5754543Smarks 5764543Smarks if (zc->zc_value[0] != '\0') { 5774543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_value, 5784543Smarks ZFS_DELEG_PERM_CLONE, cr)) != 0) 5794543Smarks return (error); 5804543Smarks } 5814543Smarks 5824543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 5834543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 5844543Smarks return (error); 5854543Smarks 5864543Smarks error = zfs_secpolicy_write_perms(parentname, 5874543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5884543Smarks 5894543Smarks return (error); 5904543Smarks } 5914543Smarks 5924543Smarks static int 5934543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) 5944543Smarks { 5954543Smarks int error; 5964543Smarks 5974543Smarks error = secpolicy_fs_unmount(cr, NULL); 5984543Smarks if (error) { 5994543Smarks error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); 6004543Smarks } 6014543Smarks return (error); 602789Sahrens } 603789Sahrens 604789Sahrens /* 605789Sahrens * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires 606789Sahrens * SYS_CONFIG privilege, which is not available in a local zone. 607789Sahrens */ 608789Sahrens /* ARGSUSED */ 609789Sahrens static int 6104543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) 611789Sahrens { 612789Sahrens if (secpolicy_sys_config(cr, B_FALSE) != 0) 613789Sahrens return (EPERM); 614789Sahrens 615789Sahrens return (0); 616789Sahrens } 617789Sahrens 618789Sahrens /* 6194543Smarks * Just like zfs_secpolicy_config, except that we will check for 6204543Smarks * mount permission on the dataset for permission to create/remove 6214543Smarks * the minor nodes. 6224543Smarks */ 6234543Smarks static int 6244543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) 6254543Smarks { 6264543Smarks if (secpolicy_sys_config(cr, B_FALSE) != 0) { 6274543Smarks return (dsl_deleg_access(zc->zc_name, 6284543Smarks ZFS_DELEG_PERM_MOUNT, cr)); 6294543Smarks } 6304543Smarks 6314543Smarks return (0); 6324543Smarks } 6334543Smarks 6344543Smarks /* 6351544Seschrock * Policy for fault injection. Requires all privileges. 6361544Seschrock */ 6371544Seschrock /* ARGSUSED */ 6381544Seschrock static int 6394543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) 6401544Seschrock { 6411544Seschrock return (secpolicy_zinject(cr)); 6421544Seschrock } 6431544Seschrock 6444849Sahrens static int 6454849Sahrens zfs_secpolicy_inherit(zfs_cmd_t *zc, cred_t *cr) 6464849Sahrens { 6474849Sahrens zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); 6484849Sahrens 6495094Slling if (prop == ZPROP_INVAL) { 6504849Sahrens if (!zfs_prop_user(zc->zc_value)) 6514849Sahrens return (EINVAL); 6524849Sahrens return (zfs_secpolicy_write_perms(zc->zc_name, 6534849Sahrens ZFS_DELEG_PERM_USERPROP, cr)); 6544849Sahrens } else { 6554849Sahrens if (!zfs_prop_inheritable(prop)) 6564849Sahrens return (EINVAL); 6574849Sahrens return (zfs_secpolicy_setprop(zc->zc_name, prop, cr)); 6584849Sahrens } 6594849Sahrens } 6604849Sahrens 6611544Seschrock /* 662789Sahrens * Returns the nvlist as specified by the user in the zfs_cmd_t. 663789Sahrens */ 664789Sahrens static int 6655094Slling get_nvlist(uint64_t nvl, uint64_t size, nvlist_t **nvp) 666789Sahrens { 667789Sahrens char *packed; 668789Sahrens int error; 6695094Slling nvlist_t *list = NULL; 670789Sahrens 671789Sahrens /* 6722676Seschrock * Read in and unpack the user-supplied nvlist. 673789Sahrens */ 6745094Slling if (size == 0) 675789Sahrens return (EINVAL); 676789Sahrens 677789Sahrens packed = kmem_alloc(size, KM_SLEEP); 678789Sahrens 6795094Slling if ((error = xcopyin((void *)(uintptr_t)nvl, packed, size)) != 0) { 680789Sahrens kmem_free(packed, size); 681789Sahrens return (error); 682789Sahrens } 683789Sahrens 6845094Slling if ((error = nvlist_unpack(packed, size, &list, 0)) != 0) { 685789Sahrens kmem_free(packed, size); 686789Sahrens return (error); 687789Sahrens } 688789Sahrens 689789Sahrens kmem_free(packed, size); 690789Sahrens 6915094Slling *nvp = list; 692789Sahrens return (0); 693789Sahrens } 694789Sahrens 695789Sahrens static int 6962676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 6972676Seschrock { 6982676Seschrock char *packed = NULL; 6992676Seschrock size_t size; 7002676Seschrock int error; 7012676Seschrock 7022676Seschrock VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 7032676Seschrock 7042676Seschrock if (size > zc->zc_nvlist_dst_size) { 7052676Seschrock error = ENOMEM; 7062676Seschrock } else { 7074611Smarks packed = kmem_alloc(size, KM_SLEEP); 7082676Seschrock VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 7092676Seschrock KM_SLEEP) == 0); 7102676Seschrock error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 7112676Seschrock size); 7122676Seschrock kmem_free(packed, size); 7132676Seschrock } 7142676Seschrock 7152676Seschrock zc->zc_nvlist_dst_size = size; 7162676Seschrock return (error); 7172676Seschrock } 7182676Seschrock 7192676Seschrock static int 720789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc) 721789Sahrens { 722789Sahrens int error; 7235094Slling nvlist_t *config, *props = NULL; 7244715Sek110237 char *buf; 725789Sahrens 7265094Slling if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7275094Slling &config)) 7284988Sek110237 return (error); 7294715Sek110237 7305094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7315094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7325094Slling nvlist_free(config); 7335094Slling return (error); 7345094Slling } 7355094Slling 7364988Sek110237 buf = history_str_get(zc); 737789Sahrens 7385094Slling error = spa_create(zc->zc_name, config, props, buf); 739789Sahrens 7404988Sek110237 if (buf != NULL) 7414988Sek110237 history_str_free(buf); 7425094Slling 743789Sahrens nvlist_free(config); 744789Sahrens 7455094Slling if (props) 7465094Slling nvlist_free(props); 7475094Slling 748789Sahrens return (error); 749789Sahrens } 750789Sahrens 751789Sahrens static int 752789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc) 753789Sahrens { 7544543Smarks int error; 7554543Smarks zfs_log_history(zc); 7564543Smarks error = spa_destroy(zc->zc_name); 7574543Smarks return (error); 758789Sahrens } 759789Sahrens 760789Sahrens static int 761789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc) 762789Sahrens { 763789Sahrens int error; 7645094Slling nvlist_t *config, *props = NULL; 765789Sahrens uint64_t guid; 766789Sahrens 7675094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7685094Slling &config)) != 0) 769789Sahrens return (error); 770789Sahrens 7715094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7725094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7735094Slling nvlist_free(config); 7745094Slling return (error); 7755094Slling } 7765094Slling 777789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 7781544Seschrock guid != zc->zc_guid) 779789Sahrens error = EINVAL; 780789Sahrens else 7815094Slling error = spa_import(zc->zc_name, config, props); 782789Sahrens 783789Sahrens nvlist_free(config); 784789Sahrens 7855094Slling if (props) 7865094Slling nvlist_free(props); 7875094Slling 788789Sahrens return (error); 789789Sahrens } 790789Sahrens 791789Sahrens static int 792789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc) 793789Sahrens { 7944543Smarks int error; 7954543Smarks zfs_log_history(zc); 7964543Smarks error = spa_export(zc->zc_name, NULL); 7974543Smarks return (error); 798789Sahrens } 799789Sahrens 800789Sahrens static int 801789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc) 802789Sahrens { 803789Sahrens nvlist_t *configs; 804789Sahrens int error; 805789Sahrens 806789Sahrens if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 807789Sahrens return (EEXIST); 808789Sahrens 8092676Seschrock error = put_nvlist(zc, configs); 810789Sahrens 811789Sahrens nvlist_free(configs); 812789Sahrens 813789Sahrens return (error); 814789Sahrens } 815789Sahrens 816789Sahrens static int 817789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc) 818789Sahrens { 819789Sahrens nvlist_t *config; 820789Sahrens int error; 8211544Seschrock int ret = 0; 822789Sahrens 8232676Seschrock error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 8242676Seschrock sizeof (zc->zc_value)); 825789Sahrens 826789Sahrens if (config != NULL) { 8272676Seschrock ret = put_nvlist(zc, config); 828789Sahrens nvlist_free(config); 8291544Seschrock 8301544Seschrock /* 8311544Seschrock * The config may be present even if 'error' is non-zero. 8321544Seschrock * In this case we return success, and preserve the real errno 8331544Seschrock * in 'zc_cookie'. 8341544Seschrock */ 8351544Seschrock zc->zc_cookie = error; 836789Sahrens } else { 8371544Seschrock ret = error; 838789Sahrens } 839789Sahrens 8401544Seschrock return (ret); 841789Sahrens } 842789Sahrens 843789Sahrens /* 844789Sahrens * Try to import the given pool, returning pool stats as appropriate so that 845789Sahrens * user land knows which devices are available and overall pool health. 846789Sahrens */ 847789Sahrens static int 848789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 849789Sahrens { 850789Sahrens nvlist_t *tryconfig, *config; 851789Sahrens int error; 852789Sahrens 8535094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 8545094Slling &tryconfig)) != 0) 855789Sahrens return (error); 856789Sahrens 857789Sahrens config = spa_tryimport(tryconfig); 858789Sahrens 859789Sahrens nvlist_free(tryconfig); 860789Sahrens 861789Sahrens if (config == NULL) 862789Sahrens return (EINVAL); 863789Sahrens 8642676Seschrock error = put_nvlist(zc, config); 865789Sahrens nvlist_free(config); 866789Sahrens 867789Sahrens return (error); 868789Sahrens } 869789Sahrens 870789Sahrens static int 871789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc) 872789Sahrens { 873789Sahrens spa_t *spa; 874789Sahrens int error; 875789Sahrens 8762926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8772926Sek110237 return (error); 8782926Sek110237 8794808Sek110237 mutex_enter(&spa_namespace_lock); 8802926Sek110237 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); 8814808Sek110237 mutex_exit(&spa_namespace_lock); 8822926Sek110237 8832926Sek110237 spa_close(spa, FTAG); 8842926Sek110237 885789Sahrens return (error); 886789Sahrens } 887789Sahrens 888789Sahrens static int 889789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 890789Sahrens { 891789Sahrens spa_t *spa; 892789Sahrens int error; 893789Sahrens 894789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 895789Sahrens if (error == 0) { 896789Sahrens spa_freeze(spa); 897789Sahrens spa_close(spa, FTAG); 898789Sahrens } 899789Sahrens return (error); 900789Sahrens } 901789Sahrens 902789Sahrens static int 9031760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 9041760Seschrock { 9051760Seschrock spa_t *spa; 9061760Seschrock int error; 9071760Seschrock 9082926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9092926Sek110237 return (error); 9102926Sek110237 9115118Slling if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) { 9125118Slling spa_close(spa, FTAG); 9135118Slling return (EINVAL); 9145118Slling } 9155118Slling 9165094Slling spa_upgrade(spa, zc->zc_cookie); 9172926Sek110237 spa_close(spa, FTAG); 9182926Sek110237 9192926Sek110237 return (error); 9202926Sek110237 } 9212926Sek110237 9222926Sek110237 static int 9232926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 9242926Sek110237 { 9252926Sek110237 spa_t *spa; 9262926Sek110237 char *hist_buf; 9272926Sek110237 uint64_t size; 9282926Sek110237 int error; 9292926Sek110237 9302926Sek110237 if ((size = zc->zc_history_len) == 0) 9312926Sek110237 return (EINVAL); 9322926Sek110237 9332926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9342926Sek110237 return (error); 9352926Sek110237 9364577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 9373863Sek110237 spa_close(spa, FTAG); 9383863Sek110237 return (ENOTSUP); 9393863Sek110237 } 9403863Sek110237 9412926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 9422926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 9432926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 9444543Smarks error = xcopyout(hist_buf, 9454543Smarks (char *)(uintptr_t)zc->zc_history, 9462926Sek110237 zc->zc_history_len); 9472926Sek110237 } 9482926Sek110237 9492926Sek110237 spa_close(spa, FTAG); 9502926Sek110237 kmem_free(hist_buf, size); 9512926Sek110237 return (error); 9522926Sek110237 } 9532926Sek110237 9542926Sek110237 static int 9553444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 9563444Sek110237 { 9573444Sek110237 int error; 9583444Sek110237 9593912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 9603444Sek110237 return (error); 9613444Sek110237 9623444Sek110237 return (0); 9633444Sek110237 } 9643444Sek110237 9653444Sek110237 static int 9663444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 9673444Sek110237 { 9683444Sek110237 objset_t *osp; 9693444Sek110237 int error; 9703444Sek110237 9713444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 9723444Sek110237 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) 9733444Sek110237 return (error); 9743444Sek110237 9753444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 9763444Sek110237 sizeof (zc->zc_value)); 9773444Sek110237 dmu_objset_close(osp); 9783444Sek110237 9793444Sek110237 return (error); 9803444Sek110237 } 9813444Sek110237 9823444Sek110237 static int 983789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 984789Sahrens { 985789Sahrens spa_t *spa; 986789Sahrens int error; 9875450Sbrendan nvlist_t *config, **l2cache; 9885450Sbrendan uint_t nl2cache; 989789Sahrens 990789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 991789Sahrens if (error != 0) 992789Sahrens return (error); 993789Sahrens 9945450Sbrendan error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 9955450Sbrendan &config); 9965450Sbrendan (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_L2CACHE, 9975450Sbrendan &l2cache, &nl2cache); 9985450Sbrendan 9993912Slling /* 10003912Slling * A root pool with concatenated devices is not supported. 10013912Slling * Thus, can not add a device to a root pool with one device. 10025450Sbrendan * Allow for l2cache devices to be added. 10033912Slling */ 10045450Sbrendan if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0 && 10055450Sbrendan nl2cache == 0) { 10063912Slling spa_close(spa, FTAG); 10073912Slling return (EDOM); 10083912Slling } 10093912Slling 10105450Sbrendan if (error == 0) { 1011789Sahrens error = spa_vdev_add(spa, config); 1012789Sahrens nvlist_free(config); 1013789Sahrens } 1014789Sahrens spa_close(spa, FTAG); 1015789Sahrens return (error); 1016789Sahrens } 1017789Sahrens 1018789Sahrens static int 1019789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 1020789Sahrens { 10212082Seschrock spa_t *spa; 10222082Seschrock int error; 10232082Seschrock 10242082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10252082Seschrock if (error != 0) 10262082Seschrock return (error); 10272082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 10282082Seschrock spa_close(spa, FTAG); 10292082Seschrock return (error); 1030789Sahrens } 1031789Sahrens 1032789Sahrens static int 10334451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 1034789Sahrens { 1035789Sahrens spa_t *spa; 1036789Sahrens int error; 10374451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 1038789Sahrens 10392926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1040789Sahrens return (error); 10414451Seschrock switch (zc->zc_cookie) { 10424451Seschrock case VDEV_STATE_ONLINE: 10434451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 10444451Seschrock break; 10454451Seschrock 10464451Seschrock case VDEV_STATE_OFFLINE: 10474451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 10484451Seschrock break; 1049789Sahrens 10504451Seschrock case VDEV_STATE_FAULTED: 10514451Seschrock error = vdev_fault(spa, zc->zc_guid); 10524451Seschrock break; 1053789Sahrens 10544451Seschrock case VDEV_STATE_DEGRADED: 10554451Seschrock error = vdev_degrade(spa, zc->zc_guid); 10564451Seschrock break; 10574451Seschrock 10584451Seschrock default: 10594451Seschrock error = EINVAL; 10604451Seschrock } 10614451Seschrock zc->zc_cookie = newstate; 1062789Sahrens spa_close(spa, FTAG); 1063789Sahrens return (error); 1064789Sahrens } 1065789Sahrens 1066789Sahrens static int 1067789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 1068789Sahrens { 1069789Sahrens spa_t *spa; 1070789Sahrens int replacing = zc->zc_cookie; 1071789Sahrens nvlist_t *config; 1072789Sahrens int error; 1073789Sahrens 10742926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1075789Sahrens return (error); 1076789Sahrens 10775094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 10785094Slling &config)) == 0) { 10791544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 1080789Sahrens nvlist_free(config); 1081789Sahrens } 1082789Sahrens 1083789Sahrens spa_close(spa, FTAG); 1084789Sahrens return (error); 1085789Sahrens } 1086789Sahrens 1087789Sahrens static int 1088789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 1089789Sahrens { 1090789Sahrens spa_t *spa; 1091789Sahrens int error; 1092789Sahrens 10932926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1094789Sahrens return (error); 1095789Sahrens 10961544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1097789Sahrens 1098789Sahrens spa_close(spa, FTAG); 1099789Sahrens return (error); 1100789Sahrens } 1101789Sahrens 1102789Sahrens static int 11031354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 11041354Seschrock { 11051354Seschrock spa_t *spa; 11062676Seschrock char *path = zc->zc_value; 11071544Seschrock uint64_t guid = zc->zc_guid; 11081354Seschrock int error; 11091354Seschrock 11101354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 11111354Seschrock if (error != 0) 11121354Seschrock return (error); 11131354Seschrock 11141354Seschrock error = spa_vdev_setpath(spa, guid, path); 11151354Seschrock spa_close(spa, FTAG); 11161354Seschrock return (error); 11171354Seschrock } 11181354Seschrock 11195498Stimh static int 11205498Stimh zfs_os_open_retry(char *name, objset_t **os) 11215498Stimh { 11225498Stimh int error; 11235498Stimh 11245498Stimh retry: 11255498Stimh error = dmu_objset_open(name, DMU_OST_ANY, 11265498Stimh DS_MODE_STANDARD | DS_MODE_READONLY, os); 11275498Stimh if (error != 0) { 11285498Stimh /* 11295498Stimh * This is ugly: dmu_objset_open() can return EBUSY if 11305498Stimh * the objset is held exclusively. Fortunately this hold is 11315498Stimh * only for a short while, so we retry here. 11325498Stimh * This avoids user code having to handle EBUSY, 11335498Stimh * for example for a "zfs list". 11345498Stimh */ 11355498Stimh if (error == EBUSY) { 11365498Stimh delay(1); 11375498Stimh goto retry; 11385498Stimh } 11395498Stimh } 11405498Stimh return (error); 11415498Stimh } 11425498Stimh 11435367Sahrens /* 11445367Sahrens * inputs: 11455367Sahrens * zc_name name of filesystem 11465367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 11475367Sahrens * 11485367Sahrens * outputs: 11495367Sahrens * zc_objset_stats stats 11505367Sahrens * zc_nvlist_dst property nvlist 11515367Sahrens * zc_nvlist_dst_size size of property nvlist 11525367Sahrens * zc_value alternate root 11535367Sahrens */ 11541354Seschrock static int 1155789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1156789Sahrens { 1157789Sahrens objset_t *os = NULL; 1158789Sahrens int error; 11591356Seschrock nvlist_t *nv; 1160789Sahrens 11615498Stimh if ((error = zfs_os_open_retry(zc->zc_name, &os)) != 0) 1162789Sahrens return (error); 1163789Sahrens 11642885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1165789Sahrens 11662856Snd150628 if (zc->zc_nvlist_dst != 0 && 11671356Seschrock (error = dsl_prop_get_all(os, &nv)) == 0) { 11682885Sahrens dmu_objset_stats(os, nv); 11693087Sahrens /* 11705147Srm160521 * NB: zvol_get_stats() will read the objset contents, 11713087Sahrens * which we aren't supposed to do with a 11723087Sahrens * DS_MODE_STANDARD open, because it could be 11733087Sahrens * inconsistent. So this is a bit of a workaround... 11743087Sahrens */ 11754577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 11764577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 11774577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 11784577Sahrens } 11792676Seschrock error = put_nvlist(zc, nv); 11801356Seschrock nvlist_free(nv); 11811356Seschrock } 1182789Sahrens 11832676Seschrock spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value)); 11841544Seschrock 1185789Sahrens dmu_objset_close(os); 1186789Sahrens return (error); 1187789Sahrens } 1188789Sahrens 11895498Stimh static int 11905498Stimh nvl_add_zplprop(objset_t *os, nvlist_t *props, zfs_prop_t prop) 11915498Stimh { 11925498Stimh uint64_t value; 11935498Stimh int error; 11945498Stimh 11955498Stimh /* 11965498Stimh * zfs_get_zplprop() will either find a value or give us 11975498Stimh * the default value (if there is one). 11985498Stimh */ 11995498Stimh if ((error = zfs_get_zplprop(os, prop, &value)) != 0) 12005498Stimh return (error); 12015498Stimh VERIFY(nvlist_add_uint64(props, zfs_prop_to_name(prop), value) == 0); 12025498Stimh return (0); 12035498Stimh } 12045498Stimh 12055498Stimh /* 12065498Stimh * inputs: 12075498Stimh * zc_name name of filesystem 12085498Stimh * zc_nvlist_dst_size size of buffer for zpl property nvlist 12095498Stimh * 12105498Stimh * outputs: 12115498Stimh * zc_nvlist_dst zpl property nvlist 12125498Stimh * zc_nvlist_dst_size size of zpl property nvlist 12135498Stimh */ 12145498Stimh static int 12155498Stimh zfs_ioc_objset_zplprops(zfs_cmd_t *zc) 12165498Stimh { 12175498Stimh objset_t *os; 12185498Stimh int err; 12195498Stimh 12205498Stimh if ((err = zfs_os_open_retry(zc->zc_name, &os)) != 0) 12215498Stimh return (err); 12225498Stimh 12235498Stimh dmu_objset_fast_stat(os, &zc->zc_objset_stats); 12245498Stimh 12255498Stimh /* 12265498Stimh * NB: nvl_add_zplprop() will read the objset contents, 12275498Stimh * which we aren't supposed to do with a DS_MODE_STANDARD 12285498Stimh * open, because it could be inconsistent. 12295498Stimh */ 12305498Stimh if (zc->zc_nvlist_dst != NULL && 12315498Stimh !zc->zc_objset_stats.dds_inconsistent && 12325498Stimh dmu_objset_type(os) == DMU_OST_ZFS) { 12335498Stimh nvlist_t *nv; 12345498Stimh 12355498Stimh VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) == 0); 12365498Stimh if ((err = nvl_add_zplprop(os, nv, ZFS_PROP_VERSION)) == 0 && 12375498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_NORMALIZE)) == 0 && 12385498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_UTF8ONLY)) == 0 && 12395498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_CASE)) == 0) 12405498Stimh err = put_nvlist(zc, nv); 12415498Stimh nvlist_free(nv); 12425498Stimh } else { 12435498Stimh err = ENOENT; 12445498Stimh } 12455498Stimh dmu_objset_close(os); 12465498Stimh return (err); 12475498Stimh } 12485498Stimh 12495367Sahrens /* 12505367Sahrens * inputs: 12515367Sahrens * zc_name name of filesystem 12525367Sahrens * zc_cookie zap cursor 12535367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 12545367Sahrens * 12555367Sahrens * outputs: 12565367Sahrens * zc_name name of next filesystem 12575367Sahrens * zc_objset_stats stats 12585367Sahrens * zc_nvlist_dst property nvlist 12595367Sahrens * zc_nvlist_dst_size size of property nvlist 12605367Sahrens * zc_value alternate root 12615367Sahrens */ 1262789Sahrens static int 1263789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1264789Sahrens { 1265885Sahrens objset_t *os; 1266789Sahrens int error; 1267789Sahrens char *p; 1268789Sahrens 12695498Stimh if ((error = zfs_os_open_retry(zc->zc_name, &os)) != 0) { 1270885Sahrens if (error == ENOENT) 1271885Sahrens error = ESRCH; 1272885Sahrens return (error); 1273789Sahrens } 1274789Sahrens 1275789Sahrens p = strrchr(zc->zc_name, '/'); 1276789Sahrens if (p == NULL || p[1] != '\0') 1277789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1278789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1279789Sahrens 1280789Sahrens do { 1281885Sahrens error = dmu_dir_list_next(os, 1282885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1283885Sahrens NULL, &zc->zc_cookie); 1284789Sahrens if (error == ENOENT) 1285789Sahrens error = ESRCH; 1286885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1287789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 1288789Sahrens 1289885Sahrens /* 1290885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1291885Sahrens * try to get stats for it. Userland will skip over it. 1292885Sahrens */ 1293885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1294885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1295789Sahrens 1296885Sahrens dmu_objset_close(os); 1297789Sahrens return (error); 1298789Sahrens } 1299789Sahrens 13005367Sahrens /* 13015367Sahrens * inputs: 13025367Sahrens * zc_name name of filesystem 13035367Sahrens * zc_cookie zap cursor 13045367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 13055367Sahrens * 13065367Sahrens * outputs: 13075367Sahrens * zc_name name of next snapshot 13085367Sahrens * zc_objset_stats stats 13095367Sahrens * zc_nvlist_dst property nvlist 13105367Sahrens * zc_nvlist_dst_size size of property nvlist 13115367Sahrens * zc_value alternate root 13125367Sahrens */ 1313789Sahrens static int 1314789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1315789Sahrens { 1316885Sahrens objset_t *os; 1317789Sahrens int error; 1318789Sahrens 13195498Stimh if ((error = zfs_os_open_retry(zc->zc_name, &os)) != 0) { 1320789Sahrens if (error == ENOENT) 1321885Sahrens error = ESRCH; 1322789Sahrens return (error); 1323789Sahrens } 1324789Sahrens 13251003Slling /* 13261003Slling * A dataset name of maximum length cannot have any snapshots, 13271003Slling * so exit immediately. 13281003Slling */ 13291003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1330885Sahrens dmu_objset_close(os); 13311003Slling return (ESRCH); 1332789Sahrens } 1333789Sahrens 1334885Sahrens error = dmu_snapshot_list_next(os, 1335885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 13365663Sck153898 zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie, NULL); 1337789Sahrens if (error == ENOENT) 1338789Sahrens error = ESRCH; 1339789Sahrens 1340885Sahrens if (error == 0) 1341885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1342789Sahrens 13435367Sahrens /* if we failed, undo the @ that we tacked on to zc_name */ 13445367Sahrens if (error != 0) 13455367Sahrens *strchr(zc->zc_name, '@') = '\0'; 13465367Sahrens 1347885Sahrens dmu_objset_close(os); 1348789Sahrens return (error); 1349789Sahrens } 1350789Sahrens 1351789Sahrens static int 13524787Sahrens zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) 1353789Sahrens { 13542676Seschrock nvpair_t *elem; 13552676Seschrock int error; 13562676Seschrock uint64_t intval; 13572676Seschrock char *strval; 13582676Seschrock 13594543Smarks /* 13604543Smarks * First validate permission to set all of the properties 13614543Smarks */ 13622676Seschrock elem = NULL; 13632676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 13644670Sahrens const char *propname = nvpair_name(elem); 13654670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 13662676Seschrock 13675094Slling if (prop == ZPROP_INVAL) { 13682676Seschrock /* 13692676Seschrock * If this is a user-defined property, it must be a 13702676Seschrock * string, and there is no further validation to do. 13712676Seschrock */ 13722676Seschrock if (!zfs_prop_user(propname) || 13732676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 13742676Seschrock return (EINVAL); 13752676Seschrock 13765331Samw if (error = zfs_secpolicy_write_perms(name, 13775331Samw ZFS_DELEG_PERM_USERPROP, CRED())) 13784670Sahrens return (error); 13794543Smarks continue; 13802676Seschrock } 13812676Seschrock 13824787Sahrens if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 13834670Sahrens return (error); 13842676Seschrock 13854670Sahrens /* 13864670Sahrens * Check that this value is valid for this pool version 13874670Sahrens */ 13884670Sahrens switch (prop) { 13893886Sahl case ZFS_PROP_COMPRESSION: 13903886Sahl /* 13913886Sahl * If the user specified gzip compression, make sure 13923886Sahl * the SPA supports it. We ignore any errors here since 13933886Sahl * we'll catch them later. 13943886Sahl */ 13953886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 13963886Sahl nvpair_value_uint64(elem, &intval) == 0 && 13973886Sahl intval >= ZIO_COMPRESS_GZIP_1 && 13983886Sahl intval <= ZIO_COMPRESS_GZIP_9) { 13995331Samw if (zfs_check_version(name, 14005331Samw SPA_VERSION_GZIP_COMPRESSION)) 14015331Samw return (ENOTSUP); 14023886Sahl } 14033886Sahl break; 14044603Sahrens 14054603Sahrens case ZFS_PROP_COPIES: 14065331Samw if (zfs_check_version(name, SPA_VERSION_DITTO_BLOCKS)) 14075331Samw return (ENOTSUP); 14084603Sahrens break; 14095977Smarks 14105977Smarks case ZFS_PROP_SHARESMB: 14115977Smarks if (zpl_check_version(name, ZPL_VERSION_FUID)) 14125977Smarks return (ENOTSUP); 14135977Smarks break; 14144603Sahrens } 14155331Samw if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 14165331Samw return (error); 14174543Smarks } 14184543Smarks 14194543Smarks elem = NULL; 14204543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 14214670Sahrens const char *propname = nvpair_name(elem); 14224670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 14234543Smarks 14245094Slling if (prop == ZPROP_INVAL) { 14254543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 14264543Smarks error = dsl_prop_set(name, propname, 1, 14274543Smarks strlen(strval) + 1, strval); 14284543Smarks if (error == 0) 14294543Smarks continue; 14304543Smarks else 14314543Smarks return (error); 14324543Smarks } 14332676Seschrock 14342676Seschrock switch (prop) { 14352676Seschrock case ZFS_PROP_QUOTA: 14362676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14374577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 14382676Seschrock return (error); 14392676Seschrock break; 14402676Seschrock 14415378Sck153898 case ZFS_PROP_REFQUOTA: 14425378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14435378Sck153898 (error = dsl_dataset_set_quota(name, intval)) != 0) 14445378Sck153898 return (error); 14455378Sck153898 break; 14465378Sck153898 14472676Seschrock case ZFS_PROP_RESERVATION: 14482676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14492676Seschrock (error = dsl_dir_set_reservation(name, 14502676Seschrock intval)) != 0) 14512676Seschrock return (error); 14522676Seschrock break; 1453789Sahrens 14545378Sck153898 case ZFS_PROP_REFRESERVATION: 14555378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14565378Sck153898 (error = dsl_dataset_set_reservation(name, 14575378Sck153898 intval)) != 0) 14585378Sck153898 return (error); 14595378Sck153898 break; 14605378Sck153898 14612676Seschrock case ZFS_PROP_VOLSIZE: 14622676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14634787Sahrens (error = zvol_set_volsize(name, 14644787Sahrens ddi_driver_major(zfs_dip), intval)) != 0) 14652676Seschrock return (error); 14662676Seschrock break; 14672676Seschrock 14682676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 14692676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14704577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 14714577Sahrens return (error); 14724577Sahrens break; 14734577Sahrens 14744577Sahrens case ZFS_PROP_VERSION: 14754577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14764577Sahrens (error = zfs_set_version(name, intval)) != 0) 14772676Seschrock return (error); 14782676Seschrock break; 14792676Seschrock 14802676Seschrock default: 14812676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 14822676Seschrock if (zfs_prop_get_type(prop) != 14834787Sahrens PROP_TYPE_STRING) 14842676Seschrock return (EINVAL); 14852717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 14862717Seschrock if ((error = dsl_prop_set(name, 14872676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 14882717Seschrock strval)) != 0) 14892717Seschrock return (error); 14902676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 14912885Sahrens const char *unused; 14922885Sahrens 14932717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 14942676Seschrock 14952676Seschrock switch (zfs_prop_get_type(prop)) { 14964787Sahrens case PROP_TYPE_NUMBER: 14972676Seschrock break; 14984787Sahrens case PROP_TYPE_STRING: 14992717Seschrock return (EINVAL); 15004787Sahrens case PROP_TYPE_INDEX: 15012717Seschrock if (zfs_prop_index_to_string(prop, 15022717Seschrock intval, &unused) != 0) 15032717Seschrock return (EINVAL); 15042676Seschrock break; 15052676Seschrock default: 15064577Sahrens cmn_err(CE_PANIC, 15074577Sahrens "unknown property type"); 15082676Seschrock break; 15092676Seschrock } 15102676Seschrock 15112717Seschrock if ((error = dsl_prop_set(name, propname, 15122717Seschrock 8, 1, &intval)) != 0) 15132717Seschrock return (error); 15142676Seschrock } else { 15152676Seschrock return (EINVAL); 15162676Seschrock } 15172676Seschrock break; 15182676Seschrock } 15192676Seschrock } 15202676Seschrock 15212676Seschrock return (0); 1522789Sahrens } 1523789Sahrens 15245367Sahrens /* 15255367Sahrens * inputs: 15265367Sahrens * zc_name name of filesystem 15275367Sahrens * zc_value name of property to inherit 15285367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 15295367Sahrens * 15305367Sahrens * outputs: none 15315367Sahrens */ 1532789Sahrens static int 15332676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1534789Sahrens { 15352676Seschrock nvlist_t *nvl; 15362676Seschrock int error; 1537789Sahrens 15385094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15395094Slling &nvl)) != 0) 15402676Seschrock return (error); 15412676Seschrock 15424787Sahrens error = zfs_set_prop_nvlist(zc->zc_name, nvl); 15434543Smarks 15442676Seschrock nvlist_free(nvl); 15452676Seschrock return (error); 1546789Sahrens } 1547789Sahrens 15485367Sahrens /* 15495367Sahrens * inputs: 15505367Sahrens * zc_name name of filesystem 15515367Sahrens * zc_value name of property to inherit 15525367Sahrens * 15535367Sahrens * outputs: none 15545367Sahrens */ 1555789Sahrens static int 15564849Sahrens zfs_ioc_inherit_prop(zfs_cmd_t *zc) 15574849Sahrens { 15584849Sahrens /* the property name has been validated by zfs_secpolicy_inherit() */ 15594849Sahrens return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 15604849Sahrens } 15614849Sahrens 15624849Sahrens static int 15634098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 15643912Slling { 15655094Slling nvlist_t *props; 15663912Slling spa_t *spa; 15675094Slling int error; 15683912Slling 15695094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15705094Slling &props))) 15713912Slling return (error); 15723912Slling 15733912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 15745094Slling nvlist_free(props); 15753912Slling return (error); 15763912Slling } 15773912Slling 15785094Slling error = spa_prop_set(spa, props); 15793912Slling 15805094Slling nvlist_free(props); 15813912Slling spa_close(spa, FTAG); 15823912Slling 15833912Slling return (error); 15843912Slling } 15853912Slling 15863912Slling static int 15874098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 15883912Slling { 15893912Slling spa_t *spa; 15903912Slling int error; 15913912Slling nvlist_t *nvp = NULL; 15923912Slling 15933912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 15943912Slling return (error); 15953912Slling 15965094Slling error = spa_prop_get(spa, &nvp); 15973912Slling 15983912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 15993912Slling error = put_nvlist(zc, nvp); 16003912Slling else 16013912Slling error = EFAULT; 16023912Slling 16033912Slling spa_close(spa, FTAG); 16043912Slling 16053912Slling if (nvp) 16063912Slling nvlist_free(nvp); 16073912Slling return (error); 16083912Slling } 16093912Slling 16103912Slling static int 16114543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 16124543Smarks { 16134543Smarks nvlist_t *nvp; 16144543Smarks int error; 16154543Smarks uint32_t uid; 16164543Smarks uint32_t gid; 16174543Smarks uint32_t *groups; 16184543Smarks uint_t group_cnt; 16194543Smarks cred_t *usercred; 16204543Smarks 16215094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16225094Slling &nvp)) != 0) { 16234543Smarks return (error); 16244543Smarks } 16254543Smarks 16264543Smarks if ((error = nvlist_lookup_uint32(nvp, 16274543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 16284543Smarks nvlist_free(nvp); 16294543Smarks return (EPERM); 16304543Smarks } 16314543Smarks 16324543Smarks if ((error = nvlist_lookup_uint32(nvp, 16334543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 16344543Smarks nvlist_free(nvp); 16354543Smarks return (EPERM); 16364543Smarks } 16374543Smarks 16384543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 16394543Smarks &groups, &group_cnt)) != 0) { 16404543Smarks nvlist_free(nvp); 16414543Smarks return (EPERM); 16424543Smarks } 16434543Smarks usercred = cralloc(); 16444543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 16454543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 16464543Smarks nvlist_free(nvp); 16474543Smarks crfree(usercred); 16484543Smarks return (EPERM); 16494543Smarks } 16504543Smarks nvlist_free(nvp); 16514543Smarks error = dsl_deleg_access(zc->zc_name, 16524787Sahrens zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); 16534543Smarks crfree(usercred); 16544543Smarks return (error); 16554543Smarks } 16564543Smarks 16575367Sahrens /* 16585367Sahrens * inputs: 16595367Sahrens * zc_name name of filesystem 16605367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 16615367Sahrens * zc_perm_action allow/unallow flag 16625367Sahrens * 16635367Sahrens * outputs: none 16645367Sahrens */ 16654543Smarks static int 16664543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 16674543Smarks { 16684543Smarks int error; 16694543Smarks nvlist_t *fsaclnv = NULL; 16704543Smarks 16715094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16725094Slling &fsaclnv)) != 0) 16734543Smarks return (error); 16744543Smarks 16754543Smarks /* 16764543Smarks * Verify nvlist is constructed correctly 16774543Smarks */ 16784543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 16794543Smarks nvlist_free(fsaclnv); 16804543Smarks return (EINVAL); 16814543Smarks } 16824543Smarks 16834543Smarks /* 16844543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 16854543Smarks * that user is allowed to hand out each permission in 16864543Smarks * the nvlist(s) 16874543Smarks */ 16884543Smarks 16894787Sahrens error = secpolicy_zfs(CRED()); 16904543Smarks if (error) { 16914787Sahrens if (zc->zc_perm_action == B_FALSE) { 16924787Sahrens error = dsl_deleg_can_allow(zc->zc_name, 16934787Sahrens fsaclnv, CRED()); 16944787Sahrens } else { 16954787Sahrens error = dsl_deleg_can_unallow(zc->zc_name, 16964787Sahrens fsaclnv, CRED()); 16974787Sahrens } 16984543Smarks } 16994543Smarks 17004543Smarks if (error == 0) 17014543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 17024543Smarks 17034543Smarks nvlist_free(fsaclnv); 17044543Smarks return (error); 17054543Smarks } 17064543Smarks 17075367Sahrens /* 17085367Sahrens * inputs: 17095367Sahrens * zc_name name of filesystem 17105367Sahrens * 17115367Sahrens * outputs: 17125367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 17135367Sahrens */ 17144543Smarks static int 17154543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 17164543Smarks { 17174543Smarks nvlist_t *nvp; 17184543Smarks int error; 17194543Smarks 17204543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 17214543Smarks error = put_nvlist(zc, nvp); 17224543Smarks nvlist_free(nvp); 17234543Smarks } 17244543Smarks 17254543Smarks return (error); 17264543Smarks } 17274543Smarks 17285367Sahrens /* 17295367Sahrens * inputs: 17305367Sahrens * zc_name name of volume 17315367Sahrens * 17325367Sahrens * outputs: none 17335367Sahrens */ 17344543Smarks static int 1735789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1736789Sahrens { 17374787Sahrens return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); 1738789Sahrens } 1739789Sahrens 17405367Sahrens /* 17415367Sahrens * inputs: 17425367Sahrens * zc_name name of volume 17435367Sahrens * 17445367Sahrens * outputs: none 17455367Sahrens */ 1746789Sahrens static int 1747789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1748789Sahrens { 17492676Seschrock return (zvol_remove_minor(zc->zc_name)); 1750789Sahrens } 1751789Sahrens 1752789Sahrens /* 1753789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1754789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1755789Sahrens * is responsible for releasing the returned vfs pointer. 1756789Sahrens */ 1757789Sahrens static vfs_t * 1758789Sahrens zfs_get_vfs(const char *resource) 1759789Sahrens { 1760789Sahrens struct vfs *vfsp; 1761789Sahrens struct vfs *vfs_found = NULL; 1762789Sahrens 1763789Sahrens vfs_list_read_lock(); 1764789Sahrens vfsp = rootvfs; 1765789Sahrens do { 1766789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1767789Sahrens VFS_HOLD(vfsp); 1768789Sahrens vfs_found = vfsp; 1769789Sahrens break; 1770789Sahrens } 1771789Sahrens vfsp = vfsp->vfs_next; 1772789Sahrens } while (vfsp != rootvfs); 1773789Sahrens vfs_list_unlock(); 1774789Sahrens return (vfs_found); 1775789Sahrens } 1776789Sahrens 17774543Smarks /* ARGSUSED */ 1778789Sahrens static void 17794543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1780789Sahrens { 17815331Samw zfs_creat_t *zct = arg; 17825498Stimh 17835498Stimh zfs_create_fs(os, cr, zct->zct_zplprops, tx); 17845331Samw } 17855331Samw 17865498Stimh #define ZFS_PROP_UNDEFINED ((uint64_t)-1) 17875498Stimh 17885331Samw /* 17895498Stimh * inputs: 17905498Stimh * createprops list of properties requested by creator 17915498Stimh * dataset name of dataset we are creating 17925331Samw * 17935498Stimh * outputs: 17945498Stimh * zplprops values for the zplprops we attach to the master node object 17955331Samw * 17965498Stimh * Determine the settings for utf8only, normalization and 17975498Stimh * casesensitivity. Specific values may have been requested by the 17985498Stimh * creator and/or we can inherit values from the parent dataset. If 17995498Stimh * the file system is of too early a vintage, a creator can not 18005498Stimh * request settings for these properties, even if the requested 18015498Stimh * setting is the default value. We don't actually want to create dsl 18025498Stimh * properties for these, so remove them from the source nvlist after 18035498Stimh * processing. 18045331Samw */ 18055331Samw static int 18065498Stimh zfs_fill_zplprops(const char *dataset, nvlist_t *createprops, 18075498Stimh nvlist_t *zplprops, uint64_t zplver) 18085331Samw { 18095498Stimh objset_t *os; 18105331Samw char parentname[MAXNAMELEN]; 18115331Samw char *cp; 18125498Stimh uint64_t sense = ZFS_PROP_UNDEFINED; 18135498Stimh uint64_t norm = ZFS_PROP_UNDEFINED; 18145498Stimh uint64_t u8 = ZFS_PROP_UNDEFINED; 18155498Stimh int error = 0; 18165498Stimh 18175498Stimh ASSERT(zplprops != NULL); 18185498Stimh 18195498Stimh (void) strlcpy(parentname, dataset, sizeof (parentname)); 18205498Stimh cp = strrchr(parentname, '/'); 18215498Stimh ASSERT(cp != NULL); 18225498Stimh cp[0] = '\0'; 18235331Samw 18245375Stimh /* 18255498Stimh * Pull out creator prop choices, if any. 18265375Stimh */ 18275498Stimh if (createprops) { 18285498Stimh (void) nvlist_lookup_uint64(createprops, 18295498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE), &norm); 18305498Stimh (void) nvlist_remove_all(createprops, 18315498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE)); 18325498Stimh (void) nvlist_lookup_uint64(createprops, 18335498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY), &u8); 18345498Stimh (void) nvlist_remove_all(createprops, 18355498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY)); 18365498Stimh (void) nvlist_lookup_uint64(createprops, 18375498Stimh zfs_prop_to_name(ZFS_PROP_CASE), &sense); 18385498Stimh (void) nvlist_remove_all(createprops, 18395498Stimh zfs_prop_to_name(ZFS_PROP_CASE)); 18405331Samw } 18415331Samw 18425375Stimh /* 18435498Stimh * If the file system or pool is version is too "young" to 18445498Stimh * support normalization and the creator tried to set a value 18455498Stimh * for one of the props, error out. We only need check the 18465498Stimh * ZPL version because we've already checked by now that the 18475498Stimh * SPA version is compatible with the selected ZPL version. 18485498Stimh */ 18495498Stimh if (zplver < ZPL_VERSION_NORMALIZATION && 18505498Stimh (norm != ZFS_PROP_UNDEFINED || u8 != ZFS_PROP_UNDEFINED || 18515498Stimh sense != ZFS_PROP_UNDEFINED)) 18525498Stimh return (ENOTSUP); 18535498Stimh 18545498Stimh /* 18555498Stimh * Put the version in the zplprops 18565498Stimh */ 18575498Stimh VERIFY(nvlist_add_uint64(zplprops, 18585498Stimh zfs_prop_to_name(ZFS_PROP_VERSION), zplver) == 0); 18595498Stimh 18605498Stimh /* 18615498Stimh * Open parent object set so we can inherit zplprop values if 18625498Stimh * necessary. 18635375Stimh */ 18645498Stimh if ((error = zfs_os_open_retry(parentname, &os)) != 0) 18655498Stimh return (error); 18665498Stimh 18675498Stimh if (norm == ZFS_PROP_UNDEFINED) 18685498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &norm) == 0); 18695498Stimh VERIFY(nvlist_add_uint64(zplprops, 18705498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE), norm) == 0); 18715498Stimh 18725498Stimh /* 18735498Stimh * If we're normalizing, names must always be valid UTF-8 strings. 18745498Stimh */ 18755498Stimh if (norm) 18765498Stimh u8 = 1; 18775498Stimh if (u8 == ZFS_PROP_UNDEFINED) 18785498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &u8) == 0); 18795498Stimh VERIFY(nvlist_add_uint64(zplprops, 18805498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY), u8) == 0); 18815498Stimh 18825498Stimh if (sense == ZFS_PROP_UNDEFINED) 18835498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_CASE, &sense) == 0); 18845498Stimh VERIFY(nvlist_add_uint64(zplprops, 18855498Stimh zfs_prop_to_name(ZFS_PROP_CASE), sense) == 0); 18865498Stimh 18875498Stimh dmu_objset_close(os); 18885331Samw return (0); 1889789Sahrens } 1890789Sahrens 18915367Sahrens /* 18925367Sahrens * inputs: 18935367Sahrens * zc_objset_type type of objset to create (fs vs zvol) 18945367Sahrens * zc_name name of new objset 18955367Sahrens * zc_value name of snapshot to clone from (may be empty) 18965367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 18975367Sahrens * 18985498Stimh * outputs: none 18995367Sahrens */ 1900789Sahrens static int 1901789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1902789Sahrens { 1903789Sahrens objset_t *clone; 1904789Sahrens int error = 0; 19055331Samw zfs_creat_t zct; 19064543Smarks nvlist_t *nvprops = NULL; 19074543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1908789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1909789Sahrens 1910789Sahrens switch (type) { 1911789Sahrens 1912789Sahrens case DMU_OST_ZFS: 1913789Sahrens cbfunc = zfs_create_cb; 1914789Sahrens break; 1915789Sahrens 1916789Sahrens case DMU_OST_ZVOL: 1917789Sahrens cbfunc = zvol_create_cb; 1918789Sahrens break; 1919789Sahrens 1920789Sahrens default: 19212199Sahrens cbfunc = NULL; 19222199Sahrens } 19235326Sek110237 if (strchr(zc->zc_name, '@') || 19245326Sek110237 strchr(zc->zc_name, '%')) 1925789Sahrens return (EINVAL); 1926789Sahrens 19272676Seschrock if (zc->zc_nvlist_src != NULL && 19285094Slling (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 19295094Slling &nvprops)) != 0) 19302676Seschrock return (error); 19312676Seschrock 19325498Stimh zct.zct_zplprops = NULL; 19335331Samw zct.zct_props = nvprops; 19345331Samw 19352676Seschrock if (zc->zc_value[0] != '\0') { 1936789Sahrens /* 1937789Sahrens * We're creating a clone of an existing snapshot. 1938789Sahrens */ 19392676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 19402676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 19414543Smarks nvlist_free(nvprops); 1942789Sahrens return (EINVAL); 19432676Seschrock } 1944789Sahrens 19452676Seschrock error = dmu_objset_open(zc->zc_value, type, 1946789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 19472676Seschrock if (error) { 19484543Smarks nvlist_free(nvprops); 1949789Sahrens return (error); 19502676Seschrock } 1951789Sahrens error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); 19525331Samw if (error) { 19535331Samw dmu_objset_close(clone); 19545331Samw nvlist_free(nvprops); 19555331Samw return (error); 19565331Samw } 1957789Sahrens dmu_objset_close(clone); 1958789Sahrens } else { 19592676Seschrock if (cbfunc == NULL) { 19604543Smarks nvlist_free(nvprops); 19612199Sahrens return (EINVAL); 19622676Seschrock } 19632676Seschrock 1964789Sahrens if (type == DMU_OST_ZVOL) { 19652676Seschrock uint64_t volsize, volblocksize; 19662676Seschrock 19674543Smarks if (nvprops == NULL || 19684543Smarks nvlist_lookup_uint64(nvprops, 19692676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 19702676Seschrock &volsize) != 0) { 19714543Smarks nvlist_free(nvprops); 19722676Seschrock return (EINVAL); 19732676Seschrock } 19742676Seschrock 19754543Smarks if ((error = nvlist_lookup_uint64(nvprops, 19762676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 19772676Seschrock &volblocksize)) != 0 && error != ENOENT) { 19784543Smarks nvlist_free(nvprops); 19792676Seschrock return (EINVAL); 19802676Seschrock } 19811133Seschrock 19822676Seschrock if (error != 0) 19832676Seschrock volblocksize = zfs_prop_default_numeric( 19842676Seschrock ZFS_PROP_VOLBLOCKSIZE); 19852676Seschrock 19862676Seschrock if ((error = zvol_check_volblocksize( 19872676Seschrock volblocksize)) != 0 || 19882676Seschrock (error = zvol_check_volsize(volsize, 19892676Seschrock volblocksize)) != 0) { 19904543Smarks nvlist_free(nvprops); 1991789Sahrens return (error); 19922676Seschrock } 19934577Sahrens } else if (type == DMU_OST_ZFS) { 19944577Sahrens uint64_t version; 19955331Samw int error; 19965331Samw 19975498Stimh /* 19985498Stimh * Default ZPL version to non-FUID capable if the 19995498Stimh * pool is not upgraded to support FUIDs. 20005498Stimh */ 20015498Stimh if (zfs_check_version(zc->zc_name, SPA_VERSION_FUID)) 20025498Stimh version = ZPL_VERSION_FUID - 1; 20035498Stimh else 20045498Stimh version = ZPL_VERSION; 20055498Stimh 20065498Stimh /* 20075498Stimh * Potentially override default ZPL version based 20085498Stimh * on creator's request. 20095498Stimh */ 20105498Stimh (void) nvlist_lookup_uint64(nvprops, 20115331Samw zfs_prop_to_name(ZFS_PROP_VERSION), &version); 20125331Samw 20135498Stimh /* 20145498Stimh * Make sure version we ended up with is kosher 20155498Stimh */ 20165498Stimh if ((version < ZPL_VERSION_INITIAL || 20175498Stimh version > ZPL_VERSION) || 20185498Stimh (version >= ZPL_VERSION_FUID && 20195498Stimh zfs_check_version(zc->zc_name, SPA_VERSION_FUID))) { 20205331Samw nvlist_free(nvprops); 20215331Samw return (ENOTSUP); 20225331Samw } 20235331Samw 20245331Samw /* 20255331Samw * We have to have normalization and 20265331Samw * case-folding flags correct when we do the 20275331Samw * file system creation, so go figure them out 20285498Stimh * now. 20295331Samw */ 20305498Stimh VERIFY(nvlist_alloc(&zct.zct_zplprops, 20315498Stimh NV_UNIQUE_NAME, KM_SLEEP) == 0); 20325498Stimh error = zfs_fill_zplprops(zc->zc_name, nvprops, 20335498Stimh zct.zct_zplprops, version); 20345331Samw if (error != 0) { 20355331Samw nvlist_free(nvprops); 20365498Stimh nvlist_free(zct.zct_zplprops); 20375331Samw return (error); 20384577Sahrens } 20392676Seschrock } 20402676Seschrock error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, 20415331Samw &zct); 20425498Stimh nvlist_free(zct.zct_zplprops); 2043789Sahrens } 20442676Seschrock 20452676Seschrock /* 20462676Seschrock * It would be nice to do this atomically. 20472676Seschrock */ 20482676Seschrock if (error == 0) { 20494787Sahrens if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) 20502676Seschrock (void) dmu_objset_destroy(zc->zc_name); 20512676Seschrock } 20522676Seschrock 20534543Smarks nvlist_free(nvprops); 2054789Sahrens return (error); 2055789Sahrens } 2056789Sahrens 20575367Sahrens /* 20585367Sahrens * inputs: 20595367Sahrens * zc_name name of filesystem 20605367Sahrens * zc_value short name of snapshot 20615367Sahrens * zc_cookie recursive flag 20625367Sahrens * 20635367Sahrens * outputs: none 20645367Sahrens */ 2065789Sahrens static int 20662199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 20672199Sahrens { 20682676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 20692199Sahrens return (EINVAL); 20702199Sahrens return (dmu_objset_snapshot(zc->zc_name, 20712676Seschrock zc->zc_value, zc->zc_cookie)); 20722199Sahrens } 20732199Sahrens 20744007Smmusante int 20752199Sahrens zfs_unmount_snap(char *name, void *arg) 2076789Sahrens { 20772199Sahrens char *snapname = arg; 20782199Sahrens char *cp; 20792417Sahrens vfs_t *vfsp = NULL; 20802199Sahrens 20812199Sahrens /* 20822199Sahrens * Snapshots (which are under .zfs control) must be unmounted 20832199Sahrens * before they can be destroyed. 20842199Sahrens */ 20852199Sahrens 20862199Sahrens if (snapname) { 20872199Sahrens (void) strcat(name, "@"); 20882199Sahrens (void) strcat(name, snapname); 20892199Sahrens vfsp = zfs_get_vfs(name); 20902199Sahrens cp = strchr(name, '@'); 20912199Sahrens *cp = '\0'; 20922417Sahrens } else if (strchr(name, '@')) { 20932199Sahrens vfsp = zfs_get_vfs(name); 20942199Sahrens } 20952199Sahrens 20962199Sahrens if (vfsp) { 20972199Sahrens /* 20982199Sahrens * Always force the unmount for snapshots. 20992199Sahrens */ 21002199Sahrens int flag = MS_FORCE; 2101789Sahrens int err; 2102789Sahrens 21032199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 21042199Sahrens VFS_RELE(vfsp); 21052199Sahrens return (err); 21062199Sahrens } 21072199Sahrens VFS_RELE(vfsp); 21082199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 21092199Sahrens return (err); 21102199Sahrens } 21112199Sahrens return (0); 21122199Sahrens } 21132199Sahrens 21145367Sahrens /* 21155367Sahrens * inputs: 21165367Sahrens * zc_name name of filesystem 21175367Sahrens * zc_value short name of snapshot 21185367Sahrens * 21195367Sahrens * outputs: none 21205367Sahrens */ 21212199Sahrens static int 21222199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 21232199Sahrens { 21242199Sahrens int err; 2125789Sahrens 21262676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 21272199Sahrens return (EINVAL); 21282199Sahrens err = dmu_objset_find(zc->zc_name, 21292676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 21302199Sahrens if (err) 21312199Sahrens return (err); 21322676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 21332199Sahrens } 21342199Sahrens 21355367Sahrens /* 21365367Sahrens * inputs: 21375367Sahrens * zc_name name of dataset to destroy 21385367Sahrens * zc_objset_type type of objset 21395367Sahrens * 21405367Sahrens * outputs: none 21415367Sahrens */ 21422199Sahrens static int 21432199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 21442199Sahrens { 21452199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 21462199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 21472199Sahrens if (err) 21482199Sahrens return (err); 2149789Sahrens } 2150789Sahrens 2151789Sahrens return (dmu_objset_destroy(zc->zc_name)); 2152789Sahrens } 2153789Sahrens 21545367Sahrens /* 21555367Sahrens * inputs: 21565446Sahrens * zc_name name of dataset to rollback (to most recent snapshot) 21575367Sahrens * 21585367Sahrens * outputs: none 21595367Sahrens */ 2160789Sahrens static int 2161789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 2162789Sahrens { 21635446Sahrens objset_t *os; 21645446Sahrens int error; 21655446Sahrens zfsvfs_t *zfsvfs = NULL; 21665446Sahrens 21675446Sahrens /* 21685446Sahrens * Get the zfsvfs for the receiving objset. There 21695446Sahrens * won't be one if we're operating on a zvol, if the 21705446Sahrens * objset doesn't exist yet, or is not mounted. 21715446Sahrens */ 21725446Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 21735446Sahrens DS_MODE_STANDARD, &os); 21745446Sahrens if (error) 21755446Sahrens return (error); 21765446Sahrens 21775446Sahrens if (dmu_objset_type(os) == DMU_OST_ZFS) { 21785446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 21795446Sahrens zfsvfs = dmu_objset_get_user(os); 21805446Sahrens if (zfsvfs != NULL) 21815446Sahrens VFS_HOLD(zfsvfs->z_vfs); 21825446Sahrens mutex_exit(&os->os->os_user_ptr_lock); 21835446Sahrens } 21845446Sahrens 21855446Sahrens if (zfsvfs != NULL) { 21865446Sahrens char osname[MAXNAMELEN]; 21875446Sahrens int mode; 21885446Sahrens 2189*6083Sek110237 error = zfs_suspend_fs(zfsvfs, osname, &mode); 2190*6083Sek110237 if (error == 0) { 2191*6083Sek110237 int resume_err; 2192*6083Sek110237 2193*6083Sek110237 ASSERT(strcmp(osname, zc->zc_name) == 0); 2194*6083Sek110237 error = dmu_objset_rollback(os); 2195*6083Sek110237 resume_err = zfs_resume_fs(zfsvfs, osname, mode); 2196*6083Sek110237 error = error ? error : resume_err; 2197*6083Sek110237 } else { 2198*6083Sek110237 dmu_objset_close(os); 2199*6083Sek110237 } 22005446Sahrens VFS_RELE(zfsvfs->z_vfs); 22015446Sahrens } else { 22025446Sahrens error = dmu_objset_rollback(os); 22035446Sahrens } 22045446Sahrens /* Note, the dmu_objset_rollback() closes the objset for us. */ 22055446Sahrens 22065446Sahrens return (error); 2207789Sahrens } 2208789Sahrens 22095367Sahrens /* 22105367Sahrens * inputs: 22115367Sahrens * zc_name old name of dataset 22125367Sahrens * zc_value new name of dataset 22135367Sahrens * zc_cookie recursive flag (only valid for snapshots) 22145367Sahrens * 22155367Sahrens * outputs: none 22165367Sahrens */ 2217789Sahrens static int 2218789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 2219789Sahrens { 22204490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 22214007Smmusante 22222676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 22235326Sek110237 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 22245326Sek110237 strchr(zc->zc_value, '%')) 2225789Sahrens return (EINVAL); 2226789Sahrens 22274007Smmusante /* 22284007Smmusante * Unmount snapshot unless we're doing a recursive rename, 22294007Smmusante * in which case the dataset code figures out which snapshots 22304007Smmusante * to unmount. 22314007Smmusante */ 22324007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 2233789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 22342199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 22352199Sahrens if (err) 22362199Sahrens return (err); 2237789Sahrens } 2238789Sahrens 22394007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 2240789Sahrens } 2241789Sahrens 22425367Sahrens /* 22435367Sahrens * inputs: 22445367Sahrens * zc_name name of containing filesystem 22455367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 22465367Sahrens * zc_value name of snapshot to create 22475367Sahrens * zc_string name of clone origin (if DRR_FLAG_CLONE) 22485367Sahrens * zc_cookie file descriptor to recv from 22495367Sahrens * zc_begin_record the BEGIN record of the stream (not byteswapped) 22505367Sahrens * zc_guid force flag 22515367Sahrens * 22525367Sahrens * outputs: 22535367Sahrens * zc_cookie number of bytes read 22545367Sahrens */ 2255789Sahrens static int 22565367Sahrens zfs_ioc_recv(zfs_cmd_t *zc) 2257789Sahrens { 2258789Sahrens file_t *fp; 22595326Sek110237 objset_t *os; 22605367Sahrens dmu_recv_cookie_t drc; 22615326Sek110237 zfsvfs_t *zfsvfs = NULL; 22625326Sek110237 boolean_t force = (boolean_t)zc->zc_guid; 2263789Sahrens int error, fd; 22645367Sahrens offset_t off; 22655367Sahrens nvlist_t *props = NULL; 22665367Sahrens objset_t *origin = NULL; 22675367Sahrens char *tosnap; 22685367Sahrens char tofs[ZFS_MAXNAMELEN]; 2269789Sahrens 22703265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 22715326Sek110237 strchr(zc->zc_value, '@') == NULL || 22725326Sek110237 strchr(zc->zc_value, '%')) 22733265Sahrens return (EINVAL); 22743265Sahrens 22755367Sahrens (void) strcpy(tofs, zc->zc_value); 22765367Sahrens tosnap = strchr(tofs, '@'); 22775367Sahrens *tosnap = '\0'; 22785367Sahrens tosnap++; 22795367Sahrens 22805367Sahrens if (zc->zc_nvlist_src != NULL && 22815367Sahrens (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 22825367Sahrens &props)) != 0) 22835367Sahrens return (error); 22845367Sahrens 2285789Sahrens fd = zc->zc_cookie; 2286789Sahrens fp = getf(fd); 22875367Sahrens if (fp == NULL) { 22885367Sahrens nvlist_free(props); 2289789Sahrens return (EBADF); 22905367Sahrens } 22915326Sek110237 22925326Sek110237 /* 22935326Sek110237 * Get the zfsvfs for the receiving objset. There 22945326Sek110237 * won't be one if we're operating on a zvol, if the 22955326Sek110237 * objset doesn't exist yet, or is not mounted. 22965326Sek110237 */ 22975367Sahrens 22985446Sahrens error = dmu_objset_open(tofs, DMU_OST_ZFS, 22995326Sek110237 DS_MODE_STANDARD | DS_MODE_READONLY, &os); 23005326Sek110237 if (!error) { 23015446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 23025446Sahrens zfsvfs = dmu_objset_get_user(os); 2303*6083Sek110237 if (zfsvfs != NULL) { 23045446Sahrens VFS_HOLD(zfsvfs->z_vfs); 2305*6083Sek110237 mutex_exit(&os->os->os_user_ptr_lock); 2306*6083Sek110237 if (!mutex_tryenter(&zfsvfs->z_online_recv_lock)) { 2307*6083Sek110237 VFS_RELE(zfsvfs->z_vfs); 2308*6083Sek110237 dmu_objset_close(os); 2309*6083Sek110237 nvlist_free(props); 2310*6083Sek110237 releasef(fd); 2311*6083Sek110237 return (EBUSY); 2312*6083Sek110237 } 2313*6083Sek110237 } else { 2314*6083Sek110237 mutex_exit(&os->os->os_user_ptr_lock); 2315*6083Sek110237 } 23165326Sek110237 dmu_objset_close(os); 23175326Sek110237 } 23185326Sek110237 23195367Sahrens if (zc->zc_string[0]) { 23205367Sahrens error = dmu_objset_open(zc->zc_string, DMU_OST_ANY, 23215367Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &origin); 23225367Sahrens if (error) { 2323*6083Sek110237 if (zfsvfs != NULL) { 2324*6083Sek110237 mutex_exit(&zfsvfs->z_online_recv_lock); 23255367Sahrens VFS_RELE(zfsvfs->z_vfs); 2326*6083Sek110237 } 23275367Sahrens nvlist_free(props); 23285367Sahrens releasef(fd); 23295367Sahrens return (error); 23305367Sahrens } 23315367Sahrens } 23325367Sahrens 23335367Sahrens error = dmu_recv_begin(tofs, tosnap, &zc->zc_begin_record, 23345367Sahrens force, origin, zfsvfs != NULL, &drc); 23355367Sahrens if (origin) 23365367Sahrens dmu_objset_close(origin); 23375367Sahrens if (error) { 2338*6083Sek110237 if (zfsvfs != NULL) { 2339*6083Sek110237 mutex_exit(&zfsvfs->z_online_recv_lock); 23405367Sahrens VFS_RELE(zfsvfs->z_vfs); 2341*6083Sek110237 } 23425367Sahrens nvlist_free(props); 23435367Sahrens releasef(fd); 23445367Sahrens return (error); 23455367Sahrens } 23465326Sek110237 23475326Sek110237 /* 23485367Sahrens * If properties are supplied, they are to completely replace 23495367Sahrens * the existing ones; "inherit" any existing properties. 23505326Sek110237 */ 23515367Sahrens if (props) { 23525367Sahrens objset_t *os; 23535367Sahrens nvlist_t *nv = NULL; 23545367Sahrens 23555367Sahrens error = dmu_objset_open(tofs, DMU_OST_ANY, 23565367Sahrens DS_MODE_STANDARD | DS_MODE_READONLY | DS_MODE_INCONSISTENT, 23575367Sahrens &os); 23585367Sahrens if (error == 0) { 23595367Sahrens error = dsl_prop_get_all(os, &nv); 23605367Sahrens dmu_objset_close(os); 23615367Sahrens } 23625367Sahrens if (error == 0) { 23635367Sahrens nvpair_t *elem; 23645446Sahrens zfs_cmd_t *zc2; 23655446Sahrens zc2 = kmem_alloc(sizeof (zfs_cmd_t), KM_SLEEP); 23665446Sahrens 23675446Sahrens (void) strcpy(zc2->zc_name, tofs); 23685367Sahrens for (elem = nvlist_next_nvpair(nv, NULL); elem; 23695367Sahrens elem = nvlist_next_nvpair(nv, elem)) { 23705446Sahrens (void) strcpy(zc2->zc_value, nvpair_name(elem)); 23715446Sahrens if (zfs_secpolicy_inherit(zc2, CRED()) == 0) 23725446Sahrens (void) zfs_ioc_inherit_prop(zc2); 23735326Sek110237 } 23745446Sahrens kmem_free(zc2, sizeof (zfs_cmd_t)); 23755326Sek110237 } 23765367Sahrens if (nv) 23775367Sahrens nvlist_free(nv); 23785367Sahrens } 23795367Sahrens 23805367Sahrens /* 23815367Sahrens * Set properties. Note, we ignore errors. Would be better to 23825367Sahrens * do best-effort in zfs_set_prop_nvlist, too. 23835367Sahrens */ 23845367Sahrens (void) zfs_set_prop_nvlist(tofs, props); 23855367Sahrens nvlist_free(props); 23865367Sahrens 23875367Sahrens off = fp->f_offset; 23885367Sahrens error = dmu_recv_stream(&drc, fp->f_vnode, &off); 23895367Sahrens 23905367Sahrens if (error == 0) { 23915367Sahrens if (zfsvfs != NULL) { 23925367Sahrens char osname[MAXNAMELEN]; 23935367Sahrens int mode; 23945367Sahrens 2395*6083Sek110237 error = zfs_suspend_fs(zfsvfs, osname, &mode); 2396*6083Sek110237 if (error == 0) { 2397*6083Sek110237 int resume_err; 2398*6083Sek110237 2399*6083Sek110237 error = dmu_recv_end(&drc); 2400*6083Sek110237 resume_err = zfs_resume_fs(zfsvfs, 2401*6083Sek110237 osname, mode); 2402*6083Sek110237 error = error ? error : resume_err; 2403*6083Sek110237 } else { 2404*6083Sek110237 dmu_recv_abort_cleanup(&drc); 2405*6083Sek110237 } 24065367Sahrens } else { 24075367Sahrens error = dmu_recv_end(&drc); 24085367Sahrens } 24095326Sek110237 } 2410*6083Sek110237 if (zfsvfs != NULL) { 2411*6083Sek110237 mutex_exit(&zfsvfs->z_online_recv_lock); 24125326Sek110237 VFS_RELE(zfsvfs->z_vfs); 2413*6083Sek110237 } 24145367Sahrens 24155367Sahrens zc->zc_cookie = off - fp->f_offset; 24165367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 24175367Sahrens fp->f_offset = off; 24182885Sahrens 2419789Sahrens releasef(fd); 2420789Sahrens return (error); 2421789Sahrens } 2422789Sahrens 24235367Sahrens /* 24245367Sahrens * inputs: 24255367Sahrens * zc_name name of snapshot to send 24265367Sahrens * zc_value short name of incremental fromsnap (may be empty) 24275367Sahrens * zc_cookie file descriptor to send stream to 24285367Sahrens * zc_obj fromorigin flag (mutually exclusive with zc_value) 24295367Sahrens * 24305367Sahrens * outputs: none 24315367Sahrens */ 2432789Sahrens static int 24335367Sahrens zfs_ioc_send(zfs_cmd_t *zc) 2434789Sahrens { 2435789Sahrens objset_t *fromsnap = NULL; 2436789Sahrens objset_t *tosnap; 2437789Sahrens file_t *fp; 2438789Sahrens int error; 24395367Sahrens offset_t off; 2440789Sahrens 2441789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 2442789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); 2443789Sahrens if (error) 2444789Sahrens return (error); 2445789Sahrens 24462676Seschrock if (zc->zc_value[0] != '\0') { 24472885Sahrens char buf[MAXPATHLEN]; 24482885Sahrens char *cp; 24492885Sahrens 24502885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 24512885Sahrens cp = strchr(buf, '@'); 24522885Sahrens if (cp) 24532885Sahrens *(cp+1) = 0; 24542885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 24552885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 2456789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); 2457789Sahrens if (error) { 2458789Sahrens dmu_objset_close(tosnap); 2459789Sahrens return (error); 2460789Sahrens } 2461789Sahrens } 2462789Sahrens 2463789Sahrens fp = getf(zc->zc_cookie); 2464789Sahrens if (fp == NULL) { 2465789Sahrens dmu_objset_close(tosnap); 2466789Sahrens if (fromsnap) 2467789Sahrens dmu_objset_close(fromsnap); 2468789Sahrens return (EBADF); 2469789Sahrens } 2470789Sahrens 24715367Sahrens off = fp->f_offset; 24725367Sahrens error = dmu_sendbackup(tosnap, fromsnap, zc->zc_obj, fp->f_vnode, &off); 24735367Sahrens 24745367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 24755367Sahrens fp->f_offset = off; 2476789Sahrens releasef(zc->zc_cookie); 2477789Sahrens if (fromsnap) 2478789Sahrens dmu_objset_close(fromsnap); 2479789Sahrens dmu_objset_close(tosnap); 2480789Sahrens return (error); 2481789Sahrens } 2482789Sahrens 24831544Seschrock static int 24841544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 24851544Seschrock { 24861544Seschrock int id, error; 24871544Seschrock 24881544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 24891544Seschrock &zc->zc_inject_record); 24901544Seschrock 24911544Seschrock if (error == 0) 24921544Seschrock zc->zc_guid = (uint64_t)id; 24931544Seschrock 24941544Seschrock return (error); 24951544Seschrock } 24961544Seschrock 24971544Seschrock static int 24981544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 24991544Seschrock { 25001544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 25011544Seschrock } 25021544Seschrock 25031544Seschrock static int 25041544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 25051544Seschrock { 25061544Seschrock int id = (int)zc->zc_guid; 25071544Seschrock int error; 25081544Seschrock 25091544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 25101544Seschrock &zc->zc_inject_record); 25111544Seschrock 25121544Seschrock zc->zc_guid = id; 25131544Seschrock 25141544Seschrock return (error); 25151544Seschrock } 25161544Seschrock 25171544Seschrock static int 25181544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 25191544Seschrock { 25201544Seschrock spa_t *spa; 25211544Seschrock int error; 25222676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 25231544Seschrock 25241544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 25251544Seschrock return (error); 25261544Seschrock 25272676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 25281544Seschrock &count); 25291544Seschrock if (error == 0) 25302676Seschrock zc->zc_nvlist_dst_size = count; 25311544Seschrock else 25322676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 25331544Seschrock 25341544Seschrock spa_close(spa, FTAG); 25351544Seschrock 25361544Seschrock return (error); 25371544Seschrock } 25381544Seschrock 25391544Seschrock static int 25401544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 25411544Seschrock { 25421544Seschrock spa_t *spa; 25431544Seschrock vdev_t *vd; 25444808Sek110237 uint64_t txg; 25451544Seschrock int error; 25461544Seschrock 25471544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 25481544Seschrock return (error); 25491544Seschrock 25505329Sgw25295 /* 25515329Sgw25295 * Try to resume any I/Os which may have been suspended 25525329Sgw25295 * as a result of a complete pool failure. 25535329Sgw25295 */ 25545329Sgw25295 if (!list_is_empty(&spa->spa_zio_list)) { 25555329Sgw25295 if (zio_vdev_resume_io(spa) != 0) { 25565329Sgw25295 spa_close(spa, FTAG); 25575329Sgw25295 return (EIO); 25585329Sgw25295 } 25595329Sgw25295 } 25605329Sgw25295 25614451Seschrock txg = spa_vdev_enter(spa); 25621544Seschrock 25632676Seschrock if (zc->zc_guid == 0) { 25641544Seschrock vd = NULL; 25652676Seschrock } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { 25665450Sbrendan spa_aux_vdev_t *sav; 25675450Sbrendan int i; 25685450Sbrendan 25695450Sbrendan /* 25705450Sbrendan * Check if this is an l2cache device. 25715450Sbrendan */ 25725450Sbrendan ASSERT(spa != NULL); 25735450Sbrendan sav = &spa->spa_l2cache; 25745450Sbrendan for (i = 0; i < sav->sav_count; i++) { 25755450Sbrendan if (sav->sav_vdevs[i]->vdev_guid == zc->zc_guid) { 25765450Sbrendan vd = sav->sav_vdevs[i]; 25775450Sbrendan break; 25785450Sbrendan } 25795450Sbrendan } 25805450Sbrendan 25815450Sbrendan if (vd == NULL) { 25825450Sbrendan (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 25835450Sbrendan spa_close(spa, FTAG); 25845450Sbrendan return (ENODEV); 25855450Sbrendan } 25861544Seschrock } 25871544Seschrock 25885329Sgw25295 vdev_clear(spa, vd, B_TRUE); 25891544Seschrock 25904451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 25911544Seschrock 25921544Seschrock spa_close(spa, FTAG); 25931544Seschrock 25941544Seschrock return (0); 25951544Seschrock } 25961544Seschrock 25975367Sahrens /* 25985367Sahrens * inputs: 25995367Sahrens * zc_name name of filesystem 26005367Sahrens * zc_value name of origin snapshot 26015367Sahrens * 26025367Sahrens * outputs: none 26035367Sahrens */ 26041544Seschrock static int 26052082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 26062082Seschrock { 26072417Sahrens char *cp; 26082417Sahrens 26092417Sahrens /* 26102417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 26112417Sahrens * it's easier. 26122417Sahrens */ 26132676Seschrock cp = strchr(zc->zc_value, '@'); 26142417Sahrens if (cp) 26152417Sahrens *cp = '\0'; 26162676Seschrock (void) dmu_objset_find(zc->zc_value, 26172417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 26182082Seschrock return (dsl_dataset_promote(zc->zc_name)); 26192082Seschrock } 26202082Seschrock 26214543Smarks /* 26224543Smarks * We don't want to have a hard dependency 26234543Smarks * against some special symbols in sharefs 26245331Samw * nfs, and smbsrv. Determine them if needed when 26254543Smarks * the first file system is shared. 26265331Samw * Neither sharefs, nfs or smbsrv are unloadable modules. 26274543Smarks */ 26285331Samw int (*znfsexport_fs)(void *arg); 26294543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 26305331Samw int (*zsmbexport_fs)(void *arg, boolean_t add_share); 26315331Samw 26325331Samw int zfs_nfsshare_inited; 26335331Samw int zfs_smbshare_inited; 26345331Samw 26354543Smarks ddi_modhandle_t nfs_mod; 26364543Smarks ddi_modhandle_t sharefs_mod; 26375331Samw ddi_modhandle_t smbsrv_mod; 26384543Smarks kmutex_t zfs_share_lock; 26394543Smarks 26404543Smarks static int 26415331Samw zfs_init_sharefs() 26425331Samw { 26435331Samw int error; 26445331Samw 26455331Samw ASSERT(MUTEX_HELD(&zfs_share_lock)); 26465331Samw /* Both NFS and SMB shares also require sharetab support. */ 26475331Samw if (sharefs_mod == NULL && ((sharefs_mod = 26485331Samw ddi_modopen("fs/sharefs", 26495331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26505331Samw return (ENOSYS); 26515331Samw } 26525331Samw if (zshare_fs == NULL && ((zshare_fs = 26535331Samw (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 26545331Samw ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 26555331Samw return (ENOSYS); 26565331Samw } 26575331Samw return (0); 26585331Samw } 26595331Samw 26605331Samw static int 26614543Smarks zfs_ioc_share(zfs_cmd_t *zc) 26624543Smarks { 26634543Smarks int error; 26644543Smarks int opcode; 26654543Smarks 26665331Samw switch (zc->zc_share.z_sharetype) { 26675331Samw case ZFS_SHARE_NFS: 26685331Samw case ZFS_UNSHARE_NFS: 26695331Samw if (zfs_nfsshare_inited == 0) { 26705331Samw mutex_enter(&zfs_share_lock); 26715331Samw if (nfs_mod == NULL && ((nfs_mod = ddi_modopen("fs/nfs", 26725331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26735331Samw mutex_exit(&zfs_share_lock); 26745331Samw return (ENOSYS); 26755331Samw } 26765331Samw if (znfsexport_fs == NULL && 26775331Samw ((znfsexport_fs = (int (*)(void *)) 26785331Samw ddi_modsym(nfs_mod, 26795331Samw "nfs_export", &error)) == NULL)) { 26805331Samw mutex_exit(&zfs_share_lock); 26815331Samw return (ENOSYS); 26825331Samw } 26835331Samw error = zfs_init_sharefs(); 26845331Samw if (error) { 26855331Samw mutex_exit(&zfs_share_lock); 26865331Samw return (ENOSYS); 26875331Samw } 26885331Samw zfs_nfsshare_inited = 1; 26894543Smarks mutex_exit(&zfs_share_lock); 26904543Smarks } 26915331Samw break; 26925331Samw case ZFS_SHARE_SMB: 26935331Samw case ZFS_UNSHARE_SMB: 26945331Samw if (zfs_smbshare_inited == 0) { 26955331Samw mutex_enter(&zfs_share_lock); 26965331Samw if (smbsrv_mod == NULL && ((smbsrv_mod = 26975331Samw ddi_modopen("drv/smbsrv", 26985331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26995331Samw mutex_exit(&zfs_share_lock); 27005331Samw return (ENOSYS); 27015331Samw } 27025331Samw if (zsmbexport_fs == NULL && ((zsmbexport_fs = 27035331Samw (int (*)(void *, boolean_t))ddi_modsym(smbsrv_mod, 27045331Samw "lmshrd_share_upcall", &error)) == NULL)) { 27055331Samw mutex_exit(&zfs_share_lock); 27065331Samw return (ENOSYS); 27075331Samw } 27085331Samw error = zfs_init_sharefs(); 27095331Samw if (error) { 27105331Samw mutex_exit(&zfs_share_lock); 27115331Samw return (ENOSYS); 27125331Samw } 27135331Samw zfs_smbshare_inited = 1; 27144543Smarks mutex_exit(&zfs_share_lock); 27154543Smarks } 27165331Samw break; 27175331Samw default: 27185331Samw return (EINVAL); 27194543Smarks } 27204543Smarks 27215331Samw switch (zc->zc_share.z_sharetype) { 27225331Samw case ZFS_SHARE_NFS: 27235331Samw case ZFS_UNSHARE_NFS: 27245331Samw if (error = 27255331Samw znfsexport_fs((void *) 27265331Samw (uintptr_t)zc->zc_share.z_exportdata)) 27275331Samw return (error); 27285331Samw break; 27295331Samw case ZFS_SHARE_SMB: 27305331Samw case ZFS_UNSHARE_SMB: 27315331Samw if (error = zsmbexport_fs((void *) 27325331Samw (uintptr_t)zc->zc_share.z_exportdata, 27335331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB ? 27345331Samw B_TRUE : B_FALSE)) { 27355331Samw return (error); 27365331Samw } 27375331Samw break; 27385331Samw } 27395331Samw 27405331Samw opcode = (zc->zc_share.z_sharetype == ZFS_SHARE_NFS || 27415331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB) ? 27424543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 27434543Smarks 27445331Samw /* 27455331Samw * Add or remove share from sharetab 27465331Samw */ 27474543Smarks error = zshare_fs(opcode, 27484543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 27494543Smarks zc->zc_share.z_sharemax); 27504543Smarks 27514543Smarks return (error); 27524543Smarks 27534543Smarks } 27544543Smarks 27554543Smarks /* 27564988Sek110237 * pool create, destroy, and export don't log the history as part of 27574988Sek110237 * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export 27584988Sek110237 * do the logging of those commands. 27594543Smarks */ 2760789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 27614715Sek110237 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27624577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27634577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27644577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27654577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 27664577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 27674577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27684577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27694577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27704577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27714577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27724577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27734577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27744577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27754577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27764577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27774577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27784577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27795498Stimh { zfs_ioc_objset_zplprops, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27804543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 27814577Sahrens DATASET_NAME, B_FALSE }, 27824543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 27834577Sahrens DATASET_NAME, B_FALSE }, 27844577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 27854577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 27864577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 27874577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 27884577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 27894577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 27904577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 27915367Sahrens { zfs_ioc_recv, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 27925367Sahrens { zfs_ioc_send, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 27934577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 27944577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 27954577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 27964577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 27974577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27984577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 27994577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 28004577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 28014577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 28024577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 28034577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 28044577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 28054577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 28064577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 28074543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 28084577Sahrens DATASET_NAME, B_FALSE }, 28094849Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }, 28104849Sahrens { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE }, 2811789Sahrens }; 2812789Sahrens 2813789Sahrens static int 2814789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2815789Sahrens { 2816789Sahrens zfs_cmd_t *zc; 2817789Sahrens uint_t vec; 28182199Sahrens int error, rc; 2819789Sahrens 2820789Sahrens if (getminor(dev) != 0) 2821789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2822789Sahrens 2823789Sahrens vec = cmd - ZFS_IOC; 28244787Sahrens ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); 2825789Sahrens 2826789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2827789Sahrens return (EINVAL); 2828789Sahrens 2829789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2830789Sahrens 2831789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2832789Sahrens 28334787Sahrens if (error == 0) 28344543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2835789Sahrens 2836789Sahrens /* 2837789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2838789Sahrens * the lower layers. 2839789Sahrens */ 2840789Sahrens if (error == 0) { 2841789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2842789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 28434577Sahrens case POOL_NAME: 2844789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2845789Sahrens error = EINVAL; 2846789Sahrens break; 2847789Sahrens 28484577Sahrens case DATASET_NAME: 2849789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2850789Sahrens error = EINVAL; 2851789Sahrens break; 28522856Snd150628 28534577Sahrens case NO_NAME: 28542856Snd150628 break; 2855789Sahrens } 2856789Sahrens } 2857789Sahrens 2858789Sahrens if (error == 0) 2859789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2860789Sahrens 28612199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 28624543Smarks if (error == 0) { 28632199Sahrens error = rc; 28644543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 28654543Smarks zfs_log_history(zc); 28664543Smarks } 2867789Sahrens 2868789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2869789Sahrens return (error); 2870789Sahrens } 2871789Sahrens 2872789Sahrens static int 2873789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2874789Sahrens { 2875789Sahrens if (cmd != DDI_ATTACH) 2876789Sahrens return (DDI_FAILURE); 2877789Sahrens 2878789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2879789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2880789Sahrens return (DDI_FAILURE); 2881789Sahrens 2882789Sahrens zfs_dip = dip; 2883789Sahrens 2884789Sahrens ddi_report_dev(dip); 2885789Sahrens 2886789Sahrens return (DDI_SUCCESS); 2887789Sahrens } 2888789Sahrens 2889789Sahrens static int 2890789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2891789Sahrens { 2892789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2893789Sahrens return (DDI_FAILURE); 2894789Sahrens 2895789Sahrens if (cmd != DDI_DETACH) 2896789Sahrens return (DDI_FAILURE); 2897789Sahrens 2898789Sahrens zfs_dip = NULL; 2899789Sahrens 2900789Sahrens ddi_prop_remove_all(dip); 2901789Sahrens ddi_remove_minor_node(dip, NULL); 2902789Sahrens 2903789Sahrens return (DDI_SUCCESS); 2904789Sahrens } 2905789Sahrens 2906789Sahrens /*ARGSUSED*/ 2907789Sahrens static int 2908789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2909789Sahrens { 2910789Sahrens switch (infocmd) { 2911789Sahrens case DDI_INFO_DEVT2DEVINFO: 2912789Sahrens *result = zfs_dip; 2913789Sahrens return (DDI_SUCCESS); 2914789Sahrens 2915789Sahrens case DDI_INFO_DEVT2INSTANCE: 2916849Sbonwick *result = (void *)0; 2917789Sahrens return (DDI_SUCCESS); 2918789Sahrens } 2919789Sahrens 2920789Sahrens return (DDI_FAILURE); 2921789Sahrens } 2922789Sahrens 2923789Sahrens /* 2924789Sahrens * OK, so this is a little weird. 2925789Sahrens * 2926789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2927789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2928789Sahrens * 2929789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2930789Sahrens * so most of the standard driver entry points are in zvol.c. 2931789Sahrens */ 2932789Sahrens static struct cb_ops zfs_cb_ops = { 2933789Sahrens zvol_open, /* open */ 2934789Sahrens zvol_close, /* close */ 2935789Sahrens zvol_strategy, /* strategy */ 2936789Sahrens nodev, /* print */ 2937789Sahrens nodev, /* dump */ 2938789Sahrens zvol_read, /* read */ 2939789Sahrens zvol_write, /* write */ 2940789Sahrens zfsdev_ioctl, /* ioctl */ 2941789Sahrens nodev, /* devmap */ 2942789Sahrens nodev, /* mmap */ 2943789Sahrens nodev, /* segmap */ 2944789Sahrens nochpoll, /* poll */ 2945789Sahrens ddi_prop_op, /* prop_op */ 2946789Sahrens NULL, /* streamtab */ 2947789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2948789Sahrens CB_REV, /* version */ 29493638Sbillm nodev, /* async read */ 29503638Sbillm nodev, /* async write */ 2951789Sahrens }; 2952789Sahrens 2953789Sahrens static struct dev_ops zfs_dev_ops = { 2954789Sahrens DEVO_REV, /* version */ 2955789Sahrens 0, /* refcnt */ 2956789Sahrens zfs_info, /* info */ 2957789Sahrens nulldev, /* identify */ 2958789Sahrens nulldev, /* probe */ 2959789Sahrens zfs_attach, /* attach */ 2960789Sahrens zfs_detach, /* detach */ 2961789Sahrens nodev, /* reset */ 2962789Sahrens &zfs_cb_ops, /* driver operations */ 2963789Sahrens NULL /* no bus operations */ 2964789Sahrens }; 2965789Sahrens 2966789Sahrens static struct modldrv zfs_modldrv = { 29674577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 29682676Seschrock &zfs_dev_ops 2969789Sahrens }; 2970789Sahrens 2971789Sahrens static struct modlinkage modlinkage = { 2972789Sahrens MODREV_1, 2973789Sahrens (void *)&zfs_modlfs, 2974789Sahrens (void *)&zfs_modldrv, 2975789Sahrens NULL 2976789Sahrens }; 2977789Sahrens 29784720Sfr157268 29794720Sfr157268 uint_t zfs_fsyncer_key; 29805326Sek110237 extern uint_t rrw_tsd_key; 29814720Sfr157268 2982789Sahrens int 2983789Sahrens _init(void) 2984789Sahrens { 2985789Sahrens int error; 2986789Sahrens 2987849Sbonwick spa_init(FREAD | FWRITE); 2988849Sbonwick zfs_init(); 2989849Sbonwick zvol_init(); 2990849Sbonwick 2991849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 2992849Sbonwick zvol_fini(); 2993849Sbonwick zfs_fini(); 2994849Sbonwick spa_fini(); 2995789Sahrens return (error); 2996849Sbonwick } 2997789Sahrens 29984720Sfr157268 tsd_create(&zfs_fsyncer_key, NULL); 29995326Sek110237 tsd_create(&rrw_tsd_key, NULL); 30004720Sfr157268 3001789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 3002789Sahrens ASSERT(error == 0); 30034543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 3004789Sahrens 3005789Sahrens return (0); 3006789Sahrens } 3007789Sahrens 3008789Sahrens int 3009789Sahrens _fini(void) 3010789Sahrens { 3011789Sahrens int error; 3012789Sahrens 30131544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 3014789Sahrens return (EBUSY); 3015789Sahrens 3016789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 3017789Sahrens return (error); 3018789Sahrens 3019789Sahrens zvol_fini(); 3020789Sahrens zfs_fini(); 3021789Sahrens spa_fini(); 30225331Samw if (zfs_nfsshare_inited) 30234543Smarks (void) ddi_modclose(nfs_mod); 30245331Samw if (zfs_smbshare_inited) 30255331Samw (void) ddi_modclose(smbsrv_mod); 30265331Samw if (zfs_nfsshare_inited || zfs_smbshare_inited) 30274543Smarks (void) ddi_modclose(sharefs_mod); 3028789Sahrens 30294720Sfr157268 tsd_destroy(&zfs_fsyncer_key); 3030789Sahrens ldi_ident_release(zfs_li); 3031789Sahrens zfs_li = NULL; 30324543Smarks mutex_destroy(&zfs_share_lock); 3033789Sahrens 3034789Sahrens return (error); 3035789Sahrens } 3036789Sahrens 3037789Sahrens int 3038789Sahrens _info(struct modinfo *modinfop) 3039789Sahrens { 3040789Sahrens return (mod_info(&modlinkage, modinfop)); 3041789Sahrens } 3042