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_znode.h> 42789Sahrens #include <sys/zap.h> 43789Sahrens #include <sys/spa.h> 443912Slling #include <sys/spa_impl.h> 45789Sahrens #include <sys/vdev.h> 463912Slling #include <sys/vdev_impl.h> 47789Sahrens #include <sys/dmu.h> 48789Sahrens #include <sys/dsl_dir.h> 49789Sahrens #include <sys/dsl_dataset.h> 50789Sahrens #include <sys/dsl_prop.h> 514543Smarks #include <sys/dsl_deleg.h> 524543Smarks #include <sys/dmu_objset.h> 53789Sahrens #include <sys/ddi.h> 54789Sahrens #include <sys/sunddi.h> 55789Sahrens #include <sys/sunldi.h> 56789Sahrens #include <sys/policy.h> 57789Sahrens #include <sys/zone.h> 58789Sahrens #include <sys/nvpair.h> 59789Sahrens #include <sys/pathname.h> 60789Sahrens #include <sys/mount.h> 61789Sahrens #include <sys/sdt.h> 62789Sahrens #include <sys/fs/zfs.h> 63789Sahrens #include <sys/zfs_ctldir.h> 645331Samw #include <sys/zfs_dir.h> 652885Sahrens #include <sys/zvol.h> 664543Smarks #include <sharefs/share.h> 675326Sek110237 #include <sys/dmu_objset.h> 68789Sahrens 69789Sahrens #include "zfs_namecheck.h" 702676Seschrock #include "zfs_prop.h" 714543Smarks #include "zfs_deleg.h" 72789Sahrens 73789Sahrens extern struct modlfs zfs_modlfs; 74789Sahrens 75789Sahrens extern void zfs_init(void); 76789Sahrens extern void zfs_fini(void); 77789Sahrens 78789Sahrens ldi_ident_t zfs_li = NULL; 79789Sahrens dev_info_t *zfs_dip; 80789Sahrens 81789Sahrens typedef int zfs_ioc_func_t(zfs_cmd_t *); 824543Smarks typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *); 83789Sahrens 84789Sahrens typedef struct zfs_ioc_vec { 85789Sahrens zfs_ioc_func_t *zvec_func; 86789Sahrens zfs_secpolicy_func_t *zvec_secpolicy; 87789Sahrens enum { 884577Sahrens NO_NAME, 894577Sahrens POOL_NAME, 904577Sahrens DATASET_NAME 914543Smarks } zvec_namecheck; 924543Smarks boolean_t zvec_his_log; 93789Sahrens } zfs_ioc_vec_t; 94789Sahrens 95789Sahrens /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */ 96789Sahrens void 97789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 98789Sahrens { 99789Sahrens const char *newfile; 100789Sahrens char buf[256]; 101789Sahrens va_list adx; 102789Sahrens 103789Sahrens /* 104789Sahrens * Get rid of annoying "../common/" prefix to filename. 105789Sahrens */ 106789Sahrens newfile = strrchr(file, '/'); 107789Sahrens if (newfile != NULL) { 108789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 109789Sahrens } else { 110789Sahrens newfile = file; 111789Sahrens } 112789Sahrens 113789Sahrens va_start(adx, fmt); 114789Sahrens (void) vsnprintf(buf, sizeof (buf), fmt, adx); 115789Sahrens va_end(adx); 116789Sahrens 117789Sahrens /* 118789Sahrens * To get this data, use the zfs-dprintf probe as so: 119789Sahrens * dtrace -q -n 'zfs-dprintf \ 120789Sahrens * /stringof(arg0) == "dbuf.c"/ \ 121789Sahrens * {printf("%s: %s", stringof(arg1), stringof(arg3))}' 122789Sahrens * arg0 = file name 123789Sahrens * arg1 = function name 124789Sahrens * arg2 = line number 125789Sahrens * arg3 = message 126789Sahrens */ 127789Sahrens DTRACE_PROBE4(zfs__dprintf, 128789Sahrens char *, newfile, char *, func, int, line, char *, buf); 129789Sahrens } 130789Sahrens 1314543Smarks static void 1324715Sek110237 history_str_free(char *buf) 1334715Sek110237 { 1344715Sek110237 kmem_free(buf, HIS_MAX_RECORD_LEN); 1354715Sek110237 } 1364715Sek110237 1374715Sek110237 static char * 1384715Sek110237 history_str_get(zfs_cmd_t *zc) 1394715Sek110237 { 1404715Sek110237 char *buf; 1414715Sek110237 1424715Sek110237 if (zc->zc_history == NULL) 1434715Sek110237 return (NULL); 1444715Sek110237 1454715Sek110237 buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP); 1464715Sek110237 if (copyinstr((void *)(uintptr_t)zc->zc_history, 1474715Sek110237 buf, HIS_MAX_RECORD_LEN, NULL) != 0) { 1484715Sek110237 history_str_free(buf); 1494715Sek110237 return (NULL); 1504715Sek110237 } 1514715Sek110237 1524715Sek110237 buf[HIS_MAX_RECORD_LEN -1] = '\0'; 1534715Sek110237 1544715Sek110237 return (buf); 1554715Sek110237 } 1564715Sek110237 1575375Stimh /* 1585375Stimh * zfs_check_version 1595375Stimh * 1605375Stimh * Return non-zero if the spa version is less than requested version. 1615375Stimh */ 1625331Samw static int 1635331Samw zfs_check_version(const char *name, int version) 1645331Samw { 1655331Samw 1665331Samw spa_t *spa; 1675331Samw 1685331Samw if (spa_open(name, &spa, FTAG) == 0) { 1695331Samw if (spa_version(spa) < version) { 1705331Samw spa_close(spa, FTAG); 1715331Samw return (1); 1725331Samw } 1735331Samw spa_close(spa, FTAG); 1745331Samw } 1755331Samw return (0); 1765331Samw } 1775331Samw 1784715Sek110237 static void 1794543Smarks zfs_log_history(zfs_cmd_t *zc) 1804543Smarks { 1814543Smarks spa_t *spa; 1824603Sahrens char *buf; 1834543Smarks 1844715Sek110237 if ((buf = history_str_get(zc)) == NULL) 1854577Sahrens return; 1864577Sahrens 1874715Sek110237 if (spa_open(zc->zc_name, &spa, FTAG) == 0) { 1884715Sek110237 if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY) 1894715Sek110237 (void) spa_history_log(spa, buf, LOG_CMD_NORMAL); 1904715Sek110237 spa_close(spa, FTAG); 1914543Smarks } 1924715Sek110237 history_str_free(buf); 1934543Smarks } 1944543Smarks 195789Sahrens /* 196789Sahrens * Policy for top-level read operations (list pools). Requires no privileges, 197789Sahrens * and can be used in the local zone, as there is no associated dataset. 198789Sahrens */ 199789Sahrens /* ARGSUSED */ 200789Sahrens static int 2014543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) 202789Sahrens { 203789Sahrens return (0); 204789Sahrens } 205789Sahrens 206789Sahrens /* 207789Sahrens * Policy for dataset read operations (list children, get statistics). Requires 208789Sahrens * no privileges, but must be visible in the local zone. 209789Sahrens */ 210789Sahrens /* ARGSUSED */ 211789Sahrens static int 2124543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) 213789Sahrens { 214789Sahrens if (INGLOBALZONE(curproc) || 2154543Smarks zone_dataset_visible(zc->zc_name, NULL)) 216789Sahrens return (0); 217789Sahrens 218789Sahrens return (ENOENT); 219789Sahrens } 220789Sahrens 221789Sahrens static int 222789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr) 223789Sahrens { 224789Sahrens uint64_t zoned; 225789Sahrens int writable = 1; 226789Sahrens 227789Sahrens /* 228789Sahrens * The dataset must be visible by this zone -- check this first 229789Sahrens * so they don't see EPERM on something they shouldn't know about. 230789Sahrens */ 231789Sahrens if (!INGLOBALZONE(curproc) && 232789Sahrens !zone_dataset_visible(dataset, &writable)) 233789Sahrens return (ENOENT); 234789Sahrens 235789Sahrens if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) 236789Sahrens return (ENOENT); 237789Sahrens 238789Sahrens if (INGLOBALZONE(curproc)) { 239789Sahrens /* 240789Sahrens * If the fs is zoned, only root can access it from the 241789Sahrens * global zone. 242789Sahrens */ 243789Sahrens if (secpolicy_zfs(cr) && zoned) 244789Sahrens return (EPERM); 245789Sahrens } else { 246789Sahrens /* 247789Sahrens * If we are in a local zone, the 'zoned' property must be set. 248789Sahrens */ 249789Sahrens if (!zoned) 250789Sahrens return (EPERM); 251789Sahrens 252789Sahrens /* must be writable by this zone */ 253789Sahrens if (!writable) 254789Sahrens return (EPERM); 255789Sahrens } 256789Sahrens return (0); 257789Sahrens } 258789Sahrens 259789Sahrens int 2604543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) 261789Sahrens { 262789Sahrens int error; 263789Sahrens 2644543Smarks error = zfs_dozonecheck(name, cr); 2654543Smarks if (error == 0) { 2664543Smarks error = secpolicy_zfs(cr); 2674670Sahrens if (error) 2684543Smarks error = dsl_deleg_access(name, perm, cr); 2694543Smarks } 2704543Smarks return (error); 2714543Smarks } 2724543Smarks 2734543Smarks static int 2744543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) 2754543Smarks { 2764543Smarks /* 2774543Smarks * Check permissions for special properties. 2784543Smarks */ 2794543Smarks switch (prop) { 2804543Smarks case ZFS_PROP_ZONED: 2814543Smarks /* 2824543Smarks * Disallow setting of 'zoned' from within a local zone. 2834543Smarks */ 2844543Smarks if (!INGLOBALZONE(curproc)) 2854543Smarks return (EPERM); 2864543Smarks break; 287789Sahrens 2884543Smarks case ZFS_PROP_QUOTA: 2894543Smarks if (!INGLOBALZONE(curproc)) { 2904543Smarks uint64_t zoned; 2914543Smarks char setpoint[MAXNAMELEN]; 2924543Smarks /* 2934543Smarks * Unprivileged users are allowed to modify the 2944543Smarks * quota on things *under* (ie. contained by) 2954543Smarks * the thing they own. 2964543Smarks */ 2974543Smarks if (dsl_prop_get_integer(name, "zoned", &zoned, 2984543Smarks setpoint)) 2994543Smarks return (EPERM); 3004670Sahrens if (!zoned || strlen(name) <= strlen(setpoint)) 3014543Smarks return (EPERM); 3024543Smarks } 3034670Sahrens break; 3044543Smarks } 3054543Smarks 3064787Sahrens return (zfs_secpolicy_write_perms(name, zfs_prop_to_name(prop), cr)); 307789Sahrens } 308789Sahrens 3094543Smarks int 3104543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) 3114543Smarks { 3124543Smarks int error; 3134543Smarks 3144543Smarks error = zfs_dozonecheck(zc->zc_name, cr); 3154543Smarks if (error) 3164543Smarks return (error); 3174543Smarks 3184543Smarks /* 3194543Smarks * permission to set permissions will be evaluated later in 3204543Smarks * dsl_deleg_can_allow() 3214543Smarks */ 3224543Smarks return (0); 3234543Smarks } 3244543Smarks 3254543Smarks int 3264543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) 3274543Smarks { 3284543Smarks int error; 3294543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3304543Smarks ZFS_DELEG_PERM_ROLLBACK, cr); 3314543Smarks if (error == 0) 3324543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3334543Smarks ZFS_DELEG_PERM_MOUNT, cr); 3344543Smarks return (error); 3354543Smarks } 3364543Smarks 3374543Smarks int 3384543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) 3394543Smarks { 3404543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 3414543Smarks ZFS_DELEG_PERM_SEND, cr)); 3424543Smarks } 3434543Smarks 3444543Smarks int 3454543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) 3464543Smarks { 3474543Smarks if (!INGLOBALZONE(curproc)) 3484543Smarks return (EPERM); 3494543Smarks 3505367Sahrens if (secpolicy_nfs(cr) == 0) { 3514543Smarks return (0); 3524543Smarks } else { 3534543Smarks vnode_t *vp; 3544543Smarks int error; 3554543Smarks 3564543Smarks if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, 3574543Smarks NO_FOLLOW, NULL, &vp)) != 0) 3584543Smarks return (error); 3594543Smarks 3604543Smarks /* Now make sure mntpnt and dataset are ZFS */ 3614543Smarks 3624543Smarks if (vp->v_vfsp->vfs_fstype != zfsfstype || 3634543Smarks (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), 3644543Smarks zc->zc_name) != 0)) { 3654543Smarks VN_RELE(vp); 3664543Smarks return (EPERM); 3674543Smarks } 3684543Smarks 3694543Smarks VN_RELE(vp); 3704543Smarks return (dsl_deleg_access(zc->zc_name, 3714543Smarks ZFS_DELEG_PERM_SHARE, cr)); 3724543Smarks } 3734543Smarks } 3744543Smarks 375789Sahrens static int 3764543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize) 377789Sahrens { 378789Sahrens char *cp; 379789Sahrens 380789Sahrens /* 381789Sahrens * Remove the @bla or /bla from the end of the name to get the parent. 382789Sahrens */ 3834543Smarks (void) strncpy(parent, datasetname, parentsize); 3844543Smarks cp = strrchr(parent, '@'); 385789Sahrens if (cp != NULL) { 386789Sahrens cp[0] = '\0'; 387789Sahrens } else { 3884543Smarks cp = strrchr(parent, '/'); 389789Sahrens if (cp == NULL) 390789Sahrens return (ENOENT); 391789Sahrens cp[0] = '\0'; 392789Sahrens } 393789Sahrens 3944543Smarks return (0); 3954543Smarks } 3964543Smarks 3974543Smarks int 3984543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 3994543Smarks { 4004543Smarks int error; 4014543Smarks 4024543Smarks if ((error = zfs_secpolicy_write_perms(name, 4034543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4044543Smarks return (error); 4054543Smarks 4064543Smarks return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); 4074543Smarks } 4084543Smarks 4094543Smarks static int 4104543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) 4114543Smarks { 4124543Smarks return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); 4134543Smarks } 4144543Smarks 4154543Smarks /* 4164543Smarks * Must have sys_config privilege to check the iscsi permission 4174543Smarks */ 4184543Smarks /* ARGSUSED */ 4194543Smarks static int 4204543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) 4214543Smarks { 4224543Smarks return (secpolicy_zfs(cr)); 4234543Smarks } 4244543Smarks 4254543Smarks int 4264543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 4274543Smarks { 4284543Smarks char parentname[MAXNAMELEN]; 4294543Smarks int error; 4304543Smarks 4314543Smarks if ((error = zfs_secpolicy_write_perms(from, 4324543Smarks ZFS_DELEG_PERM_RENAME, cr)) != 0) 4334543Smarks return (error); 4344543Smarks 4354543Smarks if ((error = zfs_secpolicy_write_perms(from, 4364543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4374543Smarks return (error); 4384543Smarks 4394543Smarks if ((error = zfs_get_parent(to, parentname, 4404543Smarks sizeof (parentname))) != 0) 4414543Smarks return (error); 4424543Smarks 4434543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4444543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 4454543Smarks return (error); 4464543Smarks 4474543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4484543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4494543Smarks return (error); 4504543Smarks 4514543Smarks return (error); 4524543Smarks } 4534543Smarks 4544543Smarks static int 4554543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) 4564543Smarks { 4574543Smarks return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); 4584543Smarks } 4594543Smarks 4604543Smarks static int 4614543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) 4624543Smarks { 4634543Smarks char parentname[MAXNAMELEN]; 4644543Smarks objset_t *clone; 4654543Smarks int error; 4664543Smarks 4674543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4684543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4694543Smarks if (error) 4704543Smarks return (error); 4714543Smarks 4724543Smarks error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 4734543Smarks DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 4744543Smarks 4754543Smarks if (error == 0) { 4764543Smarks dsl_dataset_t *pclone = NULL; 4774543Smarks dsl_dir_t *dd; 4784543Smarks dd = clone->os->os_dsl_dataset->ds_dir; 4794543Smarks 4804543Smarks rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 4814543Smarks error = dsl_dataset_open_obj(dd->dd_pool, 4825367Sahrens dd->dd_phys->dd_origin_obj, NULL, 4834543Smarks DS_MODE_NONE, FTAG, &pclone); 4844543Smarks rw_exit(&dd->dd_pool->dp_config_rwlock); 4854543Smarks if (error) { 4864543Smarks dmu_objset_close(clone); 4874543Smarks return (error); 4884543Smarks } 4894543Smarks 4904543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4914543Smarks ZFS_DELEG_PERM_MOUNT, cr); 4924543Smarks 4934543Smarks dsl_dataset_name(pclone, parentname); 4944543Smarks dmu_objset_close(clone); 4954543Smarks dsl_dataset_close(pclone, DS_MODE_NONE, FTAG); 4964543Smarks if (error == 0) 4974543Smarks error = zfs_secpolicy_write_perms(parentname, 4984543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4994543Smarks } 5004543Smarks return (error); 5014543Smarks } 5024543Smarks 5034543Smarks static int 5044543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) 5054543Smarks { 5064543Smarks int error; 5074543Smarks 5084543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5094543Smarks ZFS_DELEG_PERM_RECEIVE, cr)) != 0) 5104543Smarks return (error); 5114543Smarks 5124543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5134543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 5144543Smarks return (error); 5154543Smarks 5164543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 5174543Smarks ZFS_DELEG_PERM_CREATE, cr)); 5184543Smarks } 5194543Smarks 5204543Smarks int 5214543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 5224543Smarks { 5234543Smarks int error; 5244543Smarks 5254543Smarks if ((error = zfs_secpolicy_write_perms(name, 5264543Smarks ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) 5274543Smarks return (error); 5284543Smarks 5294543Smarks error = zfs_secpolicy_write_perms(name, 5304543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5314543Smarks 5324543Smarks return (error); 5334543Smarks } 5344543Smarks 5354543Smarks static int 5364543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) 5374543Smarks { 5384543Smarks 5394543Smarks return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); 5404543Smarks } 5414543Smarks 5424543Smarks static int 5434543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) 5444543Smarks { 5454543Smarks char parentname[MAXNAMELEN]; 5464543Smarks int error; 5474543Smarks 5484543Smarks if ((error = zfs_get_parent(zc->zc_name, parentname, 5494543Smarks sizeof (parentname))) != 0) 5504543Smarks return (error); 5514543Smarks 5524543Smarks if (zc->zc_value[0] != '\0') { 5534543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_value, 5544543Smarks ZFS_DELEG_PERM_CLONE, cr)) != 0) 5554543Smarks return (error); 5564543Smarks } 5574543Smarks 5584543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 5594543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 5604543Smarks return (error); 5614543Smarks 5624543Smarks error = zfs_secpolicy_write_perms(parentname, 5634543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5644543Smarks 5654543Smarks return (error); 5664543Smarks } 5674543Smarks 5684543Smarks static int 5694543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) 5704543Smarks { 5714543Smarks int error; 5724543Smarks 5734543Smarks error = secpolicy_fs_unmount(cr, NULL); 5744543Smarks if (error) { 5754543Smarks error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); 5764543Smarks } 5774543Smarks return (error); 578789Sahrens } 579789Sahrens 580789Sahrens /* 581789Sahrens * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires 582789Sahrens * SYS_CONFIG privilege, which is not available in a local zone. 583789Sahrens */ 584789Sahrens /* ARGSUSED */ 585789Sahrens static int 5864543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) 587789Sahrens { 588789Sahrens if (secpolicy_sys_config(cr, B_FALSE) != 0) 589789Sahrens return (EPERM); 590789Sahrens 591789Sahrens return (0); 592789Sahrens } 593789Sahrens 594789Sahrens /* 5954543Smarks * Just like zfs_secpolicy_config, except that we will check for 5964543Smarks * mount permission on the dataset for permission to create/remove 5974543Smarks * the minor nodes. 5984543Smarks */ 5994543Smarks static int 6004543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) 6014543Smarks { 6024543Smarks if (secpolicy_sys_config(cr, B_FALSE) != 0) { 6034543Smarks return (dsl_deleg_access(zc->zc_name, 6044543Smarks ZFS_DELEG_PERM_MOUNT, cr)); 6054543Smarks } 6064543Smarks 6074543Smarks return (0); 6084543Smarks } 6094543Smarks 6104543Smarks /* 6111544Seschrock * Policy for fault injection. Requires all privileges. 6121544Seschrock */ 6131544Seschrock /* ARGSUSED */ 6141544Seschrock static int 6154543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) 6161544Seschrock { 6171544Seschrock return (secpolicy_zinject(cr)); 6181544Seschrock } 6191544Seschrock 6204849Sahrens static int 6214849Sahrens zfs_secpolicy_inherit(zfs_cmd_t *zc, cred_t *cr) 6224849Sahrens { 6234849Sahrens zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); 6244849Sahrens 6255094Slling if (prop == ZPROP_INVAL) { 6264849Sahrens if (!zfs_prop_user(zc->zc_value)) 6274849Sahrens return (EINVAL); 6284849Sahrens return (zfs_secpolicy_write_perms(zc->zc_name, 6294849Sahrens ZFS_DELEG_PERM_USERPROP, cr)); 6304849Sahrens } else { 6314849Sahrens if (!zfs_prop_inheritable(prop)) 6324849Sahrens return (EINVAL); 6334849Sahrens return (zfs_secpolicy_setprop(zc->zc_name, prop, cr)); 6344849Sahrens } 6354849Sahrens } 6364849Sahrens 6371544Seschrock /* 638789Sahrens * Returns the nvlist as specified by the user in the zfs_cmd_t. 639789Sahrens */ 640789Sahrens static int 6415094Slling get_nvlist(uint64_t nvl, uint64_t size, nvlist_t **nvp) 642789Sahrens { 643789Sahrens char *packed; 644789Sahrens int error; 6455094Slling nvlist_t *list = NULL; 646789Sahrens 647789Sahrens /* 6482676Seschrock * Read in and unpack the user-supplied nvlist. 649789Sahrens */ 6505094Slling if (size == 0) 651789Sahrens return (EINVAL); 652789Sahrens 653789Sahrens packed = kmem_alloc(size, KM_SLEEP); 654789Sahrens 6555094Slling if ((error = xcopyin((void *)(uintptr_t)nvl, packed, size)) != 0) { 656789Sahrens kmem_free(packed, size); 657789Sahrens return (error); 658789Sahrens } 659789Sahrens 6605094Slling if ((error = nvlist_unpack(packed, size, &list, 0)) != 0) { 661789Sahrens kmem_free(packed, size); 662789Sahrens return (error); 663789Sahrens } 664789Sahrens 665789Sahrens kmem_free(packed, size); 666789Sahrens 6675094Slling *nvp = list; 668789Sahrens return (0); 669789Sahrens } 670789Sahrens 671789Sahrens static int 6722676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 6732676Seschrock { 6742676Seschrock char *packed = NULL; 6752676Seschrock size_t size; 6762676Seschrock int error; 6772676Seschrock 6782676Seschrock VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 6792676Seschrock 6802676Seschrock if (size > zc->zc_nvlist_dst_size) { 6812676Seschrock error = ENOMEM; 6822676Seschrock } else { 6834611Smarks packed = kmem_alloc(size, KM_SLEEP); 6842676Seschrock VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 6852676Seschrock KM_SLEEP) == 0); 6862676Seschrock error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 6872676Seschrock size); 6882676Seschrock kmem_free(packed, size); 6892676Seschrock } 6902676Seschrock 6912676Seschrock zc->zc_nvlist_dst_size = size; 6922676Seschrock return (error); 6932676Seschrock } 6942676Seschrock 6952676Seschrock static int 696789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc) 697789Sahrens { 698789Sahrens int error; 6995094Slling nvlist_t *config, *props = NULL; 7004715Sek110237 char *buf; 701789Sahrens 7025094Slling if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7035094Slling &config)) 7044988Sek110237 return (error); 7054715Sek110237 7065094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7075094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7085094Slling nvlist_free(config); 7095094Slling return (error); 7105094Slling } 7115094Slling 7124988Sek110237 buf = history_str_get(zc); 713789Sahrens 7145094Slling error = spa_create(zc->zc_name, config, props, buf); 715789Sahrens 7164988Sek110237 if (buf != NULL) 7174988Sek110237 history_str_free(buf); 7185094Slling 719789Sahrens nvlist_free(config); 720789Sahrens 7215094Slling if (props) 7225094Slling nvlist_free(props); 7235094Slling 724789Sahrens return (error); 725789Sahrens } 726789Sahrens 727789Sahrens static int 728789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc) 729789Sahrens { 7304543Smarks int error; 7314543Smarks zfs_log_history(zc); 7324543Smarks error = spa_destroy(zc->zc_name); 7334543Smarks return (error); 734789Sahrens } 735789Sahrens 736789Sahrens static int 737789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc) 738789Sahrens { 739789Sahrens int error; 7405094Slling nvlist_t *config, *props = NULL; 741789Sahrens uint64_t guid; 742789Sahrens 7435094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7445094Slling &config)) != 0) 745789Sahrens return (error); 746789Sahrens 7475094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7485094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7495094Slling nvlist_free(config); 7505094Slling return (error); 7515094Slling } 7525094Slling 753789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 7541544Seschrock guid != zc->zc_guid) 755789Sahrens error = EINVAL; 756789Sahrens else 7575094Slling error = spa_import(zc->zc_name, config, props); 758789Sahrens 759789Sahrens nvlist_free(config); 760789Sahrens 7615094Slling if (props) 7625094Slling nvlist_free(props); 7635094Slling 764789Sahrens return (error); 765789Sahrens } 766789Sahrens 767789Sahrens static int 768789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc) 769789Sahrens { 7704543Smarks int error; 7714543Smarks zfs_log_history(zc); 7724543Smarks error = spa_export(zc->zc_name, NULL); 7734543Smarks return (error); 774789Sahrens } 775789Sahrens 776789Sahrens static int 777789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc) 778789Sahrens { 779789Sahrens nvlist_t *configs; 780789Sahrens int error; 781789Sahrens 782789Sahrens if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 783789Sahrens return (EEXIST); 784789Sahrens 7852676Seschrock error = put_nvlist(zc, configs); 786789Sahrens 787789Sahrens nvlist_free(configs); 788789Sahrens 789789Sahrens return (error); 790789Sahrens } 791789Sahrens 792789Sahrens static int 793789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc) 794789Sahrens { 795789Sahrens nvlist_t *config; 796789Sahrens int error; 7971544Seschrock int ret = 0; 798789Sahrens 7992676Seschrock error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 8002676Seschrock sizeof (zc->zc_value)); 801789Sahrens 802789Sahrens if (config != NULL) { 8032676Seschrock ret = put_nvlist(zc, config); 804789Sahrens nvlist_free(config); 8051544Seschrock 8061544Seschrock /* 8071544Seschrock * The config may be present even if 'error' is non-zero. 8081544Seschrock * In this case we return success, and preserve the real errno 8091544Seschrock * in 'zc_cookie'. 8101544Seschrock */ 8111544Seschrock zc->zc_cookie = error; 812789Sahrens } else { 8131544Seschrock ret = error; 814789Sahrens } 815789Sahrens 8161544Seschrock return (ret); 817789Sahrens } 818789Sahrens 819789Sahrens /* 820789Sahrens * Try to import the given pool, returning pool stats as appropriate so that 821789Sahrens * user land knows which devices are available and overall pool health. 822789Sahrens */ 823789Sahrens static int 824789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 825789Sahrens { 826789Sahrens nvlist_t *tryconfig, *config; 827789Sahrens int error; 828789Sahrens 8295094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 8305094Slling &tryconfig)) != 0) 831789Sahrens return (error); 832789Sahrens 833789Sahrens config = spa_tryimport(tryconfig); 834789Sahrens 835789Sahrens nvlist_free(tryconfig); 836789Sahrens 837789Sahrens if (config == NULL) 838789Sahrens return (EINVAL); 839789Sahrens 8402676Seschrock error = put_nvlist(zc, config); 841789Sahrens nvlist_free(config); 842789Sahrens 843789Sahrens return (error); 844789Sahrens } 845789Sahrens 846789Sahrens static int 847789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc) 848789Sahrens { 849789Sahrens spa_t *spa; 850789Sahrens int error; 851789Sahrens 8522926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8532926Sek110237 return (error); 8542926Sek110237 8554808Sek110237 mutex_enter(&spa_namespace_lock); 8562926Sek110237 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); 8574808Sek110237 mutex_exit(&spa_namespace_lock); 8582926Sek110237 8592926Sek110237 spa_close(spa, FTAG); 8602926Sek110237 861789Sahrens return (error); 862789Sahrens } 863789Sahrens 864789Sahrens static int 865789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 866789Sahrens { 867789Sahrens spa_t *spa; 868789Sahrens int error; 869789Sahrens 870789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 871789Sahrens if (error == 0) { 872789Sahrens spa_freeze(spa); 873789Sahrens spa_close(spa, FTAG); 874789Sahrens } 875789Sahrens return (error); 876789Sahrens } 877789Sahrens 878789Sahrens static int 8791760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 8801760Seschrock { 8811760Seschrock spa_t *spa; 8821760Seschrock int error; 8831760Seschrock 8842926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8852926Sek110237 return (error); 8862926Sek110237 8875118Slling if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) { 8885118Slling spa_close(spa, FTAG); 8895118Slling return (EINVAL); 8905118Slling } 8915118Slling 8925094Slling spa_upgrade(spa, zc->zc_cookie); 8932926Sek110237 spa_close(spa, FTAG); 8942926Sek110237 8952926Sek110237 return (error); 8962926Sek110237 } 8972926Sek110237 8982926Sek110237 static int 8992926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 9002926Sek110237 { 9012926Sek110237 spa_t *spa; 9022926Sek110237 char *hist_buf; 9032926Sek110237 uint64_t size; 9042926Sek110237 int error; 9052926Sek110237 9062926Sek110237 if ((size = zc->zc_history_len) == 0) 9072926Sek110237 return (EINVAL); 9082926Sek110237 9092926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9102926Sek110237 return (error); 9112926Sek110237 9124577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 9133863Sek110237 spa_close(spa, FTAG); 9143863Sek110237 return (ENOTSUP); 9153863Sek110237 } 9163863Sek110237 9172926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 9182926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 9192926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 9204543Smarks error = xcopyout(hist_buf, 9214543Smarks (char *)(uintptr_t)zc->zc_history, 9222926Sek110237 zc->zc_history_len); 9232926Sek110237 } 9242926Sek110237 9252926Sek110237 spa_close(spa, FTAG); 9262926Sek110237 kmem_free(hist_buf, size); 9272926Sek110237 return (error); 9282926Sek110237 } 9292926Sek110237 9302926Sek110237 static int 9313444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 9323444Sek110237 { 9333444Sek110237 int error; 9343444Sek110237 9353912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 9363444Sek110237 return (error); 9373444Sek110237 9383444Sek110237 return (0); 9393444Sek110237 } 9403444Sek110237 9413444Sek110237 static int 9423444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 9433444Sek110237 { 9443444Sek110237 objset_t *osp; 9453444Sek110237 int error; 9463444Sek110237 9473444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 9483444Sek110237 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) 9493444Sek110237 return (error); 9503444Sek110237 9513444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 9523444Sek110237 sizeof (zc->zc_value)); 9533444Sek110237 dmu_objset_close(osp); 9543444Sek110237 9553444Sek110237 return (error); 9563444Sek110237 } 9573444Sek110237 9583444Sek110237 static int 959789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 960789Sahrens { 961789Sahrens spa_t *spa; 962789Sahrens int error; 9635450Sbrendan nvlist_t *config, **l2cache; 9645450Sbrendan uint_t nl2cache; 965789Sahrens 966789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 967789Sahrens if (error != 0) 968789Sahrens return (error); 969789Sahrens 9705450Sbrendan error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 9715450Sbrendan &config); 9725450Sbrendan (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_L2CACHE, 9735450Sbrendan &l2cache, &nl2cache); 9745450Sbrendan 9753912Slling /* 9763912Slling * A root pool with concatenated devices is not supported. 9773912Slling * Thus, can not add a device to a root pool with one device. 9785450Sbrendan * Allow for l2cache devices to be added. 9793912Slling */ 9805450Sbrendan if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0 && 9815450Sbrendan nl2cache == 0) { 9823912Slling spa_close(spa, FTAG); 9833912Slling return (EDOM); 9843912Slling } 9853912Slling 9865450Sbrendan if (error == 0) { 987789Sahrens error = spa_vdev_add(spa, config); 988789Sahrens nvlist_free(config); 989789Sahrens } 990789Sahrens spa_close(spa, FTAG); 991789Sahrens return (error); 992789Sahrens } 993789Sahrens 994789Sahrens static int 995789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 996789Sahrens { 9972082Seschrock spa_t *spa; 9982082Seschrock int error; 9992082Seschrock 10002082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10012082Seschrock if (error != 0) 10022082Seschrock return (error); 10032082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 10042082Seschrock spa_close(spa, FTAG); 10052082Seschrock return (error); 1006789Sahrens } 1007789Sahrens 1008789Sahrens static int 10094451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 1010789Sahrens { 1011789Sahrens spa_t *spa; 1012789Sahrens int error; 10134451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 1014789Sahrens 10152926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1016789Sahrens return (error); 10174451Seschrock switch (zc->zc_cookie) { 10184451Seschrock case VDEV_STATE_ONLINE: 10194451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 10204451Seschrock break; 10214451Seschrock 10224451Seschrock case VDEV_STATE_OFFLINE: 10234451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 10244451Seschrock break; 1025789Sahrens 10264451Seschrock case VDEV_STATE_FAULTED: 10274451Seschrock error = vdev_fault(spa, zc->zc_guid); 10284451Seschrock break; 1029789Sahrens 10304451Seschrock case VDEV_STATE_DEGRADED: 10314451Seschrock error = vdev_degrade(spa, zc->zc_guid); 10324451Seschrock break; 10334451Seschrock 10344451Seschrock default: 10354451Seschrock error = EINVAL; 10364451Seschrock } 10374451Seschrock zc->zc_cookie = newstate; 1038789Sahrens spa_close(spa, FTAG); 1039789Sahrens return (error); 1040789Sahrens } 1041789Sahrens 1042789Sahrens static int 1043789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 1044789Sahrens { 1045789Sahrens spa_t *spa; 1046789Sahrens int replacing = zc->zc_cookie; 1047789Sahrens nvlist_t *config; 1048789Sahrens int error; 1049789Sahrens 10502926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1051789Sahrens return (error); 1052789Sahrens 10535094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 10545094Slling &config)) == 0) { 10551544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 1056789Sahrens nvlist_free(config); 1057789Sahrens } 1058789Sahrens 1059789Sahrens spa_close(spa, FTAG); 1060789Sahrens return (error); 1061789Sahrens } 1062789Sahrens 1063789Sahrens static int 1064789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 1065789Sahrens { 1066789Sahrens spa_t *spa; 1067789Sahrens int error; 1068789Sahrens 10692926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1070789Sahrens return (error); 1071789Sahrens 10721544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1073789Sahrens 1074789Sahrens spa_close(spa, FTAG); 1075789Sahrens return (error); 1076789Sahrens } 1077789Sahrens 1078789Sahrens static int 10791354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 10801354Seschrock { 10811354Seschrock spa_t *spa; 10822676Seschrock char *path = zc->zc_value; 10831544Seschrock uint64_t guid = zc->zc_guid; 10841354Seschrock int error; 10851354Seschrock 10861354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10871354Seschrock if (error != 0) 10881354Seschrock return (error); 10891354Seschrock 10901354Seschrock error = spa_vdev_setpath(spa, guid, path); 10911354Seschrock spa_close(spa, FTAG); 10921354Seschrock return (error); 10931354Seschrock } 10941354Seschrock 1095*5498Stimh static int 1096*5498Stimh zfs_os_open_retry(char *name, objset_t **os) 1097*5498Stimh { 1098*5498Stimh int error; 1099*5498Stimh 1100*5498Stimh retry: 1101*5498Stimh error = dmu_objset_open(name, DMU_OST_ANY, 1102*5498Stimh DS_MODE_STANDARD | DS_MODE_READONLY, os); 1103*5498Stimh if (error != 0) { 1104*5498Stimh /* 1105*5498Stimh * This is ugly: dmu_objset_open() can return EBUSY if 1106*5498Stimh * the objset is held exclusively. Fortunately this hold is 1107*5498Stimh * only for a short while, so we retry here. 1108*5498Stimh * This avoids user code having to handle EBUSY, 1109*5498Stimh * for example for a "zfs list". 1110*5498Stimh */ 1111*5498Stimh if (error == EBUSY) { 1112*5498Stimh delay(1); 1113*5498Stimh goto retry; 1114*5498Stimh } 1115*5498Stimh } 1116*5498Stimh return (error); 1117*5498Stimh } 1118*5498Stimh 11195367Sahrens /* 11205367Sahrens * inputs: 11215367Sahrens * zc_name name of filesystem 11225367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 11235367Sahrens * 11245367Sahrens * outputs: 11255367Sahrens * zc_objset_stats stats 11265367Sahrens * zc_nvlist_dst property nvlist 11275367Sahrens * zc_nvlist_dst_size size of property nvlist 11285367Sahrens * zc_value alternate root 11295367Sahrens */ 11301354Seschrock static int 1131789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1132789Sahrens { 1133789Sahrens objset_t *os = NULL; 1134789Sahrens int error; 11351356Seschrock nvlist_t *nv; 1136789Sahrens 1137*5498Stimh if ((error = zfs_os_open_retry(zc->zc_name, &os)) != 0) 1138789Sahrens return (error); 1139789Sahrens 11402885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1141789Sahrens 11422856Snd150628 if (zc->zc_nvlist_dst != 0 && 11431356Seschrock (error = dsl_prop_get_all(os, &nv)) == 0) { 11442885Sahrens dmu_objset_stats(os, nv); 11453087Sahrens /* 11465147Srm160521 * NB: zvol_get_stats() will read the objset contents, 11473087Sahrens * which we aren't supposed to do with a 11483087Sahrens * DS_MODE_STANDARD open, because it could be 11493087Sahrens * inconsistent. So this is a bit of a workaround... 11503087Sahrens */ 11514577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 11524577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 11534577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 11544577Sahrens } 11552676Seschrock error = put_nvlist(zc, nv); 11561356Seschrock nvlist_free(nv); 11571356Seschrock } 1158789Sahrens 11592676Seschrock spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value)); 11601544Seschrock 1161789Sahrens dmu_objset_close(os); 1162789Sahrens return (error); 1163789Sahrens } 1164789Sahrens 1165*5498Stimh static int 1166*5498Stimh nvl_add_zplprop(objset_t *os, nvlist_t *props, zfs_prop_t prop) 1167*5498Stimh { 1168*5498Stimh uint64_t value; 1169*5498Stimh int error; 1170*5498Stimh 1171*5498Stimh /* 1172*5498Stimh * zfs_get_zplprop() will either find a value or give us 1173*5498Stimh * the default value (if there is one). 1174*5498Stimh */ 1175*5498Stimh if ((error = zfs_get_zplprop(os, prop, &value)) != 0) 1176*5498Stimh return (error); 1177*5498Stimh VERIFY(nvlist_add_uint64(props, zfs_prop_to_name(prop), value) == 0); 1178*5498Stimh return (0); 1179*5498Stimh } 1180*5498Stimh 1181*5498Stimh /* 1182*5498Stimh * inputs: 1183*5498Stimh * zc_name name of filesystem 1184*5498Stimh * zc_nvlist_dst_size size of buffer for zpl property nvlist 1185*5498Stimh * 1186*5498Stimh * outputs: 1187*5498Stimh * zc_nvlist_dst zpl property nvlist 1188*5498Stimh * zc_nvlist_dst_size size of zpl property nvlist 1189*5498Stimh */ 1190*5498Stimh static int 1191*5498Stimh zfs_ioc_objset_zplprops(zfs_cmd_t *zc) 1192*5498Stimh { 1193*5498Stimh objset_t *os; 1194*5498Stimh int err; 1195*5498Stimh 1196*5498Stimh if ((err = zfs_os_open_retry(zc->zc_name, &os)) != 0) 1197*5498Stimh return (err); 1198*5498Stimh 1199*5498Stimh dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1200*5498Stimh 1201*5498Stimh /* 1202*5498Stimh * NB: nvl_add_zplprop() will read the objset contents, 1203*5498Stimh * which we aren't supposed to do with a DS_MODE_STANDARD 1204*5498Stimh * open, because it could be inconsistent. 1205*5498Stimh */ 1206*5498Stimh if (zc->zc_nvlist_dst != NULL && 1207*5498Stimh !zc->zc_objset_stats.dds_inconsistent && 1208*5498Stimh dmu_objset_type(os) == DMU_OST_ZFS) { 1209*5498Stimh nvlist_t *nv; 1210*5498Stimh 1211*5498Stimh VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) == 0); 1212*5498Stimh if ((err = nvl_add_zplprop(os, nv, ZFS_PROP_VERSION)) == 0 && 1213*5498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_NORMALIZE)) == 0 && 1214*5498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_UTF8ONLY)) == 0 && 1215*5498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_CASE)) == 0) 1216*5498Stimh err = put_nvlist(zc, nv); 1217*5498Stimh nvlist_free(nv); 1218*5498Stimh } else { 1219*5498Stimh err = ENOENT; 1220*5498Stimh } 1221*5498Stimh dmu_objset_close(os); 1222*5498Stimh return (err); 1223*5498Stimh } 1224*5498Stimh 12255367Sahrens /* 12265367Sahrens * inputs: 12275367Sahrens * zc_name name of filesystem 12285367Sahrens * zc_cookie zap cursor 12295367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 12305367Sahrens * 12315367Sahrens * outputs: 12325367Sahrens * zc_name name of next filesystem 12335367Sahrens * zc_objset_stats stats 12345367Sahrens * zc_nvlist_dst property nvlist 12355367Sahrens * zc_nvlist_dst_size size of property nvlist 12365367Sahrens * zc_value alternate root 12375367Sahrens */ 1238789Sahrens static int 1239789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1240789Sahrens { 1241885Sahrens objset_t *os; 1242789Sahrens int error; 1243789Sahrens char *p; 1244789Sahrens 1245*5498Stimh if ((error = zfs_os_open_retry(zc->zc_name, &os)) != 0) { 1246885Sahrens if (error == ENOENT) 1247885Sahrens error = ESRCH; 1248885Sahrens return (error); 1249789Sahrens } 1250789Sahrens 1251789Sahrens p = strrchr(zc->zc_name, '/'); 1252789Sahrens if (p == NULL || p[1] != '\0') 1253789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1254789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1255789Sahrens 1256789Sahrens do { 1257885Sahrens error = dmu_dir_list_next(os, 1258885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1259885Sahrens NULL, &zc->zc_cookie); 1260789Sahrens if (error == ENOENT) 1261789Sahrens error = ESRCH; 1262885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1263789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 1264789Sahrens 1265885Sahrens /* 1266885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1267885Sahrens * try to get stats for it. Userland will skip over it. 1268885Sahrens */ 1269885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1270885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1271789Sahrens 1272885Sahrens dmu_objset_close(os); 1273789Sahrens return (error); 1274789Sahrens } 1275789Sahrens 12765367Sahrens /* 12775367Sahrens * inputs: 12785367Sahrens * zc_name name of filesystem 12795367Sahrens * zc_cookie zap cursor 12805367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 12815367Sahrens * 12825367Sahrens * outputs: 12835367Sahrens * zc_name name of next snapshot 12845367Sahrens * zc_objset_stats stats 12855367Sahrens * zc_nvlist_dst property nvlist 12865367Sahrens * zc_nvlist_dst_size size of property nvlist 12875367Sahrens * zc_value alternate root 12885367Sahrens */ 1289789Sahrens static int 1290789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1291789Sahrens { 1292885Sahrens objset_t *os; 1293789Sahrens int error; 1294789Sahrens 1295*5498Stimh if ((error = zfs_os_open_retry(zc->zc_name, &os)) != 0) { 1296789Sahrens if (error == ENOENT) 1297885Sahrens error = ESRCH; 1298789Sahrens return (error); 1299789Sahrens } 1300789Sahrens 13011003Slling /* 13021003Slling * A dataset name of maximum length cannot have any snapshots, 13031003Slling * so exit immediately. 13041003Slling */ 13051003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1306885Sahrens dmu_objset_close(os); 13071003Slling return (ESRCH); 1308789Sahrens } 1309789Sahrens 1310885Sahrens error = dmu_snapshot_list_next(os, 1311885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 1312885Sahrens zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie); 1313789Sahrens if (error == ENOENT) 1314789Sahrens error = ESRCH; 1315789Sahrens 1316885Sahrens if (error == 0) 1317885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1318789Sahrens 13195367Sahrens /* if we failed, undo the @ that we tacked on to zc_name */ 13205367Sahrens if (error != 0) 13215367Sahrens *strchr(zc->zc_name, '@') = '\0'; 13225367Sahrens 1323885Sahrens dmu_objset_close(os); 1324789Sahrens return (error); 1325789Sahrens } 1326789Sahrens 1327789Sahrens static int 13284787Sahrens zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) 1329789Sahrens { 13302676Seschrock nvpair_t *elem; 13312676Seschrock int error; 13322676Seschrock uint64_t intval; 13332676Seschrock char *strval; 13342676Seschrock 13354543Smarks /* 13364543Smarks * First validate permission to set all of the properties 13374543Smarks */ 13382676Seschrock elem = NULL; 13392676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 13404670Sahrens const char *propname = nvpair_name(elem); 13414670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 13422676Seschrock 13435094Slling if (prop == ZPROP_INVAL) { 13442676Seschrock /* 13452676Seschrock * If this is a user-defined property, it must be a 13462676Seschrock * string, and there is no further validation to do. 13472676Seschrock */ 13482676Seschrock if (!zfs_prop_user(propname) || 13492676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 13502676Seschrock return (EINVAL); 13512676Seschrock 13525331Samw if (error = zfs_secpolicy_write_perms(name, 13535331Samw ZFS_DELEG_PERM_USERPROP, CRED())) 13544670Sahrens return (error); 13554543Smarks continue; 13562676Seschrock } 13572676Seschrock 13584787Sahrens if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 13594670Sahrens return (error); 13602676Seschrock 13614670Sahrens /* 13624670Sahrens * Check that this value is valid for this pool version 13634670Sahrens */ 13644670Sahrens switch (prop) { 13653886Sahl case ZFS_PROP_COMPRESSION: 13663886Sahl /* 13673886Sahl * If the user specified gzip compression, make sure 13683886Sahl * the SPA supports it. We ignore any errors here since 13693886Sahl * we'll catch them later. 13703886Sahl */ 13713886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 13723886Sahl nvpair_value_uint64(elem, &intval) == 0 && 13733886Sahl intval >= ZIO_COMPRESS_GZIP_1 && 13743886Sahl intval <= ZIO_COMPRESS_GZIP_9) { 13755331Samw if (zfs_check_version(name, 13765331Samw SPA_VERSION_GZIP_COMPRESSION)) 13775331Samw return (ENOTSUP); 13783886Sahl } 13793886Sahl break; 13804603Sahrens 13814603Sahrens case ZFS_PROP_COPIES: 13825331Samw if (zfs_check_version(name, SPA_VERSION_DITTO_BLOCKS)) 13835331Samw return (ENOTSUP); 13844603Sahrens break; 13854603Sahrens } 13865331Samw if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 13875331Samw return (error); 13884543Smarks } 13894543Smarks 13904543Smarks elem = NULL; 13914543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 13924670Sahrens const char *propname = nvpair_name(elem); 13934670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 13944543Smarks 13955094Slling if (prop == ZPROP_INVAL) { 13964543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 13974543Smarks error = dsl_prop_set(name, propname, 1, 13984543Smarks strlen(strval) + 1, strval); 13994543Smarks if (error == 0) 14004543Smarks continue; 14014543Smarks else 14024543Smarks return (error); 14034543Smarks } 14042676Seschrock 14052676Seschrock switch (prop) { 14062676Seschrock case ZFS_PROP_QUOTA: 14072676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14084577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 14092676Seschrock return (error); 14102676Seschrock break; 14112676Seschrock 14125378Sck153898 case ZFS_PROP_REFQUOTA: 14135378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14145378Sck153898 (error = dsl_dataset_set_quota(name, intval)) != 0) 14155378Sck153898 return (error); 14165378Sck153898 break; 14175378Sck153898 14182676Seschrock case ZFS_PROP_RESERVATION: 14192676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14202676Seschrock (error = dsl_dir_set_reservation(name, 14212676Seschrock intval)) != 0) 14222676Seschrock return (error); 14232676Seschrock break; 1424789Sahrens 14255378Sck153898 case ZFS_PROP_REFRESERVATION: 14265378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14275378Sck153898 (error = dsl_dataset_set_reservation(name, 14285378Sck153898 intval)) != 0) 14295378Sck153898 return (error); 14305378Sck153898 break; 14315378Sck153898 14322676Seschrock case ZFS_PROP_VOLSIZE: 14332676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14344787Sahrens (error = zvol_set_volsize(name, 14354787Sahrens ddi_driver_major(zfs_dip), intval)) != 0) 14362676Seschrock return (error); 14372676Seschrock break; 14382676Seschrock 14392676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 14402676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14414577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 14424577Sahrens return (error); 14434577Sahrens break; 14444577Sahrens 14454577Sahrens case ZFS_PROP_VERSION: 14464577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14474577Sahrens (error = zfs_set_version(name, intval)) != 0) 14482676Seschrock return (error); 14492676Seschrock break; 14502676Seschrock 14512676Seschrock default: 14522676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 14532676Seschrock if (zfs_prop_get_type(prop) != 14544787Sahrens PROP_TYPE_STRING) 14552676Seschrock return (EINVAL); 14562717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 14572717Seschrock if ((error = dsl_prop_set(name, 14582676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 14592717Seschrock strval)) != 0) 14602717Seschrock return (error); 14612676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 14622885Sahrens const char *unused; 14632885Sahrens 14642717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 14652676Seschrock 14662676Seschrock switch (zfs_prop_get_type(prop)) { 14674787Sahrens case PROP_TYPE_NUMBER: 14682676Seschrock break; 14694787Sahrens case PROP_TYPE_STRING: 14702717Seschrock return (EINVAL); 14714787Sahrens case PROP_TYPE_INDEX: 14722717Seschrock if (zfs_prop_index_to_string(prop, 14732717Seschrock intval, &unused) != 0) 14742717Seschrock return (EINVAL); 14752676Seschrock break; 14762676Seschrock default: 14774577Sahrens cmn_err(CE_PANIC, 14784577Sahrens "unknown property type"); 14792676Seschrock break; 14802676Seschrock } 14812676Seschrock 14822717Seschrock if ((error = dsl_prop_set(name, propname, 14832717Seschrock 8, 1, &intval)) != 0) 14842717Seschrock return (error); 14852676Seschrock } else { 14862676Seschrock return (EINVAL); 14872676Seschrock } 14882676Seschrock break; 14892676Seschrock } 14902676Seschrock } 14912676Seschrock 14922676Seschrock return (0); 1493789Sahrens } 1494789Sahrens 14955367Sahrens /* 14965367Sahrens * inputs: 14975367Sahrens * zc_name name of filesystem 14985367Sahrens * zc_value name of property to inherit 14995367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 15005367Sahrens * 15015367Sahrens * outputs: none 15025367Sahrens */ 1503789Sahrens static int 15042676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1505789Sahrens { 15062676Seschrock nvlist_t *nvl; 15072676Seschrock int error; 1508789Sahrens 15095094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15105094Slling &nvl)) != 0) 15112676Seschrock return (error); 15122676Seschrock 15134787Sahrens error = zfs_set_prop_nvlist(zc->zc_name, nvl); 15144543Smarks 15152676Seschrock nvlist_free(nvl); 15162676Seschrock return (error); 1517789Sahrens } 1518789Sahrens 15195367Sahrens /* 15205367Sahrens * inputs: 15215367Sahrens * zc_name name of filesystem 15225367Sahrens * zc_value name of property to inherit 15235367Sahrens * 15245367Sahrens * outputs: none 15255367Sahrens */ 1526789Sahrens static int 15274849Sahrens zfs_ioc_inherit_prop(zfs_cmd_t *zc) 15284849Sahrens { 15294849Sahrens /* the property name has been validated by zfs_secpolicy_inherit() */ 15304849Sahrens return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 15314849Sahrens } 15324849Sahrens 15334849Sahrens static int 15344098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 15353912Slling { 15365094Slling nvlist_t *props; 15373912Slling spa_t *spa; 15385094Slling int error; 15393912Slling 15405094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15415094Slling &props))) 15423912Slling return (error); 15433912Slling 15443912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 15455094Slling nvlist_free(props); 15463912Slling return (error); 15473912Slling } 15483912Slling 15495094Slling error = spa_prop_set(spa, props); 15503912Slling 15515094Slling nvlist_free(props); 15523912Slling spa_close(spa, FTAG); 15533912Slling 15543912Slling return (error); 15553912Slling } 15563912Slling 15573912Slling static int 15584098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 15593912Slling { 15603912Slling spa_t *spa; 15613912Slling int error; 15623912Slling nvlist_t *nvp = NULL; 15633912Slling 15643912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 15653912Slling return (error); 15663912Slling 15675094Slling error = spa_prop_get(spa, &nvp); 15683912Slling 15693912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 15703912Slling error = put_nvlist(zc, nvp); 15713912Slling else 15723912Slling error = EFAULT; 15733912Slling 15743912Slling spa_close(spa, FTAG); 15753912Slling 15763912Slling if (nvp) 15773912Slling nvlist_free(nvp); 15783912Slling return (error); 15793912Slling } 15803912Slling 15813912Slling static int 15824543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 15834543Smarks { 15844543Smarks nvlist_t *nvp; 15854543Smarks int error; 15864543Smarks uint32_t uid; 15874543Smarks uint32_t gid; 15884543Smarks uint32_t *groups; 15894543Smarks uint_t group_cnt; 15904543Smarks cred_t *usercred; 15914543Smarks 15925094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15935094Slling &nvp)) != 0) { 15944543Smarks return (error); 15954543Smarks } 15964543Smarks 15974543Smarks if ((error = nvlist_lookup_uint32(nvp, 15984543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 15994543Smarks nvlist_free(nvp); 16004543Smarks return (EPERM); 16014543Smarks } 16024543Smarks 16034543Smarks if ((error = nvlist_lookup_uint32(nvp, 16044543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 16054543Smarks nvlist_free(nvp); 16064543Smarks return (EPERM); 16074543Smarks } 16084543Smarks 16094543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 16104543Smarks &groups, &group_cnt)) != 0) { 16114543Smarks nvlist_free(nvp); 16124543Smarks return (EPERM); 16134543Smarks } 16144543Smarks usercred = cralloc(); 16154543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 16164543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 16174543Smarks nvlist_free(nvp); 16184543Smarks crfree(usercred); 16194543Smarks return (EPERM); 16204543Smarks } 16214543Smarks nvlist_free(nvp); 16224543Smarks error = dsl_deleg_access(zc->zc_name, 16234787Sahrens zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); 16244543Smarks crfree(usercred); 16254543Smarks return (error); 16264543Smarks } 16274543Smarks 16285367Sahrens /* 16295367Sahrens * inputs: 16305367Sahrens * zc_name name of filesystem 16315367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 16325367Sahrens * zc_perm_action allow/unallow flag 16335367Sahrens * 16345367Sahrens * outputs: none 16355367Sahrens */ 16364543Smarks static int 16374543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 16384543Smarks { 16394543Smarks int error; 16404543Smarks nvlist_t *fsaclnv = NULL; 16414543Smarks 16425094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16435094Slling &fsaclnv)) != 0) 16444543Smarks return (error); 16454543Smarks 16464543Smarks /* 16474543Smarks * Verify nvlist is constructed correctly 16484543Smarks */ 16494543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 16504543Smarks nvlist_free(fsaclnv); 16514543Smarks return (EINVAL); 16524543Smarks } 16534543Smarks 16544543Smarks /* 16554543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 16564543Smarks * that user is allowed to hand out each permission in 16574543Smarks * the nvlist(s) 16584543Smarks */ 16594543Smarks 16604787Sahrens error = secpolicy_zfs(CRED()); 16614543Smarks if (error) { 16624787Sahrens if (zc->zc_perm_action == B_FALSE) { 16634787Sahrens error = dsl_deleg_can_allow(zc->zc_name, 16644787Sahrens fsaclnv, CRED()); 16654787Sahrens } else { 16664787Sahrens error = dsl_deleg_can_unallow(zc->zc_name, 16674787Sahrens fsaclnv, CRED()); 16684787Sahrens } 16694543Smarks } 16704543Smarks 16714543Smarks if (error == 0) 16724543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 16734543Smarks 16744543Smarks nvlist_free(fsaclnv); 16754543Smarks return (error); 16764543Smarks } 16774543Smarks 16785367Sahrens /* 16795367Sahrens * inputs: 16805367Sahrens * zc_name name of filesystem 16815367Sahrens * 16825367Sahrens * outputs: 16835367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 16845367Sahrens */ 16854543Smarks static int 16864543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 16874543Smarks { 16884543Smarks nvlist_t *nvp; 16894543Smarks int error; 16904543Smarks 16914543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 16924543Smarks error = put_nvlist(zc, nvp); 16934543Smarks nvlist_free(nvp); 16944543Smarks } 16954543Smarks 16964543Smarks return (error); 16974543Smarks } 16984543Smarks 16995367Sahrens /* 17005367Sahrens * inputs: 17015367Sahrens * zc_name name of volume 17025367Sahrens * 17035367Sahrens * outputs: none 17045367Sahrens */ 17054543Smarks static int 1706789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1707789Sahrens { 17084787Sahrens return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); 1709789Sahrens } 1710789Sahrens 17115367Sahrens /* 17125367Sahrens * inputs: 17135367Sahrens * zc_name name of volume 17145367Sahrens * 17155367Sahrens * outputs: none 17165367Sahrens */ 1717789Sahrens static int 1718789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1719789Sahrens { 17202676Seschrock return (zvol_remove_minor(zc->zc_name)); 1721789Sahrens } 1722789Sahrens 1723789Sahrens /* 1724789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1725789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1726789Sahrens * is responsible for releasing the returned vfs pointer. 1727789Sahrens */ 1728789Sahrens static vfs_t * 1729789Sahrens zfs_get_vfs(const char *resource) 1730789Sahrens { 1731789Sahrens struct vfs *vfsp; 1732789Sahrens struct vfs *vfs_found = NULL; 1733789Sahrens 1734789Sahrens vfs_list_read_lock(); 1735789Sahrens vfsp = rootvfs; 1736789Sahrens do { 1737789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1738789Sahrens VFS_HOLD(vfsp); 1739789Sahrens vfs_found = vfsp; 1740789Sahrens break; 1741789Sahrens } 1742789Sahrens vfsp = vfsp->vfs_next; 1743789Sahrens } while (vfsp != rootvfs); 1744789Sahrens vfs_list_unlock(); 1745789Sahrens return (vfs_found); 1746789Sahrens } 1747789Sahrens 17484543Smarks /* ARGSUSED */ 1749789Sahrens static void 17504543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1751789Sahrens { 17525331Samw zfs_creat_t *zct = arg; 1753*5498Stimh 1754*5498Stimh zfs_create_fs(os, cr, zct->zct_zplprops, tx); 17555331Samw } 17565331Samw 1757*5498Stimh #define ZFS_PROP_UNDEFINED ((uint64_t)-1) 1758*5498Stimh 17595331Samw /* 1760*5498Stimh * inputs: 1761*5498Stimh * createprops list of properties requested by creator 1762*5498Stimh * dataset name of dataset we are creating 17635331Samw * 1764*5498Stimh * outputs: 1765*5498Stimh * zplprops values for the zplprops we attach to the master node object 17665331Samw * 1767*5498Stimh * Determine the settings for utf8only, normalization and 1768*5498Stimh * casesensitivity. Specific values may have been requested by the 1769*5498Stimh * creator and/or we can inherit values from the parent dataset. If 1770*5498Stimh * the file system is of too early a vintage, a creator can not 1771*5498Stimh * request settings for these properties, even if the requested 1772*5498Stimh * setting is the default value. We don't actually want to create dsl 1773*5498Stimh * properties for these, so remove them from the source nvlist after 1774*5498Stimh * processing. 17755331Samw */ 17765331Samw static int 1777*5498Stimh zfs_fill_zplprops(const char *dataset, nvlist_t *createprops, 1778*5498Stimh nvlist_t *zplprops, uint64_t zplver) 17795331Samw { 1780*5498Stimh objset_t *os; 17815331Samw char parentname[MAXNAMELEN]; 17825331Samw char *cp; 1783*5498Stimh uint64_t sense = ZFS_PROP_UNDEFINED; 1784*5498Stimh uint64_t norm = ZFS_PROP_UNDEFINED; 1785*5498Stimh uint64_t u8 = ZFS_PROP_UNDEFINED; 1786*5498Stimh int error = 0; 1787*5498Stimh 1788*5498Stimh ASSERT(zplprops != NULL); 1789*5498Stimh 1790*5498Stimh (void) strlcpy(parentname, dataset, sizeof (parentname)); 1791*5498Stimh cp = strrchr(parentname, '/'); 1792*5498Stimh ASSERT(cp != NULL); 1793*5498Stimh cp[0] = '\0'; 17945331Samw 17955375Stimh /* 1796*5498Stimh * Pull out creator prop choices, if any. 17975375Stimh */ 1798*5498Stimh if (createprops) { 1799*5498Stimh (void) nvlist_lookup_uint64(createprops, 1800*5498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE), &norm); 1801*5498Stimh (void) nvlist_remove_all(createprops, 1802*5498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE)); 1803*5498Stimh (void) nvlist_lookup_uint64(createprops, 1804*5498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY), &u8); 1805*5498Stimh (void) nvlist_remove_all(createprops, 1806*5498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY)); 1807*5498Stimh (void) nvlist_lookup_uint64(createprops, 1808*5498Stimh zfs_prop_to_name(ZFS_PROP_CASE), &sense); 1809*5498Stimh (void) nvlist_remove_all(createprops, 1810*5498Stimh zfs_prop_to_name(ZFS_PROP_CASE)); 18115331Samw } 18125331Samw 18135375Stimh /* 1814*5498Stimh * If the file system or pool is version is too "young" to 1815*5498Stimh * support normalization and the creator tried to set a value 1816*5498Stimh * for one of the props, error out. We only need check the 1817*5498Stimh * ZPL version because we've already checked by now that the 1818*5498Stimh * SPA version is compatible with the selected ZPL version. 1819*5498Stimh */ 1820*5498Stimh if (zplver < ZPL_VERSION_NORMALIZATION && 1821*5498Stimh (norm != ZFS_PROP_UNDEFINED || u8 != ZFS_PROP_UNDEFINED || 1822*5498Stimh sense != ZFS_PROP_UNDEFINED)) 1823*5498Stimh return (ENOTSUP); 1824*5498Stimh 1825*5498Stimh /* 1826*5498Stimh * Put the version in the zplprops 1827*5498Stimh */ 1828*5498Stimh VERIFY(nvlist_add_uint64(zplprops, 1829*5498Stimh zfs_prop_to_name(ZFS_PROP_VERSION), zplver) == 0); 1830*5498Stimh 1831*5498Stimh /* 1832*5498Stimh * Open parent object set so we can inherit zplprop values if 1833*5498Stimh * necessary. 18345375Stimh */ 1835*5498Stimh if ((error = zfs_os_open_retry(parentname, &os)) != 0) 1836*5498Stimh return (error); 1837*5498Stimh 1838*5498Stimh if (norm == ZFS_PROP_UNDEFINED) 1839*5498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &norm) == 0); 1840*5498Stimh VERIFY(nvlist_add_uint64(zplprops, 1841*5498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE), norm) == 0); 1842*5498Stimh 1843*5498Stimh /* 1844*5498Stimh * If we're normalizing, names must always be valid UTF-8 strings. 1845*5498Stimh */ 1846*5498Stimh if (norm) 1847*5498Stimh u8 = 1; 1848*5498Stimh if (u8 == ZFS_PROP_UNDEFINED) 1849*5498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &u8) == 0); 1850*5498Stimh VERIFY(nvlist_add_uint64(zplprops, 1851*5498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY), u8) == 0); 1852*5498Stimh 1853*5498Stimh if (sense == ZFS_PROP_UNDEFINED) 1854*5498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_CASE, &sense) == 0); 1855*5498Stimh VERIFY(nvlist_add_uint64(zplprops, 1856*5498Stimh zfs_prop_to_name(ZFS_PROP_CASE), sense) == 0); 1857*5498Stimh 1858*5498Stimh dmu_objset_close(os); 18595331Samw return (0); 1860789Sahrens } 1861789Sahrens 18625367Sahrens /* 18635367Sahrens * inputs: 18645367Sahrens * zc_objset_type type of objset to create (fs vs zvol) 18655367Sahrens * zc_name name of new objset 18665367Sahrens * zc_value name of snapshot to clone from (may be empty) 18675367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 18685367Sahrens * 1869*5498Stimh * outputs: none 18705367Sahrens */ 1871789Sahrens static int 1872789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1873789Sahrens { 1874789Sahrens objset_t *clone; 1875789Sahrens int error = 0; 18765331Samw zfs_creat_t zct; 18774543Smarks nvlist_t *nvprops = NULL; 18784543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1879789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1880789Sahrens 1881789Sahrens switch (type) { 1882789Sahrens 1883789Sahrens case DMU_OST_ZFS: 1884789Sahrens cbfunc = zfs_create_cb; 1885789Sahrens break; 1886789Sahrens 1887789Sahrens case DMU_OST_ZVOL: 1888789Sahrens cbfunc = zvol_create_cb; 1889789Sahrens break; 1890789Sahrens 1891789Sahrens default: 18922199Sahrens cbfunc = NULL; 18932199Sahrens } 18945326Sek110237 if (strchr(zc->zc_name, '@') || 18955326Sek110237 strchr(zc->zc_name, '%')) 1896789Sahrens return (EINVAL); 1897789Sahrens 18982676Seschrock if (zc->zc_nvlist_src != NULL && 18995094Slling (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 19005094Slling &nvprops)) != 0) 19012676Seschrock return (error); 19022676Seschrock 1903*5498Stimh zct.zct_zplprops = NULL; 19045331Samw zct.zct_props = nvprops; 19055331Samw 19062676Seschrock if (zc->zc_value[0] != '\0') { 1907789Sahrens /* 1908789Sahrens * We're creating a clone of an existing snapshot. 1909789Sahrens */ 19102676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 19112676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 19124543Smarks nvlist_free(nvprops); 1913789Sahrens return (EINVAL); 19142676Seschrock } 1915789Sahrens 19162676Seschrock error = dmu_objset_open(zc->zc_value, type, 1917789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 19182676Seschrock if (error) { 19194543Smarks nvlist_free(nvprops); 1920789Sahrens return (error); 19212676Seschrock } 1922789Sahrens error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); 19235331Samw if (error) { 19245331Samw dmu_objset_close(clone); 19255331Samw nvlist_free(nvprops); 19265331Samw return (error); 19275331Samw } 1928789Sahrens dmu_objset_close(clone); 1929789Sahrens } else { 19302676Seschrock if (cbfunc == NULL) { 19314543Smarks nvlist_free(nvprops); 19322199Sahrens return (EINVAL); 19332676Seschrock } 19342676Seschrock 1935789Sahrens if (type == DMU_OST_ZVOL) { 19362676Seschrock uint64_t volsize, volblocksize; 19372676Seschrock 19384543Smarks if (nvprops == NULL || 19394543Smarks nvlist_lookup_uint64(nvprops, 19402676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 19412676Seschrock &volsize) != 0) { 19424543Smarks nvlist_free(nvprops); 19432676Seschrock return (EINVAL); 19442676Seschrock } 19452676Seschrock 19464543Smarks if ((error = nvlist_lookup_uint64(nvprops, 19472676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 19482676Seschrock &volblocksize)) != 0 && error != ENOENT) { 19494543Smarks nvlist_free(nvprops); 19502676Seschrock return (EINVAL); 19512676Seschrock } 19521133Seschrock 19532676Seschrock if (error != 0) 19542676Seschrock volblocksize = zfs_prop_default_numeric( 19552676Seschrock ZFS_PROP_VOLBLOCKSIZE); 19562676Seschrock 19572676Seschrock if ((error = zvol_check_volblocksize( 19582676Seschrock volblocksize)) != 0 || 19592676Seschrock (error = zvol_check_volsize(volsize, 19602676Seschrock volblocksize)) != 0) { 19614543Smarks nvlist_free(nvprops); 1962789Sahrens return (error); 19632676Seschrock } 19644577Sahrens } else if (type == DMU_OST_ZFS) { 19654577Sahrens uint64_t version; 19665331Samw int error; 19675331Samw 1968*5498Stimh /* 1969*5498Stimh * Default ZPL version to non-FUID capable if the 1970*5498Stimh * pool is not upgraded to support FUIDs. 1971*5498Stimh */ 1972*5498Stimh if (zfs_check_version(zc->zc_name, SPA_VERSION_FUID)) 1973*5498Stimh version = ZPL_VERSION_FUID - 1; 1974*5498Stimh else 1975*5498Stimh version = ZPL_VERSION; 1976*5498Stimh 1977*5498Stimh /* 1978*5498Stimh * Potentially override default ZPL version based 1979*5498Stimh * on creator's request. 1980*5498Stimh */ 1981*5498Stimh (void) nvlist_lookup_uint64(nvprops, 19825331Samw zfs_prop_to_name(ZFS_PROP_VERSION), &version); 19835331Samw 1984*5498Stimh /* 1985*5498Stimh * Make sure version we ended up with is kosher 1986*5498Stimh */ 1987*5498Stimh if ((version < ZPL_VERSION_INITIAL || 1988*5498Stimh version > ZPL_VERSION) || 1989*5498Stimh (version >= ZPL_VERSION_FUID && 1990*5498Stimh zfs_check_version(zc->zc_name, SPA_VERSION_FUID))) { 19915331Samw nvlist_free(nvprops); 19925331Samw return (ENOTSUP); 19935331Samw } 19945331Samw 19955331Samw /* 19965331Samw * We have to have normalization and 19975331Samw * case-folding flags correct when we do the 19985331Samw * file system creation, so go figure them out 1999*5498Stimh * now. 20005331Samw */ 2001*5498Stimh VERIFY(nvlist_alloc(&zct.zct_zplprops, 2002*5498Stimh NV_UNIQUE_NAME, KM_SLEEP) == 0); 2003*5498Stimh error = zfs_fill_zplprops(zc->zc_name, nvprops, 2004*5498Stimh zct.zct_zplprops, version); 20055331Samw if (error != 0) { 20065331Samw nvlist_free(nvprops); 2007*5498Stimh nvlist_free(zct.zct_zplprops); 20085331Samw return (error); 20094577Sahrens } 20102676Seschrock } 20112676Seschrock error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, 20125331Samw &zct); 2013*5498Stimh nvlist_free(zct.zct_zplprops); 2014789Sahrens } 20152676Seschrock 20162676Seschrock /* 20172676Seschrock * It would be nice to do this atomically. 20182676Seschrock */ 20192676Seschrock if (error == 0) { 20204787Sahrens if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) 20212676Seschrock (void) dmu_objset_destroy(zc->zc_name); 20222676Seschrock } 20232676Seschrock 20244543Smarks nvlist_free(nvprops); 2025789Sahrens return (error); 2026789Sahrens } 2027789Sahrens 20285367Sahrens /* 20295367Sahrens * inputs: 20305367Sahrens * zc_name name of filesystem 20315367Sahrens * zc_value short name of snapshot 20325367Sahrens * zc_cookie recursive flag 20335367Sahrens * 20345367Sahrens * outputs: none 20355367Sahrens */ 2036789Sahrens static int 20372199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 20382199Sahrens { 20392676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 20402199Sahrens return (EINVAL); 20412199Sahrens return (dmu_objset_snapshot(zc->zc_name, 20422676Seschrock zc->zc_value, zc->zc_cookie)); 20432199Sahrens } 20442199Sahrens 20454007Smmusante int 20462199Sahrens zfs_unmount_snap(char *name, void *arg) 2047789Sahrens { 20482199Sahrens char *snapname = arg; 20492199Sahrens char *cp; 20502417Sahrens vfs_t *vfsp = NULL; 20512199Sahrens 20522199Sahrens /* 20532199Sahrens * Snapshots (which are under .zfs control) must be unmounted 20542199Sahrens * before they can be destroyed. 20552199Sahrens */ 20562199Sahrens 20572199Sahrens if (snapname) { 20582199Sahrens (void) strcat(name, "@"); 20592199Sahrens (void) strcat(name, snapname); 20602199Sahrens vfsp = zfs_get_vfs(name); 20612199Sahrens cp = strchr(name, '@'); 20622199Sahrens *cp = '\0'; 20632417Sahrens } else if (strchr(name, '@')) { 20642199Sahrens vfsp = zfs_get_vfs(name); 20652199Sahrens } 20662199Sahrens 20672199Sahrens if (vfsp) { 20682199Sahrens /* 20692199Sahrens * Always force the unmount for snapshots. 20702199Sahrens */ 20712199Sahrens int flag = MS_FORCE; 2072789Sahrens int err; 2073789Sahrens 20742199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 20752199Sahrens VFS_RELE(vfsp); 20762199Sahrens return (err); 20772199Sahrens } 20782199Sahrens VFS_RELE(vfsp); 20792199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 20802199Sahrens return (err); 20812199Sahrens } 20822199Sahrens return (0); 20832199Sahrens } 20842199Sahrens 20855367Sahrens /* 20865367Sahrens * inputs: 20875367Sahrens * zc_name name of filesystem 20885367Sahrens * zc_value short name of snapshot 20895367Sahrens * 20905367Sahrens * outputs: none 20915367Sahrens */ 20922199Sahrens static int 20932199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 20942199Sahrens { 20952199Sahrens int err; 2096789Sahrens 20972676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 20982199Sahrens return (EINVAL); 20992199Sahrens err = dmu_objset_find(zc->zc_name, 21002676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 21012199Sahrens if (err) 21022199Sahrens return (err); 21032676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 21042199Sahrens } 21052199Sahrens 21065367Sahrens /* 21075367Sahrens * inputs: 21085367Sahrens * zc_name name of dataset to destroy 21095367Sahrens * zc_objset_type type of objset 21105367Sahrens * 21115367Sahrens * outputs: none 21125367Sahrens */ 21132199Sahrens static int 21142199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 21152199Sahrens { 21162199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 21172199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 21182199Sahrens if (err) 21192199Sahrens return (err); 2120789Sahrens } 2121789Sahrens 2122789Sahrens return (dmu_objset_destroy(zc->zc_name)); 2123789Sahrens } 2124789Sahrens 21255367Sahrens /* 21265367Sahrens * inputs: 21275446Sahrens * zc_name name of dataset to rollback (to most recent snapshot) 21285367Sahrens * 21295367Sahrens * outputs: none 21305367Sahrens */ 2131789Sahrens static int 2132789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 2133789Sahrens { 21345446Sahrens objset_t *os; 21355446Sahrens int error; 21365446Sahrens zfsvfs_t *zfsvfs = NULL; 21375446Sahrens 21385446Sahrens /* 21395446Sahrens * Get the zfsvfs for the receiving objset. There 21405446Sahrens * won't be one if we're operating on a zvol, if the 21415446Sahrens * objset doesn't exist yet, or is not mounted. 21425446Sahrens */ 21435446Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 21445446Sahrens DS_MODE_STANDARD, &os); 21455446Sahrens if (error) 21465446Sahrens return (error); 21475446Sahrens 21485446Sahrens if (dmu_objset_type(os) == DMU_OST_ZFS) { 21495446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 21505446Sahrens zfsvfs = dmu_objset_get_user(os); 21515446Sahrens if (zfsvfs != NULL) 21525446Sahrens VFS_HOLD(zfsvfs->z_vfs); 21535446Sahrens mutex_exit(&os->os->os_user_ptr_lock); 21545446Sahrens } 21555446Sahrens 21565446Sahrens if (zfsvfs != NULL) { 21575446Sahrens char osname[MAXNAMELEN]; 21585446Sahrens int mode; 21595446Sahrens 21605446Sahrens VERIFY3U(0, ==, zfs_suspend_fs(zfsvfs, osname, &mode)); 21615446Sahrens ASSERT(strcmp(osname, zc->zc_name) == 0); 21625446Sahrens error = dmu_objset_rollback(os); 21635446Sahrens VERIFY3U(0, ==, zfs_resume_fs(zfsvfs, osname, mode)); 21645446Sahrens 21655446Sahrens VFS_RELE(zfsvfs->z_vfs); 21665446Sahrens } else { 21675446Sahrens error = dmu_objset_rollback(os); 21685446Sahrens } 21695446Sahrens /* Note, the dmu_objset_rollback() closes the objset for us. */ 21705446Sahrens 21715446Sahrens return (error); 2172789Sahrens } 2173789Sahrens 21745367Sahrens /* 21755367Sahrens * inputs: 21765367Sahrens * zc_name old name of dataset 21775367Sahrens * zc_value new name of dataset 21785367Sahrens * zc_cookie recursive flag (only valid for snapshots) 21795367Sahrens * 21805367Sahrens * outputs: none 21815367Sahrens */ 2182789Sahrens static int 2183789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 2184789Sahrens { 21854490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 21864007Smmusante 21872676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 21885326Sek110237 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 21895326Sek110237 strchr(zc->zc_value, '%')) 2190789Sahrens return (EINVAL); 2191789Sahrens 21924007Smmusante /* 21934007Smmusante * Unmount snapshot unless we're doing a recursive rename, 21944007Smmusante * in which case the dataset code figures out which snapshots 21954007Smmusante * to unmount. 21964007Smmusante */ 21974007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 2198789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 21992199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 22002199Sahrens if (err) 22012199Sahrens return (err); 2202789Sahrens } 2203789Sahrens 22044007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 2205789Sahrens } 2206789Sahrens 22075367Sahrens /* 22085367Sahrens * inputs: 22095367Sahrens * zc_name name of containing filesystem 22105367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 22115367Sahrens * zc_value name of snapshot to create 22125367Sahrens * zc_string name of clone origin (if DRR_FLAG_CLONE) 22135367Sahrens * zc_cookie file descriptor to recv from 22145367Sahrens * zc_begin_record the BEGIN record of the stream (not byteswapped) 22155367Sahrens * zc_guid force flag 22165367Sahrens * 22175367Sahrens * outputs: 22185367Sahrens * zc_cookie number of bytes read 22195367Sahrens */ 2220789Sahrens static int 22215367Sahrens zfs_ioc_recv(zfs_cmd_t *zc) 2222789Sahrens { 2223789Sahrens file_t *fp; 22245326Sek110237 objset_t *os; 22255367Sahrens dmu_recv_cookie_t drc; 22265326Sek110237 zfsvfs_t *zfsvfs = NULL; 22275326Sek110237 boolean_t force = (boolean_t)zc->zc_guid; 2228789Sahrens int error, fd; 22295367Sahrens offset_t off; 22305367Sahrens nvlist_t *props = NULL; 22315367Sahrens objset_t *origin = NULL; 22325367Sahrens char *tosnap; 22335367Sahrens char tofs[ZFS_MAXNAMELEN]; 2234789Sahrens 22353265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 22365326Sek110237 strchr(zc->zc_value, '@') == NULL || 22375326Sek110237 strchr(zc->zc_value, '%')) 22383265Sahrens return (EINVAL); 22393265Sahrens 22405367Sahrens (void) strcpy(tofs, zc->zc_value); 22415367Sahrens tosnap = strchr(tofs, '@'); 22425367Sahrens *tosnap = '\0'; 22435367Sahrens tosnap++; 22445367Sahrens 22455367Sahrens if (zc->zc_nvlist_src != NULL && 22465367Sahrens (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 22475367Sahrens &props)) != 0) 22485367Sahrens return (error); 22495367Sahrens 2250789Sahrens fd = zc->zc_cookie; 2251789Sahrens fp = getf(fd); 22525367Sahrens if (fp == NULL) { 22535367Sahrens nvlist_free(props); 2254789Sahrens return (EBADF); 22555367Sahrens } 22565326Sek110237 22575326Sek110237 /* 22585326Sek110237 * Get the zfsvfs for the receiving objset. There 22595326Sek110237 * won't be one if we're operating on a zvol, if the 22605326Sek110237 * objset doesn't exist yet, or is not mounted. 22615326Sek110237 */ 22625367Sahrens 22635446Sahrens error = dmu_objset_open(tofs, DMU_OST_ZFS, 22645326Sek110237 DS_MODE_STANDARD | DS_MODE_READONLY, &os); 22655326Sek110237 if (!error) { 22665446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 22675446Sahrens zfsvfs = dmu_objset_get_user(os); 22685446Sahrens if (zfsvfs != NULL) 22695446Sahrens VFS_HOLD(zfsvfs->z_vfs); 22705446Sahrens mutex_exit(&os->os->os_user_ptr_lock); 22715326Sek110237 dmu_objset_close(os); 22725326Sek110237 } 22735326Sek110237 22745367Sahrens if (zc->zc_string[0]) { 22755367Sahrens error = dmu_objset_open(zc->zc_string, DMU_OST_ANY, 22765367Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &origin); 22775367Sahrens if (error) { 22785367Sahrens if (zfsvfs != NULL) 22795367Sahrens VFS_RELE(zfsvfs->z_vfs); 22805367Sahrens nvlist_free(props); 22815367Sahrens releasef(fd); 22825367Sahrens return (error); 22835367Sahrens } 22845367Sahrens } 22855367Sahrens 22865367Sahrens error = dmu_recv_begin(tofs, tosnap, &zc->zc_begin_record, 22875367Sahrens force, origin, zfsvfs != NULL, &drc); 22885367Sahrens if (origin) 22895367Sahrens dmu_objset_close(origin); 22905367Sahrens if (error) { 22915367Sahrens if (zfsvfs != NULL) 22925367Sahrens VFS_RELE(zfsvfs->z_vfs); 22935367Sahrens nvlist_free(props); 22945367Sahrens releasef(fd); 22955367Sahrens return (error); 22965367Sahrens } 22975326Sek110237 22985326Sek110237 /* 22995367Sahrens * If properties are supplied, they are to completely replace 23005367Sahrens * the existing ones; "inherit" any existing properties. 23015326Sek110237 */ 23025367Sahrens if (props) { 23035367Sahrens objset_t *os; 23045367Sahrens nvlist_t *nv = NULL; 23055367Sahrens 23065367Sahrens error = dmu_objset_open(tofs, DMU_OST_ANY, 23075367Sahrens DS_MODE_STANDARD | DS_MODE_READONLY | DS_MODE_INCONSISTENT, 23085367Sahrens &os); 23095367Sahrens if (error == 0) { 23105367Sahrens error = dsl_prop_get_all(os, &nv); 23115367Sahrens dmu_objset_close(os); 23125367Sahrens } 23135367Sahrens if (error == 0) { 23145367Sahrens nvpair_t *elem; 23155446Sahrens zfs_cmd_t *zc2; 23165446Sahrens zc2 = kmem_alloc(sizeof (zfs_cmd_t), KM_SLEEP); 23175446Sahrens 23185446Sahrens (void) strcpy(zc2->zc_name, tofs); 23195367Sahrens for (elem = nvlist_next_nvpair(nv, NULL); elem; 23205367Sahrens elem = nvlist_next_nvpair(nv, elem)) { 23215446Sahrens (void) strcpy(zc2->zc_value, nvpair_name(elem)); 23225446Sahrens if (zfs_secpolicy_inherit(zc2, CRED()) == 0) 23235446Sahrens (void) zfs_ioc_inherit_prop(zc2); 23245326Sek110237 } 23255446Sahrens kmem_free(zc2, sizeof (zfs_cmd_t)); 23265326Sek110237 } 23275367Sahrens if (nv) 23285367Sahrens nvlist_free(nv); 23295367Sahrens } 23305367Sahrens 23315367Sahrens /* 23325367Sahrens * Set properties. Note, we ignore errors. Would be better to 23335367Sahrens * do best-effort in zfs_set_prop_nvlist, too. 23345367Sahrens */ 23355367Sahrens (void) zfs_set_prop_nvlist(tofs, props); 23365367Sahrens nvlist_free(props); 23375367Sahrens 23385367Sahrens off = fp->f_offset; 23395367Sahrens error = dmu_recv_stream(&drc, fp->f_vnode, &off); 23405367Sahrens 23415367Sahrens if (error == 0) { 23425367Sahrens if (zfsvfs != NULL) { 23435367Sahrens char osname[MAXNAMELEN]; 23445367Sahrens int mode; 23455367Sahrens 23465367Sahrens (void) zfs_suspend_fs(zfsvfs, osname, &mode); 23475367Sahrens error = dmu_recv_end(&drc); 23485367Sahrens error |= zfs_resume_fs(zfsvfs, osname, mode); 23495367Sahrens } else { 23505367Sahrens error = dmu_recv_end(&drc); 23515367Sahrens } 23525326Sek110237 } 23535326Sek110237 if (zfsvfs != NULL) 23545326Sek110237 VFS_RELE(zfsvfs->z_vfs); 23555367Sahrens 23565367Sahrens zc->zc_cookie = off - fp->f_offset; 23575367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 23585367Sahrens fp->f_offset = off; 23592885Sahrens 2360789Sahrens releasef(fd); 2361789Sahrens return (error); 2362789Sahrens } 2363789Sahrens 23645367Sahrens /* 23655367Sahrens * inputs: 23665367Sahrens * zc_name name of snapshot to send 23675367Sahrens * zc_value short name of incremental fromsnap (may be empty) 23685367Sahrens * zc_cookie file descriptor to send stream to 23695367Sahrens * zc_obj fromorigin flag (mutually exclusive with zc_value) 23705367Sahrens * 23715367Sahrens * outputs: none 23725367Sahrens */ 2373789Sahrens static int 23745367Sahrens zfs_ioc_send(zfs_cmd_t *zc) 2375789Sahrens { 2376789Sahrens objset_t *fromsnap = NULL; 2377789Sahrens objset_t *tosnap; 2378789Sahrens file_t *fp; 2379789Sahrens int error; 23805367Sahrens offset_t off; 2381789Sahrens 2382789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 2383789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); 2384789Sahrens if (error) 2385789Sahrens return (error); 2386789Sahrens 23872676Seschrock if (zc->zc_value[0] != '\0') { 23882885Sahrens char buf[MAXPATHLEN]; 23892885Sahrens char *cp; 23902885Sahrens 23912885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 23922885Sahrens cp = strchr(buf, '@'); 23932885Sahrens if (cp) 23942885Sahrens *(cp+1) = 0; 23952885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 23962885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 2397789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); 2398789Sahrens if (error) { 2399789Sahrens dmu_objset_close(tosnap); 2400789Sahrens return (error); 2401789Sahrens } 2402789Sahrens } 2403789Sahrens 2404789Sahrens fp = getf(zc->zc_cookie); 2405789Sahrens if (fp == NULL) { 2406789Sahrens dmu_objset_close(tosnap); 2407789Sahrens if (fromsnap) 2408789Sahrens dmu_objset_close(fromsnap); 2409789Sahrens return (EBADF); 2410789Sahrens } 2411789Sahrens 24125367Sahrens off = fp->f_offset; 24135367Sahrens error = dmu_sendbackup(tosnap, fromsnap, zc->zc_obj, fp->f_vnode, &off); 24145367Sahrens 24155367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 24165367Sahrens fp->f_offset = off; 2417789Sahrens releasef(zc->zc_cookie); 2418789Sahrens if (fromsnap) 2419789Sahrens dmu_objset_close(fromsnap); 2420789Sahrens dmu_objset_close(tosnap); 2421789Sahrens return (error); 2422789Sahrens } 2423789Sahrens 24241544Seschrock static int 24251544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 24261544Seschrock { 24271544Seschrock int id, error; 24281544Seschrock 24291544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 24301544Seschrock &zc->zc_inject_record); 24311544Seschrock 24321544Seschrock if (error == 0) 24331544Seschrock zc->zc_guid = (uint64_t)id; 24341544Seschrock 24351544Seschrock return (error); 24361544Seschrock } 24371544Seschrock 24381544Seschrock static int 24391544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 24401544Seschrock { 24411544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 24421544Seschrock } 24431544Seschrock 24441544Seschrock static int 24451544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 24461544Seschrock { 24471544Seschrock int id = (int)zc->zc_guid; 24481544Seschrock int error; 24491544Seschrock 24501544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 24511544Seschrock &zc->zc_inject_record); 24521544Seschrock 24531544Seschrock zc->zc_guid = id; 24541544Seschrock 24551544Seschrock return (error); 24561544Seschrock } 24571544Seschrock 24581544Seschrock static int 24591544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 24601544Seschrock { 24611544Seschrock spa_t *spa; 24621544Seschrock int error; 24632676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 24641544Seschrock 24651544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 24661544Seschrock return (error); 24671544Seschrock 24682676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 24691544Seschrock &count); 24701544Seschrock if (error == 0) 24712676Seschrock zc->zc_nvlist_dst_size = count; 24721544Seschrock else 24732676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 24741544Seschrock 24751544Seschrock spa_close(spa, FTAG); 24761544Seschrock 24771544Seschrock return (error); 24781544Seschrock } 24791544Seschrock 24801544Seschrock static int 24811544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 24821544Seschrock { 24831544Seschrock spa_t *spa; 24841544Seschrock vdev_t *vd; 24854808Sek110237 uint64_t txg; 24861544Seschrock int error; 24871544Seschrock 24881544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 24891544Seschrock return (error); 24901544Seschrock 24915329Sgw25295 /* 24925329Sgw25295 * Try to resume any I/Os which may have been suspended 24935329Sgw25295 * as a result of a complete pool failure. 24945329Sgw25295 */ 24955329Sgw25295 if (!list_is_empty(&spa->spa_zio_list)) { 24965329Sgw25295 if (zio_vdev_resume_io(spa) != 0) { 24975329Sgw25295 spa_close(spa, FTAG); 24985329Sgw25295 return (EIO); 24995329Sgw25295 } 25005329Sgw25295 } 25015329Sgw25295 25024451Seschrock txg = spa_vdev_enter(spa); 25031544Seschrock 25042676Seschrock if (zc->zc_guid == 0) { 25051544Seschrock vd = NULL; 25062676Seschrock } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { 25075450Sbrendan spa_aux_vdev_t *sav; 25085450Sbrendan int i; 25095450Sbrendan 25105450Sbrendan /* 25115450Sbrendan * Check if this is an l2cache device. 25125450Sbrendan */ 25135450Sbrendan ASSERT(spa != NULL); 25145450Sbrendan sav = &spa->spa_l2cache; 25155450Sbrendan for (i = 0; i < sav->sav_count; i++) { 25165450Sbrendan if (sav->sav_vdevs[i]->vdev_guid == zc->zc_guid) { 25175450Sbrendan vd = sav->sav_vdevs[i]; 25185450Sbrendan break; 25195450Sbrendan } 25205450Sbrendan } 25215450Sbrendan 25225450Sbrendan if (vd == NULL) { 25235450Sbrendan (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 25245450Sbrendan spa_close(spa, FTAG); 25255450Sbrendan return (ENODEV); 25265450Sbrendan } 25271544Seschrock } 25281544Seschrock 25295329Sgw25295 vdev_clear(spa, vd, B_TRUE); 25301544Seschrock 25314451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 25321544Seschrock 25331544Seschrock spa_close(spa, FTAG); 25341544Seschrock 25351544Seschrock return (0); 25361544Seschrock } 25371544Seschrock 25385367Sahrens /* 25395367Sahrens * inputs: 25405367Sahrens * zc_name name of filesystem 25415367Sahrens * zc_value name of origin snapshot 25425367Sahrens * 25435367Sahrens * outputs: none 25445367Sahrens */ 25451544Seschrock static int 25462082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 25472082Seschrock { 25482417Sahrens char *cp; 25492417Sahrens 25502417Sahrens /* 25512417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 25522417Sahrens * it's easier. 25532417Sahrens */ 25542676Seschrock cp = strchr(zc->zc_value, '@'); 25552417Sahrens if (cp) 25562417Sahrens *cp = '\0'; 25572676Seschrock (void) dmu_objset_find(zc->zc_value, 25582417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 25592082Seschrock return (dsl_dataset_promote(zc->zc_name)); 25602082Seschrock } 25612082Seschrock 25624543Smarks /* 25634543Smarks * We don't want to have a hard dependency 25644543Smarks * against some special symbols in sharefs 25655331Samw * nfs, and smbsrv. Determine them if needed when 25664543Smarks * the first file system is shared. 25675331Samw * Neither sharefs, nfs or smbsrv are unloadable modules. 25684543Smarks */ 25695331Samw int (*znfsexport_fs)(void *arg); 25704543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 25715331Samw int (*zsmbexport_fs)(void *arg, boolean_t add_share); 25725331Samw 25735331Samw int zfs_nfsshare_inited; 25745331Samw int zfs_smbshare_inited; 25755331Samw 25764543Smarks ddi_modhandle_t nfs_mod; 25774543Smarks ddi_modhandle_t sharefs_mod; 25785331Samw ddi_modhandle_t smbsrv_mod; 25794543Smarks kmutex_t zfs_share_lock; 25804543Smarks 25814543Smarks static int 25825331Samw zfs_init_sharefs() 25835331Samw { 25845331Samw int error; 25855331Samw 25865331Samw ASSERT(MUTEX_HELD(&zfs_share_lock)); 25875331Samw /* Both NFS and SMB shares also require sharetab support. */ 25885331Samw if (sharefs_mod == NULL && ((sharefs_mod = 25895331Samw ddi_modopen("fs/sharefs", 25905331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 25915331Samw return (ENOSYS); 25925331Samw } 25935331Samw if (zshare_fs == NULL && ((zshare_fs = 25945331Samw (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 25955331Samw ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 25965331Samw return (ENOSYS); 25975331Samw } 25985331Samw return (0); 25995331Samw } 26005331Samw 26015331Samw static int 26024543Smarks zfs_ioc_share(zfs_cmd_t *zc) 26034543Smarks { 26044543Smarks int error; 26054543Smarks int opcode; 26064543Smarks 26075331Samw switch (zc->zc_share.z_sharetype) { 26085331Samw case ZFS_SHARE_NFS: 26095331Samw case ZFS_UNSHARE_NFS: 26105331Samw if (zfs_nfsshare_inited == 0) { 26115331Samw mutex_enter(&zfs_share_lock); 26125331Samw if (nfs_mod == NULL && ((nfs_mod = ddi_modopen("fs/nfs", 26135331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26145331Samw mutex_exit(&zfs_share_lock); 26155331Samw return (ENOSYS); 26165331Samw } 26175331Samw if (znfsexport_fs == NULL && 26185331Samw ((znfsexport_fs = (int (*)(void *)) 26195331Samw ddi_modsym(nfs_mod, 26205331Samw "nfs_export", &error)) == NULL)) { 26215331Samw mutex_exit(&zfs_share_lock); 26225331Samw return (ENOSYS); 26235331Samw } 26245331Samw error = zfs_init_sharefs(); 26255331Samw if (error) { 26265331Samw mutex_exit(&zfs_share_lock); 26275331Samw return (ENOSYS); 26285331Samw } 26295331Samw zfs_nfsshare_inited = 1; 26304543Smarks mutex_exit(&zfs_share_lock); 26314543Smarks } 26325331Samw break; 26335331Samw case ZFS_SHARE_SMB: 26345331Samw case ZFS_UNSHARE_SMB: 26355331Samw if (zfs_smbshare_inited == 0) { 26365331Samw mutex_enter(&zfs_share_lock); 26375331Samw if (smbsrv_mod == NULL && ((smbsrv_mod = 26385331Samw ddi_modopen("drv/smbsrv", 26395331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26405331Samw mutex_exit(&zfs_share_lock); 26415331Samw return (ENOSYS); 26425331Samw } 26435331Samw if (zsmbexport_fs == NULL && ((zsmbexport_fs = 26445331Samw (int (*)(void *, boolean_t))ddi_modsym(smbsrv_mod, 26455331Samw "lmshrd_share_upcall", &error)) == NULL)) { 26465331Samw mutex_exit(&zfs_share_lock); 26475331Samw return (ENOSYS); 26485331Samw } 26495331Samw error = zfs_init_sharefs(); 26505331Samw if (error) { 26515331Samw mutex_exit(&zfs_share_lock); 26525331Samw return (ENOSYS); 26535331Samw } 26545331Samw zfs_smbshare_inited = 1; 26554543Smarks mutex_exit(&zfs_share_lock); 26564543Smarks } 26575331Samw break; 26585331Samw default: 26595331Samw return (EINVAL); 26604543Smarks } 26614543Smarks 26625331Samw switch (zc->zc_share.z_sharetype) { 26635331Samw case ZFS_SHARE_NFS: 26645331Samw case ZFS_UNSHARE_NFS: 26655331Samw if (error = 26665331Samw znfsexport_fs((void *) 26675331Samw (uintptr_t)zc->zc_share.z_exportdata)) 26685331Samw return (error); 26695331Samw break; 26705331Samw case ZFS_SHARE_SMB: 26715331Samw case ZFS_UNSHARE_SMB: 26725331Samw if (error = zsmbexport_fs((void *) 26735331Samw (uintptr_t)zc->zc_share.z_exportdata, 26745331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB ? 26755331Samw B_TRUE : B_FALSE)) { 26765331Samw return (error); 26775331Samw } 26785331Samw break; 26795331Samw } 26805331Samw 26815331Samw opcode = (zc->zc_share.z_sharetype == ZFS_SHARE_NFS || 26825331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB) ? 26834543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 26844543Smarks 26855331Samw /* 26865331Samw * Add or remove share from sharetab 26875331Samw */ 26884543Smarks error = zshare_fs(opcode, 26894543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 26904543Smarks zc->zc_share.z_sharemax); 26914543Smarks 26924543Smarks return (error); 26934543Smarks 26944543Smarks } 26954543Smarks 26964543Smarks /* 26974988Sek110237 * pool create, destroy, and export don't log the history as part of 26984988Sek110237 * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export 26994988Sek110237 * do the logging of those commands. 27004543Smarks */ 2701789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 27024715Sek110237 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27034577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27044577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27054577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27064577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 27074577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 27084577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27094577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27104577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27114577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27124577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27134577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27144577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27154577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27164577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27174577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27184577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27194577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 2720*5498Stimh { zfs_ioc_objset_zplprops, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27214543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 27224577Sahrens DATASET_NAME, B_FALSE }, 27234543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 27244577Sahrens DATASET_NAME, B_FALSE }, 27254577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 27264577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 27274577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 27284577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 27294577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 27304577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 27314577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 27325367Sahrens { zfs_ioc_recv, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 27335367Sahrens { zfs_ioc_send, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 27344577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 27354577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 27364577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 27374577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 27384577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27394577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 27404577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 27414577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 27424577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27434577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27444577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27454577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 27464577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 27474577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27484543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 27494577Sahrens DATASET_NAME, B_FALSE }, 27504849Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }, 27514849Sahrens { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE }, 2752789Sahrens }; 2753789Sahrens 2754789Sahrens static int 2755789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2756789Sahrens { 2757789Sahrens zfs_cmd_t *zc; 2758789Sahrens uint_t vec; 27592199Sahrens int error, rc; 2760789Sahrens 2761789Sahrens if (getminor(dev) != 0) 2762789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2763789Sahrens 2764789Sahrens vec = cmd - ZFS_IOC; 27654787Sahrens ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); 2766789Sahrens 2767789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2768789Sahrens return (EINVAL); 2769789Sahrens 2770789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2771789Sahrens 2772789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2773789Sahrens 27744787Sahrens if (error == 0) 27754543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2776789Sahrens 2777789Sahrens /* 2778789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2779789Sahrens * the lower layers. 2780789Sahrens */ 2781789Sahrens if (error == 0) { 2782789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2783789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 27844577Sahrens case POOL_NAME: 2785789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2786789Sahrens error = EINVAL; 2787789Sahrens break; 2788789Sahrens 27894577Sahrens case DATASET_NAME: 2790789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2791789Sahrens error = EINVAL; 2792789Sahrens break; 27932856Snd150628 27944577Sahrens case NO_NAME: 27952856Snd150628 break; 2796789Sahrens } 2797789Sahrens } 2798789Sahrens 2799789Sahrens if (error == 0) 2800789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2801789Sahrens 28022199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 28034543Smarks if (error == 0) { 28042199Sahrens error = rc; 28054543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 28064543Smarks zfs_log_history(zc); 28074543Smarks } 2808789Sahrens 2809789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2810789Sahrens return (error); 2811789Sahrens } 2812789Sahrens 2813789Sahrens static int 2814789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2815789Sahrens { 2816789Sahrens if (cmd != DDI_ATTACH) 2817789Sahrens return (DDI_FAILURE); 2818789Sahrens 2819789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2820789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2821789Sahrens return (DDI_FAILURE); 2822789Sahrens 2823789Sahrens zfs_dip = dip; 2824789Sahrens 2825789Sahrens ddi_report_dev(dip); 2826789Sahrens 2827789Sahrens return (DDI_SUCCESS); 2828789Sahrens } 2829789Sahrens 2830789Sahrens static int 2831789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2832789Sahrens { 2833789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2834789Sahrens return (DDI_FAILURE); 2835789Sahrens 2836789Sahrens if (cmd != DDI_DETACH) 2837789Sahrens return (DDI_FAILURE); 2838789Sahrens 2839789Sahrens zfs_dip = NULL; 2840789Sahrens 2841789Sahrens ddi_prop_remove_all(dip); 2842789Sahrens ddi_remove_minor_node(dip, NULL); 2843789Sahrens 2844789Sahrens return (DDI_SUCCESS); 2845789Sahrens } 2846789Sahrens 2847789Sahrens /*ARGSUSED*/ 2848789Sahrens static int 2849789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2850789Sahrens { 2851789Sahrens switch (infocmd) { 2852789Sahrens case DDI_INFO_DEVT2DEVINFO: 2853789Sahrens *result = zfs_dip; 2854789Sahrens return (DDI_SUCCESS); 2855789Sahrens 2856789Sahrens case DDI_INFO_DEVT2INSTANCE: 2857849Sbonwick *result = (void *)0; 2858789Sahrens return (DDI_SUCCESS); 2859789Sahrens } 2860789Sahrens 2861789Sahrens return (DDI_FAILURE); 2862789Sahrens } 2863789Sahrens 2864789Sahrens /* 2865789Sahrens * OK, so this is a little weird. 2866789Sahrens * 2867789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2868789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2869789Sahrens * 2870789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2871789Sahrens * so most of the standard driver entry points are in zvol.c. 2872789Sahrens */ 2873789Sahrens static struct cb_ops zfs_cb_ops = { 2874789Sahrens zvol_open, /* open */ 2875789Sahrens zvol_close, /* close */ 2876789Sahrens zvol_strategy, /* strategy */ 2877789Sahrens nodev, /* print */ 2878789Sahrens nodev, /* dump */ 2879789Sahrens zvol_read, /* read */ 2880789Sahrens zvol_write, /* write */ 2881789Sahrens zfsdev_ioctl, /* ioctl */ 2882789Sahrens nodev, /* devmap */ 2883789Sahrens nodev, /* mmap */ 2884789Sahrens nodev, /* segmap */ 2885789Sahrens nochpoll, /* poll */ 2886789Sahrens ddi_prop_op, /* prop_op */ 2887789Sahrens NULL, /* streamtab */ 2888789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2889789Sahrens CB_REV, /* version */ 28903638Sbillm nodev, /* async read */ 28913638Sbillm nodev, /* async write */ 2892789Sahrens }; 2893789Sahrens 2894789Sahrens static struct dev_ops zfs_dev_ops = { 2895789Sahrens DEVO_REV, /* version */ 2896789Sahrens 0, /* refcnt */ 2897789Sahrens zfs_info, /* info */ 2898789Sahrens nulldev, /* identify */ 2899789Sahrens nulldev, /* probe */ 2900789Sahrens zfs_attach, /* attach */ 2901789Sahrens zfs_detach, /* detach */ 2902789Sahrens nodev, /* reset */ 2903789Sahrens &zfs_cb_ops, /* driver operations */ 2904789Sahrens NULL /* no bus operations */ 2905789Sahrens }; 2906789Sahrens 2907789Sahrens static struct modldrv zfs_modldrv = { 29084577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 29092676Seschrock &zfs_dev_ops 2910789Sahrens }; 2911789Sahrens 2912789Sahrens static struct modlinkage modlinkage = { 2913789Sahrens MODREV_1, 2914789Sahrens (void *)&zfs_modlfs, 2915789Sahrens (void *)&zfs_modldrv, 2916789Sahrens NULL 2917789Sahrens }; 2918789Sahrens 29194720Sfr157268 29204720Sfr157268 uint_t zfs_fsyncer_key; 29215326Sek110237 extern uint_t rrw_tsd_key; 29224720Sfr157268 2923789Sahrens int 2924789Sahrens _init(void) 2925789Sahrens { 2926789Sahrens int error; 2927789Sahrens 2928849Sbonwick spa_init(FREAD | FWRITE); 2929849Sbonwick zfs_init(); 2930849Sbonwick zvol_init(); 2931849Sbonwick 2932849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 2933849Sbonwick zvol_fini(); 2934849Sbonwick zfs_fini(); 2935849Sbonwick spa_fini(); 2936789Sahrens return (error); 2937849Sbonwick } 2938789Sahrens 29394720Sfr157268 tsd_create(&zfs_fsyncer_key, NULL); 29405326Sek110237 tsd_create(&rrw_tsd_key, NULL); 29414720Sfr157268 2942789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 2943789Sahrens ASSERT(error == 0); 29444543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 2945789Sahrens 2946789Sahrens return (0); 2947789Sahrens } 2948789Sahrens 2949789Sahrens int 2950789Sahrens _fini(void) 2951789Sahrens { 2952789Sahrens int error; 2953789Sahrens 29541544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 2955789Sahrens return (EBUSY); 2956789Sahrens 2957789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 2958789Sahrens return (error); 2959789Sahrens 2960789Sahrens zvol_fini(); 2961789Sahrens zfs_fini(); 2962789Sahrens spa_fini(); 29635331Samw if (zfs_nfsshare_inited) 29644543Smarks (void) ddi_modclose(nfs_mod); 29655331Samw if (zfs_smbshare_inited) 29665331Samw (void) ddi_modclose(smbsrv_mod); 29675331Samw if (zfs_nfsshare_inited || zfs_smbshare_inited) 29684543Smarks (void) ddi_modclose(sharefs_mod); 2969789Sahrens 29704720Sfr157268 tsd_destroy(&zfs_fsyncer_key); 2971789Sahrens ldi_ident_release(zfs_li); 2972789Sahrens zfs_li = NULL; 29734543Smarks mutex_destroy(&zfs_share_lock); 2974789Sahrens 2975789Sahrens return (error); 2976789Sahrens } 2977789Sahrens 2978789Sahrens int 2979789Sahrens _info(struct modinfo *modinfop) 2980789Sahrens { 2981789Sahrens return (mod_info(&modlinkage, modinfop)); 2982789Sahrens } 2983