1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51485Slling * Common Development and Distribution License (the "License"). 61485Slling * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 225977Smarks * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27789Sahrens 28789Sahrens #include <sys/types.h> 29789Sahrens #include <sys/param.h> 30789Sahrens #include <sys/errno.h> 31789Sahrens #include <sys/uio.h> 32789Sahrens #include <sys/buf.h> 33789Sahrens #include <sys/modctl.h> 34789Sahrens #include <sys/open.h> 35789Sahrens #include <sys/file.h> 36789Sahrens #include <sys/kmem.h> 37789Sahrens #include <sys/conf.h> 38789Sahrens #include <sys/cmn_err.h> 39789Sahrens #include <sys/stat.h> 40789Sahrens #include <sys/zfs_ioctl.h> 415331Samw #include <sys/zfs_znode.h> 42789Sahrens #include <sys/zap.h> 43789Sahrens #include <sys/spa.h> 443912Slling #include <sys/spa_impl.h> 45789Sahrens #include <sys/vdev.h> 463912Slling #include <sys/vdev_impl.h> 47789Sahrens #include <sys/dmu.h> 48789Sahrens #include <sys/dsl_dir.h> 49789Sahrens #include <sys/dsl_dataset.h> 50789Sahrens #include <sys/dsl_prop.h> 514543Smarks #include <sys/dsl_deleg.h> 524543Smarks #include <sys/dmu_objset.h> 53789Sahrens #include <sys/ddi.h> 54789Sahrens #include <sys/sunddi.h> 55789Sahrens #include <sys/sunldi.h> 56789Sahrens #include <sys/policy.h> 57789Sahrens #include <sys/zone.h> 58789Sahrens #include <sys/nvpair.h> 59789Sahrens #include <sys/pathname.h> 60789Sahrens #include <sys/mount.h> 61789Sahrens #include <sys/sdt.h> 62789Sahrens #include <sys/fs/zfs.h> 63789Sahrens #include <sys/zfs_ctldir.h> 645331Samw #include <sys/zfs_dir.h> 652885Sahrens #include <sys/zvol.h> 664543Smarks #include <sharefs/share.h> 675326Sek110237 #include <sys/dmu_objset.h> 68789Sahrens 69789Sahrens #include "zfs_namecheck.h" 702676Seschrock #include "zfs_prop.h" 714543Smarks #include "zfs_deleg.h" 72789Sahrens 73789Sahrens extern struct modlfs zfs_modlfs; 74789Sahrens 75789Sahrens extern void zfs_init(void); 76789Sahrens extern void zfs_fini(void); 77789Sahrens 78789Sahrens ldi_ident_t zfs_li = NULL; 79789Sahrens dev_info_t *zfs_dip; 80789Sahrens 81789Sahrens typedef int zfs_ioc_func_t(zfs_cmd_t *); 824543Smarks typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *); 83789Sahrens 84789Sahrens typedef struct zfs_ioc_vec { 85789Sahrens zfs_ioc_func_t *zvec_func; 86789Sahrens zfs_secpolicy_func_t *zvec_secpolicy; 87789Sahrens enum { 884577Sahrens NO_NAME, 894577Sahrens POOL_NAME, 904577Sahrens DATASET_NAME 914543Smarks } zvec_namecheck; 924543Smarks boolean_t zvec_his_log; 93789Sahrens } zfs_ioc_vec_t; 94789Sahrens 95789Sahrens /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */ 96789Sahrens void 97789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 98789Sahrens { 99789Sahrens const char *newfile; 100789Sahrens char buf[256]; 101789Sahrens va_list adx; 102789Sahrens 103789Sahrens /* 104789Sahrens * Get rid of annoying "../common/" prefix to filename. 105789Sahrens */ 106789Sahrens newfile = strrchr(file, '/'); 107789Sahrens if (newfile != NULL) { 108789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 109789Sahrens } else { 110789Sahrens newfile = file; 111789Sahrens } 112789Sahrens 113789Sahrens va_start(adx, fmt); 114789Sahrens (void) vsnprintf(buf, sizeof (buf), fmt, adx); 115789Sahrens va_end(adx); 116789Sahrens 117789Sahrens /* 118789Sahrens * To get this data, use the zfs-dprintf probe as so: 119789Sahrens * dtrace -q -n 'zfs-dprintf \ 120789Sahrens * /stringof(arg0) == "dbuf.c"/ \ 121789Sahrens * {printf("%s: %s", stringof(arg1), stringof(arg3))}' 122789Sahrens * arg0 = file name 123789Sahrens * arg1 = function name 124789Sahrens * arg2 = line number 125789Sahrens * arg3 = message 126789Sahrens */ 127789Sahrens DTRACE_PROBE4(zfs__dprintf, 128789Sahrens char *, newfile, char *, func, int, line, char *, buf); 129789Sahrens } 130789Sahrens 1314543Smarks static void 1324715Sek110237 history_str_free(char *buf) 1334715Sek110237 { 1344715Sek110237 kmem_free(buf, HIS_MAX_RECORD_LEN); 1354715Sek110237 } 1364715Sek110237 1374715Sek110237 static char * 1384715Sek110237 history_str_get(zfs_cmd_t *zc) 1394715Sek110237 { 1404715Sek110237 char *buf; 1414715Sek110237 1424715Sek110237 if (zc->zc_history == NULL) 1434715Sek110237 return (NULL); 1444715Sek110237 1454715Sek110237 buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP); 1464715Sek110237 if (copyinstr((void *)(uintptr_t)zc->zc_history, 1474715Sek110237 buf, HIS_MAX_RECORD_LEN, NULL) != 0) { 1484715Sek110237 history_str_free(buf); 1494715Sek110237 return (NULL); 1504715Sek110237 } 1514715Sek110237 1524715Sek110237 buf[HIS_MAX_RECORD_LEN -1] = '\0'; 1534715Sek110237 1544715Sek110237 return (buf); 1554715Sek110237 } 1564715Sek110237 1575375Stimh /* 1585375Stimh * zfs_check_version 1595375Stimh * 1605375Stimh * Return non-zero if the spa version is less than requested version. 1615375Stimh */ 1625331Samw static int 1635331Samw zfs_check_version(const char *name, int version) 1645331Samw { 1655331Samw 1665331Samw spa_t *spa; 1675331Samw 1685331Samw if (spa_open(name, &spa, FTAG) == 0) { 1695331Samw if (spa_version(spa) < version) { 1705331Samw spa_close(spa, FTAG); 1715331Samw return (1); 1725331Samw } 1735331Samw spa_close(spa, FTAG); 1745331Samw } 1755331Samw return (0); 1765331Samw } 1775331Samw 1785977Smarks /* 1795977Smarks * zpl_check_version 1805977Smarks * 1815977Smarks * Return non-zero if the ZPL version is less than requested version. 1825977Smarks */ 1835977Smarks static int 1845977Smarks zpl_check_version(const char *name, int version) 1855977Smarks { 1865977Smarks objset_t *os; 1875977Smarks int rc = 1; 1885977Smarks 1895977Smarks if (dmu_objset_open(name, DMU_OST_ANY, 1905977Smarks DS_MODE_STANDARD | DS_MODE_READONLY, &os) == 0) { 1915977Smarks uint64_t propversion; 1925977Smarks 1935977Smarks if (zfs_get_zplprop(os, ZFS_PROP_VERSION, 1945977Smarks &propversion) == 0) { 1955977Smarks rc = !(propversion >= version); 1965977Smarks } 1975977Smarks dmu_objset_close(os); 1985977Smarks } 1995977Smarks return (rc); 2005977Smarks } 2015977Smarks 2024715Sek110237 static void 2034543Smarks zfs_log_history(zfs_cmd_t *zc) 2044543Smarks { 2054543Smarks spa_t *spa; 2064603Sahrens char *buf; 2074543Smarks 2084715Sek110237 if ((buf = history_str_get(zc)) == NULL) 2094577Sahrens return; 2104577Sahrens 2114715Sek110237 if (spa_open(zc->zc_name, &spa, FTAG) == 0) { 2124715Sek110237 if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY) 2134715Sek110237 (void) spa_history_log(spa, buf, LOG_CMD_NORMAL); 2144715Sek110237 spa_close(spa, FTAG); 2154543Smarks } 2164715Sek110237 history_str_free(buf); 2174543Smarks } 2184543Smarks 219789Sahrens /* 220789Sahrens * Policy for top-level read operations (list pools). Requires no privileges, 221789Sahrens * and can be used in the local zone, as there is no associated dataset. 222789Sahrens */ 223789Sahrens /* ARGSUSED */ 224789Sahrens static int 2254543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) 226789Sahrens { 227789Sahrens return (0); 228789Sahrens } 229789Sahrens 230789Sahrens /* 231789Sahrens * Policy for dataset read operations (list children, get statistics). Requires 232789Sahrens * no privileges, but must be visible in the local zone. 233789Sahrens */ 234789Sahrens /* ARGSUSED */ 235789Sahrens static int 2364543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) 237789Sahrens { 238789Sahrens if (INGLOBALZONE(curproc) || 2394543Smarks zone_dataset_visible(zc->zc_name, NULL)) 240789Sahrens return (0); 241789Sahrens 242789Sahrens return (ENOENT); 243789Sahrens } 244789Sahrens 245789Sahrens static int 246789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr) 247789Sahrens { 248789Sahrens uint64_t zoned; 249789Sahrens int writable = 1; 250789Sahrens 251789Sahrens /* 252789Sahrens * The dataset must be visible by this zone -- check this first 253789Sahrens * so they don't see EPERM on something they shouldn't know about. 254789Sahrens */ 255789Sahrens if (!INGLOBALZONE(curproc) && 256789Sahrens !zone_dataset_visible(dataset, &writable)) 257789Sahrens return (ENOENT); 258789Sahrens 259789Sahrens if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) 260789Sahrens return (ENOENT); 261789Sahrens 262789Sahrens if (INGLOBALZONE(curproc)) { 263789Sahrens /* 264789Sahrens * If the fs is zoned, only root can access it from the 265789Sahrens * global zone. 266789Sahrens */ 267789Sahrens if (secpolicy_zfs(cr) && zoned) 268789Sahrens return (EPERM); 269789Sahrens } else { 270789Sahrens /* 271789Sahrens * If we are in a local zone, the 'zoned' property must be set. 272789Sahrens */ 273789Sahrens if (!zoned) 274789Sahrens return (EPERM); 275789Sahrens 276789Sahrens /* must be writable by this zone */ 277789Sahrens if (!writable) 278789Sahrens return (EPERM); 279789Sahrens } 280789Sahrens return (0); 281789Sahrens } 282789Sahrens 283789Sahrens int 2844543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) 285789Sahrens { 286789Sahrens int error; 287789Sahrens 2884543Smarks error = zfs_dozonecheck(name, cr); 2894543Smarks if (error == 0) { 2904543Smarks error = secpolicy_zfs(cr); 2914670Sahrens if (error) 2924543Smarks error = dsl_deleg_access(name, perm, cr); 2934543Smarks } 2944543Smarks return (error); 2954543Smarks } 2964543Smarks 2974543Smarks static int 2984543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) 2994543Smarks { 3004543Smarks /* 3014543Smarks * Check permissions for special properties. 3024543Smarks */ 3034543Smarks switch (prop) { 3044543Smarks case ZFS_PROP_ZONED: 3054543Smarks /* 3064543Smarks * Disallow setting of 'zoned' from within a local zone. 3074543Smarks */ 3084543Smarks if (!INGLOBALZONE(curproc)) 3094543Smarks return (EPERM); 3104543Smarks break; 311789Sahrens 3124543Smarks case ZFS_PROP_QUOTA: 3134543Smarks if (!INGLOBALZONE(curproc)) { 3144543Smarks uint64_t zoned; 3154543Smarks char setpoint[MAXNAMELEN]; 3164543Smarks /* 3174543Smarks * Unprivileged users are allowed to modify the 3184543Smarks * quota on things *under* (ie. contained by) 3194543Smarks * the thing they own. 3204543Smarks */ 3214543Smarks if (dsl_prop_get_integer(name, "zoned", &zoned, 3224543Smarks setpoint)) 3234543Smarks return (EPERM); 3244670Sahrens if (!zoned || strlen(name) <= strlen(setpoint)) 3254543Smarks return (EPERM); 3264543Smarks } 3274670Sahrens break; 3284543Smarks } 3294543Smarks 3304787Sahrens return (zfs_secpolicy_write_perms(name, zfs_prop_to_name(prop), cr)); 331789Sahrens } 332789Sahrens 3334543Smarks int 3344543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) 3354543Smarks { 3364543Smarks int error; 3374543Smarks 3384543Smarks error = zfs_dozonecheck(zc->zc_name, cr); 3394543Smarks if (error) 3404543Smarks return (error); 3414543Smarks 3424543Smarks /* 3434543Smarks * permission to set permissions will be evaluated later in 3444543Smarks * dsl_deleg_can_allow() 3454543Smarks */ 3464543Smarks return (0); 3474543Smarks } 3484543Smarks 3494543Smarks int 3504543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) 3514543Smarks { 3524543Smarks int error; 3534543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3544543Smarks ZFS_DELEG_PERM_ROLLBACK, cr); 3554543Smarks if (error == 0) 3564543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3574543Smarks ZFS_DELEG_PERM_MOUNT, cr); 3584543Smarks return (error); 3594543Smarks } 3604543Smarks 3614543Smarks int 3624543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) 3634543Smarks { 3644543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 3654543Smarks ZFS_DELEG_PERM_SEND, cr)); 3664543Smarks } 3674543Smarks 3684543Smarks int 3694543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) 3704543Smarks { 3714543Smarks if (!INGLOBALZONE(curproc)) 3724543Smarks return (EPERM); 3734543Smarks 3745367Sahrens if (secpolicy_nfs(cr) == 0) { 3754543Smarks return (0); 3764543Smarks } else { 3774543Smarks vnode_t *vp; 3784543Smarks int error; 3794543Smarks 3804543Smarks if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, 3814543Smarks NO_FOLLOW, NULL, &vp)) != 0) 3824543Smarks return (error); 3834543Smarks 3844543Smarks /* Now make sure mntpnt and dataset are ZFS */ 3854543Smarks 3864543Smarks if (vp->v_vfsp->vfs_fstype != zfsfstype || 3874543Smarks (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), 3884543Smarks zc->zc_name) != 0)) { 3894543Smarks VN_RELE(vp); 3904543Smarks return (EPERM); 3914543Smarks } 3924543Smarks 3934543Smarks VN_RELE(vp); 3944543Smarks return (dsl_deleg_access(zc->zc_name, 3954543Smarks ZFS_DELEG_PERM_SHARE, cr)); 3964543Smarks } 3974543Smarks } 3984543Smarks 399789Sahrens static int 4004543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize) 401789Sahrens { 402789Sahrens char *cp; 403789Sahrens 404789Sahrens /* 405789Sahrens * Remove the @bla or /bla from the end of the name to get the parent. 406789Sahrens */ 4074543Smarks (void) strncpy(parent, datasetname, parentsize); 4084543Smarks cp = strrchr(parent, '@'); 409789Sahrens if (cp != NULL) { 410789Sahrens cp[0] = '\0'; 411789Sahrens } else { 4124543Smarks cp = strrchr(parent, '/'); 413789Sahrens if (cp == NULL) 414789Sahrens return (ENOENT); 415789Sahrens cp[0] = '\0'; 416789Sahrens } 417789Sahrens 4184543Smarks return (0); 4194543Smarks } 4204543Smarks 4214543Smarks int 4224543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 4234543Smarks { 4244543Smarks int error; 4254543Smarks 4264543Smarks if ((error = zfs_secpolicy_write_perms(name, 4274543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4284543Smarks return (error); 4294543Smarks 4304543Smarks return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); 4314543Smarks } 4324543Smarks 4334543Smarks static int 4344543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) 4354543Smarks { 4364543Smarks return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); 4374543Smarks } 4384543Smarks 4394543Smarks /* 4404543Smarks * Must have sys_config privilege to check the iscsi permission 4414543Smarks */ 4424543Smarks /* ARGSUSED */ 4434543Smarks static int 4444543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) 4454543Smarks { 4464543Smarks return (secpolicy_zfs(cr)); 4474543Smarks } 4484543Smarks 4494543Smarks int 4504543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 4514543Smarks { 4524543Smarks char parentname[MAXNAMELEN]; 4534543Smarks int error; 4544543Smarks 4554543Smarks if ((error = zfs_secpolicy_write_perms(from, 4564543Smarks ZFS_DELEG_PERM_RENAME, cr)) != 0) 4574543Smarks return (error); 4584543Smarks 4594543Smarks if ((error = zfs_secpolicy_write_perms(from, 4604543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4614543Smarks return (error); 4624543Smarks 4634543Smarks if ((error = zfs_get_parent(to, parentname, 4644543Smarks sizeof (parentname))) != 0) 4654543Smarks return (error); 4664543Smarks 4674543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4684543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 4694543Smarks return (error); 4704543Smarks 4714543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4724543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4734543Smarks return (error); 4744543Smarks 4754543Smarks return (error); 4764543Smarks } 4774543Smarks 4784543Smarks static int 4794543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) 4804543Smarks { 4814543Smarks return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); 4824543Smarks } 4834543Smarks 4844543Smarks static int 4854543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) 4864543Smarks { 4874543Smarks char parentname[MAXNAMELEN]; 4884543Smarks objset_t *clone; 4894543Smarks int error; 4904543Smarks 4914543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4924543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4934543Smarks if (error) 4944543Smarks return (error); 4954543Smarks 4964543Smarks error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 4974543Smarks DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 4984543Smarks 4994543Smarks if (error == 0) { 5004543Smarks dsl_dataset_t *pclone = NULL; 5014543Smarks dsl_dir_t *dd; 5024543Smarks dd = clone->os->os_dsl_dataset->ds_dir; 5034543Smarks 5044543Smarks rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 5054543Smarks error = dsl_dataset_open_obj(dd->dd_pool, 5065367Sahrens dd->dd_phys->dd_origin_obj, NULL, 5074543Smarks DS_MODE_NONE, FTAG, &pclone); 5084543Smarks rw_exit(&dd->dd_pool->dp_config_rwlock); 5094543Smarks if (error) { 5104543Smarks dmu_objset_close(clone); 5114543Smarks return (error); 5124543Smarks } 5134543Smarks 5144543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 5154543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5164543Smarks 5174543Smarks dsl_dataset_name(pclone, parentname); 5184543Smarks dmu_objset_close(clone); 5194543Smarks dsl_dataset_close(pclone, DS_MODE_NONE, FTAG); 5204543Smarks if (error == 0) 5214543Smarks error = zfs_secpolicy_write_perms(parentname, 5224543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 5234543Smarks } 5244543Smarks return (error); 5254543Smarks } 5264543Smarks 5274543Smarks static int 5284543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) 5294543Smarks { 5304543Smarks int error; 5314543Smarks 5324543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5334543Smarks ZFS_DELEG_PERM_RECEIVE, cr)) != 0) 5344543Smarks return (error); 5354543Smarks 5364543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5374543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 5384543Smarks return (error); 5394543Smarks 5404543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 5414543Smarks ZFS_DELEG_PERM_CREATE, cr)); 5424543Smarks } 5434543Smarks 5444543Smarks int 5454543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 5464543Smarks { 5474543Smarks int error; 5484543Smarks 5494543Smarks if ((error = zfs_secpolicy_write_perms(name, 5504543Smarks ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) 5514543Smarks return (error); 5524543Smarks 5534543Smarks error = zfs_secpolicy_write_perms(name, 5544543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5554543Smarks 5564543Smarks return (error); 5574543Smarks } 5584543Smarks 5594543Smarks static int 5604543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) 5614543Smarks { 5624543Smarks 5634543Smarks return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); 5644543Smarks } 5654543Smarks 5664543Smarks static int 5674543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) 5684543Smarks { 5694543Smarks char parentname[MAXNAMELEN]; 5704543Smarks int error; 5714543Smarks 5724543Smarks if ((error = zfs_get_parent(zc->zc_name, parentname, 5734543Smarks sizeof (parentname))) != 0) 5744543Smarks return (error); 5754543Smarks 5764543Smarks if (zc->zc_value[0] != '\0') { 5774543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_value, 5784543Smarks ZFS_DELEG_PERM_CLONE, cr)) != 0) 5794543Smarks return (error); 5804543Smarks } 5814543Smarks 5824543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 5834543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 5844543Smarks return (error); 5854543Smarks 5864543Smarks error = zfs_secpolicy_write_perms(parentname, 5874543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5884543Smarks 5894543Smarks return (error); 5904543Smarks } 5914543Smarks 5924543Smarks static int 5934543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) 5944543Smarks { 5954543Smarks int error; 5964543Smarks 5974543Smarks error = secpolicy_fs_unmount(cr, NULL); 5984543Smarks if (error) { 5994543Smarks error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); 6004543Smarks } 6014543Smarks return (error); 602789Sahrens } 603789Sahrens 604789Sahrens /* 605789Sahrens * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires 606789Sahrens * SYS_CONFIG privilege, which is not available in a local zone. 607789Sahrens */ 608789Sahrens /* ARGSUSED */ 609789Sahrens static int 6104543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) 611789Sahrens { 612789Sahrens if (secpolicy_sys_config(cr, B_FALSE) != 0) 613789Sahrens return (EPERM); 614789Sahrens 615789Sahrens return (0); 616789Sahrens } 617789Sahrens 618789Sahrens /* 6194543Smarks * Just like zfs_secpolicy_config, except that we will check for 6204543Smarks * mount permission on the dataset for permission to create/remove 6214543Smarks * the minor nodes. 6224543Smarks */ 6234543Smarks static int 6244543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) 6254543Smarks { 6264543Smarks if (secpolicy_sys_config(cr, B_FALSE) != 0) { 6274543Smarks return (dsl_deleg_access(zc->zc_name, 6284543Smarks ZFS_DELEG_PERM_MOUNT, cr)); 6294543Smarks } 6304543Smarks 6314543Smarks return (0); 6324543Smarks } 6334543Smarks 6344543Smarks /* 6351544Seschrock * Policy for fault injection. Requires all privileges. 6361544Seschrock */ 6371544Seschrock /* ARGSUSED */ 6381544Seschrock static int 6394543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) 6401544Seschrock { 6411544Seschrock return (secpolicy_zinject(cr)); 6421544Seschrock } 6431544Seschrock 6444849Sahrens static int 6454849Sahrens zfs_secpolicy_inherit(zfs_cmd_t *zc, cred_t *cr) 6464849Sahrens { 6474849Sahrens zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); 6484849Sahrens 6495094Slling if (prop == ZPROP_INVAL) { 6504849Sahrens if (!zfs_prop_user(zc->zc_value)) 6514849Sahrens return (EINVAL); 6524849Sahrens return (zfs_secpolicy_write_perms(zc->zc_name, 6534849Sahrens ZFS_DELEG_PERM_USERPROP, cr)); 6544849Sahrens } else { 6554849Sahrens if (!zfs_prop_inheritable(prop)) 6564849Sahrens return (EINVAL); 6574849Sahrens return (zfs_secpolicy_setprop(zc->zc_name, prop, cr)); 6584849Sahrens } 6594849Sahrens } 6604849Sahrens 6611544Seschrock /* 662789Sahrens * Returns the nvlist as specified by the user in the zfs_cmd_t. 663789Sahrens */ 664789Sahrens static int 6655094Slling get_nvlist(uint64_t nvl, uint64_t size, nvlist_t **nvp) 666789Sahrens { 667789Sahrens char *packed; 668789Sahrens int error; 6695094Slling nvlist_t *list = NULL; 670789Sahrens 671789Sahrens /* 6722676Seschrock * Read in and unpack the user-supplied nvlist. 673789Sahrens */ 6745094Slling if (size == 0) 675789Sahrens return (EINVAL); 676789Sahrens 677789Sahrens packed = kmem_alloc(size, KM_SLEEP); 678789Sahrens 6795094Slling if ((error = xcopyin((void *)(uintptr_t)nvl, packed, size)) != 0) { 680789Sahrens kmem_free(packed, size); 681789Sahrens return (error); 682789Sahrens } 683789Sahrens 6845094Slling if ((error = nvlist_unpack(packed, size, &list, 0)) != 0) { 685789Sahrens kmem_free(packed, size); 686789Sahrens return (error); 687789Sahrens } 688789Sahrens 689789Sahrens kmem_free(packed, size); 690789Sahrens 6915094Slling *nvp = list; 692789Sahrens return (0); 693789Sahrens } 694789Sahrens 695789Sahrens static int 6962676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 6972676Seschrock { 6982676Seschrock char *packed = NULL; 6992676Seschrock size_t size; 7002676Seschrock int error; 7012676Seschrock 7022676Seschrock VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 7032676Seschrock 7042676Seschrock if (size > zc->zc_nvlist_dst_size) { 7052676Seschrock error = ENOMEM; 7062676Seschrock } else { 7074611Smarks packed = kmem_alloc(size, KM_SLEEP); 7082676Seschrock VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 7092676Seschrock KM_SLEEP) == 0); 7102676Seschrock error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 7112676Seschrock size); 7122676Seschrock kmem_free(packed, size); 7132676Seschrock } 7142676Seschrock 7152676Seschrock zc->zc_nvlist_dst_size = size; 7162676Seschrock return (error); 7172676Seschrock } 7182676Seschrock 7192676Seschrock static int 720789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc) 721789Sahrens { 722789Sahrens int error; 7235094Slling nvlist_t *config, *props = NULL; 7244715Sek110237 char *buf; 725789Sahrens 7265094Slling if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7275094Slling &config)) 7284988Sek110237 return (error); 7294715Sek110237 7305094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7315094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7325094Slling nvlist_free(config); 7335094Slling return (error); 7345094Slling } 7355094Slling 7364988Sek110237 buf = history_str_get(zc); 737789Sahrens 7385094Slling error = spa_create(zc->zc_name, config, props, buf); 739789Sahrens 7404988Sek110237 if (buf != NULL) 7414988Sek110237 history_str_free(buf); 7425094Slling 743789Sahrens nvlist_free(config); 744789Sahrens 7455094Slling if (props) 7465094Slling nvlist_free(props); 7475094Slling 748789Sahrens return (error); 749789Sahrens } 750789Sahrens 751789Sahrens static int 752789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc) 753789Sahrens { 7544543Smarks int error; 7554543Smarks zfs_log_history(zc); 7564543Smarks error = spa_destroy(zc->zc_name); 7574543Smarks return (error); 758789Sahrens } 759789Sahrens 760789Sahrens static int 761789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc) 762789Sahrens { 763789Sahrens int error; 7645094Slling nvlist_t *config, *props = NULL; 765789Sahrens uint64_t guid; 766789Sahrens 7675094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7685094Slling &config)) != 0) 769789Sahrens return (error); 770789Sahrens 7715094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7725094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7735094Slling nvlist_free(config); 7745094Slling return (error); 7755094Slling } 7765094Slling 777789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 7781544Seschrock guid != zc->zc_guid) 779789Sahrens error = EINVAL; 780789Sahrens else 7815094Slling error = spa_import(zc->zc_name, config, props); 782789Sahrens 783789Sahrens nvlist_free(config); 784789Sahrens 7855094Slling if (props) 7865094Slling nvlist_free(props); 7875094Slling 788789Sahrens return (error); 789789Sahrens } 790789Sahrens 791789Sahrens static int 792789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc) 793789Sahrens { 7944543Smarks int error; 7954543Smarks zfs_log_history(zc); 7964543Smarks error = spa_export(zc->zc_name, NULL); 7974543Smarks return (error); 798789Sahrens } 799789Sahrens 800789Sahrens static int 801789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc) 802789Sahrens { 803789Sahrens nvlist_t *configs; 804789Sahrens int error; 805789Sahrens 806789Sahrens if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 807789Sahrens return (EEXIST); 808789Sahrens 8092676Seschrock error = put_nvlist(zc, configs); 810789Sahrens 811789Sahrens nvlist_free(configs); 812789Sahrens 813789Sahrens return (error); 814789Sahrens } 815789Sahrens 816789Sahrens static int 817789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc) 818789Sahrens { 819789Sahrens nvlist_t *config; 820789Sahrens int error; 8211544Seschrock int ret = 0; 822789Sahrens 8232676Seschrock error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 8242676Seschrock sizeof (zc->zc_value)); 825789Sahrens 826789Sahrens if (config != NULL) { 8272676Seschrock ret = put_nvlist(zc, config); 828789Sahrens nvlist_free(config); 8291544Seschrock 8301544Seschrock /* 8311544Seschrock * The config may be present even if 'error' is non-zero. 8321544Seschrock * In this case we return success, and preserve the real errno 8331544Seschrock * in 'zc_cookie'. 8341544Seschrock */ 8351544Seschrock zc->zc_cookie = error; 836789Sahrens } else { 8371544Seschrock ret = error; 838789Sahrens } 839789Sahrens 8401544Seschrock return (ret); 841789Sahrens } 842789Sahrens 843789Sahrens /* 844789Sahrens * Try to import the given pool, returning pool stats as appropriate so that 845789Sahrens * user land knows which devices are available and overall pool health. 846789Sahrens */ 847789Sahrens static int 848789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 849789Sahrens { 850789Sahrens nvlist_t *tryconfig, *config; 851789Sahrens int error; 852789Sahrens 8535094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 8545094Slling &tryconfig)) != 0) 855789Sahrens return (error); 856789Sahrens 857789Sahrens config = spa_tryimport(tryconfig); 858789Sahrens 859789Sahrens nvlist_free(tryconfig); 860789Sahrens 861789Sahrens if (config == NULL) 862789Sahrens return (EINVAL); 863789Sahrens 8642676Seschrock error = put_nvlist(zc, config); 865789Sahrens nvlist_free(config); 866789Sahrens 867789Sahrens return (error); 868789Sahrens } 869789Sahrens 870789Sahrens static int 871789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc) 872789Sahrens { 873789Sahrens spa_t *spa; 874789Sahrens int error; 875789Sahrens 8762926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8772926Sek110237 return (error); 8782926Sek110237 8794808Sek110237 mutex_enter(&spa_namespace_lock); 8802926Sek110237 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); 8814808Sek110237 mutex_exit(&spa_namespace_lock); 8822926Sek110237 8832926Sek110237 spa_close(spa, FTAG); 8842926Sek110237 885789Sahrens return (error); 886789Sahrens } 887789Sahrens 888789Sahrens static int 889789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 890789Sahrens { 891789Sahrens spa_t *spa; 892789Sahrens int error; 893789Sahrens 894789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 895789Sahrens if (error == 0) { 896789Sahrens spa_freeze(spa); 897789Sahrens spa_close(spa, FTAG); 898789Sahrens } 899789Sahrens return (error); 900789Sahrens } 901789Sahrens 902789Sahrens static int 9031760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 9041760Seschrock { 9051760Seschrock spa_t *spa; 9061760Seschrock int error; 9071760Seschrock 9082926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9092926Sek110237 return (error); 9102926Sek110237 9115118Slling if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) { 9125118Slling spa_close(spa, FTAG); 9135118Slling return (EINVAL); 9145118Slling } 9155118Slling 9165094Slling spa_upgrade(spa, zc->zc_cookie); 9172926Sek110237 spa_close(spa, FTAG); 9182926Sek110237 9192926Sek110237 return (error); 9202926Sek110237 } 9212926Sek110237 9222926Sek110237 static int 9232926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 9242926Sek110237 { 9252926Sek110237 spa_t *spa; 9262926Sek110237 char *hist_buf; 9272926Sek110237 uint64_t size; 9282926Sek110237 int error; 9292926Sek110237 9302926Sek110237 if ((size = zc->zc_history_len) == 0) 9312926Sek110237 return (EINVAL); 9322926Sek110237 9332926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9342926Sek110237 return (error); 9352926Sek110237 9364577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 9373863Sek110237 spa_close(spa, FTAG); 9383863Sek110237 return (ENOTSUP); 9393863Sek110237 } 9403863Sek110237 9412926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 9422926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 9432926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 9444543Smarks error = xcopyout(hist_buf, 9454543Smarks (char *)(uintptr_t)zc->zc_history, 9462926Sek110237 zc->zc_history_len); 9472926Sek110237 } 9482926Sek110237 9492926Sek110237 spa_close(spa, FTAG); 9502926Sek110237 kmem_free(hist_buf, size); 9512926Sek110237 return (error); 9522926Sek110237 } 9532926Sek110237 9542926Sek110237 static int 9553444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 9563444Sek110237 { 9573444Sek110237 int error; 9583444Sek110237 9593912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 9603444Sek110237 return (error); 9613444Sek110237 9623444Sek110237 return (0); 9633444Sek110237 } 9643444Sek110237 9653444Sek110237 static int 9663444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 9673444Sek110237 { 9683444Sek110237 objset_t *osp; 9693444Sek110237 int error; 9703444Sek110237 9713444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 9723444Sek110237 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) 9733444Sek110237 return (error); 9743444Sek110237 9753444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 9763444Sek110237 sizeof (zc->zc_value)); 9773444Sek110237 dmu_objset_close(osp); 9783444Sek110237 9793444Sek110237 return (error); 9803444Sek110237 } 9813444Sek110237 9823444Sek110237 static int 983789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 984789Sahrens { 985789Sahrens spa_t *spa; 986789Sahrens int error; 9876423Sgw25295 nvlist_t *config, **l2cache, **spares; 9886423Sgw25295 uint_t nl2cache = 0, nspares = 0; 989789Sahrens 990789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 991789Sahrens if (error != 0) 992789Sahrens return (error); 993789Sahrens 9945450Sbrendan error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 9955450Sbrendan &config); 9965450Sbrendan (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_L2CACHE, 9975450Sbrendan &l2cache, &nl2cache); 9985450Sbrendan 9996423Sgw25295 (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_SPARES, 10006423Sgw25295 &spares, &nspares); 10016423Sgw25295 10023912Slling /* 10033912Slling * A root pool with concatenated devices is not supported. 10046423Sgw25295 * Thus, can not add a device to a root pool. 10056423Sgw25295 * 10066423Sgw25295 * Intent log device can not be added to a rootpool because 10076423Sgw25295 * during mountroot, zil is replayed, a seperated log device 10086423Sgw25295 * can not be accessed during the mountroot time. 10096423Sgw25295 * 10106423Sgw25295 * l2cache and spare devices are ok to be added to a rootpool. 10113912Slling */ 10126423Sgw25295 if (spa->spa_bootfs != 0 && nl2cache == 0 && nspares == 0) { 10133912Slling spa_close(spa, FTAG); 10143912Slling return (EDOM); 10153912Slling } 10163912Slling 10175450Sbrendan if (error == 0) { 1018789Sahrens error = spa_vdev_add(spa, config); 1019789Sahrens nvlist_free(config); 1020789Sahrens } 1021789Sahrens spa_close(spa, FTAG); 1022789Sahrens return (error); 1023789Sahrens } 1024789Sahrens 1025789Sahrens static int 1026789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 1027789Sahrens { 10282082Seschrock spa_t *spa; 10292082Seschrock int error; 10302082Seschrock 10312082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10322082Seschrock if (error != 0) 10332082Seschrock return (error); 10342082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 10352082Seschrock spa_close(spa, FTAG); 10362082Seschrock return (error); 1037789Sahrens } 1038789Sahrens 1039789Sahrens static int 10404451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 1041789Sahrens { 1042789Sahrens spa_t *spa; 1043789Sahrens int error; 10444451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 1045789Sahrens 10462926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1047789Sahrens return (error); 10484451Seschrock switch (zc->zc_cookie) { 10494451Seschrock case VDEV_STATE_ONLINE: 10504451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 10514451Seschrock break; 10524451Seschrock 10534451Seschrock case VDEV_STATE_OFFLINE: 10544451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 10554451Seschrock break; 1056789Sahrens 10574451Seschrock case VDEV_STATE_FAULTED: 10584451Seschrock error = vdev_fault(spa, zc->zc_guid); 10594451Seschrock break; 1060789Sahrens 10614451Seschrock case VDEV_STATE_DEGRADED: 10624451Seschrock error = vdev_degrade(spa, zc->zc_guid); 10634451Seschrock break; 10644451Seschrock 10654451Seschrock default: 10664451Seschrock error = EINVAL; 10674451Seschrock } 10684451Seschrock zc->zc_cookie = newstate; 1069789Sahrens spa_close(spa, FTAG); 1070789Sahrens return (error); 1071789Sahrens } 1072789Sahrens 1073789Sahrens static int 1074789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 1075789Sahrens { 1076789Sahrens spa_t *spa; 1077789Sahrens int replacing = zc->zc_cookie; 1078789Sahrens nvlist_t *config; 1079789Sahrens int error; 1080789Sahrens 10812926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1082789Sahrens return (error); 1083789Sahrens 10845094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 10855094Slling &config)) == 0) { 10861544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 1087789Sahrens nvlist_free(config); 1088789Sahrens } 1089789Sahrens 1090789Sahrens spa_close(spa, FTAG); 1091789Sahrens return (error); 1092789Sahrens } 1093789Sahrens 1094789Sahrens static int 1095789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 1096789Sahrens { 1097789Sahrens spa_t *spa; 1098789Sahrens int error; 1099789Sahrens 11002926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1101789Sahrens return (error); 1102789Sahrens 11031544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1104789Sahrens 1105789Sahrens spa_close(spa, FTAG); 1106789Sahrens return (error); 1107789Sahrens } 1108789Sahrens 1109789Sahrens static int 11101354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 11111354Seschrock { 11121354Seschrock spa_t *spa; 11132676Seschrock char *path = zc->zc_value; 11141544Seschrock uint64_t guid = zc->zc_guid; 11151354Seschrock int error; 11161354Seschrock 11171354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 11181354Seschrock if (error != 0) 11191354Seschrock return (error); 11201354Seschrock 11211354Seschrock error = spa_vdev_setpath(spa, guid, path); 11221354Seschrock spa_close(spa, FTAG); 11231354Seschrock return (error); 11241354Seschrock } 11251354Seschrock 11265498Stimh static int 11275498Stimh zfs_os_open_retry(char *name, objset_t **os) 11285498Stimh { 11295498Stimh int error; 11305498Stimh 11315498Stimh retry: 11325498Stimh error = dmu_objset_open(name, DMU_OST_ANY, 11335498Stimh DS_MODE_STANDARD | DS_MODE_READONLY, os); 11345498Stimh if (error != 0) { 11355498Stimh /* 11365498Stimh * This is ugly: dmu_objset_open() can return EBUSY if 11375498Stimh * the objset is held exclusively. Fortunately this hold is 11385498Stimh * only for a short while, so we retry here. 11395498Stimh * This avoids user code having to handle EBUSY, 11405498Stimh * for example for a "zfs list". 11415498Stimh */ 11425498Stimh if (error == EBUSY) { 11435498Stimh delay(1); 11445498Stimh goto retry; 11455498Stimh } 11465498Stimh } 11475498Stimh return (error); 11485498Stimh } 11495498Stimh 11505367Sahrens /* 11515367Sahrens * inputs: 11525367Sahrens * zc_name name of filesystem 11535367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 11545367Sahrens * 11555367Sahrens * outputs: 11565367Sahrens * zc_objset_stats stats 11575367Sahrens * zc_nvlist_dst property nvlist 11585367Sahrens * zc_nvlist_dst_size size of property nvlist 11595367Sahrens * zc_value alternate root 11605367Sahrens */ 11611354Seschrock static int 1162789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1163789Sahrens { 1164789Sahrens objset_t *os = NULL; 1165789Sahrens int error; 11661356Seschrock nvlist_t *nv; 1167789Sahrens 11685498Stimh if ((error = zfs_os_open_retry(zc->zc_name, &os)) != 0) 1169789Sahrens return (error); 1170789Sahrens 11712885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1172789Sahrens 11732856Snd150628 if (zc->zc_nvlist_dst != 0 && 11741356Seschrock (error = dsl_prop_get_all(os, &nv)) == 0) { 11752885Sahrens dmu_objset_stats(os, nv); 11763087Sahrens /* 11775147Srm160521 * NB: zvol_get_stats() will read the objset contents, 11783087Sahrens * which we aren't supposed to do with a 11793087Sahrens * DS_MODE_STANDARD open, because it could be 11803087Sahrens * inconsistent. So this is a bit of a workaround... 11813087Sahrens */ 11824577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 11834577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 11844577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 11854577Sahrens } 11862676Seschrock error = put_nvlist(zc, nv); 11871356Seschrock nvlist_free(nv); 11881356Seschrock } 1189789Sahrens 11902676Seschrock spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value)); 11911544Seschrock 1192789Sahrens dmu_objset_close(os); 1193789Sahrens return (error); 1194789Sahrens } 1195789Sahrens 11965498Stimh static int 11975498Stimh nvl_add_zplprop(objset_t *os, nvlist_t *props, zfs_prop_t prop) 11985498Stimh { 11995498Stimh uint64_t value; 12005498Stimh int error; 12015498Stimh 12025498Stimh /* 12035498Stimh * zfs_get_zplprop() will either find a value or give us 12045498Stimh * the default value (if there is one). 12055498Stimh */ 12065498Stimh if ((error = zfs_get_zplprop(os, prop, &value)) != 0) 12075498Stimh return (error); 12085498Stimh VERIFY(nvlist_add_uint64(props, zfs_prop_to_name(prop), value) == 0); 12095498Stimh return (0); 12105498Stimh } 12115498Stimh 12125498Stimh /* 12135498Stimh * inputs: 12145498Stimh * zc_name name of filesystem 12155498Stimh * zc_nvlist_dst_size size of buffer for zpl property nvlist 12165498Stimh * 12175498Stimh * outputs: 12185498Stimh * zc_nvlist_dst zpl property nvlist 12195498Stimh * zc_nvlist_dst_size size of zpl property nvlist 12205498Stimh */ 12215498Stimh static int 12225498Stimh zfs_ioc_objset_zplprops(zfs_cmd_t *zc) 12235498Stimh { 12245498Stimh objset_t *os; 12255498Stimh int err; 12265498Stimh 12275498Stimh if ((err = zfs_os_open_retry(zc->zc_name, &os)) != 0) 12285498Stimh return (err); 12295498Stimh 12305498Stimh dmu_objset_fast_stat(os, &zc->zc_objset_stats); 12315498Stimh 12325498Stimh /* 12335498Stimh * NB: nvl_add_zplprop() will read the objset contents, 12345498Stimh * which we aren't supposed to do with a DS_MODE_STANDARD 12355498Stimh * open, because it could be inconsistent. 12365498Stimh */ 12375498Stimh if (zc->zc_nvlist_dst != NULL && 12385498Stimh !zc->zc_objset_stats.dds_inconsistent && 12395498Stimh dmu_objset_type(os) == DMU_OST_ZFS) { 12405498Stimh nvlist_t *nv; 12415498Stimh 12425498Stimh VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) == 0); 12435498Stimh if ((err = nvl_add_zplprop(os, nv, ZFS_PROP_VERSION)) == 0 && 12445498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_NORMALIZE)) == 0 && 12455498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_UTF8ONLY)) == 0 && 12465498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_CASE)) == 0) 12475498Stimh err = put_nvlist(zc, nv); 12485498Stimh nvlist_free(nv); 12495498Stimh } else { 12505498Stimh err = ENOENT; 12515498Stimh } 12525498Stimh dmu_objset_close(os); 12535498Stimh return (err); 12545498Stimh } 12555498Stimh 12565367Sahrens /* 12575367Sahrens * inputs: 12585367Sahrens * zc_name name of filesystem 12595367Sahrens * zc_cookie zap cursor 12605367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 12615367Sahrens * 12625367Sahrens * outputs: 12635367Sahrens * zc_name name of next filesystem 12645367Sahrens * zc_objset_stats stats 12655367Sahrens * zc_nvlist_dst property nvlist 12665367Sahrens * zc_nvlist_dst_size size of property nvlist 12675367Sahrens * zc_value alternate root 12685367Sahrens */ 1269789Sahrens static int 1270789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1271789Sahrens { 1272885Sahrens objset_t *os; 1273789Sahrens int error; 1274789Sahrens char *p; 1275789Sahrens 12765498Stimh if ((error = zfs_os_open_retry(zc->zc_name, &os)) != 0) { 1277885Sahrens if (error == ENOENT) 1278885Sahrens error = ESRCH; 1279885Sahrens return (error); 1280789Sahrens } 1281789Sahrens 1282789Sahrens p = strrchr(zc->zc_name, '/'); 1283789Sahrens if (p == NULL || p[1] != '\0') 1284789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1285789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1286789Sahrens 1287789Sahrens do { 1288885Sahrens error = dmu_dir_list_next(os, 1289885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1290885Sahrens NULL, &zc->zc_cookie); 1291789Sahrens if (error == ENOENT) 1292789Sahrens error = ESRCH; 1293885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1294789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 1295789Sahrens 1296885Sahrens /* 1297885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1298885Sahrens * try to get stats for it. Userland will skip over it. 1299885Sahrens */ 1300885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1301885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1302789Sahrens 1303885Sahrens dmu_objset_close(os); 1304789Sahrens return (error); 1305789Sahrens } 1306789Sahrens 13075367Sahrens /* 13085367Sahrens * inputs: 13095367Sahrens * zc_name name of filesystem 13105367Sahrens * zc_cookie zap cursor 13115367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 13125367Sahrens * 13135367Sahrens * outputs: 13145367Sahrens * zc_name name of next snapshot 13155367Sahrens * zc_objset_stats stats 13165367Sahrens * zc_nvlist_dst property nvlist 13175367Sahrens * zc_nvlist_dst_size size of property nvlist 13185367Sahrens * zc_value alternate root 13195367Sahrens */ 1320789Sahrens static int 1321789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1322789Sahrens { 1323885Sahrens objset_t *os; 1324789Sahrens int error; 1325789Sahrens 13265498Stimh if ((error = zfs_os_open_retry(zc->zc_name, &os)) != 0) { 1327789Sahrens if (error == ENOENT) 1328885Sahrens error = ESRCH; 1329789Sahrens return (error); 1330789Sahrens } 1331789Sahrens 13321003Slling /* 13331003Slling * A dataset name of maximum length cannot have any snapshots, 13341003Slling * so exit immediately. 13351003Slling */ 13361003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1337885Sahrens dmu_objset_close(os); 13381003Slling return (ESRCH); 1339789Sahrens } 1340789Sahrens 1341885Sahrens error = dmu_snapshot_list_next(os, 1342885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 13435663Sck153898 zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie, NULL); 1344789Sahrens if (error == ENOENT) 1345789Sahrens error = ESRCH; 1346789Sahrens 1347885Sahrens if (error == 0) 1348885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1349789Sahrens 13505367Sahrens /* if we failed, undo the @ that we tacked on to zc_name */ 13515367Sahrens if (error != 0) 13525367Sahrens *strchr(zc->zc_name, '@') = '\0'; 13535367Sahrens 1354885Sahrens dmu_objset_close(os); 1355789Sahrens return (error); 1356789Sahrens } 1357789Sahrens 13586423Sgw25295 int 13594787Sahrens zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) 1360789Sahrens { 13612676Seschrock nvpair_t *elem; 13622676Seschrock int error; 13632676Seschrock uint64_t intval; 13642676Seschrock char *strval; 13652676Seschrock 13664543Smarks /* 13674543Smarks * First validate permission to set all of the properties 13684543Smarks */ 13692676Seschrock elem = NULL; 13702676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 13714670Sahrens const char *propname = nvpair_name(elem); 13724670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 13732676Seschrock 13745094Slling if (prop == ZPROP_INVAL) { 13752676Seschrock /* 13762676Seschrock * If this is a user-defined property, it must be a 13772676Seschrock * string, and there is no further validation to do. 13782676Seschrock */ 13792676Seschrock if (!zfs_prop_user(propname) || 13802676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 13812676Seschrock return (EINVAL); 13822676Seschrock 13835331Samw if (error = zfs_secpolicy_write_perms(name, 13845331Samw ZFS_DELEG_PERM_USERPROP, CRED())) 13854670Sahrens return (error); 13864543Smarks continue; 13872676Seschrock } 13882676Seschrock 13894787Sahrens if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 13904670Sahrens return (error); 13912676Seschrock 13924670Sahrens /* 13934670Sahrens * Check that this value is valid for this pool version 13944670Sahrens */ 13954670Sahrens switch (prop) { 13963886Sahl case ZFS_PROP_COMPRESSION: 13973886Sahl /* 13983886Sahl * If the user specified gzip compression, make sure 13993886Sahl * the SPA supports it. We ignore any errors here since 14003886Sahl * we'll catch them later. 14013886Sahl */ 14023886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 14033886Sahl nvpair_value_uint64(elem, &intval) == 0 && 14043886Sahl intval >= ZIO_COMPRESS_GZIP_1 && 14053886Sahl intval <= ZIO_COMPRESS_GZIP_9) { 14065331Samw if (zfs_check_version(name, 14075331Samw SPA_VERSION_GZIP_COMPRESSION)) 14085331Samw return (ENOTSUP); 14093886Sahl } 14103886Sahl break; 14114603Sahrens 14124603Sahrens case ZFS_PROP_COPIES: 14135331Samw if (zfs_check_version(name, SPA_VERSION_DITTO_BLOCKS)) 14145331Samw return (ENOTSUP); 14154603Sahrens break; 14165977Smarks 14175977Smarks case ZFS_PROP_SHARESMB: 14185977Smarks if (zpl_check_version(name, ZPL_VERSION_FUID)) 14195977Smarks return (ENOTSUP); 14205977Smarks break; 14214603Sahrens } 14225331Samw if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 14235331Samw return (error); 14244543Smarks } 14254543Smarks 14264543Smarks elem = NULL; 14274543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 14284670Sahrens const char *propname = nvpair_name(elem); 14294670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 14304543Smarks 14315094Slling if (prop == ZPROP_INVAL) { 14324543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 14334543Smarks error = dsl_prop_set(name, propname, 1, 14344543Smarks strlen(strval) + 1, strval); 14354543Smarks if (error == 0) 14364543Smarks continue; 14374543Smarks else 14384543Smarks return (error); 14394543Smarks } 14402676Seschrock 14412676Seschrock switch (prop) { 14422676Seschrock case ZFS_PROP_QUOTA: 14432676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14444577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 14452676Seschrock return (error); 14462676Seschrock break; 14472676Seschrock 14485378Sck153898 case ZFS_PROP_REFQUOTA: 14495378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14505378Sck153898 (error = dsl_dataset_set_quota(name, intval)) != 0) 14515378Sck153898 return (error); 14525378Sck153898 break; 14535378Sck153898 14542676Seschrock case ZFS_PROP_RESERVATION: 14552676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14562676Seschrock (error = dsl_dir_set_reservation(name, 14572676Seschrock intval)) != 0) 14582676Seschrock return (error); 14592676Seschrock break; 1460789Sahrens 14615378Sck153898 case ZFS_PROP_REFRESERVATION: 14625378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14635378Sck153898 (error = dsl_dataset_set_reservation(name, 14645378Sck153898 intval)) != 0) 14655378Sck153898 return (error); 14665378Sck153898 break; 14675378Sck153898 14682676Seschrock case ZFS_PROP_VOLSIZE: 14692676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14704787Sahrens (error = zvol_set_volsize(name, 14714787Sahrens ddi_driver_major(zfs_dip), intval)) != 0) 14722676Seschrock return (error); 14732676Seschrock break; 14742676Seschrock 14752676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 14762676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14774577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 14784577Sahrens return (error); 14794577Sahrens break; 14804577Sahrens 14814577Sahrens case ZFS_PROP_VERSION: 14824577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14834577Sahrens (error = zfs_set_version(name, intval)) != 0) 14842676Seschrock return (error); 14852676Seschrock break; 14862676Seschrock 14872676Seschrock default: 14882676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 14892676Seschrock if (zfs_prop_get_type(prop) != 14904787Sahrens PROP_TYPE_STRING) 14912676Seschrock return (EINVAL); 14922717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 14932717Seschrock if ((error = dsl_prop_set(name, 14942676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 14952717Seschrock strval)) != 0) 14962717Seschrock return (error); 14972676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 14982885Sahrens const char *unused; 14992885Sahrens 15002717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 15012676Seschrock 15022676Seschrock switch (zfs_prop_get_type(prop)) { 15034787Sahrens case PROP_TYPE_NUMBER: 15042676Seschrock break; 15054787Sahrens case PROP_TYPE_STRING: 15062717Seschrock return (EINVAL); 15074787Sahrens case PROP_TYPE_INDEX: 15082717Seschrock if (zfs_prop_index_to_string(prop, 15092717Seschrock intval, &unused) != 0) 15102717Seschrock return (EINVAL); 15112676Seschrock break; 15122676Seschrock default: 15134577Sahrens cmn_err(CE_PANIC, 15144577Sahrens "unknown property type"); 15152676Seschrock break; 15162676Seschrock } 15172676Seschrock 15182717Seschrock if ((error = dsl_prop_set(name, propname, 15192717Seschrock 8, 1, &intval)) != 0) 15202717Seschrock return (error); 15212676Seschrock } else { 15222676Seschrock return (EINVAL); 15232676Seschrock } 15242676Seschrock break; 15252676Seschrock } 15262676Seschrock } 15272676Seschrock 15282676Seschrock return (0); 1529789Sahrens } 1530789Sahrens 15315367Sahrens /* 15325367Sahrens * inputs: 15335367Sahrens * zc_name name of filesystem 15345367Sahrens * zc_value name of property to inherit 15355367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 15365367Sahrens * 15375367Sahrens * outputs: none 15385367Sahrens */ 1539789Sahrens static int 15402676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1541789Sahrens { 15422676Seschrock nvlist_t *nvl; 15432676Seschrock int error; 1544789Sahrens 15455094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15465094Slling &nvl)) != 0) 15472676Seschrock return (error); 15482676Seschrock 15494787Sahrens error = zfs_set_prop_nvlist(zc->zc_name, nvl); 15504543Smarks 15512676Seschrock nvlist_free(nvl); 15522676Seschrock return (error); 1553789Sahrens } 1554789Sahrens 15555367Sahrens /* 15565367Sahrens * inputs: 15575367Sahrens * zc_name name of filesystem 15585367Sahrens * zc_value name of property to inherit 15595367Sahrens * 15605367Sahrens * outputs: none 15615367Sahrens */ 1562789Sahrens static int 15634849Sahrens zfs_ioc_inherit_prop(zfs_cmd_t *zc) 15644849Sahrens { 15654849Sahrens /* the property name has been validated by zfs_secpolicy_inherit() */ 15664849Sahrens return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 15674849Sahrens } 15684849Sahrens 15694849Sahrens static int 15704098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 15713912Slling { 15725094Slling nvlist_t *props; 15733912Slling spa_t *spa; 15745094Slling int error; 15753912Slling 15765094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15775094Slling &props))) 15783912Slling return (error); 15793912Slling 15803912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 15815094Slling nvlist_free(props); 15823912Slling return (error); 15833912Slling } 15843912Slling 15855094Slling error = spa_prop_set(spa, props); 15863912Slling 15875094Slling nvlist_free(props); 15883912Slling spa_close(spa, FTAG); 15893912Slling 15903912Slling return (error); 15913912Slling } 15923912Slling 15933912Slling static int 15944098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 15953912Slling { 15963912Slling spa_t *spa; 15973912Slling int error; 15983912Slling nvlist_t *nvp = NULL; 15993912Slling 16003912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 16013912Slling return (error); 16023912Slling 16035094Slling error = spa_prop_get(spa, &nvp); 16043912Slling 16053912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 16063912Slling error = put_nvlist(zc, nvp); 16073912Slling else 16083912Slling error = EFAULT; 16093912Slling 16103912Slling spa_close(spa, FTAG); 16113912Slling 16123912Slling if (nvp) 16133912Slling nvlist_free(nvp); 16143912Slling return (error); 16153912Slling } 16163912Slling 16173912Slling static int 16184543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 16194543Smarks { 16204543Smarks nvlist_t *nvp; 16214543Smarks int error; 16224543Smarks uint32_t uid; 16234543Smarks uint32_t gid; 16244543Smarks uint32_t *groups; 16254543Smarks uint_t group_cnt; 16264543Smarks cred_t *usercred; 16274543Smarks 16285094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16295094Slling &nvp)) != 0) { 16304543Smarks return (error); 16314543Smarks } 16324543Smarks 16334543Smarks if ((error = nvlist_lookup_uint32(nvp, 16344543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 16354543Smarks nvlist_free(nvp); 16364543Smarks return (EPERM); 16374543Smarks } 16384543Smarks 16394543Smarks if ((error = nvlist_lookup_uint32(nvp, 16404543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 16414543Smarks nvlist_free(nvp); 16424543Smarks return (EPERM); 16434543Smarks } 16444543Smarks 16454543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 16464543Smarks &groups, &group_cnt)) != 0) { 16474543Smarks nvlist_free(nvp); 16484543Smarks return (EPERM); 16494543Smarks } 16504543Smarks usercred = cralloc(); 16514543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 16524543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 16534543Smarks nvlist_free(nvp); 16544543Smarks crfree(usercred); 16554543Smarks return (EPERM); 16564543Smarks } 16574543Smarks nvlist_free(nvp); 16584543Smarks error = dsl_deleg_access(zc->zc_name, 16594787Sahrens zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); 16604543Smarks crfree(usercred); 16614543Smarks return (error); 16624543Smarks } 16634543Smarks 16645367Sahrens /* 16655367Sahrens * inputs: 16665367Sahrens * zc_name name of filesystem 16675367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 16685367Sahrens * zc_perm_action allow/unallow flag 16695367Sahrens * 16705367Sahrens * outputs: none 16715367Sahrens */ 16724543Smarks static int 16734543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 16744543Smarks { 16754543Smarks int error; 16764543Smarks nvlist_t *fsaclnv = NULL; 16774543Smarks 16785094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16795094Slling &fsaclnv)) != 0) 16804543Smarks return (error); 16814543Smarks 16824543Smarks /* 16834543Smarks * Verify nvlist is constructed correctly 16844543Smarks */ 16854543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 16864543Smarks nvlist_free(fsaclnv); 16874543Smarks return (EINVAL); 16884543Smarks } 16894543Smarks 16904543Smarks /* 16914543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 16924543Smarks * that user is allowed to hand out each permission in 16934543Smarks * the nvlist(s) 16944543Smarks */ 16954543Smarks 16964787Sahrens error = secpolicy_zfs(CRED()); 16974543Smarks if (error) { 16984787Sahrens if (zc->zc_perm_action == B_FALSE) { 16994787Sahrens error = dsl_deleg_can_allow(zc->zc_name, 17004787Sahrens fsaclnv, CRED()); 17014787Sahrens } else { 17024787Sahrens error = dsl_deleg_can_unallow(zc->zc_name, 17034787Sahrens fsaclnv, CRED()); 17044787Sahrens } 17054543Smarks } 17064543Smarks 17074543Smarks if (error == 0) 17084543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 17094543Smarks 17104543Smarks nvlist_free(fsaclnv); 17114543Smarks return (error); 17124543Smarks } 17134543Smarks 17145367Sahrens /* 17155367Sahrens * inputs: 17165367Sahrens * zc_name name of filesystem 17175367Sahrens * 17185367Sahrens * outputs: 17195367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 17205367Sahrens */ 17214543Smarks static int 17224543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 17234543Smarks { 17244543Smarks nvlist_t *nvp; 17254543Smarks int error; 17264543Smarks 17274543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 17284543Smarks error = put_nvlist(zc, nvp); 17294543Smarks nvlist_free(nvp); 17304543Smarks } 17314543Smarks 17324543Smarks return (error); 17334543Smarks } 17344543Smarks 17355367Sahrens /* 17365367Sahrens * inputs: 17375367Sahrens * zc_name name of volume 17385367Sahrens * 17395367Sahrens * outputs: none 17405367Sahrens */ 17414543Smarks static int 1742789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1743789Sahrens { 17444787Sahrens return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); 1745789Sahrens } 1746789Sahrens 17475367Sahrens /* 17485367Sahrens * inputs: 17495367Sahrens * zc_name name of volume 17505367Sahrens * 17515367Sahrens * outputs: none 17525367Sahrens */ 1753789Sahrens static int 1754789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1755789Sahrens { 17562676Seschrock return (zvol_remove_minor(zc->zc_name)); 1757789Sahrens } 1758789Sahrens 1759789Sahrens /* 1760789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1761789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1762789Sahrens * is responsible for releasing the returned vfs pointer. 1763789Sahrens */ 1764789Sahrens static vfs_t * 1765789Sahrens zfs_get_vfs(const char *resource) 1766789Sahrens { 1767789Sahrens struct vfs *vfsp; 1768789Sahrens struct vfs *vfs_found = NULL; 1769789Sahrens 1770789Sahrens vfs_list_read_lock(); 1771789Sahrens vfsp = rootvfs; 1772789Sahrens do { 1773789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1774789Sahrens VFS_HOLD(vfsp); 1775789Sahrens vfs_found = vfsp; 1776789Sahrens break; 1777789Sahrens } 1778789Sahrens vfsp = vfsp->vfs_next; 1779789Sahrens } while (vfsp != rootvfs); 1780789Sahrens vfs_list_unlock(); 1781789Sahrens return (vfs_found); 1782789Sahrens } 1783789Sahrens 17844543Smarks /* ARGSUSED */ 1785789Sahrens static void 17864543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1787789Sahrens { 17885331Samw zfs_creat_t *zct = arg; 17895498Stimh 17905498Stimh zfs_create_fs(os, cr, zct->zct_zplprops, tx); 17915331Samw } 17925331Samw 17935498Stimh #define ZFS_PROP_UNDEFINED ((uint64_t)-1) 17945498Stimh 17955331Samw /* 17965498Stimh * inputs: 17975498Stimh * createprops list of properties requested by creator 17985498Stimh * dataset name of dataset we are creating 17995331Samw * 18005498Stimh * outputs: 18015498Stimh * zplprops values for the zplprops we attach to the master node object 18025331Samw * 18035498Stimh * Determine the settings for utf8only, normalization and 18045498Stimh * casesensitivity. Specific values may have been requested by the 18055498Stimh * creator and/or we can inherit values from the parent dataset. If 18065498Stimh * the file system is of too early a vintage, a creator can not 18075498Stimh * request settings for these properties, even if the requested 18085498Stimh * setting is the default value. We don't actually want to create dsl 18095498Stimh * properties for these, so remove them from the source nvlist after 18105498Stimh * processing. 18115331Samw */ 18125331Samw static int 18135498Stimh zfs_fill_zplprops(const char *dataset, nvlist_t *createprops, 1814*6492Stimh nvlist_t *zplprops, uint64_t zplver, boolean_t *is_ci) 18155331Samw { 18165498Stimh objset_t *os; 18175331Samw char parentname[MAXNAMELEN]; 18185331Samw char *cp; 18195498Stimh uint64_t sense = ZFS_PROP_UNDEFINED; 18205498Stimh uint64_t norm = ZFS_PROP_UNDEFINED; 18215498Stimh uint64_t u8 = ZFS_PROP_UNDEFINED; 18225498Stimh int error = 0; 18235498Stimh 18245498Stimh ASSERT(zplprops != NULL); 18255498Stimh 18265498Stimh (void) strlcpy(parentname, dataset, sizeof (parentname)); 18275498Stimh cp = strrchr(parentname, '/'); 18285498Stimh ASSERT(cp != NULL); 18295498Stimh cp[0] = '\0'; 18305331Samw 18315375Stimh /* 18325498Stimh * Pull out creator prop choices, if any. 18335375Stimh */ 18345498Stimh if (createprops) { 18355498Stimh (void) nvlist_lookup_uint64(createprops, 18365498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE), &norm); 18375498Stimh (void) nvlist_remove_all(createprops, 18385498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE)); 18395498Stimh (void) nvlist_lookup_uint64(createprops, 18405498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY), &u8); 18415498Stimh (void) nvlist_remove_all(createprops, 18425498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY)); 18435498Stimh (void) nvlist_lookup_uint64(createprops, 18445498Stimh zfs_prop_to_name(ZFS_PROP_CASE), &sense); 18455498Stimh (void) nvlist_remove_all(createprops, 18465498Stimh zfs_prop_to_name(ZFS_PROP_CASE)); 18475331Samw } 18485331Samw 18495375Stimh /* 18505498Stimh * If the file system or pool is version is too "young" to 18515498Stimh * support normalization and the creator tried to set a value 18525498Stimh * for one of the props, error out. We only need check the 18535498Stimh * ZPL version because we've already checked by now that the 18545498Stimh * SPA version is compatible with the selected ZPL version. 18555498Stimh */ 18565498Stimh if (zplver < ZPL_VERSION_NORMALIZATION && 18575498Stimh (norm != ZFS_PROP_UNDEFINED || u8 != ZFS_PROP_UNDEFINED || 18585498Stimh sense != ZFS_PROP_UNDEFINED)) 18595498Stimh return (ENOTSUP); 18605498Stimh 18615498Stimh /* 18625498Stimh * Put the version in the zplprops 18635498Stimh */ 18645498Stimh VERIFY(nvlist_add_uint64(zplprops, 18655498Stimh zfs_prop_to_name(ZFS_PROP_VERSION), zplver) == 0); 18665498Stimh 18675498Stimh /* 18685498Stimh * Open parent object set so we can inherit zplprop values if 18695498Stimh * necessary. 18705375Stimh */ 18715498Stimh if ((error = zfs_os_open_retry(parentname, &os)) != 0) 18725498Stimh return (error); 18735498Stimh 18745498Stimh if (norm == ZFS_PROP_UNDEFINED) 18755498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &norm) == 0); 18765498Stimh VERIFY(nvlist_add_uint64(zplprops, 18775498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE), norm) == 0); 18785498Stimh 18795498Stimh /* 18805498Stimh * If we're normalizing, names must always be valid UTF-8 strings. 18815498Stimh */ 18825498Stimh if (norm) 18835498Stimh u8 = 1; 18845498Stimh if (u8 == ZFS_PROP_UNDEFINED) 18855498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &u8) == 0); 18865498Stimh VERIFY(nvlist_add_uint64(zplprops, 18875498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY), u8) == 0); 18885498Stimh 18895498Stimh if (sense == ZFS_PROP_UNDEFINED) 18905498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_CASE, &sense) == 0); 18915498Stimh VERIFY(nvlist_add_uint64(zplprops, 18925498Stimh zfs_prop_to_name(ZFS_PROP_CASE), sense) == 0); 18935498Stimh 1894*6492Stimh if (is_ci) 1895*6492Stimh *is_ci = (sense == ZFS_CASE_INSENSITIVE); 1896*6492Stimh 18975498Stimh dmu_objset_close(os); 18985331Samw return (0); 1899789Sahrens } 1900789Sahrens 19015367Sahrens /* 19025367Sahrens * inputs: 19035367Sahrens * zc_objset_type type of objset to create (fs vs zvol) 19045367Sahrens * zc_name name of new objset 19055367Sahrens * zc_value name of snapshot to clone from (may be empty) 19065367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 19075367Sahrens * 19085498Stimh * outputs: none 19095367Sahrens */ 1910789Sahrens static int 1911789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1912789Sahrens { 1913789Sahrens objset_t *clone; 1914789Sahrens int error = 0; 19155331Samw zfs_creat_t zct; 19164543Smarks nvlist_t *nvprops = NULL; 19174543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1918789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1919789Sahrens 1920789Sahrens switch (type) { 1921789Sahrens 1922789Sahrens case DMU_OST_ZFS: 1923789Sahrens cbfunc = zfs_create_cb; 1924789Sahrens break; 1925789Sahrens 1926789Sahrens case DMU_OST_ZVOL: 1927789Sahrens cbfunc = zvol_create_cb; 1928789Sahrens break; 1929789Sahrens 1930789Sahrens default: 19312199Sahrens cbfunc = NULL; 19326423Sgw25295 break; 19332199Sahrens } 19345326Sek110237 if (strchr(zc->zc_name, '@') || 19355326Sek110237 strchr(zc->zc_name, '%')) 1936789Sahrens return (EINVAL); 1937789Sahrens 19382676Seschrock if (zc->zc_nvlist_src != NULL && 19395094Slling (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 19405094Slling &nvprops)) != 0) 19412676Seschrock return (error); 19422676Seschrock 19435498Stimh zct.zct_zplprops = NULL; 19445331Samw zct.zct_props = nvprops; 19455331Samw 19462676Seschrock if (zc->zc_value[0] != '\0') { 1947789Sahrens /* 1948789Sahrens * We're creating a clone of an existing snapshot. 1949789Sahrens */ 19502676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 19512676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 19524543Smarks nvlist_free(nvprops); 1953789Sahrens return (EINVAL); 19542676Seschrock } 1955789Sahrens 19562676Seschrock error = dmu_objset_open(zc->zc_value, type, 1957789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 19582676Seschrock if (error) { 19594543Smarks nvlist_free(nvprops); 1960789Sahrens return (error); 19612676Seschrock } 1962*6492Stimh 1963*6492Stimh error = dmu_objset_create(zc->zc_name, type, clone, 0, 1964*6492Stimh NULL, NULL); 19655331Samw if (error) { 19665331Samw dmu_objset_close(clone); 19675331Samw nvlist_free(nvprops); 19685331Samw return (error); 19695331Samw } 1970789Sahrens dmu_objset_close(clone); 1971789Sahrens } else { 1972*6492Stimh boolean_t is_insensitive = B_FALSE; 1973*6492Stimh 19742676Seschrock if (cbfunc == NULL) { 19754543Smarks nvlist_free(nvprops); 19762199Sahrens return (EINVAL); 19772676Seschrock } 19782676Seschrock 1979789Sahrens if (type == DMU_OST_ZVOL) { 19802676Seschrock uint64_t volsize, volblocksize; 19812676Seschrock 19824543Smarks if (nvprops == NULL || 19834543Smarks nvlist_lookup_uint64(nvprops, 19842676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 19852676Seschrock &volsize) != 0) { 19864543Smarks nvlist_free(nvprops); 19872676Seschrock return (EINVAL); 19882676Seschrock } 19892676Seschrock 19904543Smarks if ((error = nvlist_lookup_uint64(nvprops, 19912676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 19922676Seschrock &volblocksize)) != 0 && error != ENOENT) { 19934543Smarks nvlist_free(nvprops); 19942676Seschrock return (EINVAL); 19952676Seschrock } 19961133Seschrock 19972676Seschrock if (error != 0) 19982676Seschrock volblocksize = zfs_prop_default_numeric( 19992676Seschrock ZFS_PROP_VOLBLOCKSIZE); 20002676Seschrock 20012676Seschrock if ((error = zvol_check_volblocksize( 20022676Seschrock volblocksize)) != 0 || 20032676Seschrock (error = zvol_check_volsize(volsize, 20042676Seschrock volblocksize)) != 0) { 20054543Smarks nvlist_free(nvprops); 2006789Sahrens return (error); 20072676Seschrock } 20084577Sahrens } else if (type == DMU_OST_ZFS) { 20094577Sahrens uint64_t version; 20105331Samw int error; 20115331Samw 20125498Stimh /* 20135498Stimh * Default ZPL version to non-FUID capable if the 20145498Stimh * pool is not upgraded to support FUIDs. 20155498Stimh */ 20165498Stimh if (zfs_check_version(zc->zc_name, SPA_VERSION_FUID)) 20175498Stimh version = ZPL_VERSION_FUID - 1; 20185498Stimh else 20195498Stimh version = ZPL_VERSION; 20205498Stimh 20215498Stimh /* 20225498Stimh * Potentially override default ZPL version based 20235498Stimh * on creator's request. 20245498Stimh */ 20255498Stimh (void) nvlist_lookup_uint64(nvprops, 20265331Samw zfs_prop_to_name(ZFS_PROP_VERSION), &version); 20275331Samw 20285498Stimh /* 20295498Stimh * Make sure version we ended up with is kosher 20305498Stimh */ 20315498Stimh if ((version < ZPL_VERSION_INITIAL || 20325498Stimh version > ZPL_VERSION) || 20335498Stimh (version >= ZPL_VERSION_FUID && 20345498Stimh zfs_check_version(zc->zc_name, SPA_VERSION_FUID))) { 20355331Samw nvlist_free(nvprops); 20365331Samw return (ENOTSUP); 20375331Samw } 20385331Samw 20395331Samw /* 20405331Samw * We have to have normalization and 20415331Samw * case-folding flags correct when we do the 20425331Samw * file system creation, so go figure them out 20435498Stimh * now. 20445331Samw */ 20455498Stimh VERIFY(nvlist_alloc(&zct.zct_zplprops, 20465498Stimh NV_UNIQUE_NAME, KM_SLEEP) == 0); 20475498Stimh error = zfs_fill_zplprops(zc->zc_name, nvprops, 2048*6492Stimh zct.zct_zplprops, version, &is_insensitive); 20495331Samw if (error != 0) { 20505331Samw nvlist_free(nvprops); 20515498Stimh nvlist_free(zct.zct_zplprops); 20525331Samw return (error); 20534577Sahrens } 20542676Seschrock } 2055*6492Stimh error = dmu_objset_create(zc->zc_name, type, NULL, 2056*6492Stimh is_insensitive ? DS_FLAG_CI_DATASET : 0, cbfunc, &zct); 20575498Stimh nvlist_free(zct.zct_zplprops); 2058789Sahrens } 20592676Seschrock 20602676Seschrock /* 20612676Seschrock * It would be nice to do this atomically. 20622676Seschrock */ 20632676Seschrock if (error == 0) { 20644787Sahrens if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) 20652676Seschrock (void) dmu_objset_destroy(zc->zc_name); 20662676Seschrock } 20674543Smarks nvlist_free(nvprops); 2068789Sahrens return (error); 2069789Sahrens } 2070789Sahrens 20715367Sahrens /* 20725367Sahrens * inputs: 20735367Sahrens * zc_name name of filesystem 20745367Sahrens * zc_value short name of snapshot 20755367Sahrens * zc_cookie recursive flag 20765367Sahrens * 20775367Sahrens * outputs: none 20785367Sahrens */ 2079789Sahrens static int 20802199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 20812199Sahrens { 20822676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 20832199Sahrens return (EINVAL); 20842199Sahrens return (dmu_objset_snapshot(zc->zc_name, 20852676Seschrock zc->zc_value, zc->zc_cookie)); 20862199Sahrens } 20872199Sahrens 20884007Smmusante int 20892199Sahrens zfs_unmount_snap(char *name, void *arg) 2090789Sahrens { 20912199Sahrens char *snapname = arg; 20922199Sahrens char *cp; 20932417Sahrens vfs_t *vfsp = NULL; 20942199Sahrens 20952199Sahrens /* 20962199Sahrens * Snapshots (which are under .zfs control) must be unmounted 20972199Sahrens * before they can be destroyed. 20982199Sahrens */ 20992199Sahrens 21002199Sahrens if (snapname) { 21012199Sahrens (void) strcat(name, "@"); 21022199Sahrens (void) strcat(name, snapname); 21032199Sahrens vfsp = zfs_get_vfs(name); 21042199Sahrens cp = strchr(name, '@'); 21052199Sahrens *cp = '\0'; 21062417Sahrens } else if (strchr(name, '@')) { 21072199Sahrens vfsp = zfs_get_vfs(name); 21082199Sahrens } 21092199Sahrens 21102199Sahrens if (vfsp) { 21112199Sahrens /* 21122199Sahrens * Always force the unmount for snapshots. 21132199Sahrens */ 21142199Sahrens int flag = MS_FORCE; 2115789Sahrens int err; 2116789Sahrens 21172199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 21182199Sahrens VFS_RELE(vfsp); 21192199Sahrens return (err); 21202199Sahrens } 21212199Sahrens VFS_RELE(vfsp); 21222199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 21232199Sahrens return (err); 21242199Sahrens } 21252199Sahrens return (0); 21262199Sahrens } 21272199Sahrens 21285367Sahrens /* 21295367Sahrens * inputs: 21305367Sahrens * zc_name name of filesystem 21315367Sahrens * zc_value short name of snapshot 21325367Sahrens * 21335367Sahrens * outputs: none 21345367Sahrens */ 21352199Sahrens static int 21362199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 21372199Sahrens { 21382199Sahrens int err; 2139789Sahrens 21402676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 21412199Sahrens return (EINVAL); 21422199Sahrens err = dmu_objset_find(zc->zc_name, 21432676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 21442199Sahrens if (err) 21452199Sahrens return (err); 21462676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 21472199Sahrens } 21482199Sahrens 21495367Sahrens /* 21505367Sahrens * inputs: 21515367Sahrens * zc_name name of dataset to destroy 21525367Sahrens * zc_objset_type type of objset 21535367Sahrens * 21545367Sahrens * outputs: none 21555367Sahrens */ 21562199Sahrens static int 21572199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 21582199Sahrens { 21592199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 21602199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 21612199Sahrens if (err) 21622199Sahrens return (err); 2163789Sahrens } 2164789Sahrens 2165789Sahrens return (dmu_objset_destroy(zc->zc_name)); 2166789Sahrens } 2167789Sahrens 21685367Sahrens /* 21695367Sahrens * inputs: 21705446Sahrens * zc_name name of dataset to rollback (to most recent snapshot) 21715367Sahrens * 21725367Sahrens * outputs: none 21735367Sahrens */ 2174789Sahrens static int 2175789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 2176789Sahrens { 21775446Sahrens objset_t *os; 21785446Sahrens int error; 21795446Sahrens zfsvfs_t *zfsvfs = NULL; 21805446Sahrens 21815446Sahrens /* 21825446Sahrens * Get the zfsvfs for the receiving objset. There 21835446Sahrens * won't be one if we're operating on a zvol, if the 21845446Sahrens * objset doesn't exist yet, or is not mounted. 21855446Sahrens */ 21865446Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 21875446Sahrens DS_MODE_STANDARD, &os); 21885446Sahrens if (error) 21895446Sahrens return (error); 21905446Sahrens 21915446Sahrens if (dmu_objset_type(os) == DMU_OST_ZFS) { 21925446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 21935446Sahrens zfsvfs = dmu_objset_get_user(os); 21945446Sahrens if (zfsvfs != NULL) 21955446Sahrens VFS_HOLD(zfsvfs->z_vfs); 21965446Sahrens mutex_exit(&os->os->os_user_ptr_lock); 21975446Sahrens } 21985446Sahrens 21995446Sahrens if (zfsvfs != NULL) { 22005446Sahrens char osname[MAXNAMELEN]; 22015446Sahrens int mode; 22025446Sahrens 22036083Sek110237 error = zfs_suspend_fs(zfsvfs, osname, &mode); 22046083Sek110237 if (error == 0) { 22056083Sek110237 int resume_err; 22066083Sek110237 22076083Sek110237 ASSERT(strcmp(osname, zc->zc_name) == 0); 22086083Sek110237 error = dmu_objset_rollback(os); 22096083Sek110237 resume_err = zfs_resume_fs(zfsvfs, osname, mode); 22106083Sek110237 error = error ? error : resume_err; 22116083Sek110237 } else { 22126083Sek110237 dmu_objset_close(os); 22136083Sek110237 } 22145446Sahrens VFS_RELE(zfsvfs->z_vfs); 22155446Sahrens } else { 22165446Sahrens error = dmu_objset_rollback(os); 22175446Sahrens } 22185446Sahrens /* Note, the dmu_objset_rollback() closes the objset for us. */ 22195446Sahrens 22205446Sahrens return (error); 2221789Sahrens } 2222789Sahrens 22235367Sahrens /* 22245367Sahrens * inputs: 22255367Sahrens * zc_name old name of dataset 22265367Sahrens * zc_value new name of dataset 22275367Sahrens * zc_cookie recursive flag (only valid for snapshots) 22285367Sahrens * 22295367Sahrens * outputs: none 22305367Sahrens */ 2231789Sahrens static int 2232789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 2233789Sahrens { 22344490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 22354007Smmusante 22362676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 22375326Sek110237 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 22385326Sek110237 strchr(zc->zc_value, '%')) 2239789Sahrens return (EINVAL); 2240789Sahrens 22414007Smmusante /* 22424007Smmusante * Unmount snapshot unless we're doing a recursive rename, 22434007Smmusante * in which case the dataset code figures out which snapshots 22444007Smmusante * to unmount. 22454007Smmusante */ 22464007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 2247789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 22482199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 22492199Sahrens if (err) 22502199Sahrens return (err); 2251789Sahrens } 2252789Sahrens 22534007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 2254789Sahrens } 2255789Sahrens 22565367Sahrens /* 22575367Sahrens * inputs: 22585367Sahrens * zc_name name of containing filesystem 22595367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 22605367Sahrens * zc_value name of snapshot to create 22615367Sahrens * zc_string name of clone origin (if DRR_FLAG_CLONE) 22625367Sahrens * zc_cookie file descriptor to recv from 22635367Sahrens * zc_begin_record the BEGIN record of the stream (not byteswapped) 22645367Sahrens * zc_guid force flag 22655367Sahrens * 22665367Sahrens * outputs: 22675367Sahrens * zc_cookie number of bytes read 22685367Sahrens */ 2269789Sahrens static int 22705367Sahrens zfs_ioc_recv(zfs_cmd_t *zc) 2271789Sahrens { 2272789Sahrens file_t *fp; 22735326Sek110237 objset_t *os; 22745367Sahrens dmu_recv_cookie_t drc; 22755326Sek110237 zfsvfs_t *zfsvfs = NULL; 22765326Sek110237 boolean_t force = (boolean_t)zc->zc_guid; 2277789Sahrens int error, fd; 22785367Sahrens offset_t off; 22795367Sahrens nvlist_t *props = NULL; 22805367Sahrens objset_t *origin = NULL; 22815367Sahrens char *tosnap; 22825367Sahrens char tofs[ZFS_MAXNAMELEN]; 2283789Sahrens 22843265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 22855326Sek110237 strchr(zc->zc_value, '@') == NULL || 22865326Sek110237 strchr(zc->zc_value, '%')) 22873265Sahrens return (EINVAL); 22883265Sahrens 22895367Sahrens (void) strcpy(tofs, zc->zc_value); 22905367Sahrens tosnap = strchr(tofs, '@'); 22915367Sahrens *tosnap = '\0'; 22925367Sahrens tosnap++; 22935367Sahrens 22945367Sahrens if (zc->zc_nvlist_src != NULL && 22955367Sahrens (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 22965367Sahrens &props)) != 0) 22975367Sahrens return (error); 22985367Sahrens 2299789Sahrens fd = zc->zc_cookie; 2300789Sahrens fp = getf(fd); 23015367Sahrens if (fp == NULL) { 23025367Sahrens nvlist_free(props); 2303789Sahrens return (EBADF); 23045367Sahrens } 23055326Sek110237 23065326Sek110237 /* 23075326Sek110237 * Get the zfsvfs for the receiving objset. There 23085326Sek110237 * won't be one if we're operating on a zvol, if the 23095326Sek110237 * objset doesn't exist yet, or is not mounted. 23105326Sek110237 */ 23115367Sahrens 23125446Sahrens error = dmu_objset_open(tofs, DMU_OST_ZFS, 23135326Sek110237 DS_MODE_STANDARD | DS_MODE_READONLY, &os); 23145326Sek110237 if (!error) { 23155446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 23165446Sahrens zfsvfs = dmu_objset_get_user(os); 23176083Sek110237 if (zfsvfs != NULL) { 23185446Sahrens VFS_HOLD(zfsvfs->z_vfs); 23196083Sek110237 mutex_exit(&os->os->os_user_ptr_lock); 23206083Sek110237 if (!mutex_tryenter(&zfsvfs->z_online_recv_lock)) { 23216083Sek110237 VFS_RELE(zfsvfs->z_vfs); 23226083Sek110237 dmu_objset_close(os); 23236083Sek110237 nvlist_free(props); 23246083Sek110237 releasef(fd); 23256083Sek110237 return (EBUSY); 23266083Sek110237 } 23276083Sek110237 } else { 23286083Sek110237 mutex_exit(&os->os->os_user_ptr_lock); 23296083Sek110237 } 23305326Sek110237 dmu_objset_close(os); 23315326Sek110237 } 23325326Sek110237 23335367Sahrens if (zc->zc_string[0]) { 23345367Sahrens error = dmu_objset_open(zc->zc_string, DMU_OST_ANY, 23355367Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &origin); 23365367Sahrens if (error) { 23376083Sek110237 if (zfsvfs != NULL) { 23386083Sek110237 mutex_exit(&zfsvfs->z_online_recv_lock); 23395367Sahrens VFS_RELE(zfsvfs->z_vfs); 23406083Sek110237 } 23415367Sahrens nvlist_free(props); 23425367Sahrens releasef(fd); 23435367Sahrens return (error); 23445367Sahrens } 23455367Sahrens } 23465367Sahrens 23475367Sahrens error = dmu_recv_begin(tofs, tosnap, &zc->zc_begin_record, 23485367Sahrens force, origin, zfsvfs != NULL, &drc); 23495367Sahrens if (origin) 23505367Sahrens dmu_objset_close(origin); 23515367Sahrens if (error) { 23526083Sek110237 if (zfsvfs != NULL) { 23536083Sek110237 mutex_exit(&zfsvfs->z_online_recv_lock); 23545367Sahrens VFS_RELE(zfsvfs->z_vfs); 23556083Sek110237 } 23565367Sahrens nvlist_free(props); 23575367Sahrens releasef(fd); 23585367Sahrens return (error); 23595367Sahrens } 23605326Sek110237 23615326Sek110237 /* 23625367Sahrens * If properties are supplied, they are to completely replace 23635367Sahrens * the existing ones; "inherit" any existing properties. 23645326Sek110237 */ 23655367Sahrens if (props) { 23665367Sahrens objset_t *os; 23675367Sahrens nvlist_t *nv = NULL; 23685367Sahrens 23695367Sahrens error = dmu_objset_open(tofs, DMU_OST_ANY, 23705367Sahrens DS_MODE_STANDARD | DS_MODE_READONLY | DS_MODE_INCONSISTENT, 23715367Sahrens &os); 23725367Sahrens if (error == 0) { 23735367Sahrens error = dsl_prop_get_all(os, &nv); 23745367Sahrens dmu_objset_close(os); 23755367Sahrens } 23765367Sahrens if (error == 0) { 23775367Sahrens nvpair_t *elem; 23785446Sahrens zfs_cmd_t *zc2; 23795446Sahrens zc2 = kmem_alloc(sizeof (zfs_cmd_t), KM_SLEEP); 23805446Sahrens 23815446Sahrens (void) strcpy(zc2->zc_name, tofs); 23825367Sahrens for (elem = nvlist_next_nvpair(nv, NULL); elem; 23835367Sahrens elem = nvlist_next_nvpair(nv, elem)) { 23845446Sahrens (void) strcpy(zc2->zc_value, nvpair_name(elem)); 23855446Sahrens if (zfs_secpolicy_inherit(zc2, CRED()) == 0) 23865446Sahrens (void) zfs_ioc_inherit_prop(zc2); 23875326Sek110237 } 23885446Sahrens kmem_free(zc2, sizeof (zfs_cmd_t)); 23895326Sek110237 } 23905367Sahrens if (nv) 23915367Sahrens nvlist_free(nv); 23925367Sahrens } 23935367Sahrens 23945367Sahrens /* 23955367Sahrens * Set properties. Note, we ignore errors. Would be better to 23965367Sahrens * do best-effort in zfs_set_prop_nvlist, too. 23975367Sahrens */ 23985367Sahrens (void) zfs_set_prop_nvlist(tofs, props); 23995367Sahrens nvlist_free(props); 24005367Sahrens 24015367Sahrens off = fp->f_offset; 24025367Sahrens error = dmu_recv_stream(&drc, fp->f_vnode, &off); 24035367Sahrens 24045367Sahrens if (error == 0) { 24055367Sahrens if (zfsvfs != NULL) { 24065367Sahrens char osname[MAXNAMELEN]; 24075367Sahrens int mode; 24085367Sahrens 24096083Sek110237 error = zfs_suspend_fs(zfsvfs, osname, &mode); 24106083Sek110237 if (error == 0) { 24116083Sek110237 int resume_err; 24126083Sek110237 24136083Sek110237 error = dmu_recv_end(&drc); 24146083Sek110237 resume_err = zfs_resume_fs(zfsvfs, 24156083Sek110237 osname, mode); 24166083Sek110237 error = error ? error : resume_err; 24176083Sek110237 } else { 24186083Sek110237 dmu_recv_abort_cleanup(&drc); 24196083Sek110237 } 24205367Sahrens } else { 24215367Sahrens error = dmu_recv_end(&drc); 24225367Sahrens } 24235326Sek110237 } 24246083Sek110237 if (zfsvfs != NULL) { 24256083Sek110237 mutex_exit(&zfsvfs->z_online_recv_lock); 24265326Sek110237 VFS_RELE(zfsvfs->z_vfs); 24276083Sek110237 } 24285367Sahrens 24295367Sahrens zc->zc_cookie = off - fp->f_offset; 24305367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 24315367Sahrens fp->f_offset = off; 24322885Sahrens 2433789Sahrens releasef(fd); 2434789Sahrens return (error); 2435789Sahrens } 2436789Sahrens 24375367Sahrens /* 24385367Sahrens * inputs: 24395367Sahrens * zc_name name of snapshot to send 24405367Sahrens * zc_value short name of incremental fromsnap (may be empty) 24415367Sahrens * zc_cookie file descriptor to send stream to 24425367Sahrens * zc_obj fromorigin flag (mutually exclusive with zc_value) 24435367Sahrens * 24445367Sahrens * outputs: none 24455367Sahrens */ 2446789Sahrens static int 24475367Sahrens zfs_ioc_send(zfs_cmd_t *zc) 2448789Sahrens { 2449789Sahrens objset_t *fromsnap = NULL; 2450789Sahrens objset_t *tosnap; 2451789Sahrens file_t *fp; 2452789Sahrens int error; 24535367Sahrens offset_t off; 2454789Sahrens 2455789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 2456789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); 2457789Sahrens if (error) 2458789Sahrens return (error); 2459789Sahrens 24602676Seschrock if (zc->zc_value[0] != '\0') { 24612885Sahrens char buf[MAXPATHLEN]; 24622885Sahrens char *cp; 24632885Sahrens 24642885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 24652885Sahrens cp = strchr(buf, '@'); 24662885Sahrens if (cp) 24672885Sahrens *(cp+1) = 0; 24682885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 24692885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 2470789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); 2471789Sahrens if (error) { 2472789Sahrens dmu_objset_close(tosnap); 2473789Sahrens return (error); 2474789Sahrens } 2475789Sahrens } 2476789Sahrens 2477789Sahrens fp = getf(zc->zc_cookie); 2478789Sahrens if (fp == NULL) { 2479789Sahrens dmu_objset_close(tosnap); 2480789Sahrens if (fromsnap) 2481789Sahrens dmu_objset_close(fromsnap); 2482789Sahrens return (EBADF); 2483789Sahrens } 2484789Sahrens 24855367Sahrens off = fp->f_offset; 24865367Sahrens error = dmu_sendbackup(tosnap, fromsnap, zc->zc_obj, fp->f_vnode, &off); 24875367Sahrens 24885367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 24895367Sahrens fp->f_offset = off; 2490789Sahrens releasef(zc->zc_cookie); 2491789Sahrens if (fromsnap) 2492789Sahrens dmu_objset_close(fromsnap); 2493789Sahrens dmu_objset_close(tosnap); 2494789Sahrens return (error); 2495789Sahrens } 2496789Sahrens 24971544Seschrock static int 24981544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 24991544Seschrock { 25001544Seschrock int id, error; 25011544Seschrock 25021544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 25031544Seschrock &zc->zc_inject_record); 25041544Seschrock 25051544Seschrock if (error == 0) 25061544Seschrock zc->zc_guid = (uint64_t)id; 25071544Seschrock 25081544Seschrock return (error); 25091544Seschrock } 25101544Seschrock 25111544Seschrock static int 25121544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 25131544Seschrock { 25141544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 25151544Seschrock } 25161544Seschrock 25171544Seschrock static int 25181544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 25191544Seschrock { 25201544Seschrock int id = (int)zc->zc_guid; 25211544Seschrock int error; 25221544Seschrock 25231544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 25241544Seschrock &zc->zc_inject_record); 25251544Seschrock 25261544Seschrock zc->zc_guid = id; 25271544Seschrock 25281544Seschrock return (error); 25291544Seschrock } 25301544Seschrock 25311544Seschrock static int 25321544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 25331544Seschrock { 25341544Seschrock spa_t *spa; 25351544Seschrock int error; 25362676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 25371544Seschrock 25381544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 25391544Seschrock return (error); 25401544Seschrock 25412676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 25421544Seschrock &count); 25431544Seschrock if (error == 0) 25442676Seschrock zc->zc_nvlist_dst_size = count; 25451544Seschrock else 25462676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 25471544Seschrock 25481544Seschrock spa_close(spa, FTAG); 25491544Seschrock 25501544Seschrock return (error); 25511544Seschrock } 25521544Seschrock 25531544Seschrock static int 25541544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 25551544Seschrock { 25561544Seschrock spa_t *spa; 25571544Seschrock vdev_t *vd; 25584808Sek110237 uint64_t txg; 25591544Seschrock int error; 25601544Seschrock 25611544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 25621544Seschrock return (error); 25631544Seschrock 25645329Sgw25295 /* 25655329Sgw25295 * Try to resume any I/Os which may have been suspended 25665329Sgw25295 * as a result of a complete pool failure. 25675329Sgw25295 */ 25685329Sgw25295 if (!list_is_empty(&spa->spa_zio_list)) { 25695329Sgw25295 if (zio_vdev_resume_io(spa) != 0) { 25705329Sgw25295 spa_close(spa, FTAG); 25715329Sgw25295 return (EIO); 25725329Sgw25295 } 25735329Sgw25295 } 25745329Sgw25295 25754451Seschrock txg = spa_vdev_enter(spa); 25761544Seschrock 25772676Seschrock if (zc->zc_guid == 0) { 25781544Seschrock vd = NULL; 25792676Seschrock } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { 25805450Sbrendan spa_aux_vdev_t *sav; 25815450Sbrendan int i; 25825450Sbrendan 25835450Sbrendan /* 25845450Sbrendan * Check if this is an l2cache device. 25855450Sbrendan */ 25865450Sbrendan ASSERT(spa != NULL); 25875450Sbrendan sav = &spa->spa_l2cache; 25885450Sbrendan for (i = 0; i < sav->sav_count; i++) { 25895450Sbrendan if (sav->sav_vdevs[i]->vdev_guid == zc->zc_guid) { 25905450Sbrendan vd = sav->sav_vdevs[i]; 25915450Sbrendan break; 25925450Sbrendan } 25935450Sbrendan } 25945450Sbrendan 25955450Sbrendan if (vd == NULL) { 25965450Sbrendan (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 25975450Sbrendan spa_close(spa, FTAG); 25985450Sbrendan return (ENODEV); 25995450Sbrendan } 26001544Seschrock } 26011544Seschrock 26025329Sgw25295 vdev_clear(spa, vd, B_TRUE); 26031544Seschrock 26044451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 26051544Seschrock 26061544Seschrock spa_close(spa, FTAG); 26071544Seschrock 26081544Seschrock return (0); 26091544Seschrock } 26101544Seschrock 26115367Sahrens /* 26125367Sahrens * inputs: 26135367Sahrens * zc_name name of filesystem 26145367Sahrens * zc_value name of origin snapshot 26155367Sahrens * 26165367Sahrens * outputs: none 26175367Sahrens */ 26181544Seschrock static int 26192082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 26202082Seschrock { 26212417Sahrens char *cp; 26222417Sahrens 26232417Sahrens /* 26242417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 26252417Sahrens * it's easier. 26262417Sahrens */ 26272676Seschrock cp = strchr(zc->zc_value, '@'); 26282417Sahrens if (cp) 26292417Sahrens *cp = '\0'; 26302676Seschrock (void) dmu_objset_find(zc->zc_value, 26312417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 26322082Seschrock return (dsl_dataset_promote(zc->zc_name)); 26332082Seschrock } 26342082Seschrock 26354543Smarks /* 26364543Smarks * We don't want to have a hard dependency 26374543Smarks * against some special symbols in sharefs 26385331Samw * nfs, and smbsrv. Determine them if needed when 26394543Smarks * the first file system is shared. 26405331Samw * Neither sharefs, nfs or smbsrv are unloadable modules. 26414543Smarks */ 26425331Samw int (*znfsexport_fs)(void *arg); 26434543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 26445331Samw int (*zsmbexport_fs)(void *arg, boolean_t add_share); 26455331Samw 26465331Samw int zfs_nfsshare_inited; 26475331Samw int zfs_smbshare_inited; 26485331Samw 26494543Smarks ddi_modhandle_t nfs_mod; 26504543Smarks ddi_modhandle_t sharefs_mod; 26515331Samw ddi_modhandle_t smbsrv_mod; 26524543Smarks kmutex_t zfs_share_lock; 26534543Smarks 26544543Smarks static int 26555331Samw zfs_init_sharefs() 26565331Samw { 26575331Samw int error; 26585331Samw 26595331Samw ASSERT(MUTEX_HELD(&zfs_share_lock)); 26605331Samw /* Both NFS and SMB shares also require sharetab support. */ 26615331Samw if (sharefs_mod == NULL && ((sharefs_mod = 26625331Samw ddi_modopen("fs/sharefs", 26635331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26645331Samw return (ENOSYS); 26655331Samw } 26665331Samw if (zshare_fs == NULL && ((zshare_fs = 26675331Samw (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 26685331Samw ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 26695331Samw return (ENOSYS); 26705331Samw } 26715331Samw return (0); 26725331Samw } 26735331Samw 26745331Samw static int 26754543Smarks zfs_ioc_share(zfs_cmd_t *zc) 26764543Smarks { 26774543Smarks int error; 26784543Smarks int opcode; 26794543Smarks 26805331Samw switch (zc->zc_share.z_sharetype) { 26815331Samw case ZFS_SHARE_NFS: 26825331Samw case ZFS_UNSHARE_NFS: 26835331Samw if (zfs_nfsshare_inited == 0) { 26845331Samw mutex_enter(&zfs_share_lock); 26855331Samw if (nfs_mod == NULL && ((nfs_mod = ddi_modopen("fs/nfs", 26865331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26875331Samw mutex_exit(&zfs_share_lock); 26885331Samw return (ENOSYS); 26895331Samw } 26905331Samw if (znfsexport_fs == NULL && 26915331Samw ((znfsexport_fs = (int (*)(void *)) 26925331Samw ddi_modsym(nfs_mod, 26935331Samw "nfs_export", &error)) == NULL)) { 26945331Samw mutex_exit(&zfs_share_lock); 26955331Samw return (ENOSYS); 26965331Samw } 26975331Samw error = zfs_init_sharefs(); 26985331Samw if (error) { 26995331Samw mutex_exit(&zfs_share_lock); 27005331Samw return (ENOSYS); 27015331Samw } 27025331Samw zfs_nfsshare_inited = 1; 27034543Smarks mutex_exit(&zfs_share_lock); 27044543Smarks } 27055331Samw break; 27065331Samw case ZFS_SHARE_SMB: 27075331Samw case ZFS_UNSHARE_SMB: 27085331Samw if (zfs_smbshare_inited == 0) { 27095331Samw mutex_enter(&zfs_share_lock); 27105331Samw if (smbsrv_mod == NULL && ((smbsrv_mod = 27115331Samw ddi_modopen("drv/smbsrv", 27125331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 27135331Samw mutex_exit(&zfs_share_lock); 27145331Samw return (ENOSYS); 27155331Samw } 27165331Samw if (zsmbexport_fs == NULL && ((zsmbexport_fs = 27175331Samw (int (*)(void *, boolean_t))ddi_modsym(smbsrv_mod, 27186139Sjb150015 "smb_server_share", &error)) == NULL)) { 27195331Samw mutex_exit(&zfs_share_lock); 27205331Samw return (ENOSYS); 27215331Samw } 27225331Samw error = zfs_init_sharefs(); 27235331Samw if (error) { 27245331Samw mutex_exit(&zfs_share_lock); 27255331Samw return (ENOSYS); 27265331Samw } 27275331Samw zfs_smbshare_inited = 1; 27284543Smarks mutex_exit(&zfs_share_lock); 27294543Smarks } 27305331Samw break; 27315331Samw default: 27325331Samw return (EINVAL); 27334543Smarks } 27344543Smarks 27355331Samw switch (zc->zc_share.z_sharetype) { 27365331Samw case ZFS_SHARE_NFS: 27375331Samw case ZFS_UNSHARE_NFS: 27385331Samw if (error = 27395331Samw znfsexport_fs((void *) 27405331Samw (uintptr_t)zc->zc_share.z_exportdata)) 27415331Samw return (error); 27425331Samw break; 27435331Samw case ZFS_SHARE_SMB: 27445331Samw case ZFS_UNSHARE_SMB: 27455331Samw if (error = zsmbexport_fs((void *) 27465331Samw (uintptr_t)zc->zc_share.z_exportdata, 27475331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB ? 27485331Samw B_TRUE : B_FALSE)) { 27495331Samw return (error); 27505331Samw } 27515331Samw break; 27525331Samw } 27535331Samw 27545331Samw opcode = (zc->zc_share.z_sharetype == ZFS_SHARE_NFS || 27555331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB) ? 27564543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 27574543Smarks 27585331Samw /* 27595331Samw * Add or remove share from sharetab 27605331Samw */ 27614543Smarks error = zshare_fs(opcode, 27624543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 27634543Smarks zc->zc_share.z_sharemax); 27644543Smarks 27654543Smarks return (error); 27664543Smarks 27674543Smarks } 27684543Smarks 27694543Smarks /* 27704988Sek110237 * pool create, destroy, and export don't log the history as part of 27714988Sek110237 * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export 27724988Sek110237 * do the logging of those commands. 27734543Smarks */ 2774789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 27754715Sek110237 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27764577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27774577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27784577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27794577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 27804577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 27814577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27824577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27834577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27844577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27854577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27864577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27874577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27884577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27894577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27904577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27914577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27924577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27935498Stimh { zfs_ioc_objset_zplprops, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27944543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 27954577Sahrens DATASET_NAME, B_FALSE }, 27964543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 27974577Sahrens DATASET_NAME, B_FALSE }, 27984577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 27994577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 28004577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 28014577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 28024577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 28034577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 28044577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 28055367Sahrens { zfs_ioc_recv, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 28065367Sahrens { zfs_ioc_send, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 28074577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 28084577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 28094577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 28104577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 28114577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 28124577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 28134577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 28144577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 28154577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 28164577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 28174577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 28184577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 28194577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 28204577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 28214543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 28224577Sahrens DATASET_NAME, B_FALSE }, 28234849Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }, 28244849Sahrens { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE }, 2825789Sahrens }; 2826789Sahrens 2827789Sahrens static int 2828789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2829789Sahrens { 2830789Sahrens zfs_cmd_t *zc; 2831789Sahrens uint_t vec; 28322199Sahrens int error, rc; 2833789Sahrens 2834789Sahrens if (getminor(dev) != 0) 2835789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2836789Sahrens 2837789Sahrens vec = cmd - ZFS_IOC; 28384787Sahrens ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); 2839789Sahrens 2840789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2841789Sahrens return (EINVAL); 2842789Sahrens 2843789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2844789Sahrens 2845789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2846789Sahrens 28474787Sahrens if (error == 0) 28484543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2849789Sahrens 2850789Sahrens /* 2851789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2852789Sahrens * the lower layers. 2853789Sahrens */ 2854789Sahrens if (error == 0) { 2855789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2856789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 28574577Sahrens case POOL_NAME: 2858789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2859789Sahrens error = EINVAL; 2860789Sahrens break; 2861789Sahrens 28624577Sahrens case DATASET_NAME: 2863789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2864789Sahrens error = EINVAL; 2865789Sahrens break; 28662856Snd150628 28674577Sahrens case NO_NAME: 28682856Snd150628 break; 2869789Sahrens } 2870789Sahrens } 2871789Sahrens 2872789Sahrens if (error == 0) 2873789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2874789Sahrens 28752199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 28764543Smarks if (error == 0) { 28772199Sahrens error = rc; 28784543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 28794543Smarks zfs_log_history(zc); 28804543Smarks } 2881789Sahrens 2882789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2883789Sahrens return (error); 2884789Sahrens } 2885789Sahrens 2886789Sahrens static int 2887789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2888789Sahrens { 2889789Sahrens if (cmd != DDI_ATTACH) 2890789Sahrens return (DDI_FAILURE); 2891789Sahrens 2892789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2893789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2894789Sahrens return (DDI_FAILURE); 2895789Sahrens 2896789Sahrens zfs_dip = dip; 2897789Sahrens 2898789Sahrens ddi_report_dev(dip); 2899789Sahrens 2900789Sahrens return (DDI_SUCCESS); 2901789Sahrens } 2902789Sahrens 2903789Sahrens static int 2904789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2905789Sahrens { 2906789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2907789Sahrens return (DDI_FAILURE); 2908789Sahrens 2909789Sahrens if (cmd != DDI_DETACH) 2910789Sahrens return (DDI_FAILURE); 2911789Sahrens 2912789Sahrens zfs_dip = NULL; 2913789Sahrens 2914789Sahrens ddi_prop_remove_all(dip); 2915789Sahrens ddi_remove_minor_node(dip, NULL); 2916789Sahrens 2917789Sahrens return (DDI_SUCCESS); 2918789Sahrens } 2919789Sahrens 2920789Sahrens /*ARGSUSED*/ 2921789Sahrens static int 2922789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2923789Sahrens { 2924789Sahrens switch (infocmd) { 2925789Sahrens case DDI_INFO_DEVT2DEVINFO: 2926789Sahrens *result = zfs_dip; 2927789Sahrens return (DDI_SUCCESS); 2928789Sahrens 2929789Sahrens case DDI_INFO_DEVT2INSTANCE: 2930849Sbonwick *result = (void *)0; 2931789Sahrens return (DDI_SUCCESS); 2932789Sahrens } 2933789Sahrens 2934789Sahrens return (DDI_FAILURE); 2935789Sahrens } 2936789Sahrens 2937789Sahrens /* 2938789Sahrens * OK, so this is a little weird. 2939789Sahrens * 2940789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2941789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2942789Sahrens * 2943789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2944789Sahrens * so most of the standard driver entry points are in zvol.c. 2945789Sahrens */ 2946789Sahrens static struct cb_ops zfs_cb_ops = { 2947789Sahrens zvol_open, /* open */ 2948789Sahrens zvol_close, /* close */ 2949789Sahrens zvol_strategy, /* strategy */ 2950789Sahrens nodev, /* print */ 29516423Sgw25295 zvol_dump, /* dump */ 2952789Sahrens zvol_read, /* read */ 2953789Sahrens zvol_write, /* write */ 2954789Sahrens zfsdev_ioctl, /* ioctl */ 2955789Sahrens nodev, /* devmap */ 2956789Sahrens nodev, /* mmap */ 2957789Sahrens nodev, /* segmap */ 2958789Sahrens nochpoll, /* poll */ 2959789Sahrens ddi_prop_op, /* prop_op */ 2960789Sahrens NULL, /* streamtab */ 2961789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2962789Sahrens CB_REV, /* version */ 29633638Sbillm nodev, /* async read */ 29643638Sbillm nodev, /* async write */ 2965789Sahrens }; 2966789Sahrens 2967789Sahrens static struct dev_ops zfs_dev_ops = { 2968789Sahrens DEVO_REV, /* version */ 2969789Sahrens 0, /* refcnt */ 2970789Sahrens zfs_info, /* info */ 2971789Sahrens nulldev, /* identify */ 2972789Sahrens nulldev, /* probe */ 2973789Sahrens zfs_attach, /* attach */ 2974789Sahrens zfs_detach, /* detach */ 2975789Sahrens nodev, /* reset */ 2976789Sahrens &zfs_cb_ops, /* driver operations */ 2977789Sahrens NULL /* no bus operations */ 2978789Sahrens }; 2979789Sahrens 2980789Sahrens static struct modldrv zfs_modldrv = { 29814577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 29822676Seschrock &zfs_dev_ops 2983789Sahrens }; 2984789Sahrens 2985789Sahrens static struct modlinkage modlinkage = { 2986789Sahrens MODREV_1, 2987789Sahrens (void *)&zfs_modlfs, 2988789Sahrens (void *)&zfs_modldrv, 2989789Sahrens NULL 2990789Sahrens }; 2991789Sahrens 29924720Sfr157268 29934720Sfr157268 uint_t zfs_fsyncer_key; 29945326Sek110237 extern uint_t rrw_tsd_key; 29954720Sfr157268 2996789Sahrens int 2997789Sahrens _init(void) 2998789Sahrens { 2999789Sahrens int error; 3000789Sahrens 3001849Sbonwick spa_init(FREAD | FWRITE); 3002849Sbonwick zfs_init(); 3003849Sbonwick zvol_init(); 3004849Sbonwick 3005849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 3006849Sbonwick zvol_fini(); 3007849Sbonwick zfs_fini(); 3008849Sbonwick spa_fini(); 3009789Sahrens return (error); 3010849Sbonwick } 3011789Sahrens 30124720Sfr157268 tsd_create(&zfs_fsyncer_key, NULL); 30135326Sek110237 tsd_create(&rrw_tsd_key, NULL); 30144720Sfr157268 3015789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 3016789Sahrens ASSERT(error == 0); 30174543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 3018789Sahrens 3019789Sahrens return (0); 3020789Sahrens } 3021789Sahrens 3022789Sahrens int 3023789Sahrens _fini(void) 3024789Sahrens { 3025789Sahrens int error; 3026789Sahrens 30271544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 3028789Sahrens return (EBUSY); 3029789Sahrens 3030789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 3031789Sahrens return (error); 3032789Sahrens 3033789Sahrens zvol_fini(); 3034789Sahrens zfs_fini(); 3035789Sahrens spa_fini(); 30365331Samw if (zfs_nfsshare_inited) 30374543Smarks (void) ddi_modclose(nfs_mod); 30385331Samw if (zfs_smbshare_inited) 30395331Samw (void) ddi_modclose(smbsrv_mod); 30405331Samw if (zfs_nfsshare_inited || zfs_smbshare_inited) 30414543Smarks (void) ddi_modclose(sharefs_mod); 3042789Sahrens 30434720Sfr157268 tsd_destroy(&zfs_fsyncer_key); 3044789Sahrens ldi_ident_release(zfs_li); 3045789Sahrens zfs_li = NULL; 30464543Smarks mutex_destroy(&zfs_share_lock); 3047789Sahrens 3048789Sahrens return (error); 3049789Sahrens } 3050789Sahrens 3051789Sahrens int 3052789Sahrens _info(struct modinfo *modinfop) 3053789Sahrens { 3054789Sahrens return (mod_info(&modlinkage, modinfop)); 3055789Sahrens } 3056