1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51485Slling * Common Development and Distribution License (the "License"). 61485Slling * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 223444Sek110237 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27789Sahrens 28789Sahrens #include <sys/types.h> 29789Sahrens #include <sys/param.h> 30789Sahrens #include <sys/errno.h> 31789Sahrens #include <sys/uio.h> 32789Sahrens #include <sys/buf.h> 33789Sahrens #include <sys/modctl.h> 34789Sahrens #include <sys/open.h> 35789Sahrens #include <sys/file.h> 36789Sahrens #include <sys/kmem.h> 37789Sahrens #include <sys/conf.h> 38789Sahrens #include <sys/cmn_err.h> 39789Sahrens #include <sys/stat.h> 40789Sahrens #include <sys/zfs_ioctl.h> 415331Samw #include <sys/zfs_i18n.h> 425331Samw #include <sys/zfs_znode.h> 43789Sahrens #include <sys/zap.h> 44789Sahrens #include <sys/spa.h> 453912Slling #include <sys/spa_impl.h> 46789Sahrens #include <sys/vdev.h> 473912Slling #include <sys/vdev_impl.h> 48789Sahrens #include <sys/dmu.h> 49789Sahrens #include <sys/dsl_dir.h> 50789Sahrens #include <sys/dsl_dataset.h> 51789Sahrens #include <sys/dsl_prop.h> 524543Smarks #include <sys/dsl_deleg.h> 534543Smarks #include <sys/dmu_objset.h> 54789Sahrens #include <sys/ddi.h> 55789Sahrens #include <sys/sunddi.h> 56789Sahrens #include <sys/sunldi.h> 57789Sahrens #include <sys/policy.h> 58789Sahrens #include <sys/zone.h> 59789Sahrens #include <sys/nvpair.h> 60789Sahrens #include <sys/pathname.h> 61789Sahrens #include <sys/mount.h> 62789Sahrens #include <sys/sdt.h> 63789Sahrens #include <sys/fs/zfs.h> 64789Sahrens #include <sys/zfs_ctldir.h> 655331Samw #include <sys/zfs_dir.h> 662885Sahrens #include <sys/zvol.h> 674543Smarks #include <sharefs/share.h> 684577Sahrens #include <sys/zfs_znode.h> 695326Sek110237 #include <sys/zfs_vfsops.h> 705326Sek110237 #include <sys/dmu_objset.h> 71789Sahrens 72789Sahrens #include "zfs_namecheck.h" 732676Seschrock #include "zfs_prop.h" 744543Smarks #include "zfs_deleg.h" 75789Sahrens 76789Sahrens extern struct modlfs zfs_modlfs; 77789Sahrens 78789Sahrens extern void zfs_init(void); 79789Sahrens extern void zfs_fini(void); 80789Sahrens 81789Sahrens ldi_ident_t zfs_li = NULL; 82789Sahrens dev_info_t *zfs_dip; 83789Sahrens 84789Sahrens typedef int zfs_ioc_func_t(zfs_cmd_t *); 854543Smarks typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *); 86789Sahrens 87789Sahrens typedef struct zfs_ioc_vec { 88789Sahrens zfs_ioc_func_t *zvec_func; 89789Sahrens zfs_secpolicy_func_t *zvec_secpolicy; 90789Sahrens enum { 914577Sahrens NO_NAME, 924577Sahrens POOL_NAME, 934577Sahrens DATASET_NAME 944543Smarks } zvec_namecheck; 954543Smarks boolean_t zvec_his_log; 96789Sahrens } zfs_ioc_vec_t; 97789Sahrens 98789Sahrens /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */ 99789Sahrens void 100789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 101789Sahrens { 102789Sahrens const char *newfile; 103789Sahrens char buf[256]; 104789Sahrens va_list adx; 105789Sahrens 106789Sahrens /* 107789Sahrens * Get rid of annoying "../common/" prefix to filename. 108789Sahrens */ 109789Sahrens newfile = strrchr(file, '/'); 110789Sahrens if (newfile != NULL) { 111789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 112789Sahrens } else { 113789Sahrens newfile = file; 114789Sahrens } 115789Sahrens 116789Sahrens va_start(adx, fmt); 117789Sahrens (void) vsnprintf(buf, sizeof (buf), fmt, adx); 118789Sahrens va_end(adx); 119789Sahrens 120789Sahrens /* 121789Sahrens * To get this data, use the zfs-dprintf probe as so: 122789Sahrens * dtrace -q -n 'zfs-dprintf \ 123789Sahrens * /stringof(arg0) == "dbuf.c"/ \ 124789Sahrens * {printf("%s: %s", stringof(arg1), stringof(arg3))}' 125789Sahrens * arg0 = file name 126789Sahrens * arg1 = function name 127789Sahrens * arg2 = line number 128789Sahrens * arg3 = message 129789Sahrens */ 130789Sahrens DTRACE_PROBE4(zfs__dprintf, 131789Sahrens char *, newfile, char *, func, int, line, char *, buf); 132789Sahrens } 133789Sahrens 1344543Smarks static void 1354715Sek110237 history_str_free(char *buf) 1364715Sek110237 { 1374715Sek110237 kmem_free(buf, HIS_MAX_RECORD_LEN); 1384715Sek110237 } 1394715Sek110237 1404715Sek110237 static char * 1414715Sek110237 history_str_get(zfs_cmd_t *zc) 1424715Sek110237 { 1434715Sek110237 char *buf; 1444715Sek110237 1454715Sek110237 if (zc->zc_history == NULL) 1464715Sek110237 return (NULL); 1474715Sek110237 1484715Sek110237 buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP); 1494715Sek110237 if (copyinstr((void *)(uintptr_t)zc->zc_history, 1504715Sek110237 buf, HIS_MAX_RECORD_LEN, NULL) != 0) { 1514715Sek110237 history_str_free(buf); 1524715Sek110237 return (NULL); 1534715Sek110237 } 1544715Sek110237 1554715Sek110237 buf[HIS_MAX_RECORD_LEN -1] = '\0'; 1564715Sek110237 1574715Sek110237 return (buf); 1584715Sek110237 } 1594715Sek110237 1605375Stimh /* 1615375Stimh * zfs_check_version 1625375Stimh * 1635375Stimh * Return non-zero if the spa version is less than requested version. 1645375Stimh */ 1655331Samw static int 1665331Samw zfs_check_version(const char *name, int version) 1675331Samw { 1685331Samw 1695331Samw spa_t *spa; 1705331Samw 1715331Samw if (spa_open(name, &spa, FTAG) == 0) { 1725331Samw if (spa_version(spa) < version) { 1735331Samw spa_close(spa, FTAG); 1745331Samw return (1); 1755331Samw } 1765331Samw spa_close(spa, FTAG); 1775331Samw } 1785331Samw return (0); 1795331Samw } 1805331Samw 1814715Sek110237 static void 1824543Smarks zfs_log_history(zfs_cmd_t *zc) 1834543Smarks { 1844543Smarks spa_t *spa; 1854603Sahrens char *buf; 1864543Smarks 1874715Sek110237 if ((buf = history_str_get(zc)) == NULL) 1884577Sahrens return; 1894577Sahrens 1904715Sek110237 if (spa_open(zc->zc_name, &spa, FTAG) == 0) { 1914715Sek110237 if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY) 1924715Sek110237 (void) spa_history_log(spa, buf, LOG_CMD_NORMAL); 1934715Sek110237 spa_close(spa, FTAG); 1944543Smarks } 1954715Sek110237 history_str_free(buf); 1964543Smarks } 1974543Smarks 198789Sahrens /* 199789Sahrens * Policy for top-level read operations (list pools). Requires no privileges, 200789Sahrens * and can be used in the local zone, as there is no associated dataset. 201789Sahrens */ 202789Sahrens /* ARGSUSED */ 203789Sahrens static int 2044543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) 205789Sahrens { 206789Sahrens return (0); 207789Sahrens } 208789Sahrens 209789Sahrens /* 210789Sahrens * Policy for dataset read operations (list children, get statistics). Requires 211789Sahrens * no privileges, but must be visible in the local zone. 212789Sahrens */ 213789Sahrens /* ARGSUSED */ 214789Sahrens static int 2154543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) 216789Sahrens { 217789Sahrens if (INGLOBALZONE(curproc) || 2184543Smarks zone_dataset_visible(zc->zc_name, NULL)) 219789Sahrens return (0); 220789Sahrens 221789Sahrens return (ENOENT); 222789Sahrens } 223789Sahrens 224789Sahrens static int 225789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr) 226789Sahrens { 227789Sahrens uint64_t zoned; 228789Sahrens int writable = 1; 229789Sahrens 230789Sahrens /* 231789Sahrens * The dataset must be visible by this zone -- check this first 232789Sahrens * so they don't see EPERM on something they shouldn't know about. 233789Sahrens */ 234789Sahrens if (!INGLOBALZONE(curproc) && 235789Sahrens !zone_dataset_visible(dataset, &writable)) 236789Sahrens return (ENOENT); 237789Sahrens 238789Sahrens if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) 239789Sahrens return (ENOENT); 240789Sahrens 241789Sahrens if (INGLOBALZONE(curproc)) { 242789Sahrens /* 243789Sahrens * If the fs is zoned, only root can access it from the 244789Sahrens * global zone. 245789Sahrens */ 246789Sahrens if (secpolicy_zfs(cr) && zoned) 247789Sahrens return (EPERM); 248789Sahrens } else { 249789Sahrens /* 250789Sahrens * If we are in a local zone, the 'zoned' property must be set. 251789Sahrens */ 252789Sahrens if (!zoned) 253789Sahrens return (EPERM); 254789Sahrens 255789Sahrens /* must be writable by this zone */ 256789Sahrens if (!writable) 257789Sahrens return (EPERM); 258789Sahrens } 259789Sahrens return (0); 260789Sahrens } 261789Sahrens 262789Sahrens int 2634543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) 264789Sahrens { 265789Sahrens int error; 266789Sahrens 2674543Smarks error = zfs_dozonecheck(name, cr); 2684543Smarks if (error == 0) { 2694543Smarks error = secpolicy_zfs(cr); 2704670Sahrens if (error) 2714543Smarks error = dsl_deleg_access(name, perm, cr); 2724543Smarks } 2734543Smarks return (error); 2744543Smarks } 2754543Smarks 2764543Smarks static int 2774543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) 2784543Smarks { 2794543Smarks /* 2804543Smarks * Check permissions for special properties. 2814543Smarks */ 2824543Smarks switch (prop) { 2834543Smarks case ZFS_PROP_ZONED: 2844543Smarks /* 2854543Smarks * Disallow setting of 'zoned' from within a local zone. 2864543Smarks */ 2874543Smarks if (!INGLOBALZONE(curproc)) 2884543Smarks return (EPERM); 2894543Smarks break; 290789Sahrens 2914543Smarks case ZFS_PROP_QUOTA: 2924543Smarks if (!INGLOBALZONE(curproc)) { 2934543Smarks uint64_t zoned; 2944543Smarks char setpoint[MAXNAMELEN]; 2954543Smarks /* 2964543Smarks * Unprivileged users are allowed to modify the 2974543Smarks * quota on things *under* (ie. contained by) 2984543Smarks * the thing they own. 2994543Smarks */ 3004543Smarks if (dsl_prop_get_integer(name, "zoned", &zoned, 3014543Smarks setpoint)) 3024543Smarks return (EPERM); 3034670Sahrens if (!zoned || strlen(name) <= strlen(setpoint)) 3044543Smarks return (EPERM); 3054543Smarks } 3064670Sahrens break; 3074543Smarks } 3084543Smarks 3094787Sahrens return (zfs_secpolicy_write_perms(name, zfs_prop_to_name(prop), cr)); 310789Sahrens } 311789Sahrens 3124543Smarks int 3134543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) 3144543Smarks { 3154543Smarks int error; 3164543Smarks 3174543Smarks error = zfs_dozonecheck(zc->zc_name, cr); 3184543Smarks if (error) 3194543Smarks return (error); 3204543Smarks 3214543Smarks /* 3224543Smarks * permission to set permissions will be evaluated later in 3234543Smarks * dsl_deleg_can_allow() 3244543Smarks */ 3254543Smarks return (0); 3264543Smarks } 3274543Smarks 3284543Smarks int 3294543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) 3304543Smarks { 3314543Smarks int error; 3324543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3334543Smarks ZFS_DELEG_PERM_ROLLBACK, cr); 3344543Smarks if (error == 0) 3354543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3364543Smarks ZFS_DELEG_PERM_MOUNT, cr); 3374543Smarks return (error); 3384543Smarks } 3394543Smarks 3404543Smarks int 3414543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) 3424543Smarks { 3434543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 3444543Smarks ZFS_DELEG_PERM_SEND, cr)); 3454543Smarks } 3464543Smarks 3474543Smarks int 3484543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) 3494543Smarks { 3504543Smarks if (!INGLOBALZONE(curproc)) 3514543Smarks return (EPERM); 3524543Smarks 3535367Sahrens if (secpolicy_nfs(cr) == 0) { 3544543Smarks return (0); 3554543Smarks } else { 3564543Smarks vnode_t *vp; 3574543Smarks int error; 3584543Smarks 3594543Smarks if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, 3604543Smarks NO_FOLLOW, NULL, &vp)) != 0) 3614543Smarks return (error); 3624543Smarks 3634543Smarks /* Now make sure mntpnt and dataset are ZFS */ 3644543Smarks 3654543Smarks if (vp->v_vfsp->vfs_fstype != zfsfstype || 3664543Smarks (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), 3674543Smarks zc->zc_name) != 0)) { 3684543Smarks VN_RELE(vp); 3694543Smarks return (EPERM); 3704543Smarks } 3714543Smarks 3724543Smarks VN_RELE(vp); 3734543Smarks return (dsl_deleg_access(zc->zc_name, 3744543Smarks ZFS_DELEG_PERM_SHARE, cr)); 3754543Smarks } 3764543Smarks } 3774543Smarks 378789Sahrens static int 3794543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize) 380789Sahrens { 381789Sahrens char *cp; 382789Sahrens 383789Sahrens /* 384789Sahrens * Remove the @bla or /bla from the end of the name to get the parent. 385789Sahrens */ 3864543Smarks (void) strncpy(parent, datasetname, parentsize); 3874543Smarks cp = strrchr(parent, '@'); 388789Sahrens if (cp != NULL) { 389789Sahrens cp[0] = '\0'; 390789Sahrens } else { 3914543Smarks cp = strrchr(parent, '/'); 392789Sahrens if (cp == NULL) 393789Sahrens return (ENOENT); 394789Sahrens cp[0] = '\0'; 395789Sahrens } 396789Sahrens 3974543Smarks return (0); 3984543Smarks } 3994543Smarks 4004543Smarks int 4014543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 4024543Smarks { 4034543Smarks int error; 4044543Smarks 4054543Smarks if ((error = zfs_secpolicy_write_perms(name, 4064543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4074543Smarks return (error); 4084543Smarks 4094543Smarks return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); 4104543Smarks } 4114543Smarks 4124543Smarks static int 4134543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) 4144543Smarks { 4154543Smarks return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); 4164543Smarks } 4174543Smarks 4184543Smarks /* 4194543Smarks * Must have sys_config privilege to check the iscsi permission 4204543Smarks */ 4214543Smarks /* ARGSUSED */ 4224543Smarks static int 4234543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) 4244543Smarks { 4254543Smarks return (secpolicy_zfs(cr)); 4264543Smarks } 4274543Smarks 4284543Smarks int 4294543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 4304543Smarks { 4314543Smarks char parentname[MAXNAMELEN]; 4324543Smarks int error; 4334543Smarks 4344543Smarks if ((error = zfs_secpolicy_write_perms(from, 4354543Smarks ZFS_DELEG_PERM_RENAME, cr)) != 0) 4364543Smarks return (error); 4374543Smarks 4384543Smarks if ((error = zfs_secpolicy_write_perms(from, 4394543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4404543Smarks return (error); 4414543Smarks 4424543Smarks if ((error = zfs_get_parent(to, parentname, 4434543Smarks sizeof (parentname))) != 0) 4444543Smarks return (error); 4454543Smarks 4464543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4474543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 4484543Smarks return (error); 4494543Smarks 4504543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4514543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4524543Smarks return (error); 4534543Smarks 4544543Smarks return (error); 4554543Smarks } 4564543Smarks 4574543Smarks static int 4584543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) 4594543Smarks { 4604543Smarks return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); 4614543Smarks } 4624543Smarks 4634543Smarks static int 4644543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) 4654543Smarks { 4664543Smarks char parentname[MAXNAMELEN]; 4674543Smarks objset_t *clone; 4684543Smarks int error; 4694543Smarks 4704543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4714543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4724543Smarks if (error) 4734543Smarks return (error); 4744543Smarks 4754543Smarks error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 4764543Smarks DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 4774543Smarks 4784543Smarks if (error == 0) { 4794543Smarks dsl_dataset_t *pclone = NULL; 4804543Smarks dsl_dir_t *dd; 4814543Smarks dd = clone->os->os_dsl_dataset->ds_dir; 4824543Smarks 4834543Smarks rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 4844543Smarks error = dsl_dataset_open_obj(dd->dd_pool, 4855367Sahrens dd->dd_phys->dd_origin_obj, NULL, 4864543Smarks DS_MODE_NONE, FTAG, &pclone); 4874543Smarks rw_exit(&dd->dd_pool->dp_config_rwlock); 4884543Smarks if (error) { 4894543Smarks dmu_objset_close(clone); 4904543Smarks return (error); 4914543Smarks } 4924543Smarks 4934543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4944543Smarks ZFS_DELEG_PERM_MOUNT, cr); 4954543Smarks 4964543Smarks dsl_dataset_name(pclone, parentname); 4974543Smarks dmu_objset_close(clone); 4984543Smarks dsl_dataset_close(pclone, DS_MODE_NONE, FTAG); 4994543Smarks if (error == 0) 5004543Smarks error = zfs_secpolicy_write_perms(parentname, 5014543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 5024543Smarks } 5034543Smarks return (error); 5044543Smarks } 5054543Smarks 5064543Smarks static int 5074543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) 5084543Smarks { 5094543Smarks int error; 5104543Smarks 5114543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5124543Smarks ZFS_DELEG_PERM_RECEIVE, cr)) != 0) 5134543Smarks return (error); 5144543Smarks 5154543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5164543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 5174543Smarks return (error); 5184543Smarks 5194543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 5204543Smarks ZFS_DELEG_PERM_CREATE, cr)); 5214543Smarks } 5224543Smarks 5234543Smarks int 5244543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 5254543Smarks { 5264543Smarks int error; 5274543Smarks 5284543Smarks if ((error = zfs_secpolicy_write_perms(name, 5294543Smarks ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) 5304543Smarks return (error); 5314543Smarks 5324543Smarks error = zfs_secpolicy_write_perms(name, 5334543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5344543Smarks 5354543Smarks return (error); 5364543Smarks } 5374543Smarks 5384543Smarks static int 5394543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) 5404543Smarks { 5414543Smarks 5424543Smarks return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); 5434543Smarks } 5444543Smarks 5454543Smarks static int 5464543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) 5474543Smarks { 5484543Smarks char parentname[MAXNAMELEN]; 5494543Smarks int error; 5504543Smarks 5514543Smarks if ((error = zfs_get_parent(zc->zc_name, parentname, 5524543Smarks sizeof (parentname))) != 0) 5534543Smarks return (error); 5544543Smarks 5554543Smarks if (zc->zc_value[0] != '\0') { 5564543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_value, 5574543Smarks ZFS_DELEG_PERM_CLONE, cr)) != 0) 5584543Smarks return (error); 5594543Smarks } 5604543Smarks 5614543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 5624543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 5634543Smarks return (error); 5644543Smarks 5654543Smarks error = zfs_secpolicy_write_perms(parentname, 5664543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5674543Smarks 5684543Smarks return (error); 5694543Smarks } 5704543Smarks 5714543Smarks static int 5724543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) 5734543Smarks { 5744543Smarks int error; 5754543Smarks 5764543Smarks error = secpolicy_fs_unmount(cr, NULL); 5774543Smarks if (error) { 5784543Smarks error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); 5794543Smarks } 5804543Smarks return (error); 581789Sahrens } 582789Sahrens 583789Sahrens /* 584789Sahrens * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires 585789Sahrens * SYS_CONFIG privilege, which is not available in a local zone. 586789Sahrens */ 587789Sahrens /* ARGSUSED */ 588789Sahrens static int 5894543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) 590789Sahrens { 591789Sahrens if (secpolicy_sys_config(cr, B_FALSE) != 0) 592789Sahrens return (EPERM); 593789Sahrens 594789Sahrens return (0); 595789Sahrens } 596789Sahrens 597789Sahrens /* 5984543Smarks * Just like zfs_secpolicy_config, except that we will check for 5994543Smarks * mount permission on the dataset for permission to create/remove 6004543Smarks * the minor nodes. 6014543Smarks */ 6024543Smarks static int 6034543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) 6044543Smarks { 6054543Smarks if (secpolicy_sys_config(cr, B_FALSE) != 0) { 6064543Smarks return (dsl_deleg_access(zc->zc_name, 6074543Smarks ZFS_DELEG_PERM_MOUNT, cr)); 6084543Smarks } 6094543Smarks 6104543Smarks return (0); 6114543Smarks } 6124543Smarks 6134543Smarks /* 6141544Seschrock * Policy for fault injection. Requires all privileges. 6151544Seschrock */ 6161544Seschrock /* ARGSUSED */ 6171544Seschrock static int 6184543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) 6191544Seschrock { 6201544Seschrock return (secpolicy_zinject(cr)); 6211544Seschrock } 6221544Seschrock 6234849Sahrens static int 6244849Sahrens zfs_secpolicy_inherit(zfs_cmd_t *zc, cred_t *cr) 6254849Sahrens { 6264849Sahrens zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); 6274849Sahrens 6285094Slling if (prop == ZPROP_INVAL) { 6294849Sahrens if (!zfs_prop_user(zc->zc_value)) 6304849Sahrens return (EINVAL); 6314849Sahrens return (zfs_secpolicy_write_perms(zc->zc_name, 6324849Sahrens ZFS_DELEG_PERM_USERPROP, cr)); 6334849Sahrens } else { 6344849Sahrens if (!zfs_prop_inheritable(prop)) 6354849Sahrens return (EINVAL); 6364849Sahrens return (zfs_secpolicy_setprop(zc->zc_name, prop, cr)); 6374849Sahrens } 6384849Sahrens } 6394849Sahrens 6401544Seschrock /* 641789Sahrens * Returns the nvlist as specified by the user in the zfs_cmd_t. 642789Sahrens */ 643789Sahrens static int 6445094Slling get_nvlist(uint64_t nvl, uint64_t size, nvlist_t **nvp) 645789Sahrens { 646789Sahrens char *packed; 647789Sahrens int error; 6485094Slling nvlist_t *list = NULL; 649789Sahrens 650789Sahrens /* 6512676Seschrock * Read in and unpack the user-supplied nvlist. 652789Sahrens */ 6535094Slling if (size == 0) 654789Sahrens return (EINVAL); 655789Sahrens 656789Sahrens packed = kmem_alloc(size, KM_SLEEP); 657789Sahrens 6585094Slling if ((error = xcopyin((void *)(uintptr_t)nvl, packed, size)) != 0) { 659789Sahrens kmem_free(packed, size); 660789Sahrens return (error); 661789Sahrens } 662789Sahrens 6635094Slling if ((error = nvlist_unpack(packed, size, &list, 0)) != 0) { 664789Sahrens kmem_free(packed, size); 665789Sahrens return (error); 666789Sahrens } 667789Sahrens 668789Sahrens kmem_free(packed, size); 669789Sahrens 6705094Slling *nvp = list; 671789Sahrens return (0); 672789Sahrens } 673789Sahrens 674789Sahrens static int 6752676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 6762676Seschrock { 6772676Seschrock char *packed = NULL; 6782676Seschrock size_t size; 6792676Seschrock int error; 6802676Seschrock 6812676Seschrock VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 6822676Seschrock 6832676Seschrock if (size > zc->zc_nvlist_dst_size) { 6842676Seschrock error = ENOMEM; 6852676Seschrock } else { 6864611Smarks packed = kmem_alloc(size, KM_SLEEP); 6872676Seschrock VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 6882676Seschrock KM_SLEEP) == 0); 6892676Seschrock error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 6902676Seschrock size); 6912676Seschrock kmem_free(packed, size); 6922676Seschrock } 6932676Seschrock 6942676Seschrock zc->zc_nvlist_dst_size = size; 6952676Seschrock return (error); 6962676Seschrock } 6972676Seschrock 6982676Seschrock static int 699789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc) 700789Sahrens { 701789Sahrens int error; 7025094Slling nvlist_t *config, *props = NULL; 7034715Sek110237 char *buf; 704789Sahrens 7055094Slling if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7065094Slling &config)) 7074988Sek110237 return (error); 7084715Sek110237 7095094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7105094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7115094Slling nvlist_free(config); 7125094Slling return (error); 7135094Slling } 7145094Slling 7154988Sek110237 buf = history_str_get(zc); 716789Sahrens 7175094Slling error = spa_create(zc->zc_name, config, props, buf); 718789Sahrens 7194988Sek110237 if (buf != NULL) 7204988Sek110237 history_str_free(buf); 7215094Slling 722789Sahrens nvlist_free(config); 723789Sahrens 7245094Slling if (props) 7255094Slling nvlist_free(props); 7265094Slling 727789Sahrens return (error); 728789Sahrens } 729789Sahrens 730789Sahrens static int 731789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc) 732789Sahrens { 7334543Smarks int error; 7344543Smarks zfs_log_history(zc); 7354543Smarks error = spa_destroy(zc->zc_name); 7364543Smarks return (error); 737789Sahrens } 738789Sahrens 739789Sahrens static int 740789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc) 741789Sahrens { 742789Sahrens int error; 7435094Slling nvlist_t *config, *props = NULL; 744789Sahrens uint64_t guid; 745789Sahrens 7465094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7475094Slling &config)) != 0) 748789Sahrens return (error); 749789Sahrens 7505094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7515094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7525094Slling nvlist_free(config); 7535094Slling return (error); 7545094Slling } 7555094Slling 756789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 7571544Seschrock guid != zc->zc_guid) 758789Sahrens error = EINVAL; 759789Sahrens else 7605094Slling error = spa_import(zc->zc_name, config, props); 761789Sahrens 762789Sahrens nvlist_free(config); 763789Sahrens 7645094Slling if (props) 7655094Slling nvlist_free(props); 7665094Slling 767789Sahrens return (error); 768789Sahrens } 769789Sahrens 770789Sahrens static int 771789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc) 772789Sahrens { 7734543Smarks int error; 7744543Smarks zfs_log_history(zc); 7754543Smarks error = spa_export(zc->zc_name, NULL); 7764543Smarks return (error); 777789Sahrens } 778789Sahrens 779789Sahrens static int 780789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc) 781789Sahrens { 782789Sahrens nvlist_t *configs; 783789Sahrens int error; 784789Sahrens 785789Sahrens if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 786789Sahrens return (EEXIST); 787789Sahrens 7882676Seschrock error = put_nvlist(zc, configs); 789789Sahrens 790789Sahrens nvlist_free(configs); 791789Sahrens 792789Sahrens return (error); 793789Sahrens } 794789Sahrens 795789Sahrens static int 796789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc) 797789Sahrens { 798789Sahrens nvlist_t *config; 799789Sahrens int error; 8001544Seschrock int ret = 0; 801789Sahrens 8022676Seschrock error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 8032676Seschrock sizeof (zc->zc_value)); 804789Sahrens 805789Sahrens if (config != NULL) { 8062676Seschrock ret = put_nvlist(zc, config); 807789Sahrens nvlist_free(config); 8081544Seschrock 8091544Seschrock /* 8101544Seschrock * The config may be present even if 'error' is non-zero. 8111544Seschrock * In this case we return success, and preserve the real errno 8121544Seschrock * in 'zc_cookie'. 8131544Seschrock */ 8141544Seschrock zc->zc_cookie = error; 815789Sahrens } else { 8161544Seschrock ret = error; 817789Sahrens } 818789Sahrens 8191544Seschrock return (ret); 820789Sahrens } 821789Sahrens 822789Sahrens /* 823789Sahrens * Try to import the given pool, returning pool stats as appropriate so that 824789Sahrens * user land knows which devices are available and overall pool health. 825789Sahrens */ 826789Sahrens static int 827789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 828789Sahrens { 829789Sahrens nvlist_t *tryconfig, *config; 830789Sahrens int error; 831789Sahrens 8325094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 8335094Slling &tryconfig)) != 0) 834789Sahrens return (error); 835789Sahrens 836789Sahrens config = spa_tryimport(tryconfig); 837789Sahrens 838789Sahrens nvlist_free(tryconfig); 839789Sahrens 840789Sahrens if (config == NULL) 841789Sahrens return (EINVAL); 842789Sahrens 8432676Seschrock error = put_nvlist(zc, config); 844789Sahrens nvlist_free(config); 845789Sahrens 846789Sahrens return (error); 847789Sahrens } 848789Sahrens 849789Sahrens static int 850789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc) 851789Sahrens { 852789Sahrens spa_t *spa; 853789Sahrens int error; 854789Sahrens 8552926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8562926Sek110237 return (error); 8572926Sek110237 8584808Sek110237 mutex_enter(&spa_namespace_lock); 8592926Sek110237 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); 8604808Sek110237 mutex_exit(&spa_namespace_lock); 8612926Sek110237 8622926Sek110237 spa_close(spa, FTAG); 8632926Sek110237 864789Sahrens return (error); 865789Sahrens } 866789Sahrens 867789Sahrens static int 868789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 869789Sahrens { 870789Sahrens spa_t *spa; 871789Sahrens int error; 872789Sahrens 873789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 874789Sahrens if (error == 0) { 875789Sahrens spa_freeze(spa); 876789Sahrens spa_close(spa, FTAG); 877789Sahrens } 878789Sahrens return (error); 879789Sahrens } 880789Sahrens 881789Sahrens static int 8821760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 8831760Seschrock { 8841760Seschrock spa_t *spa; 8851760Seschrock int error; 8861760Seschrock 8872926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8882926Sek110237 return (error); 8892926Sek110237 8905118Slling if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) { 8915118Slling spa_close(spa, FTAG); 8925118Slling return (EINVAL); 8935118Slling } 8945118Slling 8955094Slling spa_upgrade(spa, zc->zc_cookie); 8962926Sek110237 spa_close(spa, FTAG); 8972926Sek110237 8982926Sek110237 return (error); 8992926Sek110237 } 9002926Sek110237 9012926Sek110237 static int 9022926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 9032926Sek110237 { 9042926Sek110237 spa_t *spa; 9052926Sek110237 char *hist_buf; 9062926Sek110237 uint64_t size; 9072926Sek110237 int error; 9082926Sek110237 9092926Sek110237 if ((size = zc->zc_history_len) == 0) 9102926Sek110237 return (EINVAL); 9112926Sek110237 9122926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9132926Sek110237 return (error); 9142926Sek110237 9154577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 9163863Sek110237 spa_close(spa, FTAG); 9173863Sek110237 return (ENOTSUP); 9183863Sek110237 } 9193863Sek110237 9202926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 9212926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 9222926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 9234543Smarks error = xcopyout(hist_buf, 9244543Smarks (char *)(uintptr_t)zc->zc_history, 9252926Sek110237 zc->zc_history_len); 9262926Sek110237 } 9272926Sek110237 9282926Sek110237 spa_close(spa, FTAG); 9292926Sek110237 kmem_free(hist_buf, size); 9302926Sek110237 return (error); 9312926Sek110237 } 9322926Sek110237 9332926Sek110237 static int 9343444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 9353444Sek110237 { 9363444Sek110237 int error; 9373444Sek110237 9383912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 9393444Sek110237 return (error); 9403444Sek110237 9413444Sek110237 return (0); 9423444Sek110237 } 9433444Sek110237 9443444Sek110237 static int 9453444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 9463444Sek110237 { 9473444Sek110237 objset_t *osp; 9483444Sek110237 int error; 9493444Sek110237 9503444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 9513444Sek110237 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) 9523444Sek110237 return (error); 9533444Sek110237 9543444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 9553444Sek110237 sizeof (zc->zc_value)); 9563444Sek110237 dmu_objset_close(osp); 9573444Sek110237 9583444Sek110237 return (error); 9593444Sek110237 } 9603444Sek110237 9613444Sek110237 static int 962789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 963789Sahrens { 964789Sahrens spa_t *spa; 965789Sahrens int error; 966*5450Sbrendan nvlist_t *config, **l2cache; 967*5450Sbrendan uint_t nl2cache; 968789Sahrens 969789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 970789Sahrens if (error != 0) 971789Sahrens return (error); 972789Sahrens 973*5450Sbrendan error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 974*5450Sbrendan &config); 975*5450Sbrendan (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_L2CACHE, 976*5450Sbrendan &l2cache, &nl2cache); 977*5450Sbrendan 9783912Slling /* 9793912Slling * A root pool with concatenated devices is not supported. 9803912Slling * Thus, can not add a device to a root pool with one device. 981*5450Sbrendan * Allow for l2cache devices to be added. 9823912Slling */ 983*5450Sbrendan if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0 && 984*5450Sbrendan nl2cache == 0) { 9853912Slling spa_close(spa, FTAG); 9863912Slling return (EDOM); 9873912Slling } 9883912Slling 989*5450Sbrendan if (error == 0) { 990789Sahrens error = spa_vdev_add(spa, config); 991789Sahrens nvlist_free(config); 992789Sahrens } 993789Sahrens spa_close(spa, FTAG); 994789Sahrens return (error); 995789Sahrens } 996789Sahrens 997789Sahrens static int 998789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 999789Sahrens { 10002082Seschrock spa_t *spa; 10012082Seschrock int error; 10022082Seschrock 10032082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10042082Seschrock if (error != 0) 10052082Seschrock return (error); 10062082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 10072082Seschrock spa_close(spa, FTAG); 10082082Seschrock return (error); 1009789Sahrens } 1010789Sahrens 1011789Sahrens static int 10124451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 1013789Sahrens { 1014789Sahrens spa_t *spa; 1015789Sahrens int error; 10164451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 1017789Sahrens 10182926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1019789Sahrens return (error); 10204451Seschrock switch (zc->zc_cookie) { 10214451Seschrock case VDEV_STATE_ONLINE: 10224451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 10234451Seschrock break; 10244451Seschrock 10254451Seschrock case VDEV_STATE_OFFLINE: 10264451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 10274451Seschrock break; 1028789Sahrens 10294451Seschrock case VDEV_STATE_FAULTED: 10304451Seschrock error = vdev_fault(spa, zc->zc_guid); 10314451Seschrock break; 1032789Sahrens 10334451Seschrock case VDEV_STATE_DEGRADED: 10344451Seschrock error = vdev_degrade(spa, zc->zc_guid); 10354451Seschrock break; 10364451Seschrock 10374451Seschrock default: 10384451Seschrock error = EINVAL; 10394451Seschrock } 10404451Seschrock zc->zc_cookie = newstate; 1041789Sahrens spa_close(spa, FTAG); 1042789Sahrens return (error); 1043789Sahrens } 1044789Sahrens 1045789Sahrens static int 1046789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 1047789Sahrens { 1048789Sahrens spa_t *spa; 1049789Sahrens int replacing = zc->zc_cookie; 1050789Sahrens nvlist_t *config; 1051789Sahrens int error; 1052789Sahrens 10532926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1054789Sahrens return (error); 1055789Sahrens 10565094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 10575094Slling &config)) == 0) { 10581544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 1059789Sahrens nvlist_free(config); 1060789Sahrens } 1061789Sahrens 1062789Sahrens spa_close(spa, FTAG); 1063789Sahrens return (error); 1064789Sahrens } 1065789Sahrens 1066789Sahrens static int 1067789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 1068789Sahrens { 1069789Sahrens spa_t *spa; 1070789Sahrens int error; 1071789Sahrens 10722926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1073789Sahrens return (error); 1074789Sahrens 10751544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1076789Sahrens 1077789Sahrens spa_close(spa, FTAG); 1078789Sahrens return (error); 1079789Sahrens } 1080789Sahrens 1081789Sahrens static int 10821354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 10831354Seschrock { 10841354Seschrock spa_t *spa; 10852676Seschrock char *path = zc->zc_value; 10861544Seschrock uint64_t guid = zc->zc_guid; 10871354Seschrock int error; 10881354Seschrock 10891354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10901354Seschrock if (error != 0) 10911354Seschrock return (error); 10921354Seschrock 10931354Seschrock error = spa_vdev_setpath(spa, guid, path); 10941354Seschrock spa_close(spa, FTAG); 10951354Seschrock return (error); 10961354Seschrock } 10971354Seschrock 10985367Sahrens /* 10995367Sahrens * inputs: 11005367Sahrens * zc_name name of filesystem 11015367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 11025367Sahrens * 11035367Sahrens * outputs: 11045367Sahrens * zc_objset_stats stats 11055367Sahrens * zc_nvlist_dst property nvlist 11065367Sahrens * zc_nvlist_dst_size size of property nvlist 11075367Sahrens * zc_value alternate root 11085367Sahrens */ 11091354Seschrock static int 1110789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1111789Sahrens { 1112789Sahrens objset_t *os = NULL; 1113789Sahrens int error; 11141356Seschrock nvlist_t *nv; 1115789Sahrens 1116789Sahrens retry: 1117789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1118789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1119789Sahrens if (error != 0) { 1120789Sahrens /* 1121789Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1122789Sahrens * the objset is held exclusively. Fortunately this hold is 1123789Sahrens * only for a short while, so we retry here. 1124789Sahrens * This avoids user code having to handle EBUSY, 1125789Sahrens * for example for a "zfs list". 1126789Sahrens */ 1127789Sahrens if (error == EBUSY) { 1128789Sahrens delay(1); 1129789Sahrens goto retry; 1130789Sahrens } 1131789Sahrens return (error); 1132789Sahrens } 1133789Sahrens 11342885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1135789Sahrens 11362856Snd150628 if (zc->zc_nvlist_dst != 0 && 11371356Seschrock (error = dsl_prop_get_all(os, &nv)) == 0) { 11382885Sahrens dmu_objset_stats(os, nv); 11393087Sahrens /* 11405147Srm160521 * NB: zvol_get_stats() will read the objset contents, 11413087Sahrens * which we aren't supposed to do with a 11423087Sahrens * DS_MODE_STANDARD open, because it could be 11433087Sahrens * inconsistent. So this is a bit of a workaround... 11443087Sahrens */ 11454577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 11464577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 11474577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 11484577Sahrens } 11492676Seschrock error = put_nvlist(zc, nv); 11501356Seschrock nvlist_free(nv); 11511356Seschrock } 1152789Sahrens 11532676Seschrock spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value)); 11541544Seschrock 1155789Sahrens dmu_objset_close(os); 1156789Sahrens return (error); 1157789Sahrens } 1158789Sahrens 11595367Sahrens /* 11605367Sahrens * inputs: 11615367Sahrens * zc_name name of filesystem 11625367Sahrens * zc_cookie zap cursor 11635367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 11645367Sahrens * 11655367Sahrens * outputs: 11665367Sahrens * zc_name name of next filesystem 11675367Sahrens * zc_objset_stats stats 11685367Sahrens * zc_nvlist_dst property nvlist 11695367Sahrens * zc_nvlist_dst_size size of property nvlist 11705367Sahrens * zc_value alternate root 11715367Sahrens */ 1172789Sahrens static int 11735147Srm160521 zfs_ioc_objset_version(zfs_cmd_t *zc) 11745147Srm160521 { 11755147Srm160521 objset_t *os = NULL; 11765147Srm160521 int error; 11775147Srm160521 11785147Srm160521 retry: 11795147Srm160521 error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 11805147Srm160521 DS_MODE_STANDARD | DS_MODE_READONLY, &os); 11815147Srm160521 if (error != 0) { 11825147Srm160521 /* 11835147Srm160521 * This is ugly: dmu_objset_open() can return EBUSY if 11845147Srm160521 * the objset is held exclusively. Fortunately this hold is 11855147Srm160521 * only for a short while, so we retry here. 11865147Srm160521 * This avoids user code having to handle EBUSY, 11875147Srm160521 * for example for a "zfs list". 11885147Srm160521 */ 11895147Srm160521 if (error == EBUSY) { 11905147Srm160521 delay(1); 11915147Srm160521 goto retry; 11925147Srm160521 } 11935147Srm160521 return (error); 11945147Srm160521 } 11955147Srm160521 11965147Srm160521 dmu_objset_fast_stat(os, &zc->zc_objset_stats); 11975147Srm160521 11985147Srm160521 /* 11995147Srm160521 * NB: zfs_get_version() will read the objset contents, 12005147Srm160521 * which we aren't supposed to do with a 12015147Srm160521 * DS_MODE_STANDARD open, because it could be 12025147Srm160521 * inconsistent. So this is a bit of a workaround... 12035147Srm160521 */ 12045147Srm160521 zc->zc_cookie = 0; 12055147Srm160521 if (!zc->zc_objset_stats.dds_inconsistent) 12065147Srm160521 if (dmu_objset_type(os) == DMU_OST_ZFS) 12075147Srm160521 (void) zfs_get_version(os, &zc->zc_cookie); 12085147Srm160521 12095147Srm160521 dmu_objset_close(os); 12105147Srm160521 return (0); 12115147Srm160521 } 12125147Srm160521 12135147Srm160521 static int 1214789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1215789Sahrens { 1216885Sahrens objset_t *os; 1217789Sahrens int error; 1218789Sahrens char *p; 1219789Sahrens 1220885Sahrens retry: 1221885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1222885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1223885Sahrens if (error != 0) { 1224885Sahrens /* 1225885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1226885Sahrens * the objset is held exclusively. Fortunately this hold is 1227885Sahrens * only for a short while, so we retry here. 1228885Sahrens * This avoids user code having to handle EBUSY, 1229885Sahrens * for example for a "zfs list". 1230885Sahrens */ 1231885Sahrens if (error == EBUSY) { 1232885Sahrens delay(1); 1233885Sahrens goto retry; 1234885Sahrens } 1235885Sahrens if (error == ENOENT) 1236885Sahrens error = ESRCH; 1237885Sahrens return (error); 1238789Sahrens } 1239789Sahrens 1240789Sahrens p = strrchr(zc->zc_name, '/'); 1241789Sahrens if (p == NULL || p[1] != '\0') 1242789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1243789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1244789Sahrens 1245789Sahrens do { 1246885Sahrens error = dmu_dir_list_next(os, 1247885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1248885Sahrens NULL, &zc->zc_cookie); 1249789Sahrens if (error == ENOENT) 1250789Sahrens error = ESRCH; 1251885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1252789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 1253789Sahrens 1254885Sahrens /* 1255885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1256885Sahrens * try to get stats for it. Userland will skip over it. 1257885Sahrens */ 1258885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1259885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1260789Sahrens 1261885Sahrens dmu_objset_close(os); 1262789Sahrens return (error); 1263789Sahrens } 1264789Sahrens 12655367Sahrens /* 12665367Sahrens * inputs: 12675367Sahrens * zc_name name of filesystem 12685367Sahrens * zc_cookie zap cursor 12695367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 12705367Sahrens * 12715367Sahrens * outputs: 12725367Sahrens * zc_name name of next snapshot 12735367Sahrens * zc_objset_stats stats 12745367Sahrens * zc_nvlist_dst property nvlist 12755367Sahrens * zc_nvlist_dst_size size of property nvlist 12765367Sahrens * zc_value alternate root 12775367Sahrens */ 1278789Sahrens static int 1279789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1280789Sahrens { 1281885Sahrens objset_t *os; 1282789Sahrens int error; 1283789Sahrens 1284789Sahrens retry: 1285885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1286885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1287885Sahrens if (error != 0) { 1288789Sahrens /* 1289885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1290789Sahrens * the objset is held exclusively. Fortunately this hold is 1291789Sahrens * only for a short while, so we retry here. 1292789Sahrens * This avoids user code having to handle EBUSY, 1293885Sahrens * for example for a "zfs list". 1294789Sahrens */ 1295789Sahrens if (error == EBUSY) { 1296789Sahrens delay(1); 1297789Sahrens goto retry; 1298789Sahrens } 1299789Sahrens if (error == ENOENT) 1300885Sahrens error = ESRCH; 1301789Sahrens return (error); 1302789Sahrens } 1303789Sahrens 13041003Slling /* 13051003Slling * A dataset name of maximum length cannot have any snapshots, 13061003Slling * so exit immediately. 13071003Slling */ 13081003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1309885Sahrens dmu_objset_close(os); 13101003Slling return (ESRCH); 1311789Sahrens } 1312789Sahrens 1313885Sahrens error = dmu_snapshot_list_next(os, 1314885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 1315885Sahrens zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie); 1316789Sahrens if (error == ENOENT) 1317789Sahrens error = ESRCH; 1318789Sahrens 1319885Sahrens if (error == 0) 1320885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1321789Sahrens 13225367Sahrens /* if we failed, undo the @ that we tacked on to zc_name */ 13235367Sahrens if (error != 0) 13245367Sahrens *strchr(zc->zc_name, '@') = '\0'; 13255367Sahrens 1326885Sahrens dmu_objset_close(os); 1327789Sahrens return (error); 1328789Sahrens } 1329789Sahrens 1330789Sahrens static int 13314787Sahrens zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) 1332789Sahrens { 13332676Seschrock nvpair_t *elem; 13342676Seschrock int error; 13352676Seschrock uint64_t intval; 13362676Seschrock char *strval; 13372676Seschrock 13384543Smarks /* 13394543Smarks * First validate permission to set all of the properties 13404543Smarks */ 13412676Seschrock elem = NULL; 13422676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 13434670Sahrens const char *propname = nvpair_name(elem); 13444670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 13452676Seschrock 13465094Slling if (prop == ZPROP_INVAL) { 13472676Seschrock /* 13482676Seschrock * If this is a user-defined property, it must be a 13492676Seschrock * string, and there is no further validation to do. 13502676Seschrock */ 13512676Seschrock if (!zfs_prop_user(propname) || 13522676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 13532676Seschrock return (EINVAL); 13542676Seschrock 13555331Samw if (error = zfs_secpolicy_write_perms(name, 13565331Samw ZFS_DELEG_PERM_USERPROP, CRED())) 13574670Sahrens return (error); 13584543Smarks continue; 13592676Seschrock } 13602676Seschrock 13614787Sahrens if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 13624670Sahrens return (error); 13632676Seschrock 13644670Sahrens /* 13654670Sahrens * Check that this value is valid for this pool version 13664670Sahrens */ 13674670Sahrens switch (prop) { 13683886Sahl case ZFS_PROP_COMPRESSION: 13693886Sahl /* 13703886Sahl * If the user specified gzip compression, make sure 13713886Sahl * the SPA supports it. We ignore any errors here since 13723886Sahl * we'll catch them later. 13733886Sahl */ 13743886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 13753886Sahl nvpair_value_uint64(elem, &intval) == 0 && 13763886Sahl intval >= ZIO_COMPRESS_GZIP_1 && 13773886Sahl intval <= ZIO_COMPRESS_GZIP_9) { 13785331Samw if (zfs_check_version(name, 13795331Samw SPA_VERSION_GZIP_COMPRESSION)) 13805331Samw return (ENOTSUP); 13813886Sahl } 13823886Sahl break; 13834603Sahrens 13844603Sahrens case ZFS_PROP_COPIES: 13855331Samw if (zfs_check_version(name, SPA_VERSION_DITTO_BLOCKS)) 13865331Samw return (ENOTSUP); 13874603Sahrens break; 13885331Samw case ZFS_PROP_NORMALIZE: 13895331Samw case ZFS_PROP_UTF8ONLY: 13905331Samw case ZFS_PROP_CASE: 13915331Samw if (zfs_check_version(name, SPA_VERSION_NORMALIZATION)) 13925331Samw return (ENOTSUP); 13935331Samw 13944603Sahrens } 13955331Samw if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 13965331Samw return (error); 13974543Smarks } 13984543Smarks 13994543Smarks elem = NULL; 14004543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 14014670Sahrens const char *propname = nvpair_name(elem); 14024670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 14034543Smarks 14045094Slling if (prop == ZPROP_INVAL) { 14054543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 14064543Smarks error = dsl_prop_set(name, propname, 1, 14074543Smarks strlen(strval) + 1, strval); 14084543Smarks if (error == 0) 14094543Smarks continue; 14104543Smarks else 14114543Smarks return (error); 14124543Smarks } 14132676Seschrock 14142676Seschrock switch (prop) { 14152676Seschrock case ZFS_PROP_QUOTA: 14162676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14174577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 14182676Seschrock return (error); 14192676Seschrock break; 14202676Seschrock 14215378Sck153898 case ZFS_PROP_REFQUOTA: 14225378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14235378Sck153898 (error = dsl_dataset_set_quota(name, intval)) != 0) 14245378Sck153898 return (error); 14255378Sck153898 break; 14265378Sck153898 14272676Seschrock case ZFS_PROP_RESERVATION: 14282676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14292676Seschrock (error = dsl_dir_set_reservation(name, 14302676Seschrock intval)) != 0) 14312676Seschrock return (error); 14322676Seschrock break; 1433789Sahrens 14345378Sck153898 case ZFS_PROP_REFRESERVATION: 14355378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14365378Sck153898 (error = dsl_dataset_set_reservation(name, 14375378Sck153898 intval)) != 0) 14385378Sck153898 return (error); 14395378Sck153898 break; 14405378Sck153898 14412676Seschrock case ZFS_PROP_VOLSIZE: 14422676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14434787Sahrens (error = zvol_set_volsize(name, 14444787Sahrens ddi_driver_major(zfs_dip), intval)) != 0) 14452676Seschrock return (error); 14462676Seschrock break; 14472676Seschrock 14482676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 14492676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14504577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 14514577Sahrens return (error); 14524577Sahrens break; 14534577Sahrens 14544577Sahrens case ZFS_PROP_VERSION: 14554577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14564577Sahrens (error = zfs_set_version(name, intval)) != 0) 14572676Seschrock return (error); 14582676Seschrock break; 14592676Seschrock 14602676Seschrock default: 14612676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 14622676Seschrock if (zfs_prop_get_type(prop) != 14634787Sahrens PROP_TYPE_STRING) 14642676Seschrock return (EINVAL); 14652717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 14662717Seschrock if ((error = dsl_prop_set(name, 14672676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 14682717Seschrock strval)) != 0) 14692717Seschrock return (error); 14702676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 14712885Sahrens const char *unused; 14722885Sahrens 14732717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 14742676Seschrock 14752676Seschrock switch (zfs_prop_get_type(prop)) { 14764787Sahrens case PROP_TYPE_NUMBER: 14772676Seschrock break; 14784787Sahrens case PROP_TYPE_STRING: 14792717Seschrock return (EINVAL); 14804787Sahrens case PROP_TYPE_INDEX: 14812717Seschrock if (zfs_prop_index_to_string(prop, 14822717Seschrock intval, &unused) != 0) 14832717Seschrock return (EINVAL); 14842676Seschrock break; 14852676Seschrock default: 14864577Sahrens cmn_err(CE_PANIC, 14874577Sahrens "unknown property type"); 14882676Seschrock break; 14892676Seschrock } 14902676Seschrock 14912717Seschrock if ((error = dsl_prop_set(name, propname, 14922717Seschrock 8, 1, &intval)) != 0) 14932717Seschrock return (error); 14942676Seschrock } else { 14952676Seschrock return (EINVAL); 14962676Seschrock } 14972676Seschrock break; 14982676Seschrock } 14992676Seschrock } 15002676Seschrock 15012676Seschrock return (0); 1502789Sahrens } 1503789Sahrens 15045367Sahrens /* 15055367Sahrens * inputs: 15065367Sahrens * zc_name name of filesystem 15075367Sahrens * zc_value name of property to inherit 15085367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 15095367Sahrens * 15105367Sahrens * outputs: none 15115367Sahrens */ 1512789Sahrens static int 15132676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1514789Sahrens { 15152676Seschrock nvlist_t *nvl; 15162676Seschrock int error; 1517789Sahrens 15185094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15195094Slling &nvl)) != 0) 15202676Seschrock return (error); 15212676Seschrock 15224787Sahrens error = zfs_set_prop_nvlist(zc->zc_name, nvl); 15234543Smarks 15242676Seschrock nvlist_free(nvl); 15252676Seschrock return (error); 1526789Sahrens } 1527789Sahrens 15285367Sahrens /* 15295367Sahrens * inputs: 15305367Sahrens * zc_name name of filesystem 15315367Sahrens * zc_value name of property to inherit 15325367Sahrens * 15335367Sahrens * outputs: none 15345367Sahrens */ 1535789Sahrens static int 15364849Sahrens zfs_ioc_inherit_prop(zfs_cmd_t *zc) 15374849Sahrens { 15384849Sahrens /* the property name has been validated by zfs_secpolicy_inherit() */ 15394849Sahrens return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 15404849Sahrens } 15414849Sahrens 15424849Sahrens static int 15434098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 15443912Slling { 15455094Slling nvlist_t *props; 15463912Slling spa_t *spa; 15475094Slling int error; 15483912Slling 15495094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15505094Slling &props))) 15513912Slling return (error); 15523912Slling 15533912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 15545094Slling nvlist_free(props); 15553912Slling return (error); 15563912Slling } 15573912Slling 15585094Slling error = spa_prop_set(spa, props); 15593912Slling 15605094Slling nvlist_free(props); 15613912Slling spa_close(spa, FTAG); 15623912Slling 15633912Slling return (error); 15643912Slling } 15653912Slling 15663912Slling static int 15674098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 15683912Slling { 15693912Slling spa_t *spa; 15703912Slling int error; 15713912Slling nvlist_t *nvp = NULL; 15723912Slling 15733912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 15743912Slling return (error); 15753912Slling 15765094Slling error = spa_prop_get(spa, &nvp); 15773912Slling 15783912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 15793912Slling error = put_nvlist(zc, nvp); 15803912Slling else 15813912Slling error = EFAULT; 15823912Slling 15833912Slling spa_close(spa, FTAG); 15843912Slling 15853912Slling if (nvp) 15863912Slling nvlist_free(nvp); 15873912Slling return (error); 15883912Slling } 15893912Slling 15903912Slling static int 15914543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 15924543Smarks { 15934543Smarks nvlist_t *nvp; 15944543Smarks int error; 15954543Smarks uint32_t uid; 15964543Smarks uint32_t gid; 15974543Smarks uint32_t *groups; 15984543Smarks uint_t group_cnt; 15994543Smarks cred_t *usercred; 16004543Smarks 16015094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16025094Slling &nvp)) != 0) { 16034543Smarks return (error); 16044543Smarks } 16054543Smarks 16064543Smarks if ((error = nvlist_lookup_uint32(nvp, 16074543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 16084543Smarks nvlist_free(nvp); 16094543Smarks return (EPERM); 16104543Smarks } 16114543Smarks 16124543Smarks if ((error = nvlist_lookup_uint32(nvp, 16134543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 16144543Smarks nvlist_free(nvp); 16154543Smarks return (EPERM); 16164543Smarks } 16174543Smarks 16184543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 16194543Smarks &groups, &group_cnt)) != 0) { 16204543Smarks nvlist_free(nvp); 16214543Smarks return (EPERM); 16224543Smarks } 16234543Smarks usercred = cralloc(); 16244543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 16254543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 16264543Smarks nvlist_free(nvp); 16274543Smarks crfree(usercred); 16284543Smarks return (EPERM); 16294543Smarks } 16304543Smarks nvlist_free(nvp); 16314543Smarks error = dsl_deleg_access(zc->zc_name, 16324787Sahrens zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); 16334543Smarks crfree(usercred); 16344543Smarks return (error); 16354543Smarks } 16364543Smarks 16375367Sahrens /* 16385367Sahrens * inputs: 16395367Sahrens * zc_name name of filesystem 16405367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 16415367Sahrens * zc_perm_action allow/unallow flag 16425367Sahrens * 16435367Sahrens * outputs: none 16445367Sahrens */ 16454543Smarks static int 16464543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 16474543Smarks { 16484543Smarks int error; 16494543Smarks nvlist_t *fsaclnv = NULL; 16504543Smarks 16515094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16525094Slling &fsaclnv)) != 0) 16534543Smarks return (error); 16544543Smarks 16554543Smarks /* 16564543Smarks * Verify nvlist is constructed correctly 16574543Smarks */ 16584543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 16594543Smarks nvlist_free(fsaclnv); 16604543Smarks return (EINVAL); 16614543Smarks } 16624543Smarks 16634543Smarks /* 16644543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 16654543Smarks * that user is allowed to hand out each permission in 16664543Smarks * the nvlist(s) 16674543Smarks */ 16684543Smarks 16694787Sahrens error = secpolicy_zfs(CRED()); 16704543Smarks if (error) { 16714787Sahrens if (zc->zc_perm_action == B_FALSE) { 16724787Sahrens error = dsl_deleg_can_allow(zc->zc_name, 16734787Sahrens fsaclnv, CRED()); 16744787Sahrens } else { 16754787Sahrens error = dsl_deleg_can_unallow(zc->zc_name, 16764787Sahrens fsaclnv, CRED()); 16774787Sahrens } 16784543Smarks } 16794543Smarks 16804543Smarks if (error == 0) 16814543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 16824543Smarks 16834543Smarks nvlist_free(fsaclnv); 16844543Smarks return (error); 16854543Smarks } 16864543Smarks 16875367Sahrens /* 16885367Sahrens * inputs: 16895367Sahrens * zc_name name of filesystem 16905367Sahrens * 16915367Sahrens * outputs: 16925367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 16935367Sahrens */ 16944543Smarks static int 16954543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 16964543Smarks { 16974543Smarks nvlist_t *nvp; 16984543Smarks int error; 16994543Smarks 17004543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 17014543Smarks error = put_nvlist(zc, nvp); 17024543Smarks nvlist_free(nvp); 17034543Smarks } 17044543Smarks 17054543Smarks return (error); 17064543Smarks } 17074543Smarks 17085367Sahrens /* 17095367Sahrens * inputs: 17105367Sahrens * zc_name name of volume 17115367Sahrens * 17125367Sahrens * outputs: none 17135367Sahrens */ 17144543Smarks static int 1715789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1716789Sahrens { 17174787Sahrens return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); 1718789Sahrens } 1719789Sahrens 17205367Sahrens /* 17215367Sahrens * inputs: 17225367Sahrens * zc_name name of volume 17235367Sahrens * 17245367Sahrens * outputs: none 17255367Sahrens */ 1726789Sahrens static int 1727789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1728789Sahrens { 17292676Seschrock return (zvol_remove_minor(zc->zc_name)); 1730789Sahrens } 1731789Sahrens 1732789Sahrens /* 1733789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1734789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1735789Sahrens * is responsible for releasing the returned vfs pointer. 1736789Sahrens */ 1737789Sahrens static vfs_t * 1738789Sahrens zfs_get_vfs(const char *resource) 1739789Sahrens { 1740789Sahrens struct vfs *vfsp; 1741789Sahrens struct vfs *vfs_found = NULL; 1742789Sahrens 1743789Sahrens vfs_list_read_lock(); 1744789Sahrens vfsp = rootvfs; 1745789Sahrens do { 1746789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1747789Sahrens VFS_HOLD(vfsp); 1748789Sahrens vfs_found = vfsp; 1749789Sahrens break; 1750789Sahrens } 1751789Sahrens vfsp = vfsp->vfs_next; 1752789Sahrens } while (vfsp != rootvfs); 1753789Sahrens vfs_list_unlock(); 1754789Sahrens return (vfs_found); 1755789Sahrens } 1756789Sahrens 17574543Smarks /* ARGSUSED */ 1758789Sahrens static void 17594543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1760789Sahrens { 17615331Samw zfs_creat_t *zct = arg; 17625331Samw uint64_t version; 17635331Samw 17645331Samw if (spa_version(dmu_objset_spa(os)) >= SPA_VERSION_FUID) 17655331Samw version = ZPL_VERSION; 17665331Samw else 17675331Samw version = ZPL_VERSION_FUID - 1; 17685331Samw 17695331Samw (void) nvlist_lookup_uint64(zct->zct_props, 17704577Sahrens zfs_prop_to_name(ZFS_PROP_VERSION), &version); 17714577Sahrens 17725331Samw zfs_create_fs(os, cr, version, zct->zct_norm, tx); 17735331Samw } 17745331Samw 17755331Samw /* 17765331Samw * zfs_prop_lookup() 17775331Samw * 17785331Samw * Look for the property first in the existing property nvlist. If 17795331Samw * it's already present, you're done. If it's not there, attempt to 17805331Samw * find the property value from a parent dataset. If that fails, fall 17815331Samw * back to the property's default value. In either of these two 17825331Samw * cases, if update is TRUE, add a value for the property to the 17835331Samw * property nvlist. 17845331Samw * 17855331Samw * If the rval pointer is non-NULL, copy the discovered value to rval. 17865331Samw * 17875331Samw * If we get any unexpected errors, bail and return the error number 17885331Samw * to the caller. 17895331Samw * 17905331Samw * If we succeed, return 0. 17915331Samw */ 17925331Samw static int 17935331Samw zfs_prop_lookup(const char *parentname, zfs_prop_t propnum, 17945331Samw nvlist_t *proplist, uint64_t *rval, boolean_t update) 17955331Samw { 17965331Samw const char *propname; 17975331Samw uint64_t value; 17985331Samw int error = ENOENT; 17995331Samw 18005331Samw propname = zfs_prop_to_name(propnum); 18015331Samw if (proplist != NULL) 18025331Samw error = nvlist_lookup_uint64(proplist, propname, &value); 18035331Samw if (error == ENOENT) { 18045331Samw error = dsl_prop_get_integer(parentname, propname, 18055331Samw &value, NULL); 18065331Samw if (error == ENOENT) 18075331Samw value = zfs_prop_default_numeric(propnum); 18085331Samw else if (error != 0) 18095331Samw return (error); 18105331Samw if (update) { 18115331Samw ASSERT(proplist != NULL); 18125331Samw error = nvlist_add_uint64(proplist, propname, value); 18135331Samw } 18145331Samw } 18155331Samw if (error == 0 && rval) 18165331Samw *rval = value; 18175331Samw return (error); 18185331Samw } 18195331Samw 18205331Samw /* 18215331Samw * zfs_normalization_get 18225331Samw * 18235331Samw * Get the normalization flag value. If the properties have 18245331Samw * non-default values, make sure the pool version is recent enough to 18255331Samw * support these choices. 18265331Samw */ 18275331Samw static int 18285331Samw zfs_normalization_get(const char *dataset, nvlist_t *proplist, int *norm, 18295331Samw boolean_t update) 18305331Samw { 18315331Samw char parentname[MAXNAMELEN]; 18325331Samw char poolname[MAXNAMELEN]; 18335331Samw char *cp; 18345331Samw uint64_t value; 18355331Samw int check = 0; 18365331Samw int error; 18375331Samw 18385331Samw ASSERT(norm != NULL); 18395331Samw *norm = 0; 18405331Samw 18415331Samw (void) strncpy(parentname, dataset, sizeof (parentname)); 18425331Samw cp = strrchr(parentname, '@'); 18435331Samw if (cp != NULL) { 18445331Samw cp[0] = '\0'; 18455331Samw } else { 18465331Samw cp = strrchr(parentname, '/'); 18475331Samw if (cp == NULL) 18485331Samw return (ENOENT); 18495331Samw cp[0] = '\0'; 18505331Samw } 18515331Samw 18525331Samw (void) strncpy(poolname, dataset, sizeof (poolname)); 18535331Samw cp = strchr(poolname, '/'); 18545331Samw if (cp != NULL) 18555331Samw cp[0] = '\0'; 18565331Samw 18575375Stimh /* 18585375Stimh * Make sure pool is of new enough vintage to support normalization. 18595375Stimh */ 18605375Stimh if (zfs_check_version(poolname, SPA_VERSION_NORMALIZATION)) 18615375Stimh return (0); 18625375Stimh 18635331Samw error = zfs_prop_lookup(parentname, ZFS_PROP_UTF8ONLY, 18645331Samw proplist, &value, update); 18655331Samw if (error != 0) 18665331Samw return (error); 18675331Samw if (value != zfs_prop_default_numeric(ZFS_PROP_UTF8ONLY)) 18685331Samw check = 1; 18695331Samw 18705331Samw error = zfs_prop_lookup(parentname, ZFS_PROP_NORMALIZE, 18715331Samw proplist, &value, update); 18725331Samw if (error != 0) 18735331Samw return (error); 18745331Samw if (value != zfs_prop_default_numeric(ZFS_PROP_NORMALIZE)) { 18755331Samw check = 1; 18765331Samw switch ((int)value) { 18775331Samw case ZFS_NORMALIZE_NONE: 18785331Samw break; 18795331Samw case ZFS_NORMALIZE_C: 18805331Samw *norm |= U8_TEXTPREP_NFC; 18815331Samw break; 18825331Samw case ZFS_NORMALIZE_D: 18835331Samw *norm |= U8_TEXTPREP_NFD; 18845331Samw break; 18855331Samw case ZFS_NORMALIZE_KC: 18865331Samw *norm |= U8_TEXTPREP_NFKC; 18875331Samw break; 18885331Samw case ZFS_NORMALIZE_KD: 18895331Samw *norm |= U8_TEXTPREP_NFKD; 18905331Samw break; 18915331Samw default: 18925331Samw ASSERT((int)value >= ZFS_NORMALIZE_NONE); 18935331Samw ASSERT((int)value <= ZFS_NORMALIZE_KD); 18945331Samw break; 18955331Samw } 18965331Samw } 18975331Samw 18985331Samw error = zfs_prop_lookup(parentname, ZFS_PROP_CASE, 18995331Samw proplist, &value, update); 19005331Samw if (error != 0) 19015331Samw return (error); 19025331Samw if (value != zfs_prop_default_numeric(ZFS_PROP_CASE)) { 19035331Samw check = 1; 19045331Samw switch ((int)value) { 19055331Samw case ZFS_CASE_SENSITIVE: 19065331Samw break; 19075331Samw case ZFS_CASE_INSENSITIVE: 19085331Samw *norm |= U8_TEXTPREP_TOUPPER; 19095331Samw break; 19105331Samw case ZFS_CASE_MIXED: 19115331Samw *norm |= U8_TEXTPREP_TOUPPER; 19125331Samw break; 19135331Samw default: 19145331Samw ASSERT((int)value >= ZFS_CASE_SENSITIVE); 19155331Samw ASSERT((int)value <= ZFS_CASE_MIXED); 19165331Samw break; 19175331Samw } 19185331Samw } 19195331Samw 19205375Stimh /* 19215375Stimh * At the moment we are disabling non-default values for these 19225375Stimh * properties because they cannot be preserved properly with a 19235375Stimh * zfs send. 19245375Stimh */ 19255331Samw if (check == 1) 19265375Stimh return (ENOTSUP); 19275375Stimh 19285331Samw return (0); 1929789Sahrens } 1930789Sahrens 19315367Sahrens /* 19325367Sahrens * inputs: 19335367Sahrens * zc_objset_type type of objset to create (fs vs zvol) 19345367Sahrens * zc_name name of new objset 19355367Sahrens * zc_value name of snapshot to clone from (may be empty) 19365367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 19375367Sahrens * 19385367Sahrens * outputs: none 19395367Sahrens */ 1940789Sahrens static int 1941789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1942789Sahrens { 1943789Sahrens objset_t *clone; 1944789Sahrens int error = 0; 19455331Samw zfs_creat_t zct; 19464543Smarks nvlist_t *nvprops = NULL; 19474543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1948789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1949789Sahrens 1950789Sahrens switch (type) { 1951789Sahrens 1952789Sahrens case DMU_OST_ZFS: 1953789Sahrens cbfunc = zfs_create_cb; 1954789Sahrens break; 1955789Sahrens 1956789Sahrens case DMU_OST_ZVOL: 1957789Sahrens cbfunc = zvol_create_cb; 1958789Sahrens break; 1959789Sahrens 1960789Sahrens default: 19612199Sahrens cbfunc = NULL; 19622199Sahrens } 19635326Sek110237 if (strchr(zc->zc_name, '@') || 19645326Sek110237 strchr(zc->zc_name, '%')) 1965789Sahrens return (EINVAL); 1966789Sahrens 19672676Seschrock if (zc->zc_nvlist_src != NULL && 19685094Slling (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 19695094Slling &nvprops)) != 0) 19702676Seschrock return (error); 19712676Seschrock 19725331Samw zct.zct_norm = 0; 19735331Samw zct.zct_props = nvprops; 19745331Samw 19752676Seschrock if (zc->zc_value[0] != '\0') { 1976789Sahrens /* 1977789Sahrens * We're creating a clone of an existing snapshot. 1978789Sahrens */ 19792676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 19802676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 19814543Smarks nvlist_free(nvprops); 1982789Sahrens return (EINVAL); 19832676Seschrock } 1984789Sahrens 19852676Seschrock error = dmu_objset_open(zc->zc_value, type, 1986789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 19872676Seschrock if (error) { 19884543Smarks nvlist_free(nvprops); 1989789Sahrens return (error); 19902676Seschrock } 1991789Sahrens error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); 19925331Samw if (error) { 19935331Samw dmu_objset_close(clone); 19945331Samw nvlist_free(nvprops); 19955331Samw return (error); 19965331Samw } 19975331Samw /* 19985331Samw * If caller did not provide any properties, allocate 19995331Samw * an nvlist for properties, as we will be adding our set-once 20005331Samw * properties to it. This carries the choices made on the 20015331Samw * original file system into the clone. 20025331Samw */ 20035331Samw if (nvprops == NULL) 20045331Samw VERIFY(nvlist_alloc(&nvprops, 20055331Samw NV_UNIQUE_NAME, KM_SLEEP) == 0); 20065331Samw 20075331Samw /* 20085331Samw * We have to have normalization and case-folding 20095331Samw * flags correct when we do the file system creation, 20105331Samw * so go figure them out now. All we really care about 20115331Samw * here is getting these values into the property list. 20125331Samw */ 20135331Samw error = zfs_normalization_get(zc->zc_value, nvprops, 20145331Samw &zct.zct_norm, B_TRUE); 20155331Samw if (error != 0) { 20165331Samw dmu_objset_close(clone); 20175331Samw nvlist_free(nvprops); 20185331Samw return (error); 20195331Samw } 2020789Sahrens dmu_objset_close(clone); 2021789Sahrens } else { 20222676Seschrock if (cbfunc == NULL) { 20234543Smarks nvlist_free(nvprops); 20242199Sahrens return (EINVAL); 20252676Seschrock } 20262676Seschrock 2027789Sahrens if (type == DMU_OST_ZVOL) { 20282676Seschrock uint64_t volsize, volblocksize; 20292676Seschrock 20304543Smarks if (nvprops == NULL || 20314543Smarks nvlist_lookup_uint64(nvprops, 20322676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 20332676Seschrock &volsize) != 0) { 20344543Smarks nvlist_free(nvprops); 20352676Seschrock return (EINVAL); 20362676Seschrock } 20372676Seschrock 20384543Smarks if ((error = nvlist_lookup_uint64(nvprops, 20392676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 20402676Seschrock &volblocksize)) != 0 && error != ENOENT) { 20414543Smarks nvlist_free(nvprops); 20422676Seschrock return (EINVAL); 20432676Seschrock } 20441133Seschrock 20452676Seschrock if (error != 0) 20462676Seschrock volblocksize = zfs_prop_default_numeric( 20472676Seschrock ZFS_PROP_VOLBLOCKSIZE); 20482676Seschrock 20492676Seschrock if ((error = zvol_check_volblocksize( 20502676Seschrock volblocksize)) != 0 || 20512676Seschrock (error = zvol_check_volsize(volsize, 20522676Seschrock volblocksize)) != 0) { 20534543Smarks nvlist_free(nvprops); 2054789Sahrens return (error); 20552676Seschrock } 20564577Sahrens } else if (type == DMU_OST_ZFS) { 20574577Sahrens uint64_t version; 20585331Samw int error; 20595331Samw 20605331Samw error = nvlist_lookup_uint64(nvprops, 20615331Samw zfs_prop_to_name(ZFS_PROP_VERSION), &version); 20625331Samw 20635331Samw if (error == 0 && (version < ZPL_VERSION_INITIAL || 20644577Sahrens version > ZPL_VERSION)) { 20654577Sahrens nvlist_free(nvprops); 20665331Samw return (ENOTSUP); 20675331Samw } else if (error == 0 && version >= ZPL_VERSION_FUID && 20685331Samw zfs_check_version(zc->zc_name, SPA_VERSION_FUID)) { 20695331Samw nvlist_free(nvprops); 20705331Samw return (ENOTSUP); 20715331Samw } 20725331Samw 20735331Samw /* 20745331Samw * We have to have normalization and 20755331Samw * case-folding flags correct when we do the 20765331Samw * file system creation, so go figure them out 20775331Samw * now. The final argument to zfs_normalization_get() 20785331Samw * tells that routine not to update the nvprops 20795331Samw * list. 20805331Samw */ 20815331Samw error = zfs_normalization_get(zc->zc_name, nvprops, 20825331Samw &zct.zct_norm, B_FALSE); 20835331Samw if (error != 0) { 20845331Samw nvlist_free(nvprops); 20855331Samw return (error); 20864577Sahrens } 20872676Seschrock } 20882676Seschrock error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, 20895331Samw &zct); 2090789Sahrens } 20912676Seschrock 20922676Seschrock /* 20932676Seschrock * It would be nice to do this atomically. 20942676Seschrock */ 20952676Seschrock if (error == 0) { 20964787Sahrens if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) 20972676Seschrock (void) dmu_objset_destroy(zc->zc_name); 20982676Seschrock } 20992676Seschrock 21004543Smarks nvlist_free(nvprops); 2101789Sahrens return (error); 2102789Sahrens } 2103789Sahrens 21045367Sahrens /* 21055367Sahrens * inputs: 21065367Sahrens * zc_name name of filesystem 21075367Sahrens * zc_value short name of snapshot 21085367Sahrens * zc_cookie recursive flag 21095367Sahrens * 21105367Sahrens * outputs: none 21115367Sahrens */ 2112789Sahrens static int 21132199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 21142199Sahrens { 21152676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 21162199Sahrens return (EINVAL); 21172199Sahrens return (dmu_objset_snapshot(zc->zc_name, 21182676Seschrock zc->zc_value, zc->zc_cookie)); 21192199Sahrens } 21202199Sahrens 21214007Smmusante int 21222199Sahrens zfs_unmount_snap(char *name, void *arg) 2123789Sahrens { 21242199Sahrens char *snapname = arg; 21252199Sahrens char *cp; 21262417Sahrens vfs_t *vfsp = NULL; 21272199Sahrens 21282199Sahrens /* 21292199Sahrens * Snapshots (which are under .zfs control) must be unmounted 21302199Sahrens * before they can be destroyed. 21312199Sahrens */ 21322199Sahrens 21332199Sahrens if (snapname) { 21342199Sahrens (void) strcat(name, "@"); 21352199Sahrens (void) strcat(name, snapname); 21362199Sahrens vfsp = zfs_get_vfs(name); 21372199Sahrens cp = strchr(name, '@'); 21382199Sahrens *cp = '\0'; 21392417Sahrens } else if (strchr(name, '@')) { 21402199Sahrens vfsp = zfs_get_vfs(name); 21412199Sahrens } 21422199Sahrens 21432199Sahrens if (vfsp) { 21442199Sahrens /* 21452199Sahrens * Always force the unmount for snapshots. 21462199Sahrens */ 21472199Sahrens int flag = MS_FORCE; 2148789Sahrens int err; 2149789Sahrens 21502199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 21512199Sahrens VFS_RELE(vfsp); 21522199Sahrens return (err); 21532199Sahrens } 21542199Sahrens VFS_RELE(vfsp); 21552199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 21562199Sahrens return (err); 21572199Sahrens } 21582199Sahrens return (0); 21592199Sahrens } 21602199Sahrens 21615367Sahrens /* 21625367Sahrens * inputs: 21635367Sahrens * zc_name name of filesystem 21645367Sahrens * zc_value short name of snapshot 21655367Sahrens * 21665367Sahrens * outputs: none 21675367Sahrens */ 21682199Sahrens static int 21692199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 21702199Sahrens { 21712199Sahrens int err; 2172789Sahrens 21732676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 21742199Sahrens return (EINVAL); 21752199Sahrens err = dmu_objset_find(zc->zc_name, 21762676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 21772199Sahrens if (err) 21782199Sahrens return (err); 21792676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 21802199Sahrens } 21812199Sahrens 21825367Sahrens /* 21835367Sahrens * inputs: 21845367Sahrens * zc_name name of dataset to destroy 21855367Sahrens * zc_objset_type type of objset 21865367Sahrens * 21875367Sahrens * outputs: none 21885367Sahrens */ 21892199Sahrens static int 21902199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 21912199Sahrens { 21922199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 21932199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 21942199Sahrens if (err) 21952199Sahrens return (err); 2196789Sahrens } 2197789Sahrens 2198789Sahrens return (dmu_objset_destroy(zc->zc_name)); 2199789Sahrens } 2200789Sahrens 22015367Sahrens /* 22025367Sahrens * inputs: 22035446Sahrens * zc_name name of dataset to rollback (to most recent snapshot) 22045367Sahrens * 22055367Sahrens * outputs: none 22065367Sahrens */ 2207789Sahrens static int 2208789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 2209789Sahrens { 22105446Sahrens objset_t *os; 22115446Sahrens int error; 22125446Sahrens zfsvfs_t *zfsvfs = NULL; 22135446Sahrens 22145446Sahrens /* 22155446Sahrens * Get the zfsvfs for the receiving objset. There 22165446Sahrens * won't be one if we're operating on a zvol, if the 22175446Sahrens * objset doesn't exist yet, or is not mounted. 22185446Sahrens */ 22195446Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 22205446Sahrens DS_MODE_STANDARD, &os); 22215446Sahrens if (error) 22225446Sahrens return (error); 22235446Sahrens 22245446Sahrens if (dmu_objset_type(os) == DMU_OST_ZFS) { 22255446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 22265446Sahrens zfsvfs = dmu_objset_get_user(os); 22275446Sahrens if (zfsvfs != NULL) 22285446Sahrens VFS_HOLD(zfsvfs->z_vfs); 22295446Sahrens mutex_exit(&os->os->os_user_ptr_lock); 22305446Sahrens } 22315446Sahrens 22325446Sahrens if (zfsvfs != NULL) { 22335446Sahrens char osname[MAXNAMELEN]; 22345446Sahrens int mode; 22355446Sahrens 22365446Sahrens VERIFY3U(0, ==, zfs_suspend_fs(zfsvfs, osname, &mode)); 22375446Sahrens ASSERT(strcmp(osname, zc->zc_name) == 0); 22385446Sahrens error = dmu_objset_rollback(os); 22395446Sahrens VERIFY3U(0, ==, zfs_resume_fs(zfsvfs, osname, mode)); 22405446Sahrens 22415446Sahrens VFS_RELE(zfsvfs->z_vfs); 22425446Sahrens } else { 22435446Sahrens error = dmu_objset_rollback(os); 22445446Sahrens } 22455446Sahrens /* Note, the dmu_objset_rollback() closes the objset for us. */ 22465446Sahrens 22475446Sahrens return (error); 2248789Sahrens } 2249789Sahrens 22505367Sahrens /* 22515367Sahrens * inputs: 22525367Sahrens * zc_name old name of dataset 22535367Sahrens * zc_value new name of dataset 22545367Sahrens * zc_cookie recursive flag (only valid for snapshots) 22555367Sahrens * 22565367Sahrens * outputs: none 22575367Sahrens */ 2258789Sahrens static int 2259789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 2260789Sahrens { 22614490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 22624007Smmusante 22632676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 22645326Sek110237 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 22655326Sek110237 strchr(zc->zc_value, '%')) 2266789Sahrens return (EINVAL); 2267789Sahrens 22684007Smmusante /* 22694007Smmusante * Unmount snapshot unless we're doing a recursive rename, 22704007Smmusante * in which case the dataset code figures out which snapshots 22714007Smmusante * to unmount. 22724007Smmusante */ 22734007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 2274789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 22752199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 22762199Sahrens if (err) 22772199Sahrens return (err); 2278789Sahrens } 2279789Sahrens 22804007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 2281789Sahrens } 2282789Sahrens 22835367Sahrens /* 22845367Sahrens * inputs: 22855367Sahrens * zc_name name of containing filesystem 22865367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 22875367Sahrens * zc_value name of snapshot to create 22885367Sahrens * zc_string name of clone origin (if DRR_FLAG_CLONE) 22895367Sahrens * zc_cookie file descriptor to recv from 22905367Sahrens * zc_begin_record the BEGIN record of the stream (not byteswapped) 22915367Sahrens * zc_guid force flag 22925367Sahrens * 22935367Sahrens * outputs: 22945367Sahrens * zc_cookie number of bytes read 22955367Sahrens */ 2296789Sahrens static int 22975367Sahrens zfs_ioc_recv(zfs_cmd_t *zc) 2298789Sahrens { 2299789Sahrens file_t *fp; 23005326Sek110237 objset_t *os; 23015367Sahrens dmu_recv_cookie_t drc; 23025326Sek110237 zfsvfs_t *zfsvfs = NULL; 23035326Sek110237 boolean_t force = (boolean_t)zc->zc_guid; 2304789Sahrens int error, fd; 23055367Sahrens offset_t off; 23065367Sahrens nvlist_t *props = NULL; 23075367Sahrens objset_t *origin = NULL; 23085367Sahrens char *tosnap; 23095367Sahrens char tofs[ZFS_MAXNAMELEN]; 2310789Sahrens 23113265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 23125326Sek110237 strchr(zc->zc_value, '@') == NULL || 23135326Sek110237 strchr(zc->zc_value, '%')) 23143265Sahrens return (EINVAL); 23153265Sahrens 23165367Sahrens (void) strcpy(tofs, zc->zc_value); 23175367Sahrens tosnap = strchr(tofs, '@'); 23185367Sahrens *tosnap = '\0'; 23195367Sahrens tosnap++; 23205367Sahrens 23215367Sahrens if (zc->zc_nvlist_src != NULL && 23225367Sahrens (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 23235367Sahrens &props)) != 0) 23245367Sahrens return (error); 23255367Sahrens 2326789Sahrens fd = zc->zc_cookie; 2327789Sahrens fp = getf(fd); 23285367Sahrens if (fp == NULL) { 23295367Sahrens nvlist_free(props); 2330789Sahrens return (EBADF); 23315367Sahrens } 23325326Sek110237 23335326Sek110237 /* 23345326Sek110237 * Get the zfsvfs for the receiving objset. There 23355326Sek110237 * won't be one if we're operating on a zvol, if the 23365326Sek110237 * objset doesn't exist yet, or is not mounted. 23375326Sek110237 */ 23385367Sahrens 23395446Sahrens error = dmu_objset_open(tofs, DMU_OST_ZFS, 23405326Sek110237 DS_MODE_STANDARD | DS_MODE_READONLY, &os); 23415326Sek110237 if (!error) { 23425446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 23435446Sahrens zfsvfs = dmu_objset_get_user(os); 23445446Sahrens if (zfsvfs != NULL) 23455446Sahrens VFS_HOLD(zfsvfs->z_vfs); 23465446Sahrens mutex_exit(&os->os->os_user_ptr_lock); 23475326Sek110237 dmu_objset_close(os); 23485326Sek110237 } 23495326Sek110237 23505367Sahrens if (zc->zc_string[0]) { 23515367Sahrens error = dmu_objset_open(zc->zc_string, DMU_OST_ANY, 23525367Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &origin); 23535367Sahrens if (error) { 23545367Sahrens if (zfsvfs != NULL) 23555367Sahrens VFS_RELE(zfsvfs->z_vfs); 23565367Sahrens nvlist_free(props); 23575367Sahrens releasef(fd); 23585367Sahrens return (error); 23595367Sahrens } 23605367Sahrens } 23615367Sahrens 23625367Sahrens error = dmu_recv_begin(tofs, tosnap, &zc->zc_begin_record, 23635367Sahrens force, origin, zfsvfs != NULL, &drc); 23645367Sahrens if (origin) 23655367Sahrens dmu_objset_close(origin); 23665367Sahrens if (error) { 23675367Sahrens if (zfsvfs != NULL) 23685367Sahrens VFS_RELE(zfsvfs->z_vfs); 23695367Sahrens nvlist_free(props); 23705367Sahrens releasef(fd); 23715367Sahrens return (error); 23725367Sahrens } 23735326Sek110237 23745326Sek110237 /* 23755367Sahrens * If properties are supplied, they are to completely replace 23765367Sahrens * the existing ones; "inherit" any existing properties. 23775326Sek110237 */ 23785367Sahrens if (props) { 23795367Sahrens objset_t *os; 23805367Sahrens nvlist_t *nv = NULL; 23815367Sahrens 23825367Sahrens error = dmu_objset_open(tofs, DMU_OST_ANY, 23835367Sahrens DS_MODE_STANDARD | DS_MODE_READONLY | DS_MODE_INCONSISTENT, 23845367Sahrens &os); 23855367Sahrens if (error == 0) { 23865367Sahrens error = dsl_prop_get_all(os, &nv); 23875367Sahrens dmu_objset_close(os); 23885367Sahrens } 23895367Sahrens if (error == 0) { 23905367Sahrens nvpair_t *elem; 23915446Sahrens zfs_cmd_t *zc2; 23925446Sahrens zc2 = kmem_alloc(sizeof (zfs_cmd_t), KM_SLEEP); 23935446Sahrens 23945446Sahrens (void) strcpy(zc2->zc_name, tofs); 23955367Sahrens for (elem = nvlist_next_nvpair(nv, NULL); elem; 23965367Sahrens elem = nvlist_next_nvpair(nv, elem)) { 23975446Sahrens (void) strcpy(zc2->zc_value, nvpair_name(elem)); 23985446Sahrens if (zfs_secpolicy_inherit(zc2, CRED()) == 0) 23995446Sahrens (void) zfs_ioc_inherit_prop(zc2); 24005326Sek110237 } 24015446Sahrens kmem_free(zc2, sizeof (zfs_cmd_t)); 24025326Sek110237 } 24035367Sahrens if (nv) 24045367Sahrens nvlist_free(nv); 24055367Sahrens } 24065367Sahrens 24075367Sahrens /* 24085367Sahrens * Set properties. Note, we ignore errors. Would be better to 24095367Sahrens * do best-effort in zfs_set_prop_nvlist, too. 24105367Sahrens */ 24115367Sahrens (void) zfs_set_prop_nvlist(tofs, props); 24125367Sahrens nvlist_free(props); 24135367Sahrens 24145367Sahrens off = fp->f_offset; 24155367Sahrens error = dmu_recv_stream(&drc, fp->f_vnode, &off); 24165367Sahrens 24175367Sahrens if (error == 0) { 24185367Sahrens if (zfsvfs != NULL) { 24195367Sahrens char osname[MAXNAMELEN]; 24205367Sahrens int mode; 24215367Sahrens 24225367Sahrens (void) zfs_suspend_fs(zfsvfs, osname, &mode); 24235367Sahrens error = dmu_recv_end(&drc); 24245367Sahrens error |= zfs_resume_fs(zfsvfs, osname, mode); 24255367Sahrens } else { 24265367Sahrens error = dmu_recv_end(&drc); 24275367Sahrens } 24285326Sek110237 } 24295326Sek110237 if (zfsvfs != NULL) 24305326Sek110237 VFS_RELE(zfsvfs->z_vfs); 24315367Sahrens 24325367Sahrens zc->zc_cookie = off - fp->f_offset; 24335367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 24345367Sahrens fp->f_offset = off; 24352885Sahrens 2436789Sahrens releasef(fd); 2437789Sahrens return (error); 2438789Sahrens } 2439789Sahrens 24405367Sahrens /* 24415367Sahrens * inputs: 24425367Sahrens * zc_name name of snapshot to send 24435367Sahrens * zc_value short name of incremental fromsnap (may be empty) 24445367Sahrens * zc_cookie file descriptor to send stream to 24455367Sahrens * zc_obj fromorigin flag (mutually exclusive with zc_value) 24465367Sahrens * 24475367Sahrens * outputs: none 24485367Sahrens */ 2449789Sahrens static int 24505367Sahrens zfs_ioc_send(zfs_cmd_t *zc) 2451789Sahrens { 2452789Sahrens objset_t *fromsnap = NULL; 2453789Sahrens objset_t *tosnap; 2454789Sahrens file_t *fp; 2455789Sahrens int error; 24565367Sahrens offset_t off; 2457789Sahrens 2458789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 2459789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); 2460789Sahrens if (error) 2461789Sahrens return (error); 2462789Sahrens 24632676Seschrock if (zc->zc_value[0] != '\0') { 24642885Sahrens char buf[MAXPATHLEN]; 24652885Sahrens char *cp; 24662885Sahrens 24672885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 24682885Sahrens cp = strchr(buf, '@'); 24692885Sahrens if (cp) 24702885Sahrens *(cp+1) = 0; 24712885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 24722885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 2473789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); 2474789Sahrens if (error) { 2475789Sahrens dmu_objset_close(tosnap); 2476789Sahrens return (error); 2477789Sahrens } 2478789Sahrens } 2479789Sahrens 2480789Sahrens fp = getf(zc->zc_cookie); 2481789Sahrens if (fp == NULL) { 2482789Sahrens dmu_objset_close(tosnap); 2483789Sahrens if (fromsnap) 2484789Sahrens dmu_objset_close(fromsnap); 2485789Sahrens return (EBADF); 2486789Sahrens } 2487789Sahrens 24885367Sahrens off = fp->f_offset; 24895367Sahrens error = dmu_sendbackup(tosnap, fromsnap, zc->zc_obj, fp->f_vnode, &off); 24905367Sahrens 24915367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 24925367Sahrens fp->f_offset = off; 2493789Sahrens releasef(zc->zc_cookie); 2494789Sahrens if (fromsnap) 2495789Sahrens dmu_objset_close(fromsnap); 2496789Sahrens dmu_objset_close(tosnap); 2497789Sahrens return (error); 2498789Sahrens } 2499789Sahrens 25001544Seschrock static int 25011544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 25021544Seschrock { 25031544Seschrock int id, error; 25041544Seschrock 25051544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 25061544Seschrock &zc->zc_inject_record); 25071544Seschrock 25081544Seschrock if (error == 0) 25091544Seschrock zc->zc_guid = (uint64_t)id; 25101544Seschrock 25111544Seschrock return (error); 25121544Seschrock } 25131544Seschrock 25141544Seschrock static int 25151544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 25161544Seschrock { 25171544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 25181544Seschrock } 25191544Seschrock 25201544Seschrock static int 25211544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 25221544Seschrock { 25231544Seschrock int id = (int)zc->zc_guid; 25241544Seschrock int error; 25251544Seschrock 25261544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 25271544Seschrock &zc->zc_inject_record); 25281544Seschrock 25291544Seschrock zc->zc_guid = id; 25301544Seschrock 25311544Seschrock return (error); 25321544Seschrock } 25331544Seschrock 25341544Seschrock static int 25351544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 25361544Seschrock { 25371544Seschrock spa_t *spa; 25381544Seschrock int error; 25392676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 25401544Seschrock 25411544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 25421544Seschrock return (error); 25431544Seschrock 25442676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 25451544Seschrock &count); 25461544Seschrock if (error == 0) 25472676Seschrock zc->zc_nvlist_dst_size = count; 25481544Seschrock else 25492676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 25501544Seschrock 25511544Seschrock spa_close(spa, FTAG); 25521544Seschrock 25531544Seschrock return (error); 25541544Seschrock } 25551544Seschrock 25561544Seschrock static int 25571544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 25581544Seschrock { 25591544Seschrock spa_t *spa; 25601544Seschrock vdev_t *vd; 25614808Sek110237 uint64_t txg; 25621544Seschrock int error; 25631544Seschrock 25641544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 25651544Seschrock return (error); 25661544Seschrock 25675329Sgw25295 /* 25685329Sgw25295 * Try to resume any I/Os which may have been suspended 25695329Sgw25295 * as a result of a complete pool failure. 25705329Sgw25295 */ 25715329Sgw25295 if (!list_is_empty(&spa->spa_zio_list)) { 25725329Sgw25295 if (zio_vdev_resume_io(spa) != 0) { 25735329Sgw25295 spa_close(spa, FTAG); 25745329Sgw25295 return (EIO); 25755329Sgw25295 } 25765329Sgw25295 } 25775329Sgw25295 25784451Seschrock txg = spa_vdev_enter(spa); 25791544Seschrock 25802676Seschrock if (zc->zc_guid == 0) { 25811544Seschrock vd = NULL; 25822676Seschrock } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { 2583*5450Sbrendan spa_aux_vdev_t *sav; 2584*5450Sbrendan int i; 2585*5450Sbrendan 2586*5450Sbrendan /* 2587*5450Sbrendan * Check if this is an l2cache device. 2588*5450Sbrendan */ 2589*5450Sbrendan ASSERT(spa != NULL); 2590*5450Sbrendan sav = &spa->spa_l2cache; 2591*5450Sbrendan for (i = 0; i < sav->sav_count; i++) { 2592*5450Sbrendan if (sav->sav_vdevs[i]->vdev_guid == zc->zc_guid) { 2593*5450Sbrendan vd = sav->sav_vdevs[i]; 2594*5450Sbrendan break; 2595*5450Sbrendan } 2596*5450Sbrendan } 2597*5450Sbrendan 2598*5450Sbrendan if (vd == NULL) { 2599*5450Sbrendan (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 2600*5450Sbrendan spa_close(spa, FTAG); 2601*5450Sbrendan return (ENODEV); 2602*5450Sbrendan } 26031544Seschrock } 26041544Seschrock 26055329Sgw25295 vdev_clear(spa, vd, B_TRUE); 26061544Seschrock 26074451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 26081544Seschrock 26091544Seschrock spa_close(spa, FTAG); 26101544Seschrock 26111544Seschrock return (0); 26121544Seschrock } 26131544Seschrock 26145367Sahrens /* 26155367Sahrens * inputs: 26165367Sahrens * zc_name name of filesystem 26175367Sahrens * zc_value name of origin snapshot 26185367Sahrens * 26195367Sahrens * outputs: none 26205367Sahrens */ 26211544Seschrock static int 26222082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 26232082Seschrock { 26242417Sahrens char *cp; 26252417Sahrens 26262417Sahrens /* 26272417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 26282417Sahrens * it's easier. 26292417Sahrens */ 26302676Seschrock cp = strchr(zc->zc_value, '@'); 26312417Sahrens if (cp) 26322417Sahrens *cp = '\0'; 26332676Seschrock (void) dmu_objset_find(zc->zc_value, 26342417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 26352082Seschrock return (dsl_dataset_promote(zc->zc_name)); 26362082Seschrock } 26372082Seschrock 26384543Smarks /* 26394543Smarks * We don't want to have a hard dependency 26404543Smarks * against some special symbols in sharefs 26415331Samw * nfs, and smbsrv. Determine them if needed when 26424543Smarks * the first file system is shared. 26435331Samw * Neither sharefs, nfs or smbsrv are unloadable modules. 26444543Smarks */ 26455331Samw int (*znfsexport_fs)(void *arg); 26464543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 26475331Samw int (*zsmbexport_fs)(void *arg, boolean_t add_share); 26485331Samw 26495331Samw int zfs_nfsshare_inited; 26505331Samw int zfs_smbshare_inited; 26515331Samw 26524543Smarks ddi_modhandle_t nfs_mod; 26534543Smarks ddi_modhandle_t sharefs_mod; 26545331Samw ddi_modhandle_t smbsrv_mod; 26554543Smarks kmutex_t zfs_share_lock; 26564543Smarks 26574543Smarks static int 26585331Samw zfs_init_sharefs() 26595331Samw { 26605331Samw int error; 26615331Samw 26625331Samw ASSERT(MUTEX_HELD(&zfs_share_lock)); 26635331Samw /* Both NFS and SMB shares also require sharetab support. */ 26645331Samw if (sharefs_mod == NULL && ((sharefs_mod = 26655331Samw ddi_modopen("fs/sharefs", 26665331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26675331Samw return (ENOSYS); 26685331Samw } 26695331Samw if (zshare_fs == NULL && ((zshare_fs = 26705331Samw (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 26715331Samw ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 26725331Samw return (ENOSYS); 26735331Samw } 26745331Samw return (0); 26755331Samw } 26765331Samw 26775331Samw static int 26784543Smarks zfs_ioc_share(zfs_cmd_t *zc) 26794543Smarks { 26804543Smarks int error; 26814543Smarks int opcode; 26824543Smarks 26835331Samw switch (zc->zc_share.z_sharetype) { 26845331Samw case ZFS_SHARE_NFS: 26855331Samw case ZFS_UNSHARE_NFS: 26865331Samw if (zfs_nfsshare_inited == 0) { 26875331Samw mutex_enter(&zfs_share_lock); 26885331Samw if (nfs_mod == NULL && ((nfs_mod = ddi_modopen("fs/nfs", 26895331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26905331Samw mutex_exit(&zfs_share_lock); 26915331Samw return (ENOSYS); 26925331Samw } 26935331Samw if (znfsexport_fs == NULL && 26945331Samw ((znfsexport_fs = (int (*)(void *)) 26955331Samw ddi_modsym(nfs_mod, 26965331Samw "nfs_export", &error)) == NULL)) { 26975331Samw mutex_exit(&zfs_share_lock); 26985331Samw return (ENOSYS); 26995331Samw } 27005331Samw error = zfs_init_sharefs(); 27015331Samw if (error) { 27025331Samw mutex_exit(&zfs_share_lock); 27035331Samw return (ENOSYS); 27045331Samw } 27055331Samw zfs_nfsshare_inited = 1; 27064543Smarks mutex_exit(&zfs_share_lock); 27074543Smarks } 27085331Samw break; 27095331Samw case ZFS_SHARE_SMB: 27105331Samw case ZFS_UNSHARE_SMB: 27115331Samw if (zfs_smbshare_inited == 0) { 27125331Samw mutex_enter(&zfs_share_lock); 27135331Samw if (smbsrv_mod == NULL && ((smbsrv_mod = 27145331Samw ddi_modopen("drv/smbsrv", 27155331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 27165331Samw mutex_exit(&zfs_share_lock); 27175331Samw return (ENOSYS); 27185331Samw } 27195331Samw if (zsmbexport_fs == NULL && ((zsmbexport_fs = 27205331Samw (int (*)(void *, boolean_t))ddi_modsym(smbsrv_mod, 27215331Samw "lmshrd_share_upcall", &error)) == NULL)) { 27225331Samw mutex_exit(&zfs_share_lock); 27235331Samw return (ENOSYS); 27245331Samw } 27255331Samw error = zfs_init_sharefs(); 27265331Samw if (error) { 27275331Samw mutex_exit(&zfs_share_lock); 27285331Samw return (ENOSYS); 27295331Samw } 27305331Samw zfs_smbshare_inited = 1; 27314543Smarks mutex_exit(&zfs_share_lock); 27324543Smarks } 27335331Samw break; 27345331Samw default: 27355331Samw return (EINVAL); 27364543Smarks } 27374543Smarks 27385331Samw switch (zc->zc_share.z_sharetype) { 27395331Samw case ZFS_SHARE_NFS: 27405331Samw case ZFS_UNSHARE_NFS: 27415331Samw if (error = 27425331Samw znfsexport_fs((void *) 27435331Samw (uintptr_t)zc->zc_share.z_exportdata)) 27445331Samw return (error); 27455331Samw break; 27465331Samw case ZFS_SHARE_SMB: 27475331Samw case ZFS_UNSHARE_SMB: 27485331Samw if (error = zsmbexport_fs((void *) 27495331Samw (uintptr_t)zc->zc_share.z_exportdata, 27505331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB ? 27515331Samw B_TRUE : B_FALSE)) { 27525331Samw return (error); 27535331Samw } 27545331Samw break; 27555331Samw } 27565331Samw 27575331Samw opcode = (zc->zc_share.z_sharetype == ZFS_SHARE_NFS || 27585331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB) ? 27594543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 27604543Smarks 27615331Samw /* 27625331Samw * Add or remove share from sharetab 27635331Samw */ 27644543Smarks error = zshare_fs(opcode, 27654543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 27664543Smarks zc->zc_share.z_sharemax); 27674543Smarks 27684543Smarks return (error); 27694543Smarks 27704543Smarks } 27714543Smarks 27724543Smarks /* 27734988Sek110237 * pool create, destroy, and export don't log the history as part of 27744988Sek110237 * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export 27754988Sek110237 * do the logging of those commands. 27764543Smarks */ 2777789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 27784715Sek110237 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27794577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27804577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27814577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27824577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 27834577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 27844577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27854577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27864577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27874577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27884577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27894577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27904577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27914577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27924577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27934577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27944577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27954577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27965147Srm160521 { zfs_ioc_objset_version, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27974543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 27984577Sahrens DATASET_NAME, B_FALSE }, 27994543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 28004577Sahrens DATASET_NAME, B_FALSE }, 28014577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 28024577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 28034577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 28044577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 28054577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 28064577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 28074577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 28085367Sahrens { zfs_ioc_recv, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 28095367Sahrens { zfs_ioc_send, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 28104577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 28114577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 28124577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 28134577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 28144577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 28154577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 28164577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 28174577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 28184577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 28194577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 28204577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 28214577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 28224577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 28234577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 28244543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 28254577Sahrens DATASET_NAME, B_FALSE }, 28264849Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }, 28274849Sahrens { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE }, 2828789Sahrens }; 2829789Sahrens 2830789Sahrens static int 2831789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2832789Sahrens { 2833789Sahrens zfs_cmd_t *zc; 2834789Sahrens uint_t vec; 28352199Sahrens int error, rc; 2836789Sahrens 2837789Sahrens if (getminor(dev) != 0) 2838789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2839789Sahrens 2840789Sahrens vec = cmd - ZFS_IOC; 28414787Sahrens ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); 2842789Sahrens 2843789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2844789Sahrens return (EINVAL); 2845789Sahrens 2846789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2847789Sahrens 2848789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2849789Sahrens 28504787Sahrens if (error == 0) 28514543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2852789Sahrens 2853789Sahrens /* 2854789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2855789Sahrens * the lower layers. 2856789Sahrens */ 2857789Sahrens if (error == 0) { 2858789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2859789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 28604577Sahrens case POOL_NAME: 2861789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2862789Sahrens error = EINVAL; 2863789Sahrens break; 2864789Sahrens 28654577Sahrens case DATASET_NAME: 2866789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2867789Sahrens error = EINVAL; 2868789Sahrens break; 28692856Snd150628 28704577Sahrens case NO_NAME: 28712856Snd150628 break; 2872789Sahrens } 2873789Sahrens } 2874789Sahrens 2875789Sahrens if (error == 0) 2876789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2877789Sahrens 28782199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 28794543Smarks if (error == 0) { 28802199Sahrens error = rc; 28814543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 28824543Smarks zfs_log_history(zc); 28834543Smarks } 2884789Sahrens 2885789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2886789Sahrens return (error); 2887789Sahrens } 2888789Sahrens 2889789Sahrens static int 2890789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2891789Sahrens { 2892789Sahrens if (cmd != DDI_ATTACH) 2893789Sahrens return (DDI_FAILURE); 2894789Sahrens 2895789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2896789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2897789Sahrens return (DDI_FAILURE); 2898789Sahrens 2899789Sahrens zfs_dip = dip; 2900789Sahrens 2901789Sahrens ddi_report_dev(dip); 2902789Sahrens 2903789Sahrens return (DDI_SUCCESS); 2904789Sahrens } 2905789Sahrens 2906789Sahrens static int 2907789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2908789Sahrens { 2909789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2910789Sahrens return (DDI_FAILURE); 2911789Sahrens 2912789Sahrens if (cmd != DDI_DETACH) 2913789Sahrens return (DDI_FAILURE); 2914789Sahrens 2915789Sahrens zfs_dip = NULL; 2916789Sahrens 2917789Sahrens ddi_prop_remove_all(dip); 2918789Sahrens ddi_remove_minor_node(dip, NULL); 2919789Sahrens 2920789Sahrens return (DDI_SUCCESS); 2921789Sahrens } 2922789Sahrens 2923789Sahrens /*ARGSUSED*/ 2924789Sahrens static int 2925789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2926789Sahrens { 2927789Sahrens switch (infocmd) { 2928789Sahrens case DDI_INFO_DEVT2DEVINFO: 2929789Sahrens *result = zfs_dip; 2930789Sahrens return (DDI_SUCCESS); 2931789Sahrens 2932789Sahrens case DDI_INFO_DEVT2INSTANCE: 2933849Sbonwick *result = (void *)0; 2934789Sahrens return (DDI_SUCCESS); 2935789Sahrens } 2936789Sahrens 2937789Sahrens return (DDI_FAILURE); 2938789Sahrens } 2939789Sahrens 2940789Sahrens /* 2941789Sahrens * OK, so this is a little weird. 2942789Sahrens * 2943789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2944789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2945789Sahrens * 2946789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2947789Sahrens * so most of the standard driver entry points are in zvol.c. 2948789Sahrens */ 2949789Sahrens static struct cb_ops zfs_cb_ops = { 2950789Sahrens zvol_open, /* open */ 2951789Sahrens zvol_close, /* close */ 2952789Sahrens zvol_strategy, /* strategy */ 2953789Sahrens nodev, /* print */ 2954789Sahrens nodev, /* dump */ 2955789Sahrens zvol_read, /* read */ 2956789Sahrens zvol_write, /* write */ 2957789Sahrens zfsdev_ioctl, /* ioctl */ 2958789Sahrens nodev, /* devmap */ 2959789Sahrens nodev, /* mmap */ 2960789Sahrens nodev, /* segmap */ 2961789Sahrens nochpoll, /* poll */ 2962789Sahrens ddi_prop_op, /* prop_op */ 2963789Sahrens NULL, /* streamtab */ 2964789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2965789Sahrens CB_REV, /* version */ 29663638Sbillm nodev, /* async read */ 29673638Sbillm nodev, /* async write */ 2968789Sahrens }; 2969789Sahrens 2970789Sahrens static struct dev_ops zfs_dev_ops = { 2971789Sahrens DEVO_REV, /* version */ 2972789Sahrens 0, /* refcnt */ 2973789Sahrens zfs_info, /* info */ 2974789Sahrens nulldev, /* identify */ 2975789Sahrens nulldev, /* probe */ 2976789Sahrens zfs_attach, /* attach */ 2977789Sahrens zfs_detach, /* detach */ 2978789Sahrens nodev, /* reset */ 2979789Sahrens &zfs_cb_ops, /* driver operations */ 2980789Sahrens NULL /* no bus operations */ 2981789Sahrens }; 2982789Sahrens 2983789Sahrens static struct modldrv zfs_modldrv = { 29844577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 29852676Seschrock &zfs_dev_ops 2986789Sahrens }; 2987789Sahrens 2988789Sahrens static struct modlinkage modlinkage = { 2989789Sahrens MODREV_1, 2990789Sahrens (void *)&zfs_modlfs, 2991789Sahrens (void *)&zfs_modldrv, 2992789Sahrens NULL 2993789Sahrens }; 2994789Sahrens 29954720Sfr157268 29964720Sfr157268 uint_t zfs_fsyncer_key; 29975326Sek110237 extern uint_t rrw_tsd_key; 29984720Sfr157268 2999789Sahrens int 3000789Sahrens _init(void) 3001789Sahrens { 3002789Sahrens int error; 3003789Sahrens 3004849Sbonwick spa_init(FREAD | FWRITE); 3005849Sbonwick zfs_init(); 3006849Sbonwick zvol_init(); 3007849Sbonwick 3008849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 3009849Sbonwick zvol_fini(); 3010849Sbonwick zfs_fini(); 3011849Sbonwick spa_fini(); 3012789Sahrens return (error); 3013849Sbonwick } 3014789Sahrens 30154720Sfr157268 tsd_create(&zfs_fsyncer_key, NULL); 30165326Sek110237 tsd_create(&rrw_tsd_key, NULL); 30174720Sfr157268 3018789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 3019789Sahrens ASSERT(error == 0); 30204543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 3021789Sahrens 3022789Sahrens return (0); 3023789Sahrens } 3024789Sahrens 3025789Sahrens int 3026789Sahrens _fini(void) 3027789Sahrens { 3028789Sahrens int error; 3029789Sahrens 30301544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 3031789Sahrens return (EBUSY); 3032789Sahrens 3033789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 3034789Sahrens return (error); 3035789Sahrens 3036789Sahrens zvol_fini(); 3037789Sahrens zfs_fini(); 3038789Sahrens spa_fini(); 30395331Samw if (zfs_nfsshare_inited) 30404543Smarks (void) ddi_modclose(nfs_mod); 30415331Samw if (zfs_smbshare_inited) 30425331Samw (void) ddi_modclose(smbsrv_mod); 30435331Samw if (zfs_nfsshare_inited || zfs_smbshare_inited) 30444543Smarks (void) ddi_modclose(sharefs_mod); 3045789Sahrens 30464720Sfr157268 tsd_destroy(&zfs_fsyncer_key); 3047789Sahrens ldi_ident_release(zfs_li); 3048789Sahrens zfs_li = NULL; 30494543Smarks mutex_destroy(&zfs_share_lock); 3050789Sahrens 3051789Sahrens return (error); 3052789Sahrens } 3053789Sahrens 3054789Sahrens int 3055789Sahrens _info(struct modinfo *modinfop) 3056789Sahrens { 3057789Sahrens return (mod_info(&modlinkage, modinfop)); 3058789Sahrens } 3059