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 /* 22*5977Smarks * 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 178*5977Smarks /* 179*5977Smarks * zpl_check_version 180*5977Smarks * 181*5977Smarks * Return non-zero if the ZPL version is less than requested version. 182*5977Smarks */ 183*5977Smarks static int 184*5977Smarks zpl_check_version(const char *name, int version) 185*5977Smarks { 186*5977Smarks objset_t *os; 187*5977Smarks int rc = 1; 188*5977Smarks 189*5977Smarks if (dmu_objset_open(name, DMU_OST_ANY, 190*5977Smarks DS_MODE_STANDARD | DS_MODE_READONLY, &os) == 0) { 191*5977Smarks uint64_t propversion; 192*5977Smarks 193*5977Smarks if (zfs_get_zplprop(os, ZFS_PROP_VERSION, 194*5977Smarks &propversion) == 0) { 195*5977Smarks rc = !(propversion >= version); 196*5977Smarks } 197*5977Smarks dmu_objset_close(os); 198*5977Smarks } 199*5977Smarks return (rc); 200*5977Smarks } 201*5977Smarks 2024715Sek110237 static void 2034543Smarks zfs_log_history(zfs_cmd_t *zc) 2044543Smarks { 2054543Smarks spa_t *spa; 2064603Sahrens char *buf; 2074543Smarks 2084715Sek110237 if ((buf = history_str_get(zc)) == NULL) 2094577Sahrens return; 2104577Sahrens 2114715Sek110237 if (spa_open(zc->zc_name, &spa, FTAG) == 0) { 2124715Sek110237 if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY) 2134715Sek110237 (void) spa_history_log(spa, buf, LOG_CMD_NORMAL); 2144715Sek110237 spa_close(spa, FTAG); 2154543Smarks } 2164715Sek110237 history_str_free(buf); 2174543Smarks } 2184543Smarks 219789Sahrens /* 220789Sahrens * Policy for top-level read operations (list pools). Requires no privileges, 221789Sahrens * and can be used in the local zone, as there is no associated dataset. 222789Sahrens */ 223789Sahrens /* ARGSUSED */ 224789Sahrens static int 2254543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) 226789Sahrens { 227789Sahrens return (0); 228789Sahrens } 229789Sahrens 230789Sahrens /* 231789Sahrens * Policy for dataset read operations (list children, get statistics). Requires 232789Sahrens * no privileges, but must be visible in the local zone. 233789Sahrens */ 234789Sahrens /* ARGSUSED */ 235789Sahrens static int 2364543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) 237789Sahrens { 238789Sahrens if (INGLOBALZONE(curproc) || 2394543Smarks zone_dataset_visible(zc->zc_name, NULL)) 240789Sahrens return (0); 241789Sahrens 242789Sahrens return (ENOENT); 243789Sahrens } 244789Sahrens 245789Sahrens static int 246789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr) 247789Sahrens { 248789Sahrens uint64_t zoned; 249789Sahrens int writable = 1; 250789Sahrens 251789Sahrens /* 252789Sahrens * The dataset must be visible by this zone -- check this first 253789Sahrens * so they don't see EPERM on something they shouldn't know about. 254789Sahrens */ 255789Sahrens if (!INGLOBALZONE(curproc) && 256789Sahrens !zone_dataset_visible(dataset, &writable)) 257789Sahrens return (ENOENT); 258789Sahrens 259789Sahrens if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) 260789Sahrens return (ENOENT); 261789Sahrens 262789Sahrens if (INGLOBALZONE(curproc)) { 263789Sahrens /* 264789Sahrens * If the fs is zoned, only root can access it from the 265789Sahrens * global zone. 266789Sahrens */ 267789Sahrens if (secpolicy_zfs(cr) && zoned) 268789Sahrens return (EPERM); 269789Sahrens } else { 270789Sahrens /* 271789Sahrens * If we are in a local zone, the 'zoned' property must be set. 272789Sahrens */ 273789Sahrens if (!zoned) 274789Sahrens return (EPERM); 275789Sahrens 276789Sahrens /* must be writable by this zone */ 277789Sahrens if (!writable) 278789Sahrens return (EPERM); 279789Sahrens } 280789Sahrens return (0); 281789Sahrens } 282789Sahrens 283789Sahrens int 2844543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) 285789Sahrens { 286789Sahrens int error; 287789Sahrens 2884543Smarks error = zfs_dozonecheck(name, cr); 2894543Smarks if (error == 0) { 2904543Smarks error = secpolicy_zfs(cr); 2914670Sahrens if (error) 2924543Smarks error = dsl_deleg_access(name, perm, cr); 2934543Smarks } 2944543Smarks return (error); 2954543Smarks } 2964543Smarks 2974543Smarks static int 2984543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) 2994543Smarks { 3004543Smarks /* 3014543Smarks * Check permissions for special properties. 3024543Smarks */ 3034543Smarks switch (prop) { 3044543Smarks case ZFS_PROP_ZONED: 3054543Smarks /* 3064543Smarks * Disallow setting of 'zoned' from within a local zone. 3074543Smarks */ 3084543Smarks if (!INGLOBALZONE(curproc)) 3094543Smarks return (EPERM); 3104543Smarks break; 311789Sahrens 3124543Smarks case ZFS_PROP_QUOTA: 3134543Smarks if (!INGLOBALZONE(curproc)) { 3144543Smarks uint64_t zoned; 3154543Smarks char setpoint[MAXNAMELEN]; 3164543Smarks /* 3174543Smarks * Unprivileged users are allowed to modify the 3184543Smarks * quota on things *under* (ie. contained by) 3194543Smarks * the thing they own. 3204543Smarks */ 3214543Smarks if (dsl_prop_get_integer(name, "zoned", &zoned, 3224543Smarks setpoint)) 3234543Smarks return (EPERM); 3244670Sahrens if (!zoned || strlen(name) <= strlen(setpoint)) 3254543Smarks return (EPERM); 3264543Smarks } 3274670Sahrens break; 3284543Smarks } 3294543Smarks 3304787Sahrens return (zfs_secpolicy_write_perms(name, zfs_prop_to_name(prop), cr)); 331789Sahrens } 332789Sahrens 3334543Smarks int 3344543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) 3354543Smarks { 3364543Smarks int error; 3374543Smarks 3384543Smarks error = zfs_dozonecheck(zc->zc_name, cr); 3394543Smarks if (error) 3404543Smarks return (error); 3414543Smarks 3424543Smarks /* 3434543Smarks * permission to set permissions will be evaluated later in 3444543Smarks * dsl_deleg_can_allow() 3454543Smarks */ 3464543Smarks return (0); 3474543Smarks } 3484543Smarks 3494543Smarks int 3504543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) 3514543Smarks { 3524543Smarks int error; 3534543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3544543Smarks ZFS_DELEG_PERM_ROLLBACK, cr); 3554543Smarks if (error == 0) 3564543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 3574543Smarks ZFS_DELEG_PERM_MOUNT, cr); 3584543Smarks return (error); 3594543Smarks } 3604543Smarks 3614543Smarks int 3624543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) 3634543Smarks { 3644543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 3654543Smarks ZFS_DELEG_PERM_SEND, cr)); 3664543Smarks } 3674543Smarks 3684543Smarks int 3694543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) 3704543Smarks { 3714543Smarks if (!INGLOBALZONE(curproc)) 3724543Smarks return (EPERM); 3734543Smarks 3745367Sahrens if (secpolicy_nfs(cr) == 0) { 3754543Smarks return (0); 3764543Smarks } else { 3774543Smarks vnode_t *vp; 3784543Smarks int error; 3794543Smarks 3804543Smarks if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, 3814543Smarks NO_FOLLOW, NULL, &vp)) != 0) 3824543Smarks return (error); 3834543Smarks 3844543Smarks /* Now make sure mntpnt and dataset are ZFS */ 3854543Smarks 3864543Smarks if (vp->v_vfsp->vfs_fstype != zfsfstype || 3874543Smarks (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), 3884543Smarks zc->zc_name) != 0)) { 3894543Smarks VN_RELE(vp); 3904543Smarks return (EPERM); 3914543Smarks } 3924543Smarks 3934543Smarks VN_RELE(vp); 3944543Smarks return (dsl_deleg_access(zc->zc_name, 3954543Smarks ZFS_DELEG_PERM_SHARE, cr)); 3964543Smarks } 3974543Smarks } 3984543Smarks 399789Sahrens static int 4004543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize) 401789Sahrens { 402789Sahrens char *cp; 403789Sahrens 404789Sahrens /* 405789Sahrens * Remove the @bla or /bla from the end of the name to get the parent. 406789Sahrens */ 4074543Smarks (void) strncpy(parent, datasetname, parentsize); 4084543Smarks cp = strrchr(parent, '@'); 409789Sahrens if (cp != NULL) { 410789Sahrens cp[0] = '\0'; 411789Sahrens } else { 4124543Smarks cp = strrchr(parent, '/'); 413789Sahrens if (cp == NULL) 414789Sahrens return (ENOENT); 415789Sahrens cp[0] = '\0'; 416789Sahrens } 417789Sahrens 4184543Smarks return (0); 4194543Smarks } 4204543Smarks 4214543Smarks int 4224543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 4234543Smarks { 4244543Smarks int error; 4254543Smarks 4264543Smarks if ((error = zfs_secpolicy_write_perms(name, 4274543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4284543Smarks return (error); 4294543Smarks 4304543Smarks return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); 4314543Smarks } 4324543Smarks 4334543Smarks static int 4344543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) 4354543Smarks { 4364543Smarks return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); 4374543Smarks } 4384543Smarks 4394543Smarks /* 4404543Smarks * Must have sys_config privilege to check the iscsi permission 4414543Smarks */ 4424543Smarks /* ARGSUSED */ 4434543Smarks static int 4444543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) 4454543Smarks { 4464543Smarks return (secpolicy_zfs(cr)); 4474543Smarks } 4484543Smarks 4494543Smarks int 4504543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 4514543Smarks { 4524543Smarks char parentname[MAXNAMELEN]; 4534543Smarks int error; 4544543Smarks 4554543Smarks if ((error = zfs_secpolicy_write_perms(from, 4564543Smarks ZFS_DELEG_PERM_RENAME, cr)) != 0) 4574543Smarks return (error); 4584543Smarks 4594543Smarks if ((error = zfs_secpolicy_write_perms(from, 4604543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4614543Smarks return (error); 4624543Smarks 4634543Smarks if ((error = zfs_get_parent(to, parentname, 4644543Smarks sizeof (parentname))) != 0) 4654543Smarks return (error); 4664543Smarks 4674543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4684543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 4694543Smarks return (error); 4704543Smarks 4714543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 4724543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 4734543Smarks return (error); 4744543Smarks 4754543Smarks return (error); 4764543Smarks } 4774543Smarks 4784543Smarks static int 4794543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) 4804543Smarks { 4814543Smarks return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); 4824543Smarks } 4834543Smarks 4844543Smarks static int 4854543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) 4864543Smarks { 4874543Smarks char parentname[MAXNAMELEN]; 4884543Smarks objset_t *clone; 4894543Smarks int error; 4904543Smarks 4914543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 4924543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 4934543Smarks if (error) 4944543Smarks return (error); 4954543Smarks 4964543Smarks error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 4974543Smarks DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 4984543Smarks 4994543Smarks if (error == 0) { 5004543Smarks dsl_dataset_t *pclone = NULL; 5014543Smarks dsl_dir_t *dd; 5024543Smarks dd = clone->os->os_dsl_dataset->ds_dir; 5034543Smarks 5044543Smarks rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 5054543Smarks error = dsl_dataset_open_obj(dd->dd_pool, 5065367Sahrens dd->dd_phys->dd_origin_obj, NULL, 5074543Smarks DS_MODE_NONE, FTAG, &pclone); 5084543Smarks rw_exit(&dd->dd_pool->dp_config_rwlock); 5094543Smarks if (error) { 5104543Smarks dmu_objset_close(clone); 5114543Smarks return (error); 5124543Smarks } 5134543Smarks 5144543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 5154543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5164543Smarks 5174543Smarks dsl_dataset_name(pclone, parentname); 5184543Smarks dmu_objset_close(clone); 5194543Smarks dsl_dataset_close(pclone, DS_MODE_NONE, FTAG); 5204543Smarks if (error == 0) 5214543Smarks error = zfs_secpolicy_write_perms(parentname, 5224543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 5234543Smarks } 5244543Smarks return (error); 5254543Smarks } 5264543Smarks 5274543Smarks static int 5284543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) 5294543Smarks { 5304543Smarks int error; 5314543Smarks 5324543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5334543Smarks ZFS_DELEG_PERM_RECEIVE, cr)) != 0) 5344543Smarks return (error); 5354543Smarks 5364543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 5374543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 5384543Smarks return (error); 5394543Smarks 5404543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 5414543Smarks ZFS_DELEG_PERM_CREATE, cr)); 5424543Smarks } 5434543Smarks 5444543Smarks int 5454543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 5464543Smarks { 5474543Smarks int error; 5484543Smarks 5494543Smarks if ((error = zfs_secpolicy_write_perms(name, 5504543Smarks ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) 5514543Smarks return (error); 5524543Smarks 5534543Smarks error = zfs_secpolicy_write_perms(name, 5544543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5554543Smarks 5564543Smarks return (error); 5574543Smarks } 5584543Smarks 5594543Smarks static int 5604543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) 5614543Smarks { 5624543Smarks 5634543Smarks return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); 5644543Smarks } 5654543Smarks 5664543Smarks static int 5674543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) 5684543Smarks { 5694543Smarks char parentname[MAXNAMELEN]; 5704543Smarks int error; 5714543Smarks 5724543Smarks if ((error = zfs_get_parent(zc->zc_name, parentname, 5734543Smarks sizeof (parentname))) != 0) 5744543Smarks return (error); 5754543Smarks 5764543Smarks if (zc->zc_value[0] != '\0') { 5774543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_value, 5784543Smarks ZFS_DELEG_PERM_CLONE, cr)) != 0) 5794543Smarks return (error); 5804543Smarks } 5814543Smarks 5824543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 5834543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 5844543Smarks return (error); 5854543Smarks 5864543Smarks error = zfs_secpolicy_write_perms(parentname, 5874543Smarks ZFS_DELEG_PERM_MOUNT, cr); 5884543Smarks 5894543Smarks return (error); 5904543Smarks } 5914543Smarks 5924543Smarks static int 5934543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) 5944543Smarks { 5954543Smarks int error; 5964543Smarks 5974543Smarks error = secpolicy_fs_unmount(cr, NULL); 5984543Smarks if (error) { 5994543Smarks error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); 6004543Smarks } 6014543Smarks return (error); 602789Sahrens } 603789Sahrens 604789Sahrens /* 605789Sahrens * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires 606789Sahrens * SYS_CONFIG privilege, which is not available in a local zone. 607789Sahrens */ 608789Sahrens /* ARGSUSED */ 609789Sahrens static int 6104543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) 611789Sahrens { 612789Sahrens if (secpolicy_sys_config(cr, B_FALSE) != 0) 613789Sahrens return (EPERM); 614789Sahrens 615789Sahrens return (0); 616789Sahrens } 617789Sahrens 618789Sahrens /* 6194543Smarks * Just like zfs_secpolicy_config, except that we will check for 6204543Smarks * mount permission on the dataset for permission to create/remove 6214543Smarks * the minor nodes. 6224543Smarks */ 6234543Smarks static int 6244543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) 6254543Smarks { 6264543Smarks if (secpolicy_sys_config(cr, B_FALSE) != 0) { 6274543Smarks return (dsl_deleg_access(zc->zc_name, 6284543Smarks ZFS_DELEG_PERM_MOUNT, cr)); 6294543Smarks } 6304543Smarks 6314543Smarks return (0); 6324543Smarks } 6334543Smarks 6344543Smarks /* 6351544Seschrock * Policy for fault injection. Requires all privileges. 6361544Seschrock */ 6371544Seschrock /* ARGSUSED */ 6381544Seschrock static int 6394543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) 6401544Seschrock { 6411544Seschrock return (secpolicy_zinject(cr)); 6421544Seschrock } 6431544Seschrock 6444849Sahrens static int 6454849Sahrens zfs_secpolicy_inherit(zfs_cmd_t *zc, cred_t *cr) 6464849Sahrens { 6474849Sahrens zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); 6484849Sahrens 6495094Slling if (prop == ZPROP_INVAL) { 6504849Sahrens if (!zfs_prop_user(zc->zc_value)) 6514849Sahrens return (EINVAL); 6524849Sahrens return (zfs_secpolicy_write_perms(zc->zc_name, 6534849Sahrens ZFS_DELEG_PERM_USERPROP, cr)); 6544849Sahrens } else { 6554849Sahrens if (!zfs_prop_inheritable(prop)) 6564849Sahrens return (EINVAL); 6574849Sahrens return (zfs_secpolicy_setprop(zc->zc_name, prop, cr)); 6584849Sahrens } 6594849Sahrens } 6604849Sahrens 6611544Seschrock /* 662789Sahrens * Returns the nvlist as specified by the user in the zfs_cmd_t. 663789Sahrens */ 664789Sahrens static int 6655094Slling get_nvlist(uint64_t nvl, uint64_t size, nvlist_t **nvp) 666789Sahrens { 667789Sahrens char *packed; 668789Sahrens int error; 6695094Slling nvlist_t *list = NULL; 670789Sahrens 671789Sahrens /* 6722676Seschrock * Read in and unpack the user-supplied nvlist. 673789Sahrens */ 6745094Slling if (size == 0) 675789Sahrens return (EINVAL); 676789Sahrens 677789Sahrens packed = kmem_alloc(size, KM_SLEEP); 678789Sahrens 6795094Slling if ((error = xcopyin((void *)(uintptr_t)nvl, packed, size)) != 0) { 680789Sahrens kmem_free(packed, size); 681789Sahrens return (error); 682789Sahrens } 683789Sahrens 6845094Slling if ((error = nvlist_unpack(packed, size, &list, 0)) != 0) { 685789Sahrens kmem_free(packed, size); 686789Sahrens return (error); 687789Sahrens } 688789Sahrens 689789Sahrens kmem_free(packed, size); 690789Sahrens 6915094Slling *nvp = list; 692789Sahrens return (0); 693789Sahrens } 694789Sahrens 695789Sahrens static int 6962676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 6972676Seschrock { 6982676Seschrock char *packed = NULL; 6992676Seschrock size_t size; 7002676Seschrock int error; 7012676Seschrock 7022676Seschrock VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 7032676Seschrock 7042676Seschrock if (size > zc->zc_nvlist_dst_size) { 7052676Seschrock error = ENOMEM; 7062676Seschrock } else { 7074611Smarks packed = kmem_alloc(size, KM_SLEEP); 7082676Seschrock VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 7092676Seschrock KM_SLEEP) == 0); 7102676Seschrock error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 7112676Seschrock size); 7122676Seschrock kmem_free(packed, size); 7132676Seschrock } 7142676Seschrock 7152676Seschrock zc->zc_nvlist_dst_size = size; 7162676Seschrock return (error); 7172676Seschrock } 7182676Seschrock 7192676Seschrock static int 720789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc) 721789Sahrens { 722789Sahrens int error; 7235094Slling nvlist_t *config, *props = NULL; 7244715Sek110237 char *buf; 725789Sahrens 7265094Slling if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7275094Slling &config)) 7284988Sek110237 return (error); 7294715Sek110237 7305094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7315094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7325094Slling nvlist_free(config); 7335094Slling return (error); 7345094Slling } 7355094Slling 7364988Sek110237 buf = history_str_get(zc); 737789Sahrens 7385094Slling error = spa_create(zc->zc_name, config, props, buf); 739789Sahrens 7404988Sek110237 if (buf != NULL) 7414988Sek110237 history_str_free(buf); 7425094Slling 743789Sahrens nvlist_free(config); 744789Sahrens 7455094Slling if (props) 7465094Slling nvlist_free(props); 7475094Slling 748789Sahrens return (error); 749789Sahrens } 750789Sahrens 751789Sahrens static int 752789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc) 753789Sahrens { 7544543Smarks int error; 7554543Smarks zfs_log_history(zc); 7564543Smarks error = spa_destroy(zc->zc_name); 7574543Smarks return (error); 758789Sahrens } 759789Sahrens 760789Sahrens static int 761789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc) 762789Sahrens { 763789Sahrens int error; 7645094Slling nvlist_t *config, *props = NULL; 765789Sahrens uint64_t guid; 766789Sahrens 7675094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 7685094Slling &config)) != 0) 769789Sahrens return (error); 770789Sahrens 7715094Slling if (zc->zc_nvlist_src_size != 0 && (error = 7725094Slling get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { 7735094Slling nvlist_free(config); 7745094Slling return (error); 7755094Slling } 7765094Slling 777789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 7781544Seschrock guid != zc->zc_guid) 779789Sahrens error = EINVAL; 780789Sahrens else 7815094Slling error = spa_import(zc->zc_name, config, props); 782789Sahrens 783789Sahrens nvlist_free(config); 784789Sahrens 7855094Slling if (props) 7865094Slling nvlist_free(props); 7875094Slling 788789Sahrens return (error); 789789Sahrens } 790789Sahrens 791789Sahrens static int 792789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc) 793789Sahrens { 7944543Smarks int error; 7954543Smarks zfs_log_history(zc); 7964543Smarks error = spa_export(zc->zc_name, NULL); 7974543Smarks return (error); 798789Sahrens } 799789Sahrens 800789Sahrens static int 801789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc) 802789Sahrens { 803789Sahrens nvlist_t *configs; 804789Sahrens int error; 805789Sahrens 806789Sahrens if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 807789Sahrens return (EEXIST); 808789Sahrens 8092676Seschrock error = put_nvlist(zc, configs); 810789Sahrens 811789Sahrens nvlist_free(configs); 812789Sahrens 813789Sahrens return (error); 814789Sahrens } 815789Sahrens 816789Sahrens static int 817789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc) 818789Sahrens { 819789Sahrens nvlist_t *config; 820789Sahrens int error; 8211544Seschrock int ret = 0; 822789Sahrens 8232676Seschrock error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 8242676Seschrock sizeof (zc->zc_value)); 825789Sahrens 826789Sahrens if (config != NULL) { 8272676Seschrock ret = put_nvlist(zc, config); 828789Sahrens nvlist_free(config); 8291544Seschrock 8301544Seschrock /* 8311544Seschrock * The config may be present even if 'error' is non-zero. 8321544Seschrock * In this case we return success, and preserve the real errno 8331544Seschrock * in 'zc_cookie'. 8341544Seschrock */ 8351544Seschrock zc->zc_cookie = error; 836789Sahrens } else { 8371544Seschrock ret = error; 838789Sahrens } 839789Sahrens 8401544Seschrock return (ret); 841789Sahrens } 842789Sahrens 843789Sahrens /* 844789Sahrens * Try to import the given pool, returning pool stats as appropriate so that 845789Sahrens * user land knows which devices are available and overall pool health. 846789Sahrens */ 847789Sahrens static int 848789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 849789Sahrens { 850789Sahrens nvlist_t *tryconfig, *config; 851789Sahrens int error; 852789Sahrens 8535094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 8545094Slling &tryconfig)) != 0) 855789Sahrens return (error); 856789Sahrens 857789Sahrens config = spa_tryimport(tryconfig); 858789Sahrens 859789Sahrens nvlist_free(tryconfig); 860789Sahrens 861789Sahrens if (config == NULL) 862789Sahrens return (EINVAL); 863789Sahrens 8642676Seschrock error = put_nvlist(zc, config); 865789Sahrens nvlist_free(config); 866789Sahrens 867789Sahrens return (error); 868789Sahrens } 869789Sahrens 870789Sahrens static int 871789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc) 872789Sahrens { 873789Sahrens spa_t *spa; 874789Sahrens int error; 875789Sahrens 8762926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8772926Sek110237 return (error); 8782926Sek110237 8794808Sek110237 mutex_enter(&spa_namespace_lock); 8802926Sek110237 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); 8814808Sek110237 mutex_exit(&spa_namespace_lock); 8822926Sek110237 8832926Sek110237 spa_close(spa, FTAG); 8842926Sek110237 885789Sahrens return (error); 886789Sahrens } 887789Sahrens 888789Sahrens static int 889789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 890789Sahrens { 891789Sahrens spa_t *spa; 892789Sahrens int error; 893789Sahrens 894789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 895789Sahrens if (error == 0) { 896789Sahrens spa_freeze(spa); 897789Sahrens spa_close(spa, FTAG); 898789Sahrens } 899789Sahrens return (error); 900789Sahrens } 901789Sahrens 902789Sahrens static int 9031760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 9041760Seschrock { 9051760Seschrock spa_t *spa; 9061760Seschrock int error; 9071760Seschrock 9082926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9092926Sek110237 return (error); 9102926Sek110237 9115118Slling if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) { 9125118Slling spa_close(spa, FTAG); 9135118Slling return (EINVAL); 9145118Slling } 9155118Slling 9165094Slling spa_upgrade(spa, zc->zc_cookie); 9172926Sek110237 spa_close(spa, FTAG); 9182926Sek110237 9192926Sek110237 return (error); 9202926Sek110237 } 9212926Sek110237 9222926Sek110237 static int 9232926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 9242926Sek110237 { 9252926Sek110237 spa_t *spa; 9262926Sek110237 char *hist_buf; 9272926Sek110237 uint64_t size; 9282926Sek110237 int error; 9292926Sek110237 9302926Sek110237 if ((size = zc->zc_history_len) == 0) 9312926Sek110237 return (EINVAL); 9322926Sek110237 9332926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 9342926Sek110237 return (error); 9352926Sek110237 9364577Sahrens if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { 9373863Sek110237 spa_close(spa, FTAG); 9383863Sek110237 return (ENOTSUP); 9393863Sek110237 } 9403863Sek110237 9412926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 9422926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 9432926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 9444543Smarks error = xcopyout(hist_buf, 9454543Smarks (char *)(uintptr_t)zc->zc_history, 9462926Sek110237 zc->zc_history_len); 9472926Sek110237 } 9482926Sek110237 9492926Sek110237 spa_close(spa, FTAG); 9502926Sek110237 kmem_free(hist_buf, size); 9512926Sek110237 return (error); 9522926Sek110237 } 9532926Sek110237 9542926Sek110237 static int 9553444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 9563444Sek110237 { 9573444Sek110237 int error; 9583444Sek110237 9593912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 9603444Sek110237 return (error); 9613444Sek110237 9623444Sek110237 return (0); 9633444Sek110237 } 9643444Sek110237 9653444Sek110237 static int 9663444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 9673444Sek110237 { 9683444Sek110237 objset_t *osp; 9693444Sek110237 int error; 9703444Sek110237 9713444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 9723444Sek110237 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) 9733444Sek110237 return (error); 9743444Sek110237 9753444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 9763444Sek110237 sizeof (zc->zc_value)); 9773444Sek110237 dmu_objset_close(osp); 9783444Sek110237 9793444Sek110237 return (error); 9803444Sek110237 } 9813444Sek110237 9823444Sek110237 static int 983789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 984789Sahrens { 985789Sahrens spa_t *spa; 986789Sahrens int error; 9875450Sbrendan nvlist_t *config, **l2cache; 9885450Sbrendan uint_t nl2cache; 989789Sahrens 990789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 991789Sahrens if (error != 0) 992789Sahrens return (error); 993789Sahrens 9945450Sbrendan error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 9955450Sbrendan &config); 9965450Sbrendan (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_L2CACHE, 9975450Sbrendan &l2cache, &nl2cache); 9985450Sbrendan 9993912Slling /* 10003912Slling * A root pool with concatenated devices is not supported. 10013912Slling * Thus, can not add a device to a root pool with one device. 10025450Sbrendan * Allow for l2cache devices to be added. 10033912Slling */ 10045450Sbrendan if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0 && 10055450Sbrendan nl2cache == 0) { 10063912Slling spa_close(spa, FTAG); 10073912Slling return (EDOM); 10083912Slling } 10093912Slling 10105450Sbrendan if (error == 0) { 1011789Sahrens error = spa_vdev_add(spa, config); 1012789Sahrens nvlist_free(config); 1013789Sahrens } 1014789Sahrens spa_close(spa, FTAG); 1015789Sahrens return (error); 1016789Sahrens } 1017789Sahrens 1018789Sahrens static int 1019789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 1020789Sahrens { 10212082Seschrock spa_t *spa; 10222082Seschrock int error; 10232082Seschrock 10242082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10252082Seschrock if (error != 0) 10262082Seschrock return (error); 10272082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 10282082Seschrock spa_close(spa, FTAG); 10292082Seschrock return (error); 1030789Sahrens } 1031789Sahrens 1032789Sahrens static int 10334451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 1034789Sahrens { 1035789Sahrens spa_t *spa; 1036789Sahrens int error; 10374451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 1038789Sahrens 10392926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1040789Sahrens return (error); 10414451Seschrock switch (zc->zc_cookie) { 10424451Seschrock case VDEV_STATE_ONLINE: 10434451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 10444451Seschrock break; 10454451Seschrock 10464451Seschrock case VDEV_STATE_OFFLINE: 10474451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 10484451Seschrock break; 1049789Sahrens 10504451Seschrock case VDEV_STATE_FAULTED: 10514451Seschrock error = vdev_fault(spa, zc->zc_guid); 10524451Seschrock break; 1053789Sahrens 10544451Seschrock case VDEV_STATE_DEGRADED: 10554451Seschrock error = vdev_degrade(spa, zc->zc_guid); 10564451Seschrock break; 10574451Seschrock 10584451Seschrock default: 10594451Seschrock error = EINVAL; 10604451Seschrock } 10614451Seschrock zc->zc_cookie = newstate; 1062789Sahrens spa_close(spa, FTAG); 1063789Sahrens return (error); 1064789Sahrens } 1065789Sahrens 1066789Sahrens static int 1067789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 1068789Sahrens { 1069789Sahrens spa_t *spa; 1070789Sahrens int replacing = zc->zc_cookie; 1071789Sahrens nvlist_t *config; 1072789Sahrens int error; 1073789Sahrens 10742926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1075789Sahrens return (error); 1076789Sahrens 10775094Slling if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, 10785094Slling &config)) == 0) { 10791544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 1080789Sahrens nvlist_free(config); 1081789Sahrens } 1082789Sahrens 1083789Sahrens spa_close(spa, FTAG); 1084789Sahrens return (error); 1085789Sahrens } 1086789Sahrens 1087789Sahrens static int 1088789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 1089789Sahrens { 1090789Sahrens spa_t *spa; 1091789Sahrens int error; 1092789Sahrens 10932926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 1094789Sahrens return (error); 1095789Sahrens 10961544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1097789Sahrens 1098789Sahrens spa_close(spa, FTAG); 1099789Sahrens return (error); 1100789Sahrens } 1101789Sahrens 1102789Sahrens static int 11031354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 11041354Seschrock { 11051354Seschrock spa_t *spa; 11062676Seschrock char *path = zc->zc_value; 11071544Seschrock uint64_t guid = zc->zc_guid; 11081354Seschrock int error; 11091354Seschrock 11101354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 11111354Seschrock if (error != 0) 11121354Seschrock return (error); 11131354Seschrock 11141354Seschrock error = spa_vdev_setpath(spa, guid, path); 11151354Seschrock spa_close(spa, FTAG); 11161354Seschrock return (error); 11171354Seschrock } 11181354Seschrock 11195498Stimh static int 11205498Stimh zfs_os_open_retry(char *name, objset_t **os) 11215498Stimh { 11225498Stimh int error; 11235498Stimh 11245498Stimh retry: 11255498Stimh error = dmu_objset_open(name, DMU_OST_ANY, 11265498Stimh DS_MODE_STANDARD | DS_MODE_READONLY, os); 11275498Stimh if (error != 0) { 11285498Stimh /* 11295498Stimh * This is ugly: dmu_objset_open() can return EBUSY if 11305498Stimh * the objset is held exclusively. Fortunately this hold is 11315498Stimh * only for a short while, so we retry here. 11325498Stimh * This avoids user code having to handle EBUSY, 11335498Stimh * for example for a "zfs list". 11345498Stimh */ 11355498Stimh if (error == EBUSY) { 11365498Stimh delay(1); 11375498Stimh goto retry; 11385498Stimh } 11395498Stimh } 11405498Stimh return (error); 11415498Stimh } 11425498Stimh 11435367Sahrens /* 11445367Sahrens * inputs: 11455367Sahrens * zc_name name of filesystem 11465367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 11475367Sahrens * 11485367Sahrens * outputs: 11495367Sahrens * zc_objset_stats stats 11505367Sahrens * zc_nvlist_dst property nvlist 11515367Sahrens * zc_nvlist_dst_size size of property nvlist 11525367Sahrens * zc_value alternate root 11535367Sahrens */ 11541354Seschrock static int 1155789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1156789Sahrens { 1157789Sahrens objset_t *os = NULL; 1158789Sahrens int error; 11591356Seschrock nvlist_t *nv; 1160789Sahrens 11615498Stimh if ((error = zfs_os_open_retry(zc->zc_name, &os)) != 0) 1162789Sahrens return (error); 1163789Sahrens 11642885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1165789Sahrens 11662856Snd150628 if (zc->zc_nvlist_dst != 0 && 11671356Seschrock (error = dsl_prop_get_all(os, &nv)) == 0) { 11682885Sahrens dmu_objset_stats(os, nv); 11693087Sahrens /* 11705147Srm160521 * NB: zvol_get_stats() will read the objset contents, 11713087Sahrens * which we aren't supposed to do with a 11723087Sahrens * DS_MODE_STANDARD open, because it could be 11733087Sahrens * inconsistent. So this is a bit of a workaround... 11743087Sahrens */ 11754577Sahrens if (!zc->zc_objset_stats.dds_inconsistent) { 11764577Sahrens if (dmu_objset_type(os) == DMU_OST_ZVOL) 11774577Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 11784577Sahrens } 11792676Seschrock error = put_nvlist(zc, nv); 11801356Seschrock nvlist_free(nv); 11811356Seschrock } 1182789Sahrens 11832676Seschrock spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value)); 11841544Seschrock 1185789Sahrens dmu_objset_close(os); 1186789Sahrens return (error); 1187789Sahrens } 1188789Sahrens 11895498Stimh static int 11905498Stimh nvl_add_zplprop(objset_t *os, nvlist_t *props, zfs_prop_t prop) 11915498Stimh { 11925498Stimh uint64_t value; 11935498Stimh int error; 11945498Stimh 11955498Stimh /* 11965498Stimh * zfs_get_zplprop() will either find a value or give us 11975498Stimh * the default value (if there is one). 11985498Stimh */ 11995498Stimh if ((error = zfs_get_zplprop(os, prop, &value)) != 0) 12005498Stimh return (error); 12015498Stimh VERIFY(nvlist_add_uint64(props, zfs_prop_to_name(prop), value) == 0); 12025498Stimh return (0); 12035498Stimh } 12045498Stimh 12055498Stimh /* 12065498Stimh * inputs: 12075498Stimh * zc_name name of filesystem 12085498Stimh * zc_nvlist_dst_size size of buffer for zpl property nvlist 12095498Stimh * 12105498Stimh * outputs: 12115498Stimh * zc_nvlist_dst zpl property nvlist 12125498Stimh * zc_nvlist_dst_size size of zpl property nvlist 12135498Stimh */ 12145498Stimh static int 12155498Stimh zfs_ioc_objset_zplprops(zfs_cmd_t *zc) 12165498Stimh { 12175498Stimh objset_t *os; 12185498Stimh int err; 12195498Stimh 12205498Stimh if ((err = zfs_os_open_retry(zc->zc_name, &os)) != 0) 12215498Stimh return (err); 12225498Stimh 12235498Stimh dmu_objset_fast_stat(os, &zc->zc_objset_stats); 12245498Stimh 12255498Stimh /* 12265498Stimh * NB: nvl_add_zplprop() will read the objset contents, 12275498Stimh * which we aren't supposed to do with a DS_MODE_STANDARD 12285498Stimh * open, because it could be inconsistent. 12295498Stimh */ 12305498Stimh if (zc->zc_nvlist_dst != NULL && 12315498Stimh !zc->zc_objset_stats.dds_inconsistent && 12325498Stimh dmu_objset_type(os) == DMU_OST_ZFS) { 12335498Stimh nvlist_t *nv; 12345498Stimh 12355498Stimh VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) == 0); 12365498Stimh if ((err = nvl_add_zplprop(os, nv, ZFS_PROP_VERSION)) == 0 && 12375498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_NORMALIZE)) == 0 && 12385498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_UTF8ONLY)) == 0 && 12395498Stimh (err = nvl_add_zplprop(os, nv, ZFS_PROP_CASE)) == 0) 12405498Stimh err = put_nvlist(zc, nv); 12415498Stimh nvlist_free(nv); 12425498Stimh } else { 12435498Stimh err = ENOENT; 12445498Stimh } 12455498Stimh dmu_objset_close(os); 12465498Stimh return (err); 12475498Stimh } 12485498Stimh 12495367Sahrens /* 12505367Sahrens * inputs: 12515367Sahrens * zc_name name of filesystem 12525367Sahrens * zc_cookie zap cursor 12535367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 12545367Sahrens * 12555367Sahrens * outputs: 12565367Sahrens * zc_name name of next filesystem 12575367Sahrens * zc_objset_stats stats 12585367Sahrens * zc_nvlist_dst property nvlist 12595367Sahrens * zc_nvlist_dst_size size of property nvlist 12605367Sahrens * zc_value alternate root 12615367Sahrens */ 1262789Sahrens static int 1263789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1264789Sahrens { 1265885Sahrens objset_t *os; 1266789Sahrens int error; 1267789Sahrens char *p; 1268789Sahrens 12695498Stimh if ((error = zfs_os_open_retry(zc->zc_name, &os)) != 0) { 1270885Sahrens if (error == ENOENT) 1271885Sahrens error = ESRCH; 1272885Sahrens return (error); 1273789Sahrens } 1274789Sahrens 1275789Sahrens p = strrchr(zc->zc_name, '/'); 1276789Sahrens if (p == NULL || p[1] != '\0') 1277789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1278789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1279789Sahrens 1280789Sahrens do { 1281885Sahrens error = dmu_dir_list_next(os, 1282885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1283885Sahrens NULL, &zc->zc_cookie); 1284789Sahrens if (error == ENOENT) 1285789Sahrens error = ESRCH; 1286885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1287789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 1288789Sahrens 1289885Sahrens /* 1290885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1291885Sahrens * try to get stats for it. Userland will skip over it. 1292885Sahrens */ 1293885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1294885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1295789Sahrens 1296885Sahrens dmu_objset_close(os); 1297789Sahrens return (error); 1298789Sahrens } 1299789Sahrens 13005367Sahrens /* 13015367Sahrens * inputs: 13025367Sahrens * zc_name name of filesystem 13035367Sahrens * zc_cookie zap cursor 13045367Sahrens * zc_nvlist_dst_size size of buffer for property nvlist 13055367Sahrens * 13065367Sahrens * outputs: 13075367Sahrens * zc_name name of next snapshot 13085367Sahrens * zc_objset_stats stats 13095367Sahrens * zc_nvlist_dst property nvlist 13105367Sahrens * zc_nvlist_dst_size size of property nvlist 13115367Sahrens * zc_value alternate root 13125367Sahrens */ 1313789Sahrens static int 1314789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1315789Sahrens { 1316885Sahrens objset_t *os; 1317789Sahrens int error; 1318789Sahrens 13195498Stimh if ((error = zfs_os_open_retry(zc->zc_name, &os)) != 0) { 1320789Sahrens if (error == ENOENT) 1321885Sahrens error = ESRCH; 1322789Sahrens return (error); 1323789Sahrens } 1324789Sahrens 13251003Slling /* 13261003Slling * A dataset name of maximum length cannot have any snapshots, 13271003Slling * so exit immediately. 13281003Slling */ 13291003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1330885Sahrens dmu_objset_close(os); 13311003Slling return (ESRCH); 1332789Sahrens } 1333789Sahrens 1334885Sahrens error = dmu_snapshot_list_next(os, 1335885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 13365663Sck153898 zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie, NULL); 1337789Sahrens if (error == ENOENT) 1338789Sahrens error = ESRCH; 1339789Sahrens 1340885Sahrens if (error == 0) 1341885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1342789Sahrens 13435367Sahrens /* if we failed, undo the @ that we tacked on to zc_name */ 13445367Sahrens if (error != 0) 13455367Sahrens *strchr(zc->zc_name, '@') = '\0'; 13465367Sahrens 1347885Sahrens dmu_objset_close(os); 1348789Sahrens return (error); 1349789Sahrens } 1350789Sahrens 1351789Sahrens static int 13524787Sahrens zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) 1353789Sahrens { 13542676Seschrock nvpair_t *elem; 13552676Seschrock int error; 13562676Seschrock uint64_t intval; 13572676Seschrock char *strval; 13582676Seschrock 13594543Smarks /* 13604543Smarks * First validate permission to set all of the properties 13614543Smarks */ 13622676Seschrock elem = NULL; 13632676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 13644670Sahrens const char *propname = nvpair_name(elem); 13654670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 13662676Seschrock 13675094Slling if (prop == ZPROP_INVAL) { 13682676Seschrock /* 13692676Seschrock * If this is a user-defined property, it must be a 13702676Seschrock * string, and there is no further validation to do. 13712676Seschrock */ 13722676Seschrock if (!zfs_prop_user(propname) || 13732676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 13742676Seschrock return (EINVAL); 13752676Seschrock 13765331Samw if (error = zfs_secpolicy_write_perms(name, 13775331Samw ZFS_DELEG_PERM_USERPROP, CRED())) 13784670Sahrens return (error); 13794543Smarks continue; 13802676Seschrock } 13812676Seschrock 13824787Sahrens if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 13834670Sahrens return (error); 13842676Seschrock 13854670Sahrens /* 13864670Sahrens * Check that this value is valid for this pool version 13874670Sahrens */ 13884670Sahrens switch (prop) { 13893886Sahl case ZFS_PROP_COMPRESSION: 13903886Sahl /* 13913886Sahl * If the user specified gzip compression, make sure 13923886Sahl * the SPA supports it. We ignore any errors here since 13933886Sahl * we'll catch them later. 13943886Sahl */ 13953886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 13963886Sahl nvpair_value_uint64(elem, &intval) == 0 && 13973886Sahl intval >= ZIO_COMPRESS_GZIP_1 && 13983886Sahl intval <= ZIO_COMPRESS_GZIP_9) { 13995331Samw if (zfs_check_version(name, 14005331Samw SPA_VERSION_GZIP_COMPRESSION)) 14015331Samw return (ENOTSUP); 14023886Sahl } 14033886Sahl break; 14044603Sahrens 14054603Sahrens case ZFS_PROP_COPIES: 14065331Samw if (zfs_check_version(name, SPA_VERSION_DITTO_BLOCKS)) 14075331Samw return (ENOTSUP); 14084603Sahrens break; 1409*5977Smarks 1410*5977Smarks case ZFS_PROP_SHARESMB: 1411*5977Smarks if (zpl_check_version(name, ZPL_VERSION_FUID)) 1412*5977Smarks return (ENOTSUP); 1413*5977Smarks break; 14144603Sahrens } 14155331Samw if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) 14165331Samw return (error); 14174543Smarks } 14184543Smarks 14194543Smarks elem = NULL; 14204543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 14214670Sahrens const char *propname = nvpair_name(elem); 14224670Sahrens zfs_prop_t prop = zfs_name_to_prop(propname); 14234543Smarks 14245094Slling if (prop == ZPROP_INVAL) { 14254543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 14264543Smarks error = dsl_prop_set(name, propname, 1, 14274543Smarks strlen(strval) + 1, strval); 14284543Smarks if (error == 0) 14294543Smarks continue; 14304543Smarks else 14314543Smarks return (error); 14324543Smarks } 14332676Seschrock 14342676Seschrock switch (prop) { 14352676Seschrock case ZFS_PROP_QUOTA: 14362676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14374577Sahrens (error = dsl_dir_set_quota(name, intval)) != 0) 14382676Seschrock return (error); 14392676Seschrock break; 14402676Seschrock 14415378Sck153898 case ZFS_PROP_REFQUOTA: 14425378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14435378Sck153898 (error = dsl_dataset_set_quota(name, intval)) != 0) 14445378Sck153898 return (error); 14455378Sck153898 break; 14465378Sck153898 14472676Seschrock case ZFS_PROP_RESERVATION: 14482676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14492676Seschrock (error = dsl_dir_set_reservation(name, 14502676Seschrock intval)) != 0) 14512676Seschrock return (error); 14522676Seschrock break; 1453789Sahrens 14545378Sck153898 case ZFS_PROP_REFRESERVATION: 14555378Sck153898 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14565378Sck153898 (error = dsl_dataset_set_reservation(name, 14575378Sck153898 intval)) != 0) 14585378Sck153898 return (error); 14595378Sck153898 break; 14605378Sck153898 14612676Seschrock case ZFS_PROP_VOLSIZE: 14622676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14634787Sahrens (error = zvol_set_volsize(name, 14644787Sahrens ddi_driver_major(zfs_dip), intval)) != 0) 14652676Seschrock return (error); 14662676Seschrock break; 14672676Seschrock 14682676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 14692676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14704577Sahrens (error = zvol_set_volblocksize(name, intval)) != 0) 14714577Sahrens return (error); 14724577Sahrens break; 14734577Sahrens 14744577Sahrens case ZFS_PROP_VERSION: 14754577Sahrens if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 14764577Sahrens (error = zfs_set_version(name, intval)) != 0) 14772676Seschrock return (error); 14782676Seschrock break; 14792676Seschrock 14802676Seschrock default: 14812676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 14822676Seschrock if (zfs_prop_get_type(prop) != 14834787Sahrens PROP_TYPE_STRING) 14842676Seschrock return (EINVAL); 14852717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 14862717Seschrock if ((error = dsl_prop_set(name, 14872676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 14882717Seschrock strval)) != 0) 14892717Seschrock return (error); 14902676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 14912885Sahrens const char *unused; 14922885Sahrens 14932717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 14942676Seschrock 14952676Seschrock switch (zfs_prop_get_type(prop)) { 14964787Sahrens case PROP_TYPE_NUMBER: 14972676Seschrock break; 14984787Sahrens case PROP_TYPE_STRING: 14992717Seschrock return (EINVAL); 15004787Sahrens case PROP_TYPE_INDEX: 15012717Seschrock if (zfs_prop_index_to_string(prop, 15022717Seschrock intval, &unused) != 0) 15032717Seschrock return (EINVAL); 15042676Seschrock break; 15052676Seschrock default: 15064577Sahrens cmn_err(CE_PANIC, 15074577Sahrens "unknown property type"); 15082676Seschrock break; 15092676Seschrock } 15102676Seschrock 15112717Seschrock if ((error = dsl_prop_set(name, propname, 15122717Seschrock 8, 1, &intval)) != 0) 15132717Seschrock return (error); 15142676Seschrock } else { 15152676Seschrock return (EINVAL); 15162676Seschrock } 15172676Seschrock break; 15182676Seschrock } 15192676Seschrock } 15202676Seschrock 15212676Seschrock return (0); 1522789Sahrens } 1523789Sahrens 15245367Sahrens /* 15255367Sahrens * inputs: 15265367Sahrens * zc_name name of filesystem 15275367Sahrens * zc_value name of property to inherit 15285367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 15295367Sahrens * 15305367Sahrens * outputs: none 15315367Sahrens */ 1532789Sahrens static int 15332676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1534789Sahrens { 15352676Seschrock nvlist_t *nvl; 15362676Seschrock int error; 1537789Sahrens 15385094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15395094Slling &nvl)) != 0) 15402676Seschrock return (error); 15412676Seschrock 15424787Sahrens error = zfs_set_prop_nvlist(zc->zc_name, nvl); 15434543Smarks 15442676Seschrock nvlist_free(nvl); 15452676Seschrock return (error); 1546789Sahrens } 1547789Sahrens 15485367Sahrens /* 15495367Sahrens * inputs: 15505367Sahrens * zc_name name of filesystem 15515367Sahrens * zc_value name of property to inherit 15525367Sahrens * 15535367Sahrens * outputs: none 15545367Sahrens */ 1555789Sahrens static int 15564849Sahrens zfs_ioc_inherit_prop(zfs_cmd_t *zc) 15574849Sahrens { 15584849Sahrens /* the property name has been validated by zfs_secpolicy_inherit() */ 15594849Sahrens return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 15604849Sahrens } 15614849Sahrens 15624849Sahrens static int 15634098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 15643912Slling { 15655094Slling nvlist_t *props; 15663912Slling spa_t *spa; 15675094Slling int error; 15683912Slling 15695094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 15705094Slling &props))) 15713912Slling return (error); 15723912Slling 15733912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 15745094Slling nvlist_free(props); 15753912Slling return (error); 15763912Slling } 15773912Slling 15785094Slling error = spa_prop_set(spa, props); 15793912Slling 15805094Slling nvlist_free(props); 15813912Slling spa_close(spa, FTAG); 15823912Slling 15833912Slling return (error); 15843912Slling } 15853912Slling 15863912Slling static int 15874098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 15883912Slling { 15893912Slling spa_t *spa; 15903912Slling int error; 15913912Slling nvlist_t *nvp = NULL; 15923912Slling 15933912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 15943912Slling return (error); 15953912Slling 15965094Slling error = spa_prop_get(spa, &nvp); 15973912Slling 15983912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 15993912Slling error = put_nvlist(zc, nvp); 16003912Slling else 16013912Slling error = EFAULT; 16023912Slling 16033912Slling spa_close(spa, FTAG); 16043912Slling 16053912Slling if (nvp) 16063912Slling nvlist_free(nvp); 16073912Slling return (error); 16083912Slling } 16093912Slling 16103912Slling static int 16114543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 16124543Smarks { 16134543Smarks nvlist_t *nvp; 16144543Smarks int error; 16154543Smarks uint32_t uid; 16164543Smarks uint32_t gid; 16174543Smarks uint32_t *groups; 16184543Smarks uint_t group_cnt; 16194543Smarks cred_t *usercred; 16204543Smarks 16215094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16225094Slling &nvp)) != 0) { 16234543Smarks return (error); 16244543Smarks } 16254543Smarks 16264543Smarks if ((error = nvlist_lookup_uint32(nvp, 16274543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 16284543Smarks nvlist_free(nvp); 16294543Smarks return (EPERM); 16304543Smarks } 16314543Smarks 16324543Smarks if ((error = nvlist_lookup_uint32(nvp, 16334543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 16344543Smarks nvlist_free(nvp); 16354543Smarks return (EPERM); 16364543Smarks } 16374543Smarks 16384543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 16394543Smarks &groups, &group_cnt)) != 0) { 16404543Smarks nvlist_free(nvp); 16414543Smarks return (EPERM); 16424543Smarks } 16434543Smarks usercred = cralloc(); 16444543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 16454543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 16464543Smarks nvlist_free(nvp); 16474543Smarks crfree(usercred); 16484543Smarks return (EPERM); 16494543Smarks } 16504543Smarks nvlist_free(nvp); 16514543Smarks error = dsl_deleg_access(zc->zc_name, 16524787Sahrens zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); 16534543Smarks crfree(usercred); 16544543Smarks return (error); 16554543Smarks } 16564543Smarks 16575367Sahrens /* 16585367Sahrens * inputs: 16595367Sahrens * zc_name name of filesystem 16605367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 16615367Sahrens * zc_perm_action allow/unallow flag 16625367Sahrens * 16635367Sahrens * outputs: none 16645367Sahrens */ 16654543Smarks static int 16664543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 16674543Smarks { 16684543Smarks int error; 16694543Smarks nvlist_t *fsaclnv = NULL; 16704543Smarks 16715094Slling if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 16725094Slling &fsaclnv)) != 0) 16734543Smarks return (error); 16744543Smarks 16754543Smarks /* 16764543Smarks * Verify nvlist is constructed correctly 16774543Smarks */ 16784543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 16794543Smarks nvlist_free(fsaclnv); 16804543Smarks return (EINVAL); 16814543Smarks } 16824543Smarks 16834543Smarks /* 16844543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 16854543Smarks * that user is allowed to hand out each permission in 16864543Smarks * the nvlist(s) 16874543Smarks */ 16884543Smarks 16894787Sahrens error = secpolicy_zfs(CRED()); 16904543Smarks if (error) { 16914787Sahrens if (zc->zc_perm_action == B_FALSE) { 16924787Sahrens error = dsl_deleg_can_allow(zc->zc_name, 16934787Sahrens fsaclnv, CRED()); 16944787Sahrens } else { 16954787Sahrens error = dsl_deleg_can_unallow(zc->zc_name, 16964787Sahrens fsaclnv, CRED()); 16974787Sahrens } 16984543Smarks } 16994543Smarks 17004543Smarks if (error == 0) 17014543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 17024543Smarks 17034543Smarks nvlist_free(fsaclnv); 17044543Smarks return (error); 17054543Smarks } 17064543Smarks 17075367Sahrens /* 17085367Sahrens * inputs: 17095367Sahrens * zc_name name of filesystem 17105367Sahrens * 17115367Sahrens * outputs: 17125367Sahrens * zc_nvlist_src{_size} nvlist of delegated permissions 17135367Sahrens */ 17144543Smarks static int 17154543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 17164543Smarks { 17174543Smarks nvlist_t *nvp; 17184543Smarks int error; 17194543Smarks 17204543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 17214543Smarks error = put_nvlist(zc, nvp); 17224543Smarks nvlist_free(nvp); 17234543Smarks } 17244543Smarks 17254543Smarks return (error); 17264543Smarks } 17274543Smarks 17285367Sahrens /* 17295367Sahrens * inputs: 17305367Sahrens * zc_name name of volume 17315367Sahrens * 17325367Sahrens * outputs: none 17335367Sahrens */ 17344543Smarks static int 1735789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1736789Sahrens { 17374787Sahrens return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); 1738789Sahrens } 1739789Sahrens 17405367Sahrens /* 17415367Sahrens * inputs: 17425367Sahrens * zc_name name of volume 17435367Sahrens * 17445367Sahrens * outputs: none 17455367Sahrens */ 1746789Sahrens static int 1747789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1748789Sahrens { 17492676Seschrock return (zvol_remove_minor(zc->zc_name)); 1750789Sahrens } 1751789Sahrens 1752789Sahrens /* 1753789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1754789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1755789Sahrens * is responsible for releasing the returned vfs pointer. 1756789Sahrens */ 1757789Sahrens static vfs_t * 1758789Sahrens zfs_get_vfs(const char *resource) 1759789Sahrens { 1760789Sahrens struct vfs *vfsp; 1761789Sahrens struct vfs *vfs_found = NULL; 1762789Sahrens 1763789Sahrens vfs_list_read_lock(); 1764789Sahrens vfsp = rootvfs; 1765789Sahrens do { 1766789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1767789Sahrens VFS_HOLD(vfsp); 1768789Sahrens vfs_found = vfsp; 1769789Sahrens break; 1770789Sahrens } 1771789Sahrens vfsp = vfsp->vfs_next; 1772789Sahrens } while (vfsp != rootvfs); 1773789Sahrens vfs_list_unlock(); 1774789Sahrens return (vfs_found); 1775789Sahrens } 1776789Sahrens 17774543Smarks /* ARGSUSED */ 1778789Sahrens static void 17794543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1780789Sahrens { 17815331Samw zfs_creat_t *zct = arg; 17825498Stimh 17835498Stimh zfs_create_fs(os, cr, zct->zct_zplprops, tx); 17845331Samw } 17855331Samw 17865498Stimh #define ZFS_PROP_UNDEFINED ((uint64_t)-1) 17875498Stimh 17885331Samw /* 17895498Stimh * inputs: 17905498Stimh * createprops list of properties requested by creator 17915498Stimh * dataset name of dataset we are creating 17925331Samw * 17935498Stimh * outputs: 17945498Stimh * zplprops values for the zplprops we attach to the master node object 17955331Samw * 17965498Stimh * Determine the settings for utf8only, normalization and 17975498Stimh * casesensitivity. Specific values may have been requested by the 17985498Stimh * creator and/or we can inherit values from the parent dataset. If 17995498Stimh * the file system is of too early a vintage, a creator can not 18005498Stimh * request settings for these properties, even if the requested 18015498Stimh * setting is the default value. We don't actually want to create dsl 18025498Stimh * properties for these, so remove them from the source nvlist after 18035498Stimh * processing. 18045331Samw */ 18055331Samw static int 18065498Stimh zfs_fill_zplprops(const char *dataset, nvlist_t *createprops, 18075498Stimh nvlist_t *zplprops, uint64_t zplver) 18085331Samw { 18095498Stimh objset_t *os; 18105331Samw char parentname[MAXNAMELEN]; 18115331Samw char *cp; 18125498Stimh uint64_t sense = ZFS_PROP_UNDEFINED; 18135498Stimh uint64_t norm = ZFS_PROP_UNDEFINED; 18145498Stimh uint64_t u8 = ZFS_PROP_UNDEFINED; 18155498Stimh int error = 0; 18165498Stimh 18175498Stimh ASSERT(zplprops != NULL); 18185498Stimh 18195498Stimh (void) strlcpy(parentname, dataset, sizeof (parentname)); 18205498Stimh cp = strrchr(parentname, '/'); 18215498Stimh ASSERT(cp != NULL); 18225498Stimh cp[0] = '\0'; 18235331Samw 18245375Stimh /* 18255498Stimh * Pull out creator prop choices, if any. 18265375Stimh */ 18275498Stimh if (createprops) { 18285498Stimh (void) nvlist_lookup_uint64(createprops, 18295498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE), &norm); 18305498Stimh (void) nvlist_remove_all(createprops, 18315498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE)); 18325498Stimh (void) nvlist_lookup_uint64(createprops, 18335498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY), &u8); 18345498Stimh (void) nvlist_remove_all(createprops, 18355498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY)); 18365498Stimh (void) nvlist_lookup_uint64(createprops, 18375498Stimh zfs_prop_to_name(ZFS_PROP_CASE), &sense); 18385498Stimh (void) nvlist_remove_all(createprops, 18395498Stimh zfs_prop_to_name(ZFS_PROP_CASE)); 18405331Samw } 18415331Samw 18425375Stimh /* 18435498Stimh * If the file system or pool is version is too "young" to 18445498Stimh * support normalization and the creator tried to set a value 18455498Stimh * for one of the props, error out. We only need check the 18465498Stimh * ZPL version because we've already checked by now that the 18475498Stimh * SPA version is compatible with the selected ZPL version. 18485498Stimh */ 18495498Stimh if (zplver < ZPL_VERSION_NORMALIZATION && 18505498Stimh (norm != ZFS_PROP_UNDEFINED || u8 != ZFS_PROP_UNDEFINED || 18515498Stimh sense != ZFS_PROP_UNDEFINED)) 18525498Stimh return (ENOTSUP); 18535498Stimh 18545498Stimh /* 18555498Stimh * Put the version in the zplprops 18565498Stimh */ 18575498Stimh VERIFY(nvlist_add_uint64(zplprops, 18585498Stimh zfs_prop_to_name(ZFS_PROP_VERSION), zplver) == 0); 18595498Stimh 18605498Stimh /* 18615498Stimh * Open parent object set so we can inherit zplprop values if 18625498Stimh * necessary. 18635375Stimh */ 18645498Stimh if ((error = zfs_os_open_retry(parentname, &os)) != 0) 18655498Stimh return (error); 18665498Stimh 18675498Stimh if (norm == ZFS_PROP_UNDEFINED) 18685498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &norm) == 0); 18695498Stimh VERIFY(nvlist_add_uint64(zplprops, 18705498Stimh zfs_prop_to_name(ZFS_PROP_NORMALIZE), norm) == 0); 18715498Stimh 18725498Stimh /* 18735498Stimh * If we're normalizing, names must always be valid UTF-8 strings. 18745498Stimh */ 18755498Stimh if (norm) 18765498Stimh u8 = 1; 18775498Stimh if (u8 == ZFS_PROP_UNDEFINED) 18785498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &u8) == 0); 18795498Stimh VERIFY(nvlist_add_uint64(zplprops, 18805498Stimh zfs_prop_to_name(ZFS_PROP_UTF8ONLY), u8) == 0); 18815498Stimh 18825498Stimh if (sense == ZFS_PROP_UNDEFINED) 18835498Stimh VERIFY(zfs_get_zplprop(os, ZFS_PROP_CASE, &sense) == 0); 18845498Stimh VERIFY(nvlist_add_uint64(zplprops, 18855498Stimh zfs_prop_to_name(ZFS_PROP_CASE), sense) == 0); 18865498Stimh 18875498Stimh dmu_objset_close(os); 18885331Samw return (0); 1889789Sahrens } 1890789Sahrens 18915367Sahrens /* 18925367Sahrens * inputs: 18935367Sahrens * zc_objset_type type of objset to create (fs vs zvol) 18945367Sahrens * zc_name name of new objset 18955367Sahrens * zc_value name of snapshot to clone from (may be empty) 18965367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 18975367Sahrens * 18985498Stimh * outputs: none 18995367Sahrens */ 1900789Sahrens static int 1901789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1902789Sahrens { 1903789Sahrens objset_t *clone; 1904789Sahrens int error = 0; 19055331Samw zfs_creat_t zct; 19064543Smarks nvlist_t *nvprops = NULL; 19074543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1908789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1909789Sahrens 1910789Sahrens switch (type) { 1911789Sahrens 1912789Sahrens case DMU_OST_ZFS: 1913789Sahrens cbfunc = zfs_create_cb; 1914789Sahrens break; 1915789Sahrens 1916789Sahrens case DMU_OST_ZVOL: 1917789Sahrens cbfunc = zvol_create_cb; 1918789Sahrens break; 1919789Sahrens 1920789Sahrens default: 19212199Sahrens cbfunc = NULL; 19222199Sahrens } 19235326Sek110237 if (strchr(zc->zc_name, '@') || 19245326Sek110237 strchr(zc->zc_name, '%')) 1925789Sahrens return (EINVAL); 1926789Sahrens 19272676Seschrock if (zc->zc_nvlist_src != NULL && 19285094Slling (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 19295094Slling &nvprops)) != 0) 19302676Seschrock return (error); 19312676Seschrock 19325498Stimh zct.zct_zplprops = NULL; 19335331Samw zct.zct_props = nvprops; 19345331Samw 19352676Seschrock if (zc->zc_value[0] != '\0') { 1936789Sahrens /* 1937789Sahrens * We're creating a clone of an existing snapshot. 1938789Sahrens */ 19392676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 19402676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 19414543Smarks nvlist_free(nvprops); 1942789Sahrens return (EINVAL); 19432676Seschrock } 1944789Sahrens 19452676Seschrock error = dmu_objset_open(zc->zc_value, type, 1946789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 19472676Seschrock if (error) { 19484543Smarks nvlist_free(nvprops); 1949789Sahrens return (error); 19502676Seschrock } 1951789Sahrens error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); 19525331Samw if (error) { 19535331Samw dmu_objset_close(clone); 19545331Samw nvlist_free(nvprops); 19555331Samw return (error); 19565331Samw } 1957789Sahrens dmu_objset_close(clone); 1958789Sahrens } else { 19592676Seschrock if (cbfunc == NULL) { 19604543Smarks nvlist_free(nvprops); 19612199Sahrens return (EINVAL); 19622676Seschrock } 19632676Seschrock 1964789Sahrens if (type == DMU_OST_ZVOL) { 19652676Seschrock uint64_t volsize, volblocksize; 19662676Seschrock 19674543Smarks if (nvprops == NULL || 19684543Smarks nvlist_lookup_uint64(nvprops, 19692676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 19702676Seschrock &volsize) != 0) { 19714543Smarks nvlist_free(nvprops); 19722676Seschrock return (EINVAL); 19732676Seschrock } 19742676Seschrock 19754543Smarks if ((error = nvlist_lookup_uint64(nvprops, 19762676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 19772676Seschrock &volblocksize)) != 0 && error != ENOENT) { 19784543Smarks nvlist_free(nvprops); 19792676Seschrock return (EINVAL); 19802676Seschrock } 19811133Seschrock 19822676Seschrock if (error != 0) 19832676Seschrock volblocksize = zfs_prop_default_numeric( 19842676Seschrock ZFS_PROP_VOLBLOCKSIZE); 19852676Seschrock 19862676Seschrock if ((error = zvol_check_volblocksize( 19872676Seschrock volblocksize)) != 0 || 19882676Seschrock (error = zvol_check_volsize(volsize, 19892676Seschrock volblocksize)) != 0) { 19904543Smarks nvlist_free(nvprops); 1991789Sahrens return (error); 19922676Seschrock } 19934577Sahrens } else if (type == DMU_OST_ZFS) { 19944577Sahrens uint64_t version; 19955331Samw int error; 19965331Samw 19975498Stimh /* 19985498Stimh * Default ZPL version to non-FUID capable if the 19995498Stimh * pool is not upgraded to support FUIDs. 20005498Stimh */ 20015498Stimh if (zfs_check_version(zc->zc_name, SPA_VERSION_FUID)) 20025498Stimh version = ZPL_VERSION_FUID - 1; 20035498Stimh else 20045498Stimh version = ZPL_VERSION; 20055498Stimh 20065498Stimh /* 20075498Stimh * Potentially override default ZPL version based 20085498Stimh * on creator's request. 20095498Stimh */ 20105498Stimh (void) nvlist_lookup_uint64(nvprops, 20115331Samw zfs_prop_to_name(ZFS_PROP_VERSION), &version); 20125331Samw 20135498Stimh /* 20145498Stimh * Make sure version we ended up with is kosher 20155498Stimh */ 20165498Stimh if ((version < ZPL_VERSION_INITIAL || 20175498Stimh version > ZPL_VERSION) || 20185498Stimh (version >= ZPL_VERSION_FUID && 20195498Stimh zfs_check_version(zc->zc_name, SPA_VERSION_FUID))) { 20205331Samw nvlist_free(nvprops); 20215331Samw return (ENOTSUP); 20225331Samw } 20235331Samw 20245331Samw /* 20255331Samw * We have to have normalization and 20265331Samw * case-folding flags correct when we do the 20275331Samw * file system creation, so go figure them out 20285498Stimh * now. 20295331Samw */ 20305498Stimh VERIFY(nvlist_alloc(&zct.zct_zplprops, 20315498Stimh NV_UNIQUE_NAME, KM_SLEEP) == 0); 20325498Stimh error = zfs_fill_zplprops(zc->zc_name, nvprops, 20335498Stimh zct.zct_zplprops, version); 20345331Samw if (error != 0) { 20355331Samw nvlist_free(nvprops); 20365498Stimh nvlist_free(zct.zct_zplprops); 20375331Samw return (error); 20384577Sahrens } 20392676Seschrock } 20402676Seschrock error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, 20415331Samw &zct); 20425498Stimh nvlist_free(zct.zct_zplprops); 2043789Sahrens } 20442676Seschrock 20452676Seschrock /* 20462676Seschrock * It would be nice to do this atomically. 20472676Seschrock */ 20482676Seschrock if (error == 0) { 20494787Sahrens if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) 20502676Seschrock (void) dmu_objset_destroy(zc->zc_name); 20512676Seschrock } 20522676Seschrock 20534543Smarks nvlist_free(nvprops); 2054789Sahrens return (error); 2055789Sahrens } 2056789Sahrens 20575367Sahrens /* 20585367Sahrens * inputs: 20595367Sahrens * zc_name name of filesystem 20605367Sahrens * zc_value short name of snapshot 20615367Sahrens * zc_cookie recursive flag 20625367Sahrens * 20635367Sahrens * outputs: none 20645367Sahrens */ 2065789Sahrens static int 20662199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 20672199Sahrens { 20682676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 20692199Sahrens return (EINVAL); 20702199Sahrens return (dmu_objset_snapshot(zc->zc_name, 20712676Seschrock zc->zc_value, zc->zc_cookie)); 20722199Sahrens } 20732199Sahrens 20744007Smmusante int 20752199Sahrens zfs_unmount_snap(char *name, void *arg) 2076789Sahrens { 20772199Sahrens char *snapname = arg; 20782199Sahrens char *cp; 20792417Sahrens vfs_t *vfsp = NULL; 20802199Sahrens 20812199Sahrens /* 20822199Sahrens * Snapshots (which are under .zfs control) must be unmounted 20832199Sahrens * before they can be destroyed. 20842199Sahrens */ 20852199Sahrens 20862199Sahrens if (snapname) { 20872199Sahrens (void) strcat(name, "@"); 20882199Sahrens (void) strcat(name, snapname); 20892199Sahrens vfsp = zfs_get_vfs(name); 20902199Sahrens cp = strchr(name, '@'); 20912199Sahrens *cp = '\0'; 20922417Sahrens } else if (strchr(name, '@')) { 20932199Sahrens vfsp = zfs_get_vfs(name); 20942199Sahrens } 20952199Sahrens 20962199Sahrens if (vfsp) { 20972199Sahrens /* 20982199Sahrens * Always force the unmount for snapshots. 20992199Sahrens */ 21002199Sahrens int flag = MS_FORCE; 2101789Sahrens int err; 2102789Sahrens 21032199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 21042199Sahrens VFS_RELE(vfsp); 21052199Sahrens return (err); 21062199Sahrens } 21072199Sahrens VFS_RELE(vfsp); 21082199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 21092199Sahrens return (err); 21102199Sahrens } 21112199Sahrens return (0); 21122199Sahrens } 21132199Sahrens 21145367Sahrens /* 21155367Sahrens * inputs: 21165367Sahrens * zc_name name of filesystem 21175367Sahrens * zc_value short name of snapshot 21185367Sahrens * 21195367Sahrens * outputs: none 21205367Sahrens */ 21212199Sahrens static int 21222199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 21232199Sahrens { 21242199Sahrens int err; 2125789Sahrens 21262676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 21272199Sahrens return (EINVAL); 21282199Sahrens err = dmu_objset_find(zc->zc_name, 21292676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 21302199Sahrens if (err) 21312199Sahrens return (err); 21322676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 21332199Sahrens } 21342199Sahrens 21355367Sahrens /* 21365367Sahrens * inputs: 21375367Sahrens * zc_name name of dataset to destroy 21385367Sahrens * zc_objset_type type of objset 21395367Sahrens * 21405367Sahrens * outputs: none 21415367Sahrens */ 21422199Sahrens static int 21432199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 21442199Sahrens { 21452199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 21462199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 21472199Sahrens if (err) 21482199Sahrens return (err); 2149789Sahrens } 2150789Sahrens 2151789Sahrens return (dmu_objset_destroy(zc->zc_name)); 2152789Sahrens } 2153789Sahrens 21545367Sahrens /* 21555367Sahrens * inputs: 21565446Sahrens * zc_name name of dataset to rollback (to most recent snapshot) 21575367Sahrens * 21585367Sahrens * outputs: none 21595367Sahrens */ 2160789Sahrens static int 2161789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 2162789Sahrens { 21635446Sahrens objset_t *os; 21645446Sahrens int error; 21655446Sahrens zfsvfs_t *zfsvfs = NULL; 21665446Sahrens 21675446Sahrens /* 21685446Sahrens * Get the zfsvfs for the receiving objset. There 21695446Sahrens * won't be one if we're operating on a zvol, if the 21705446Sahrens * objset doesn't exist yet, or is not mounted. 21715446Sahrens */ 21725446Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 21735446Sahrens DS_MODE_STANDARD, &os); 21745446Sahrens if (error) 21755446Sahrens return (error); 21765446Sahrens 21775446Sahrens if (dmu_objset_type(os) == DMU_OST_ZFS) { 21785446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 21795446Sahrens zfsvfs = dmu_objset_get_user(os); 21805446Sahrens if (zfsvfs != NULL) 21815446Sahrens VFS_HOLD(zfsvfs->z_vfs); 21825446Sahrens mutex_exit(&os->os->os_user_ptr_lock); 21835446Sahrens } 21845446Sahrens 21855446Sahrens if (zfsvfs != NULL) { 21865446Sahrens char osname[MAXNAMELEN]; 21875446Sahrens int mode; 21885446Sahrens 21895446Sahrens VERIFY3U(0, ==, zfs_suspend_fs(zfsvfs, osname, &mode)); 21905446Sahrens ASSERT(strcmp(osname, zc->zc_name) == 0); 21915446Sahrens error = dmu_objset_rollback(os); 21925446Sahrens VERIFY3U(0, ==, zfs_resume_fs(zfsvfs, osname, mode)); 21935446Sahrens 21945446Sahrens VFS_RELE(zfsvfs->z_vfs); 21955446Sahrens } else { 21965446Sahrens error = dmu_objset_rollback(os); 21975446Sahrens } 21985446Sahrens /* Note, the dmu_objset_rollback() closes the objset for us. */ 21995446Sahrens 22005446Sahrens return (error); 2201789Sahrens } 2202789Sahrens 22035367Sahrens /* 22045367Sahrens * inputs: 22055367Sahrens * zc_name old name of dataset 22065367Sahrens * zc_value new name of dataset 22075367Sahrens * zc_cookie recursive flag (only valid for snapshots) 22085367Sahrens * 22095367Sahrens * outputs: none 22105367Sahrens */ 2211789Sahrens static int 2212789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 2213789Sahrens { 22144490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 22154007Smmusante 22162676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 22175326Sek110237 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 22185326Sek110237 strchr(zc->zc_value, '%')) 2219789Sahrens return (EINVAL); 2220789Sahrens 22214007Smmusante /* 22224007Smmusante * Unmount snapshot unless we're doing a recursive rename, 22234007Smmusante * in which case the dataset code figures out which snapshots 22244007Smmusante * to unmount. 22254007Smmusante */ 22264007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 2227789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 22282199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 22292199Sahrens if (err) 22302199Sahrens return (err); 2231789Sahrens } 2232789Sahrens 22334007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 2234789Sahrens } 2235789Sahrens 22365367Sahrens /* 22375367Sahrens * inputs: 22385367Sahrens * zc_name name of containing filesystem 22395367Sahrens * zc_nvlist_src{_size} nvlist of properties to apply 22405367Sahrens * zc_value name of snapshot to create 22415367Sahrens * zc_string name of clone origin (if DRR_FLAG_CLONE) 22425367Sahrens * zc_cookie file descriptor to recv from 22435367Sahrens * zc_begin_record the BEGIN record of the stream (not byteswapped) 22445367Sahrens * zc_guid force flag 22455367Sahrens * 22465367Sahrens * outputs: 22475367Sahrens * zc_cookie number of bytes read 22485367Sahrens */ 2249789Sahrens static int 22505367Sahrens zfs_ioc_recv(zfs_cmd_t *zc) 2251789Sahrens { 2252789Sahrens file_t *fp; 22535326Sek110237 objset_t *os; 22545367Sahrens dmu_recv_cookie_t drc; 22555326Sek110237 zfsvfs_t *zfsvfs = NULL; 22565326Sek110237 boolean_t force = (boolean_t)zc->zc_guid; 2257789Sahrens int error, fd; 22585367Sahrens offset_t off; 22595367Sahrens nvlist_t *props = NULL; 22605367Sahrens objset_t *origin = NULL; 22615367Sahrens char *tosnap; 22625367Sahrens char tofs[ZFS_MAXNAMELEN]; 2263789Sahrens 22643265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 22655326Sek110237 strchr(zc->zc_value, '@') == NULL || 22665326Sek110237 strchr(zc->zc_value, '%')) 22673265Sahrens return (EINVAL); 22683265Sahrens 22695367Sahrens (void) strcpy(tofs, zc->zc_value); 22705367Sahrens tosnap = strchr(tofs, '@'); 22715367Sahrens *tosnap = '\0'; 22725367Sahrens tosnap++; 22735367Sahrens 22745367Sahrens if (zc->zc_nvlist_src != NULL && 22755367Sahrens (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, 22765367Sahrens &props)) != 0) 22775367Sahrens return (error); 22785367Sahrens 2279789Sahrens fd = zc->zc_cookie; 2280789Sahrens fp = getf(fd); 22815367Sahrens if (fp == NULL) { 22825367Sahrens nvlist_free(props); 2283789Sahrens return (EBADF); 22845367Sahrens } 22855326Sek110237 22865326Sek110237 /* 22875326Sek110237 * Get the zfsvfs for the receiving objset. There 22885326Sek110237 * won't be one if we're operating on a zvol, if the 22895326Sek110237 * objset doesn't exist yet, or is not mounted. 22905326Sek110237 */ 22915367Sahrens 22925446Sahrens error = dmu_objset_open(tofs, DMU_OST_ZFS, 22935326Sek110237 DS_MODE_STANDARD | DS_MODE_READONLY, &os); 22945326Sek110237 if (!error) { 22955446Sahrens mutex_enter(&os->os->os_user_ptr_lock); 22965446Sahrens zfsvfs = dmu_objset_get_user(os); 22975446Sahrens if (zfsvfs != NULL) 22985446Sahrens VFS_HOLD(zfsvfs->z_vfs); 22995446Sahrens mutex_exit(&os->os->os_user_ptr_lock); 23005326Sek110237 dmu_objset_close(os); 23015326Sek110237 } 23025326Sek110237 23035367Sahrens if (zc->zc_string[0]) { 23045367Sahrens error = dmu_objset_open(zc->zc_string, DMU_OST_ANY, 23055367Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &origin); 23065367Sahrens if (error) { 23075367Sahrens if (zfsvfs != NULL) 23085367Sahrens VFS_RELE(zfsvfs->z_vfs); 23095367Sahrens nvlist_free(props); 23105367Sahrens releasef(fd); 23115367Sahrens return (error); 23125367Sahrens } 23135367Sahrens } 23145367Sahrens 23155367Sahrens error = dmu_recv_begin(tofs, tosnap, &zc->zc_begin_record, 23165367Sahrens force, origin, zfsvfs != NULL, &drc); 23175367Sahrens if (origin) 23185367Sahrens dmu_objset_close(origin); 23195367Sahrens if (error) { 23205367Sahrens if (zfsvfs != NULL) 23215367Sahrens VFS_RELE(zfsvfs->z_vfs); 23225367Sahrens nvlist_free(props); 23235367Sahrens releasef(fd); 23245367Sahrens return (error); 23255367Sahrens } 23265326Sek110237 23275326Sek110237 /* 23285367Sahrens * If properties are supplied, they are to completely replace 23295367Sahrens * the existing ones; "inherit" any existing properties. 23305326Sek110237 */ 23315367Sahrens if (props) { 23325367Sahrens objset_t *os; 23335367Sahrens nvlist_t *nv = NULL; 23345367Sahrens 23355367Sahrens error = dmu_objset_open(tofs, DMU_OST_ANY, 23365367Sahrens DS_MODE_STANDARD | DS_MODE_READONLY | DS_MODE_INCONSISTENT, 23375367Sahrens &os); 23385367Sahrens if (error == 0) { 23395367Sahrens error = dsl_prop_get_all(os, &nv); 23405367Sahrens dmu_objset_close(os); 23415367Sahrens } 23425367Sahrens if (error == 0) { 23435367Sahrens nvpair_t *elem; 23445446Sahrens zfs_cmd_t *zc2; 23455446Sahrens zc2 = kmem_alloc(sizeof (zfs_cmd_t), KM_SLEEP); 23465446Sahrens 23475446Sahrens (void) strcpy(zc2->zc_name, tofs); 23485367Sahrens for (elem = nvlist_next_nvpair(nv, NULL); elem; 23495367Sahrens elem = nvlist_next_nvpair(nv, elem)) { 23505446Sahrens (void) strcpy(zc2->zc_value, nvpair_name(elem)); 23515446Sahrens if (zfs_secpolicy_inherit(zc2, CRED()) == 0) 23525446Sahrens (void) zfs_ioc_inherit_prop(zc2); 23535326Sek110237 } 23545446Sahrens kmem_free(zc2, sizeof (zfs_cmd_t)); 23555326Sek110237 } 23565367Sahrens if (nv) 23575367Sahrens nvlist_free(nv); 23585367Sahrens } 23595367Sahrens 23605367Sahrens /* 23615367Sahrens * Set properties. Note, we ignore errors. Would be better to 23625367Sahrens * do best-effort in zfs_set_prop_nvlist, too. 23635367Sahrens */ 23645367Sahrens (void) zfs_set_prop_nvlist(tofs, props); 23655367Sahrens nvlist_free(props); 23665367Sahrens 23675367Sahrens off = fp->f_offset; 23685367Sahrens error = dmu_recv_stream(&drc, fp->f_vnode, &off); 23695367Sahrens 23705367Sahrens if (error == 0) { 23715367Sahrens if (zfsvfs != NULL) { 23725367Sahrens char osname[MAXNAMELEN]; 23735367Sahrens int mode; 23745367Sahrens 23755367Sahrens (void) zfs_suspend_fs(zfsvfs, osname, &mode); 23765367Sahrens error = dmu_recv_end(&drc); 23775367Sahrens error |= zfs_resume_fs(zfsvfs, osname, mode); 23785367Sahrens } else { 23795367Sahrens error = dmu_recv_end(&drc); 23805367Sahrens } 23815326Sek110237 } 23825326Sek110237 if (zfsvfs != NULL) 23835326Sek110237 VFS_RELE(zfsvfs->z_vfs); 23845367Sahrens 23855367Sahrens zc->zc_cookie = off - fp->f_offset; 23865367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 23875367Sahrens fp->f_offset = off; 23882885Sahrens 2389789Sahrens releasef(fd); 2390789Sahrens return (error); 2391789Sahrens } 2392789Sahrens 23935367Sahrens /* 23945367Sahrens * inputs: 23955367Sahrens * zc_name name of snapshot to send 23965367Sahrens * zc_value short name of incremental fromsnap (may be empty) 23975367Sahrens * zc_cookie file descriptor to send stream to 23985367Sahrens * zc_obj fromorigin flag (mutually exclusive with zc_value) 23995367Sahrens * 24005367Sahrens * outputs: none 24015367Sahrens */ 2402789Sahrens static int 24035367Sahrens zfs_ioc_send(zfs_cmd_t *zc) 2404789Sahrens { 2405789Sahrens objset_t *fromsnap = NULL; 2406789Sahrens objset_t *tosnap; 2407789Sahrens file_t *fp; 2408789Sahrens int error; 24095367Sahrens offset_t off; 2410789Sahrens 2411789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 2412789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); 2413789Sahrens if (error) 2414789Sahrens return (error); 2415789Sahrens 24162676Seschrock if (zc->zc_value[0] != '\0') { 24172885Sahrens char buf[MAXPATHLEN]; 24182885Sahrens char *cp; 24192885Sahrens 24202885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 24212885Sahrens cp = strchr(buf, '@'); 24222885Sahrens if (cp) 24232885Sahrens *(cp+1) = 0; 24242885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 24252885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 2426789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); 2427789Sahrens if (error) { 2428789Sahrens dmu_objset_close(tosnap); 2429789Sahrens return (error); 2430789Sahrens } 2431789Sahrens } 2432789Sahrens 2433789Sahrens fp = getf(zc->zc_cookie); 2434789Sahrens if (fp == NULL) { 2435789Sahrens dmu_objset_close(tosnap); 2436789Sahrens if (fromsnap) 2437789Sahrens dmu_objset_close(fromsnap); 2438789Sahrens return (EBADF); 2439789Sahrens } 2440789Sahrens 24415367Sahrens off = fp->f_offset; 24425367Sahrens error = dmu_sendbackup(tosnap, fromsnap, zc->zc_obj, fp->f_vnode, &off); 24435367Sahrens 24445367Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) 24455367Sahrens fp->f_offset = off; 2446789Sahrens releasef(zc->zc_cookie); 2447789Sahrens if (fromsnap) 2448789Sahrens dmu_objset_close(fromsnap); 2449789Sahrens dmu_objset_close(tosnap); 2450789Sahrens return (error); 2451789Sahrens } 2452789Sahrens 24531544Seschrock static int 24541544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 24551544Seschrock { 24561544Seschrock int id, error; 24571544Seschrock 24581544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 24591544Seschrock &zc->zc_inject_record); 24601544Seschrock 24611544Seschrock if (error == 0) 24621544Seschrock zc->zc_guid = (uint64_t)id; 24631544Seschrock 24641544Seschrock return (error); 24651544Seschrock } 24661544Seschrock 24671544Seschrock static int 24681544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 24691544Seschrock { 24701544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 24711544Seschrock } 24721544Seschrock 24731544Seschrock static int 24741544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 24751544Seschrock { 24761544Seschrock int id = (int)zc->zc_guid; 24771544Seschrock int error; 24781544Seschrock 24791544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 24801544Seschrock &zc->zc_inject_record); 24811544Seschrock 24821544Seschrock zc->zc_guid = id; 24831544Seschrock 24841544Seschrock return (error); 24851544Seschrock } 24861544Seschrock 24871544Seschrock static int 24881544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 24891544Seschrock { 24901544Seschrock spa_t *spa; 24911544Seschrock int error; 24922676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 24931544Seschrock 24941544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 24951544Seschrock return (error); 24961544Seschrock 24972676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 24981544Seschrock &count); 24991544Seschrock if (error == 0) 25002676Seschrock zc->zc_nvlist_dst_size = count; 25011544Seschrock else 25022676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 25031544Seschrock 25041544Seschrock spa_close(spa, FTAG); 25051544Seschrock 25061544Seschrock return (error); 25071544Seschrock } 25081544Seschrock 25091544Seschrock static int 25101544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 25111544Seschrock { 25121544Seschrock spa_t *spa; 25131544Seschrock vdev_t *vd; 25144808Sek110237 uint64_t txg; 25151544Seschrock int error; 25161544Seschrock 25171544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 25181544Seschrock return (error); 25191544Seschrock 25205329Sgw25295 /* 25215329Sgw25295 * Try to resume any I/Os which may have been suspended 25225329Sgw25295 * as a result of a complete pool failure. 25235329Sgw25295 */ 25245329Sgw25295 if (!list_is_empty(&spa->spa_zio_list)) { 25255329Sgw25295 if (zio_vdev_resume_io(spa) != 0) { 25265329Sgw25295 spa_close(spa, FTAG); 25275329Sgw25295 return (EIO); 25285329Sgw25295 } 25295329Sgw25295 } 25305329Sgw25295 25314451Seschrock txg = spa_vdev_enter(spa); 25321544Seschrock 25332676Seschrock if (zc->zc_guid == 0) { 25341544Seschrock vd = NULL; 25352676Seschrock } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { 25365450Sbrendan spa_aux_vdev_t *sav; 25375450Sbrendan int i; 25385450Sbrendan 25395450Sbrendan /* 25405450Sbrendan * Check if this is an l2cache device. 25415450Sbrendan */ 25425450Sbrendan ASSERT(spa != NULL); 25435450Sbrendan sav = &spa->spa_l2cache; 25445450Sbrendan for (i = 0; i < sav->sav_count; i++) { 25455450Sbrendan if (sav->sav_vdevs[i]->vdev_guid == zc->zc_guid) { 25465450Sbrendan vd = sav->sav_vdevs[i]; 25475450Sbrendan break; 25485450Sbrendan } 25495450Sbrendan } 25505450Sbrendan 25515450Sbrendan if (vd == NULL) { 25525450Sbrendan (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 25535450Sbrendan spa_close(spa, FTAG); 25545450Sbrendan return (ENODEV); 25555450Sbrendan } 25561544Seschrock } 25571544Seschrock 25585329Sgw25295 vdev_clear(spa, vd, B_TRUE); 25591544Seschrock 25604451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 25611544Seschrock 25621544Seschrock spa_close(spa, FTAG); 25631544Seschrock 25641544Seschrock return (0); 25651544Seschrock } 25661544Seschrock 25675367Sahrens /* 25685367Sahrens * inputs: 25695367Sahrens * zc_name name of filesystem 25705367Sahrens * zc_value name of origin snapshot 25715367Sahrens * 25725367Sahrens * outputs: none 25735367Sahrens */ 25741544Seschrock static int 25752082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 25762082Seschrock { 25772417Sahrens char *cp; 25782417Sahrens 25792417Sahrens /* 25802417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 25812417Sahrens * it's easier. 25822417Sahrens */ 25832676Seschrock cp = strchr(zc->zc_value, '@'); 25842417Sahrens if (cp) 25852417Sahrens *cp = '\0'; 25862676Seschrock (void) dmu_objset_find(zc->zc_value, 25872417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 25882082Seschrock return (dsl_dataset_promote(zc->zc_name)); 25892082Seschrock } 25902082Seschrock 25914543Smarks /* 25924543Smarks * We don't want to have a hard dependency 25934543Smarks * against some special symbols in sharefs 25945331Samw * nfs, and smbsrv. Determine them if needed when 25954543Smarks * the first file system is shared. 25965331Samw * Neither sharefs, nfs or smbsrv are unloadable modules. 25974543Smarks */ 25985331Samw int (*znfsexport_fs)(void *arg); 25994543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 26005331Samw int (*zsmbexport_fs)(void *arg, boolean_t add_share); 26015331Samw 26025331Samw int zfs_nfsshare_inited; 26035331Samw int zfs_smbshare_inited; 26045331Samw 26054543Smarks ddi_modhandle_t nfs_mod; 26064543Smarks ddi_modhandle_t sharefs_mod; 26075331Samw ddi_modhandle_t smbsrv_mod; 26084543Smarks kmutex_t zfs_share_lock; 26094543Smarks 26104543Smarks static int 26115331Samw zfs_init_sharefs() 26125331Samw { 26135331Samw int error; 26145331Samw 26155331Samw ASSERT(MUTEX_HELD(&zfs_share_lock)); 26165331Samw /* Both NFS and SMB shares also require sharetab support. */ 26175331Samw if (sharefs_mod == NULL && ((sharefs_mod = 26185331Samw ddi_modopen("fs/sharefs", 26195331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26205331Samw return (ENOSYS); 26215331Samw } 26225331Samw if (zshare_fs == NULL && ((zshare_fs = 26235331Samw (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 26245331Samw ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 26255331Samw return (ENOSYS); 26265331Samw } 26275331Samw return (0); 26285331Samw } 26295331Samw 26305331Samw static int 26314543Smarks zfs_ioc_share(zfs_cmd_t *zc) 26324543Smarks { 26334543Smarks int error; 26344543Smarks int opcode; 26354543Smarks 26365331Samw switch (zc->zc_share.z_sharetype) { 26375331Samw case ZFS_SHARE_NFS: 26385331Samw case ZFS_UNSHARE_NFS: 26395331Samw if (zfs_nfsshare_inited == 0) { 26405331Samw mutex_enter(&zfs_share_lock); 26415331Samw if (nfs_mod == NULL && ((nfs_mod = ddi_modopen("fs/nfs", 26425331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26435331Samw mutex_exit(&zfs_share_lock); 26445331Samw return (ENOSYS); 26455331Samw } 26465331Samw if (znfsexport_fs == NULL && 26475331Samw ((znfsexport_fs = (int (*)(void *)) 26485331Samw ddi_modsym(nfs_mod, 26495331Samw "nfs_export", &error)) == NULL)) { 26505331Samw mutex_exit(&zfs_share_lock); 26515331Samw return (ENOSYS); 26525331Samw } 26535331Samw error = zfs_init_sharefs(); 26545331Samw if (error) { 26555331Samw mutex_exit(&zfs_share_lock); 26565331Samw return (ENOSYS); 26575331Samw } 26585331Samw zfs_nfsshare_inited = 1; 26594543Smarks mutex_exit(&zfs_share_lock); 26604543Smarks } 26615331Samw break; 26625331Samw case ZFS_SHARE_SMB: 26635331Samw case ZFS_UNSHARE_SMB: 26645331Samw if (zfs_smbshare_inited == 0) { 26655331Samw mutex_enter(&zfs_share_lock); 26665331Samw if (smbsrv_mod == NULL && ((smbsrv_mod = 26675331Samw ddi_modopen("drv/smbsrv", 26685331Samw KRTLD_MODE_FIRST, &error)) == NULL)) { 26695331Samw mutex_exit(&zfs_share_lock); 26705331Samw return (ENOSYS); 26715331Samw } 26725331Samw if (zsmbexport_fs == NULL && ((zsmbexport_fs = 26735331Samw (int (*)(void *, boolean_t))ddi_modsym(smbsrv_mod, 26745331Samw "lmshrd_share_upcall", &error)) == NULL)) { 26755331Samw mutex_exit(&zfs_share_lock); 26765331Samw return (ENOSYS); 26775331Samw } 26785331Samw error = zfs_init_sharefs(); 26795331Samw if (error) { 26805331Samw mutex_exit(&zfs_share_lock); 26815331Samw return (ENOSYS); 26825331Samw } 26835331Samw zfs_smbshare_inited = 1; 26844543Smarks mutex_exit(&zfs_share_lock); 26854543Smarks } 26865331Samw break; 26875331Samw default: 26885331Samw return (EINVAL); 26894543Smarks } 26904543Smarks 26915331Samw switch (zc->zc_share.z_sharetype) { 26925331Samw case ZFS_SHARE_NFS: 26935331Samw case ZFS_UNSHARE_NFS: 26945331Samw if (error = 26955331Samw znfsexport_fs((void *) 26965331Samw (uintptr_t)zc->zc_share.z_exportdata)) 26975331Samw return (error); 26985331Samw break; 26995331Samw case ZFS_SHARE_SMB: 27005331Samw case ZFS_UNSHARE_SMB: 27015331Samw if (error = zsmbexport_fs((void *) 27025331Samw (uintptr_t)zc->zc_share.z_exportdata, 27035331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB ? 27045331Samw B_TRUE : B_FALSE)) { 27055331Samw return (error); 27065331Samw } 27075331Samw break; 27085331Samw } 27095331Samw 27105331Samw opcode = (zc->zc_share.z_sharetype == ZFS_SHARE_NFS || 27115331Samw zc->zc_share.z_sharetype == ZFS_SHARE_SMB) ? 27124543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 27134543Smarks 27145331Samw /* 27155331Samw * Add or remove share from sharetab 27165331Samw */ 27174543Smarks error = zshare_fs(opcode, 27184543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 27194543Smarks zc->zc_share.z_sharemax); 27204543Smarks 27214543Smarks return (error); 27224543Smarks 27234543Smarks } 27244543Smarks 27254543Smarks /* 27264988Sek110237 * pool create, destroy, and export don't log the history as part of 27274988Sek110237 * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export 27284988Sek110237 * do the logging of those commands. 27294543Smarks */ 2730789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 27314715Sek110237 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27324577Sahrens { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27334577Sahrens { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27344577Sahrens { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27354577Sahrens { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, 27364577Sahrens { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 27374577Sahrens { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27384577Sahrens { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27394577Sahrens { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27404577Sahrens { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27414577Sahrens { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27424577Sahrens { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27434577Sahrens { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27444577Sahrens { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27454577Sahrens { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27464577Sahrens { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27474577Sahrens { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27484577Sahrens { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27495498Stimh { zfs_ioc_objset_zplprops, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27504543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 27514577Sahrens DATASET_NAME, B_FALSE }, 27524543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 27534577Sahrens DATASET_NAME, B_FALSE }, 27544577Sahrens { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, 27554577Sahrens { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 27564577Sahrens { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, 27574577Sahrens { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, 27584577Sahrens { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 27594577Sahrens { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, 27604577Sahrens { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, 27615367Sahrens { zfs_ioc_recv, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, 27625367Sahrens { zfs_ioc_send, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, 27634577Sahrens { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 27644577Sahrens { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 27654577Sahrens { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, 27664577Sahrens { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, 27674577Sahrens { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27684577Sahrens { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, 27694577Sahrens { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, 27704577Sahrens { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, 27714577Sahrens { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, 27724577Sahrens { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, 27734577Sahrens { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, 27744577Sahrens { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, 27754577Sahrens { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, 27764577Sahrens { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, 27774543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 27784577Sahrens DATASET_NAME, B_FALSE }, 27794849Sahrens { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }, 27804849Sahrens { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE }, 2781789Sahrens }; 2782789Sahrens 2783789Sahrens static int 2784789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2785789Sahrens { 2786789Sahrens zfs_cmd_t *zc; 2787789Sahrens uint_t vec; 27882199Sahrens int error, rc; 2789789Sahrens 2790789Sahrens if (getminor(dev) != 0) 2791789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2792789Sahrens 2793789Sahrens vec = cmd - ZFS_IOC; 27944787Sahrens ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); 2795789Sahrens 2796789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2797789Sahrens return (EINVAL); 2798789Sahrens 2799789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2800789Sahrens 2801789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2802789Sahrens 28034787Sahrens if (error == 0) 28044543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2805789Sahrens 2806789Sahrens /* 2807789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2808789Sahrens * the lower layers. 2809789Sahrens */ 2810789Sahrens if (error == 0) { 2811789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2812789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 28134577Sahrens case POOL_NAME: 2814789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2815789Sahrens error = EINVAL; 2816789Sahrens break; 2817789Sahrens 28184577Sahrens case DATASET_NAME: 2819789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2820789Sahrens error = EINVAL; 2821789Sahrens break; 28222856Snd150628 28234577Sahrens case NO_NAME: 28242856Snd150628 break; 2825789Sahrens } 2826789Sahrens } 2827789Sahrens 2828789Sahrens if (error == 0) 2829789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2830789Sahrens 28312199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 28324543Smarks if (error == 0) { 28332199Sahrens error = rc; 28344543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 28354543Smarks zfs_log_history(zc); 28364543Smarks } 2837789Sahrens 2838789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2839789Sahrens return (error); 2840789Sahrens } 2841789Sahrens 2842789Sahrens static int 2843789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2844789Sahrens { 2845789Sahrens if (cmd != DDI_ATTACH) 2846789Sahrens return (DDI_FAILURE); 2847789Sahrens 2848789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2849789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2850789Sahrens return (DDI_FAILURE); 2851789Sahrens 2852789Sahrens zfs_dip = dip; 2853789Sahrens 2854789Sahrens ddi_report_dev(dip); 2855789Sahrens 2856789Sahrens return (DDI_SUCCESS); 2857789Sahrens } 2858789Sahrens 2859789Sahrens static int 2860789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2861789Sahrens { 2862789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2863789Sahrens return (DDI_FAILURE); 2864789Sahrens 2865789Sahrens if (cmd != DDI_DETACH) 2866789Sahrens return (DDI_FAILURE); 2867789Sahrens 2868789Sahrens zfs_dip = NULL; 2869789Sahrens 2870789Sahrens ddi_prop_remove_all(dip); 2871789Sahrens ddi_remove_minor_node(dip, NULL); 2872789Sahrens 2873789Sahrens return (DDI_SUCCESS); 2874789Sahrens } 2875789Sahrens 2876789Sahrens /*ARGSUSED*/ 2877789Sahrens static int 2878789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2879789Sahrens { 2880789Sahrens switch (infocmd) { 2881789Sahrens case DDI_INFO_DEVT2DEVINFO: 2882789Sahrens *result = zfs_dip; 2883789Sahrens return (DDI_SUCCESS); 2884789Sahrens 2885789Sahrens case DDI_INFO_DEVT2INSTANCE: 2886849Sbonwick *result = (void *)0; 2887789Sahrens return (DDI_SUCCESS); 2888789Sahrens } 2889789Sahrens 2890789Sahrens return (DDI_FAILURE); 2891789Sahrens } 2892789Sahrens 2893789Sahrens /* 2894789Sahrens * OK, so this is a little weird. 2895789Sahrens * 2896789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2897789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2898789Sahrens * 2899789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2900789Sahrens * so most of the standard driver entry points are in zvol.c. 2901789Sahrens */ 2902789Sahrens static struct cb_ops zfs_cb_ops = { 2903789Sahrens zvol_open, /* open */ 2904789Sahrens zvol_close, /* close */ 2905789Sahrens zvol_strategy, /* strategy */ 2906789Sahrens nodev, /* print */ 2907789Sahrens nodev, /* dump */ 2908789Sahrens zvol_read, /* read */ 2909789Sahrens zvol_write, /* write */ 2910789Sahrens zfsdev_ioctl, /* ioctl */ 2911789Sahrens nodev, /* devmap */ 2912789Sahrens nodev, /* mmap */ 2913789Sahrens nodev, /* segmap */ 2914789Sahrens nochpoll, /* poll */ 2915789Sahrens ddi_prop_op, /* prop_op */ 2916789Sahrens NULL, /* streamtab */ 2917789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2918789Sahrens CB_REV, /* version */ 29193638Sbillm nodev, /* async read */ 29203638Sbillm nodev, /* async write */ 2921789Sahrens }; 2922789Sahrens 2923789Sahrens static struct dev_ops zfs_dev_ops = { 2924789Sahrens DEVO_REV, /* version */ 2925789Sahrens 0, /* refcnt */ 2926789Sahrens zfs_info, /* info */ 2927789Sahrens nulldev, /* identify */ 2928789Sahrens nulldev, /* probe */ 2929789Sahrens zfs_attach, /* attach */ 2930789Sahrens zfs_detach, /* detach */ 2931789Sahrens nodev, /* reset */ 2932789Sahrens &zfs_cb_ops, /* driver operations */ 2933789Sahrens NULL /* no bus operations */ 2934789Sahrens }; 2935789Sahrens 2936789Sahrens static struct modldrv zfs_modldrv = { 29374577Sahrens &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, 29382676Seschrock &zfs_dev_ops 2939789Sahrens }; 2940789Sahrens 2941789Sahrens static struct modlinkage modlinkage = { 2942789Sahrens MODREV_1, 2943789Sahrens (void *)&zfs_modlfs, 2944789Sahrens (void *)&zfs_modldrv, 2945789Sahrens NULL 2946789Sahrens }; 2947789Sahrens 29484720Sfr157268 29494720Sfr157268 uint_t zfs_fsyncer_key; 29505326Sek110237 extern uint_t rrw_tsd_key; 29514720Sfr157268 2952789Sahrens int 2953789Sahrens _init(void) 2954789Sahrens { 2955789Sahrens int error; 2956789Sahrens 2957849Sbonwick spa_init(FREAD | FWRITE); 2958849Sbonwick zfs_init(); 2959849Sbonwick zvol_init(); 2960849Sbonwick 2961849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 2962849Sbonwick zvol_fini(); 2963849Sbonwick zfs_fini(); 2964849Sbonwick spa_fini(); 2965789Sahrens return (error); 2966849Sbonwick } 2967789Sahrens 29684720Sfr157268 tsd_create(&zfs_fsyncer_key, NULL); 29695326Sek110237 tsd_create(&rrw_tsd_key, NULL); 29704720Sfr157268 2971789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 2972789Sahrens ASSERT(error == 0); 29734543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 2974789Sahrens 2975789Sahrens return (0); 2976789Sahrens } 2977789Sahrens 2978789Sahrens int 2979789Sahrens _fini(void) 2980789Sahrens { 2981789Sahrens int error; 2982789Sahrens 29831544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 2984789Sahrens return (EBUSY); 2985789Sahrens 2986789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 2987789Sahrens return (error); 2988789Sahrens 2989789Sahrens zvol_fini(); 2990789Sahrens zfs_fini(); 2991789Sahrens spa_fini(); 29925331Samw if (zfs_nfsshare_inited) 29934543Smarks (void) ddi_modclose(nfs_mod); 29945331Samw if (zfs_smbshare_inited) 29955331Samw (void) ddi_modclose(smbsrv_mod); 29965331Samw if (zfs_nfsshare_inited || zfs_smbshare_inited) 29974543Smarks (void) ddi_modclose(sharefs_mod); 2998789Sahrens 29994720Sfr157268 tsd_destroy(&zfs_fsyncer_key); 3000789Sahrens ldi_ident_release(zfs_li); 3001789Sahrens zfs_li = NULL; 30024543Smarks mutex_destroy(&zfs_share_lock); 3003789Sahrens 3004789Sahrens return (error); 3005789Sahrens } 3006789Sahrens 3007789Sahrens int 3008789Sahrens _info(struct modinfo *modinfop) 3009789Sahrens { 3010789Sahrens return (mod_info(&modlinkage, modinfop)); 3011789Sahrens } 3012