1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51485Slling * Common Development and Distribution License (the "License"). 61485Slling * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 223444Sek110237 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27789Sahrens 28789Sahrens #include <sys/types.h> 29789Sahrens #include <sys/param.h> 30789Sahrens #include <sys/errno.h> 31789Sahrens #include <sys/uio.h> 32789Sahrens #include <sys/buf.h> 33789Sahrens #include <sys/modctl.h> 34789Sahrens #include <sys/open.h> 35789Sahrens #include <sys/file.h> 36789Sahrens #include <sys/kmem.h> 37789Sahrens #include <sys/conf.h> 38789Sahrens #include <sys/cmn_err.h> 39789Sahrens #include <sys/stat.h> 40789Sahrens #include <sys/zfs_ioctl.h> 41789Sahrens #include <sys/zap.h> 42789Sahrens #include <sys/spa.h> 433912Slling #include <sys/spa_impl.h> 44789Sahrens #include <sys/vdev.h> 453912Slling #include <sys/vdev_impl.h> 46789Sahrens #include <sys/dmu.h> 47789Sahrens #include <sys/dsl_dir.h> 48789Sahrens #include <sys/dsl_dataset.h> 49789Sahrens #include <sys/dsl_prop.h> 50*4543Smarks #include <sys/dsl_deleg.h> 51*4543Smarks #include <sys/dmu_objset.h> 52789Sahrens #include <sys/ddi.h> 53789Sahrens #include <sys/sunddi.h> 54789Sahrens #include <sys/sunldi.h> 55789Sahrens #include <sys/policy.h> 56789Sahrens #include <sys/zone.h> 57789Sahrens #include <sys/nvpair.h> 58789Sahrens #include <sys/pathname.h> 59789Sahrens #include <sys/mount.h> 60789Sahrens #include <sys/sdt.h> 61789Sahrens #include <sys/fs/zfs.h> 62789Sahrens #include <sys/zfs_ctldir.h> 632885Sahrens #include <sys/zvol.h> 64*4543Smarks #include <sharefs/share.h> 65789Sahrens 66789Sahrens #include "zfs_namecheck.h" 672676Seschrock #include "zfs_prop.h" 68*4543Smarks #include "zfs_deleg.h" 69789Sahrens 70789Sahrens extern struct modlfs zfs_modlfs; 71789Sahrens 72789Sahrens extern void zfs_init(void); 73789Sahrens extern void zfs_fini(void); 74789Sahrens 75789Sahrens ldi_ident_t zfs_li = NULL; 76789Sahrens dev_info_t *zfs_dip; 77789Sahrens 78789Sahrens typedef int zfs_ioc_func_t(zfs_cmd_t *); 79*4543Smarks typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *); 80789Sahrens 81789Sahrens typedef struct zfs_ioc_vec { 82789Sahrens zfs_ioc_func_t *zvec_func; 83789Sahrens zfs_secpolicy_func_t *zvec_secpolicy; 84789Sahrens enum { 85789Sahrens no_name, 86789Sahrens pool_name, 87789Sahrens dataset_name 88*4543Smarks } zvec_namecheck; 89*4543Smarks boolean_t zvec_his_log; 90789Sahrens } zfs_ioc_vec_t; 91789Sahrens 92789Sahrens /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */ 93789Sahrens void 94789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 95789Sahrens { 96789Sahrens const char *newfile; 97789Sahrens char buf[256]; 98789Sahrens va_list adx; 99789Sahrens 100789Sahrens /* 101789Sahrens * Get rid of annoying "../common/" prefix to filename. 102789Sahrens */ 103789Sahrens newfile = strrchr(file, '/'); 104789Sahrens if (newfile != NULL) { 105789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 106789Sahrens } else { 107789Sahrens newfile = file; 108789Sahrens } 109789Sahrens 110789Sahrens va_start(adx, fmt); 111789Sahrens (void) vsnprintf(buf, sizeof (buf), fmt, adx); 112789Sahrens va_end(adx); 113789Sahrens 114789Sahrens /* 115789Sahrens * To get this data, use the zfs-dprintf probe as so: 116789Sahrens * dtrace -q -n 'zfs-dprintf \ 117789Sahrens * /stringof(arg0) == "dbuf.c"/ \ 118789Sahrens * {printf("%s: %s", stringof(arg1), stringof(arg3))}' 119789Sahrens * arg0 = file name 120789Sahrens * arg1 = function name 121789Sahrens * arg2 = line number 122789Sahrens * arg3 = message 123789Sahrens */ 124789Sahrens DTRACE_PROBE4(zfs__dprintf, 125789Sahrens char *, newfile, char *, func, int, line, char *, buf); 126789Sahrens } 127789Sahrens 128*4543Smarks static void 129*4543Smarks zfs_log_history(zfs_cmd_t *zc) 130*4543Smarks { 131*4543Smarks spa_t *spa; 132*4543Smarks char poolname[MAXNAMELEN]; 133*4543Smarks char *buf, *cp; 134*4543Smarks 135*4543Smarks if (zc->zc_history == NULL) 136*4543Smarks return; 137*4543Smarks 138*4543Smarks buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP); 139*4543Smarks if (copyinstr((void *)(uintptr_t)zc->zc_history, 140*4543Smarks buf, HIS_MAX_RECORD_LEN, NULL) != 0) { 141*4543Smarks kmem_free(buf, HIS_MAX_RECORD_LEN); 142*4543Smarks return; 143*4543Smarks } 144*4543Smarks 145*4543Smarks buf[HIS_MAX_RECORD_LEN -1] = '\0'; 146*4543Smarks 147*4543Smarks (void) strlcpy(poolname, zc->zc_name, sizeof (poolname)); 148*4543Smarks cp = strpbrk(poolname, "/@"); 149*4543Smarks if (cp != NULL) 150*4543Smarks *cp = '\0'; 151*4543Smarks 152*4543Smarks if (spa_open(poolname, &spa, FTAG) != 0) { 153*4543Smarks kmem_free(buf, HIS_MAX_RECORD_LEN); 154*4543Smarks return; 155*4543Smarks } 156*4543Smarks 157*4543Smarks if (spa_version(spa) >= ZFS_VERSION_ZPOOL_HISTORY) 158*4543Smarks (void) spa_history_log(spa, buf, zc->zc_history_offset); 159*4543Smarks 160*4543Smarks spa_close(spa, FTAG); 161*4543Smarks kmem_free(buf, HIS_MAX_RECORD_LEN); 162*4543Smarks } 163*4543Smarks 164789Sahrens /* 165789Sahrens * Policy for top-level read operations (list pools). Requires no privileges, 166789Sahrens * and can be used in the local zone, as there is no associated dataset. 167789Sahrens */ 168789Sahrens /* ARGSUSED */ 169789Sahrens static int 170*4543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) 171789Sahrens { 172789Sahrens return (0); 173789Sahrens } 174789Sahrens 175789Sahrens /* 176789Sahrens * Policy for dataset read operations (list children, get statistics). Requires 177789Sahrens * no privileges, but must be visible in the local zone. 178789Sahrens */ 179789Sahrens /* ARGSUSED */ 180789Sahrens static int 181*4543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) 182789Sahrens { 183789Sahrens if (INGLOBALZONE(curproc) || 184*4543Smarks zone_dataset_visible(zc->zc_name, NULL)) 185789Sahrens return (0); 186789Sahrens 187789Sahrens return (ENOENT); 188789Sahrens } 189789Sahrens 190789Sahrens static int 191789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr) 192789Sahrens { 193789Sahrens uint64_t zoned; 194789Sahrens int writable = 1; 195789Sahrens 196789Sahrens /* 197789Sahrens * The dataset must be visible by this zone -- check this first 198789Sahrens * so they don't see EPERM on something they shouldn't know about. 199789Sahrens */ 200789Sahrens if (!INGLOBALZONE(curproc) && 201789Sahrens !zone_dataset_visible(dataset, &writable)) 202789Sahrens return (ENOENT); 203789Sahrens 204789Sahrens if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) 205789Sahrens return (ENOENT); 206789Sahrens 207789Sahrens if (INGLOBALZONE(curproc)) { 208789Sahrens /* 209789Sahrens * If the fs is zoned, only root can access it from the 210789Sahrens * global zone. 211789Sahrens */ 212789Sahrens if (secpolicy_zfs(cr) && zoned) 213789Sahrens return (EPERM); 214789Sahrens } else { 215789Sahrens /* 216789Sahrens * If we are in a local zone, the 'zoned' property must be set. 217789Sahrens */ 218789Sahrens if (!zoned) 219789Sahrens return (EPERM); 220789Sahrens 221789Sahrens /* must be writable by this zone */ 222789Sahrens if (!writable) 223789Sahrens return (EPERM); 224789Sahrens } 225789Sahrens return (0); 226789Sahrens } 227789Sahrens 228789Sahrens int 229*4543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) 230789Sahrens { 231789Sahrens int error; 232789Sahrens 233*4543Smarks error = zfs_dozonecheck(name, cr); 234*4543Smarks if (error == 0) { 235*4543Smarks error = secpolicy_zfs(cr); 236*4543Smarks if (error) { 237*4543Smarks error = dsl_deleg_access(name, perm, cr); 238*4543Smarks } 239*4543Smarks } 240*4543Smarks return (error); 241*4543Smarks } 242*4543Smarks 243*4543Smarks static int 244*4543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) 245*4543Smarks { 246*4543Smarks int error = 0; 247*4543Smarks 248*4543Smarks /* 249*4543Smarks * Check permissions for special properties. 250*4543Smarks */ 251*4543Smarks switch (prop) { 252*4543Smarks case ZFS_PROP_ZONED: 253*4543Smarks /* 254*4543Smarks * Disallow setting of 'zoned' from within a local zone. 255*4543Smarks */ 256*4543Smarks if (!INGLOBALZONE(curproc)) 257*4543Smarks return (EPERM); 258*4543Smarks break; 259789Sahrens 260*4543Smarks case ZFS_PROP_QUOTA: 261*4543Smarks if (error = 262*4543Smarks zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_QUOTA, cr)) 263*4543Smarks return (error); 264*4543Smarks 265*4543Smarks if (!INGLOBALZONE(curproc)) { 266*4543Smarks uint64_t zoned; 267*4543Smarks char setpoint[MAXNAMELEN]; 268*4543Smarks int dslen; 269*4543Smarks /* 270*4543Smarks * Unprivileged users are allowed to modify the 271*4543Smarks * quota on things *under* (ie. contained by) 272*4543Smarks * the thing they own. 273*4543Smarks */ 274*4543Smarks if (dsl_prop_get_integer(name, "zoned", &zoned, 275*4543Smarks setpoint)) 276*4543Smarks return (EPERM); 277*4543Smarks if (!zoned) /* this shouldn't happen */ 278*4543Smarks return (EPERM); 279*4543Smarks dslen = strlen(name); 280*4543Smarks if (dslen <= strlen(setpoint)) 281*4543Smarks return (EPERM); 282*4543Smarks } 283*4543Smarks default: 284*4543Smarks error = zfs_secpolicy_write_perms(name, 285*4543Smarks zfs_prop_perm(prop), cr); 286*4543Smarks } 287*4543Smarks 288*4543Smarks return (error); 289789Sahrens } 290789Sahrens 291*4543Smarks int 292*4543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) 293*4543Smarks { 294*4543Smarks int error; 295*4543Smarks 296*4543Smarks error = zfs_dozonecheck(zc->zc_name, cr); 297*4543Smarks if (error) 298*4543Smarks return (error); 299*4543Smarks 300*4543Smarks /* 301*4543Smarks * permission to set permissions will be evaluated later in 302*4543Smarks * dsl_deleg_can_allow() 303*4543Smarks */ 304*4543Smarks return (0); 305*4543Smarks } 306*4543Smarks 307*4543Smarks int 308*4543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) 309*4543Smarks { 310*4543Smarks int error; 311*4543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 312*4543Smarks ZFS_DELEG_PERM_ROLLBACK, cr); 313*4543Smarks if (error == 0) 314*4543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 315*4543Smarks ZFS_DELEG_PERM_MOUNT, cr); 316*4543Smarks return (error); 317*4543Smarks } 318*4543Smarks 319*4543Smarks int 320*4543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) 321*4543Smarks { 322*4543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 323*4543Smarks ZFS_DELEG_PERM_SEND, cr)); 324*4543Smarks } 325*4543Smarks 326*4543Smarks int 327*4543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) 328*4543Smarks { 329*4543Smarks if (!INGLOBALZONE(curproc)) 330*4543Smarks return (EPERM); 331*4543Smarks 332*4543Smarks if (secpolicy_nfs(CRED()) == 0) { 333*4543Smarks return (0); 334*4543Smarks } else { 335*4543Smarks vnode_t *vp; 336*4543Smarks int error; 337*4543Smarks 338*4543Smarks if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, 339*4543Smarks NO_FOLLOW, NULL, &vp)) != 0) 340*4543Smarks return (error); 341*4543Smarks 342*4543Smarks /* Now make sure mntpnt and dataset are ZFS */ 343*4543Smarks 344*4543Smarks if (vp->v_vfsp->vfs_fstype != zfsfstype || 345*4543Smarks (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), 346*4543Smarks zc->zc_name) != 0)) { 347*4543Smarks VN_RELE(vp); 348*4543Smarks return (EPERM); 349*4543Smarks } 350*4543Smarks 351*4543Smarks VN_RELE(vp); 352*4543Smarks return (dsl_deleg_access(zc->zc_name, 353*4543Smarks ZFS_DELEG_PERM_SHARE, cr)); 354*4543Smarks } 355*4543Smarks } 356*4543Smarks 357789Sahrens static int 358*4543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize) 359789Sahrens { 360789Sahrens char *cp; 361789Sahrens 362789Sahrens /* 363789Sahrens * Remove the @bla or /bla from the end of the name to get the parent. 364789Sahrens */ 365*4543Smarks (void) strncpy(parent, datasetname, parentsize); 366*4543Smarks cp = strrchr(parent, '@'); 367789Sahrens if (cp != NULL) { 368789Sahrens cp[0] = '\0'; 369789Sahrens } else { 370*4543Smarks cp = strrchr(parent, '/'); 371789Sahrens if (cp == NULL) 372789Sahrens return (ENOENT); 373789Sahrens cp[0] = '\0'; 374789Sahrens } 375789Sahrens 376*4543Smarks return (0); 377*4543Smarks } 378*4543Smarks 379*4543Smarks int 380*4543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 381*4543Smarks { 382*4543Smarks int error; 383*4543Smarks 384*4543Smarks if ((error = zfs_secpolicy_write_perms(name, 385*4543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 386*4543Smarks return (error); 387*4543Smarks 388*4543Smarks return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); 389*4543Smarks } 390*4543Smarks 391*4543Smarks static int 392*4543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) 393*4543Smarks { 394*4543Smarks return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); 395*4543Smarks } 396*4543Smarks 397*4543Smarks /* 398*4543Smarks * Must have sys_config privilege to check the iscsi permission 399*4543Smarks */ 400*4543Smarks /* ARGSUSED */ 401*4543Smarks static int 402*4543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) 403*4543Smarks { 404*4543Smarks return (secpolicy_zfs(cr)); 405*4543Smarks } 406*4543Smarks 407*4543Smarks int 408*4543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 409*4543Smarks { 410*4543Smarks char parentname[MAXNAMELEN]; 411*4543Smarks int error; 412*4543Smarks 413*4543Smarks if ((error = zfs_secpolicy_write_perms(from, 414*4543Smarks ZFS_DELEG_PERM_RENAME, cr)) != 0) 415*4543Smarks return (error); 416*4543Smarks 417*4543Smarks if ((error = zfs_secpolicy_write_perms(from, 418*4543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 419*4543Smarks return (error); 420*4543Smarks 421*4543Smarks if ((error = zfs_get_parent(to, parentname, 422*4543Smarks sizeof (parentname))) != 0) 423*4543Smarks return (error); 424*4543Smarks 425*4543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 426*4543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 427*4543Smarks return (error); 428*4543Smarks 429*4543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 430*4543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 431*4543Smarks return (error); 432*4543Smarks 433*4543Smarks return (error); 434*4543Smarks } 435*4543Smarks 436*4543Smarks static int 437*4543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) 438*4543Smarks { 439*4543Smarks return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); 440*4543Smarks } 441*4543Smarks 442*4543Smarks static int 443*4543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) 444*4543Smarks { 445*4543Smarks char parentname[MAXNAMELEN]; 446*4543Smarks objset_t *clone; 447*4543Smarks int error; 448*4543Smarks 449*4543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 450*4543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 451*4543Smarks if (error) 452*4543Smarks return (error); 453*4543Smarks 454*4543Smarks error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 455*4543Smarks DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 456*4543Smarks 457*4543Smarks if (error == 0) { 458*4543Smarks dsl_dataset_t *pclone = NULL; 459*4543Smarks dsl_dir_t *dd; 460*4543Smarks dd = clone->os->os_dsl_dataset->ds_dir; 461*4543Smarks 462*4543Smarks rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 463*4543Smarks error = dsl_dataset_open_obj(dd->dd_pool, 464*4543Smarks dd->dd_phys->dd_clone_parent_obj, NULL, 465*4543Smarks DS_MODE_NONE, FTAG, &pclone); 466*4543Smarks rw_exit(&dd->dd_pool->dp_config_rwlock); 467*4543Smarks if (error) { 468*4543Smarks dmu_objset_close(clone); 469*4543Smarks return (error); 470*4543Smarks } 471*4543Smarks 472*4543Smarks error = zfs_secpolicy_write_perms(zc->zc_name, 473*4543Smarks ZFS_DELEG_PERM_MOUNT, cr); 474*4543Smarks 475*4543Smarks dsl_dataset_name(pclone, parentname); 476*4543Smarks dmu_objset_close(clone); 477*4543Smarks dsl_dataset_close(pclone, DS_MODE_NONE, FTAG); 478*4543Smarks if (error == 0) 479*4543Smarks error = zfs_secpolicy_write_perms(parentname, 480*4543Smarks ZFS_DELEG_PERM_PROMOTE, cr); 481*4543Smarks } 482*4543Smarks return (error); 483*4543Smarks } 484*4543Smarks 485*4543Smarks static int 486*4543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) 487*4543Smarks { 488*4543Smarks int error; 489*4543Smarks 490*4543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 491*4543Smarks ZFS_DELEG_PERM_RECEIVE, cr)) != 0) 492*4543Smarks return (error); 493*4543Smarks 494*4543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_name, 495*4543Smarks ZFS_DELEG_PERM_MOUNT, cr)) != 0) 496*4543Smarks return (error); 497*4543Smarks 498*4543Smarks return (zfs_secpolicy_write_perms(zc->zc_name, 499*4543Smarks ZFS_DELEG_PERM_CREATE, cr)); 500*4543Smarks } 501*4543Smarks 502*4543Smarks int 503*4543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 504*4543Smarks { 505*4543Smarks int error; 506*4543Smarks 507*4543Smarks if ((error = zfs_secpolicy_write_perms(name, 508*4543Smarks ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) 509*4543Smarks return (error); 510*4543Smarks 511*4543Smarks error = zfs_secpolicy_write_perms(name, 512*4543Smarks ZFS_DELEG_PERM_MOUNT, cr); 513*4543Smarks 514*4543Smarks return (error); 515*4543Smarks } 516*4543Smarks 517*4543Smarks static int 518*4543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) 519*4543Smarks { 520*4543Smarks 521*4543Smarks return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); 522*4543Smarks } 523*4543Smarks 524*4543Smarks 525*4543Smarks 526*4543Smarks static int 527*4543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) 528*4543Smarks { 529*4543Smarks char parentname[MAXNAMELEN]; 530*4543Smarks int error; 531*4543Smarks 532*4543Smarks if ((error = zfs_get_parent(zc->zc_name, parentname, 533*4543Smarks sizeof (parentname))) != 0) 534*4543Smarks return (error); 535*4543Smarks 536*4543Smarks if (zc->zc_value[0] != '\0') { 537*4543Smarks if ((error = zfs_secpolicy_write_perms(zc->zc_value, 538*4543Smarks ZFS_DELEG_PERM_CLONE, cr)) != 0) 539*4543Smarks return (error); 540*4543Smarks } 541*4543Smarks 542*4543Smarks if ((error = zfs_secpolicy_write_perms(parentname, 543*4543Smarks ZFS_DELEG_PERM_CREATE, cr)) != 0) 544*4543Smarks return (error); 545*4543Smarks 546*4543Smarks error = zfs_secpolicy_write_perms(parentname, 547*4543Smarks ZFS_DELEG_PERM_MOUNT, cr); 548*4543Smarks 549*4543Smarks return (error); 550*4543Smarks } 551*4543Smarks 552*4543Smarks static int 553*4543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) 554*4543Smarks { 555*4543Smarks int error; 556*4543Smarks 557*4543Smarks error = secpolicy_fs_unmount(cr, NULL); 558*4543Smarks if (error) { 559*4543Smarks error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); 560*4543Smarks } 561*4543Smarks return (error); 562789Sahrens } 563789Sahrens 564789Sahrens /* 565789Sahrens * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires 566789Sahrens * SYS_CONFIG privilege, which is not available in a local zone. 567789Sahrens */ 568789Sahrens /* ARGSUSED */ 569789Sahrens static int 570*4543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) 571789Sahrens { 572789Sahrens if (secpolicy_sys_config(cr, B_FALSE) != 0) 573789Sahrens return (EPERM); 574789Sahrens 575789Sahrens return (0); 576789Sahrens } 577789Sahrens 578789Sahrens /* 579*4543Smarks * Just like zfs_secpolicy_config, except that we will check for 580*4543Smarks * mount permission on the dataset for permission to create/remove 581*4543Smarks * the minor nodes. 582*4543Smarks */ 583*4543Smarks static int 584*4543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) 585*4543Smarks { 586*4543Smarks if (secpolicy_sys_config(cr, B_FALSE) != 0) { 587*4543Smarks return (dsl_deleg_access(zc->zc_name, 588*4543Smarks ZFS_DELEG_PERM_MOUNT, cr)); 589*4543Smarks } 590*4543Smarks 591*4543Smarks return (0); 592*4543Smarks } 593*4543Smarks 594*4543Smarks /* 5951544Seschrock * Policy for fault injection. Requires all privileges. 5961544Seschrock */ 5971544Seschrock /* ARGSUSED */ 5981544Seschrock static int 599*4543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) 6001544Seschrock { 6011544Seschrock return (secpolicy_zinject(cr)); 6021544Seschrock } 6031544Seschrock 6041544Seschrock /* 605789Sahrens * Returns the nvlist as specified by the user in the zfs_cmd_t. 606789Sahrens */ 607789Sahrens static int 6082676Seschrock get_nvlist(zfs_cmd_t *zc, nvlist_t **nvp) 609789Sahrens { 610789Sahrens char *packed; 611789Sahrens size_t size; 612789Sahrens int error; 613789Sahrens nvlist_t *config = NULL; 614789Sahrens 615789Sahrens /* 6162676Seschrock * Read in and unpack the user-supplied nvlist. 617789Sahrens */ 6182676Seschrock if ((size = zc->zc_nvlist_src_size) == 0) 619789Sahrens return (EINVAL); 620789Sahrens 621789Sahrens packed = kmem_alloc(size, KM_SLEEP); 622789Sahrens 6232676Seschrock if ((error = xcopyin((void *)(uintptr_t)zc->zc_nvlist_src, packed, 624789Sahrens size)) != 0) { 625789Sahrens kmem_free(packed, size); 626789Sahrens return (error); 627789Sahrens } 628789Sahrens 629789Sahrens if ((error = nvlist_unpack(packed, size, &config, 0)) != 0) { 630789Sahrens kmem_free(packed, size); 631789Sahrens return (error); 632789Sahrens } 633789Sahrens 634789Sahrens kmem_free(packed, size); 635789Sahrens 636789Sahrens *nvp = config; 637789Sahrens return (0); 638789Sahrens } 639789Sahrens 640789Sahrens static int 6412676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 6422676Seschrock { 6432676Seschrock char *packed = NULL; 6442676Seschrock size_t size; 6452676Seschrock int error; 6462676Seschrock 6472676Seschrock VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 6482676Seschrock 6492676Seschrock if (size > zc->zc_nvlist_dst_size) { 6502676Seschrock error = ENOMEM; 6512676Seschrock } else { 6522676Seschrock VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 6532676Seschrock KM_SLEEP) == 0); 6542676Seschrock error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, 6552676Seschrock size); 6562676Seschrock kmem_free(packed, size); 6572676Seschrock } 6582676Seschrock 6592676Seschrock zc->zc_nvlist_dst_size = size; 6602676Seschrock return (error); 6612676Seschrock } 6622676Seschrock 6632676Seschrock static int 664789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc) 665789Sahrens { 666789Sahrens int error; 667789Sahrens nvlist_t *config; 668789Sahrens 6692676Seschrock if ((error = get_nvlist(zc, &config)) != 0) 670789Sahrens return (error); 671789Sahrens 6722676Seschrock error = spa_create(zc->zc_name, config, zc->zc_value[0] == '\0' ? 6732676Seschrock NULL : zc->zc_value); 674789Sahrens 675789Sahrens nvlist_free(config); 676789Sahrens 677789Sahrens return (error); 678789Sahrens } 679789Sahrens 680789Sahrens static int 681789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc) 682789Sahrens { 683*4543Smarks int error; 684*4543Smarks zfs_log_history(zc); 685*4543Smarks error = spa_destroy(zc->zc_name); 686*4543Smarks return (error); 687789Sahrens } 688789Sahrens 689789Sahrens static int 690789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc) 691789Sahrens { 692789Sahrens int error; 693789Sahrens nvlist_t *config; 694789Sahrens uint64_t guid; 695789Sahrens 6962676Seschrock if ((error = get_nvlist(zc, &config)) != 0) 697789Sahrens return (error); 698789Sahrens 699789Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || 7001544Seschrock guid != zc->zc_guid) 701789Sahrens error = EINVAL; 702789Sahrens else 703789Sahrens error = spa_import(zc->zc_name, config, 7042676Seschrock zc->zc_value[0] == '\0' ? NULL : zc->zc_value); 705789Sahrens 706789Sahrens nvlist_free(config); 707789Sahrens 708789Sahrens return (error); 709789Sahrens } 710789Sahrens 711789Sahrens static int 712789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc) 713789Sahrens { 714*4543Smarks int error; 715*4543Smarks zfs_log_history(zc); 716*4543Smarks error = spa_export(zc->zc_name, NULL); 717*4543Smarks return (error); 718789Sahrens } 719789Sahrens 720789Sahrens static int 721789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc) 722789Sahrens { 723789Sahrens nvlist_t *configs; 724789Sahrens int error; 725789Sahrens 726789Sahrens if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) 727789Sahrens return (EEXIST); 728789Sahrens 7292676Seschrock error = put_nvlist(zc, configs); 730789Sahrens 731789Sahrens nvlist_free(configs); 732789Sahrens 733789Sahrens return (error); 734789Sahrens } 735789Sahrens 736789Sahrens static int 737789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc) 738789Sahrens { 739789Sahrens nvlist_t *config; 740789Sahrens int error; 7411544Seschrock int ret = 0; 742789Sahrens 7432676Seschrock error = spa_get_stats(zc->zc_name, &config, zc->zc_value, 7442676Seschrock sizeof (zc->zc_value)); 745789Sahrens 746789Sahrens if (config != NULL) { 7472676Seschrock ret = put_nvlist(zc, config); 748789Sahrens nvlist_free(config); 7491544Seschrock 7501544Seschrock /* 7511544Seschrock * The config may be present even if 'error' is non-zero. 7521544Seschrock * In this case we return success, and preserve the real errno 7531544Seschrock * in 'zc_cookie'. 7541544Seschrock */ 7551544Seschrock zc->zc_cookie = error; 756789Sahrens } else { 7571544Seschrock ret = error; 758789Sahrens } 759789Sahrens 7601544Seschrock return (ret); 761789Sahrens } 762789Sahrens 763789Sahrens /* 764789Sahrens * Try to import the given pool, returning pool stats as appropriate so that 765789Sahrens * user land knows which devices are available and overall pool health. 766789Sahrens */ 767789Sahrens static int 768789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc) 769789Sahrens { 770789Sahrens nvlist_t *tryconfig, *config; 771789Sahrens int error; 772789Sahrens 7732676Seschrock if ((error = get_nvlist(zc, &tryconfig)) != 0) 774789Sahrens return (error); 775789Sahrens 776789Sahrens config = spa_tryimport(tryconfig); 777789Sahrens 778789Sahrens nvlist_free(tryconfig); 779789Sahrens 780789Sahrens if (config == NULL) 781789Sahrens return (EINVAL); 782789Sahrens 7832676Seschrock error = put_nvlist(zc, config); 784789Sahrens nvlist_free(config); 785789Sahrens 786789Sahrens return (error); 787789Sahrens } 788789Sahrens 789789Sahrens static int 790789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc) 791789Sahrens { 792789Sahrens spa_t *spa; 793789Sahrens int error; 794789Sahrens 7952926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 7962926Sek110237 return (error); 7972926Sek110237 7984451Seschrock spa_config_enter(spa, RW_READER, FTAG); 7992926Sek110237 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); 8004451Seschrock spa_config_exit(spa, FTAG); 8012926Sek110237 8022926Sek110237 spa_close(spa, FTAG); 8032926Sek110237 804789Sahrens return (error); 805789Sahrens } 806789Sahrens 807789Sahrens static int 808789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc) 809789Sahrens { 810789Sahrens spa_t *spa; 811789Sahrens int error; 812789Sahrens 813789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 814789Sahrens if (error == 0) { 815789Sahrens spa_freeze(spa); 816789Sahrens spa_close(spa, FTAG); 817789Sahrens } 818789Sahrens return (error); 819789Sahrens } 820789Sahrens 821789Sahrens static int 8221760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc) 8231760Seschrock { 8241760Seschrock spa_t *spa; 8251760Seschrock int error; 8261760Seschrock 8272926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8282926Sek110237 return (error); 8292926Sek110237 8302926Sek110237 spa_upgrade(spa); 8312926Sek110237 spa_close(spa, FTAG); 8322926Sek110237 8332926Sek110237 return (error); 8342926Sek110237 } 8352926Sek110237 8362926Sek110237 static int 8372926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc) 8382926Sek110237 { 8392926Sek110237 spa_t *spa; 8402926Sek110237 char *hist_buf; 8412926Sek110237 uint64_t size; 8422926Sek110237 int error; 8432926Sek110237 8442926Sek110237 if ((size = zc->zc_history_len) == 0) 8452926Sek110237 return (EINVAL); 8462926Sek110237 8472926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 8482926Sek110237 return (error); 8492926Sek110237 8503863Sek110237 if (spa_version(spa) < ZFS_VERSION_ZPOOL_HISTORY) { 8513863Sek110237 spa_close(spa, FTAG); 8523863Sek110237 return (ENOTSUP); 8533863Sek110237 } 8543863Sek110237 8552926Sek110237 hist_buf = kmem_alloc(size, KM_SLEEP); 8562926Sek110237 if ((error = spa_history_get(spa, &zc->zc_history_offset, 8572926Sek110237 &zc->zc_history_len, hist_buf)) == 0) { 858*4543Smarks error = xcopyout(hist_buf, 859*4543Smarks (char *)(uintptr_t)zc->zc_history, 8602926Sek110237 zc->zc_history_len); 8612926Sek110237 } 8622926Sek110237 8632926Sek110237 spa_close(spa, FTAG); 8642926Sek110237 kmem_free(hist_buf, size); 8652926Sek110237 return (error); 8662926Sek110237 } 8672926Sek110237 8682926Sek110237 static int 8693444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) 8703444Sek110237 { 8713444Sek110237 int error; 8723444Sek110237 8733912Slling if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) 8743444Sek110237 return (error); 8753444Sek110237 8763444Sek110237 return (0); 8773444Sek110237 } 8783444Sek110237 8793444Sek110237 static int 8803444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc) 8813444Sek110237 { 8823444Sek110237 objset_t *osp; 8833444Sek110237 int error; 8843444Sek110237 8853444Sek110237 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, 8863444Sek110237 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) 8873444Sek110237 return (error); 8883444Sek110237 8893444Sek110237 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, 8903444Sek110237 sizeof (zc->zc_value)); 8913444Sek110237 dmu_objset_close(osp); 8923444Sek110237 8933444Sek110237 return (error); 8943444Sek110237 } 8953444Sek110237 8963444Sek110237 static int 897789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc) 898789Sahrens { 899789Sahrens spa_t *spa; 900789Sahrens int error; 901789Sahrens nvlist_t *config; 902789Sahrens 903789Sahrens error = spa_open(zc->zc_name, &spa, FTAG); 904789Sahrens if (error != 0) 905789Sahrens return (error); 906789Sahrens 9073912Slling /* 9083912Slling * A root pool with concatenated devices is not supported. 9093912Slling * Thus, can not add a device to a root pool with one device. 9103912Slling */ 9113912Slling if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0) { 9123912Slling spa_close(spa, FTAG); 9133912Slling return (EDOM); 9143912Slling } 9153912Slling 9162676Seschrock if ((error = get_nvlist(zc, &config)) == 0) { 917789Sahrens error = spa_vdev_add(spa, config); 918789Sahrens nvlist_free(config); 919789Sahrens } 920789Sahrens spa_close(spa, FTAG); 921789Sahrens return (error); 922789Sahrens } 923789Sahrens 924789Sahrens static int 925789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc) 926789Sahrens { 9272082Seschrock spa_t *spa; 9282082Seschrock int error; 9292082Seschrock 9302082Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 9312082Seschrock if (error != 0) 9322082Seschrock return (error); 9332082Seschrock error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); 9342082Seschrock spa_close(spa, FTAG); 9352082Seschrock return (error); 936789Sahrens } 937789Sahrens 938789Sahrens static int 9394451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc) 940789Sahrens { 941789Sahrens spa_t *spa; 942789Sahrens int error; 9434451Seschrock vdev_state_t newstate = VDEV_STATE_UNKNOWN; 944789Sahrens 9452926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 946789Sahrens return (error); 9474451Seschrock switch (zc->zc_cookie) { 9484451Seschrock case VDEV_STATE_ONLINE: 9494451Seschrock error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); 9504451Seschrock break; 9514451Seschrock 9524451Seschrock case VDEV_STATE_OFFLINE: 9534451Seschrock error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); 9544451Seschrock break; 955789Sahrens 9564451Seschrock case VDEV_STATE_FAULTED: 9574451Seschrock error = vdev_fault(spa, zc->zc_guid); 9584451Seschrock break; 959789Sahrens 9604451Seschrock case VDEV_STATE_DEGRADED: 9614451Seschrock error = vdev_degrade(spa, zc->zc_guid); 9624451Seschrock break; 9634451Seschrock 9644451Seschrock default: 9654451Seschrock error = EINVAL; 9664451Seschrock } 9674451Seschrock zc->zc_cookie = newstate; 968789Sahrens spa_close(spa, FTAG); 969789Sahrens return (error); 970789Sahrens } 971789Sahrens 972789Sahrens static int 973789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc) 974789Sahrens { 975789Sahrens spa_t *spa; 976789Sahrens int replacing = zc->zc_cookie; 977789Sahrens nvlist_t *config; 978789Sahrens int error; 979789Sahrens 9802926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 981789Sahrens return (error); 982789Sahrens 9832676Seschrock if ((error = get_nvlist(zc, &config)) == 0) { 9841544Seschrock error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); 985789Sahrens nvlist_free(config); 986789Sahrens } 987789Sahrens 988789Sahrens spa_close(spa, FTAG); 989789Sahrens return (error); 990789Sahrens } 991789Sahrens 992789Sahrens static int 993789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc) 994789Sahrens { 995789Sahrens spa_t *spa; 996789Sahrens int error; 997789Sahrens 9982926Sek110237 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 999789Sahrens return (error); 1000789Sahrens 10011544Seschrock error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); 1002789Sahrens 1003789Sahrens spa_close(spa, FTAG); 1004789Sahrens return (error); 1005789Sahrens } 1006789Sahrens 1007789Sahrens static int 10081354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc) 10091354Seschrock { 10101354Seschrock spa_t *spa; 10112676Seschrock char *path = zc->zc_value; 10121544Seschrock uint64_t guid = zc->zc_guid; 10131354Seschrock int error; 10141354Seschrock 10151354Seschrock error = spa_open(zc->zc_name, &spa, FTAG); 10161354Seschrock if (error != 0) 10171354Seschrock return (error); 10181354Seschrock 10191354Seschrock error = spa_vdev_setpath(spa, guid, path); 10201354Seschrock spa_close(spa, FTAG); 10211354Seschrock return (error); 10221354Seschrock } 10231354Seschrock 10241354Seschrock static int 1025789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc) 1026789Sahrens { 1027789Sahrens objset_t *os = NULL; 1028789Sahrens int error; 10291356Seschrock nvlist_t *nv; 1030789Sahrens 1031789Sahrens retry: 1032789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1033789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1034789Sahrens if (error != 0) { 1035789Sahrens /* 1036789Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1037789Sahrens * the objset is held exclusively. Fortunately this hold is 1038789Sahrens * only for a short while, so we retry here. 1039789Sahrens * This avoids user code having to handle EBUSY, 1040789Sahrens * for example for a "zfs list". 1041789Sahrens */ 1042789Sahrens if (error == EBUSY) { 1043789Sahrens delay(1); 1044789Sahrens goto retry; 1045789Sahrens } 1046789Sahrens return (error); 1047789Sahrens } 1048789Sahrens 10492885Sahrens dmu_objset_fast_stat(os, &zc->zc_objset_stats); 1050789Sahrens 10512856Snd150628 if (zc->zc_nvlist_dst != 0 && 10521356Seschrock (error = dsl_prop_get_all(os, &nv)) == 0) { 10532885Sahrens dmu_objset_stats(os, nv); 10543087Sahrens /* 10553087Sahrens * NB: zvol_get_stats() will read the objset contents, 10563087Sahrens * which we aren't supposed to do with a 10573087Sahrens * DS_MODE_STANDARD open, because it could be 10583087Sahrens * inconsistent. So this is a bit of a workaround... 10593087Sahrens */ 10603087Sahrens if (!zc->zc_objset_stats.dds_inconsistent && 10613087Sahrens dmu_objset_type(os) == DMU_OST_ZVOL) 10622885Sahrens VERIFY(zvol_get_stats(os, nv) == 0); 10632676Seschrock error = put_nvlist(zc, nv); 10641356Seschrock nvlist_free(nv); 10651356Seschrock } 1066789Sahrens 10672676Seschrock spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value)); 10681544Seschrock 1069789Sahrens dmu_objset_close(os); 1070789Sahrens return (error); 1071789Sahrens } 1072789Sahrens 1073789Sahrens static int 1074789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc) 1075789Sahrens { 1076885Sahrens objset_t *os; 1077789Sahrens int error; 1078789Sahrens char *p; 1079789Sahrens 1080885Sahrens retry: 1081885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1082885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1083885Sahrens if (error != 0) { 1084885Sahrens /* 1085885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1086885Sahrens * the objset is held exclusively. Fortunately this hold is 1087885Sahrens * only for a short while, so we retry here. 1088885Sahrens * This avoids user code having to handle EBUSY, 1089885Sahrens * for example for a "zfs list". 1090885Sahrens */ 1091885Sahrens if (error == EBUSY) { 1092885Sahrens delay(1); 1093885Sahrens goto retry; 1094885Sahrens } 1095885Sahrens if (error == ENOENT) 1096885Sahrens error = ESRCH; 1097885Sahrens return (error); 1098789Sahrens } 1099789Sahrens 1100789Sahrens p = strrchr(zc->zc_name, '/'); 1101789Sahrens if (p == NULL || p[1] != '\0') 1102789Sahrens (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); 1103789Sahrens p = zc->zc_name + strlen(zc->zc_name); 1104789Sahrens 1105789Sahrens do { 1106885Sahrens error = dmu_dir_list_next(os, 1107885Sahrens sizeof (zc->zc_name) - (p - zc->zc_name), p, 1108885Sahrens NULL, &zc->zc_cookie); 1109789Sahrens if (error == ENOENT) 1110789Sahrens error = ESRCH; 1111885Sahrens } while (error == 0 && !INGLOBALZONE(curproc) && 1112789Sahrens !zone_dataset_visible(zc->zc_name, NULL)); 1113789Sahrens 1114885Sahrens /* 1115885Sahrens * If it's a hidden dataset (ie. with a '$' in its name), don't 1116885Sahrens * try to get stats for it. Userland will skip over it. 1117885Sahrens */ 1118885Sahrens if (error == 0 && strchr(zc->zc_name, '$') == NULL) 1119885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1120789Sahrens 1121885Sahrens dmu_objset_close(os); 1122789Sahrens return (error); 1123789Sahrens } 1124789Sahrens 1125789Sahrens static int 1126789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) 1127789Sahrens { 1128885Sahrens objset_t *os; 1129789Sahrens int error; 1130789Sahrens 1131789Sahrens retry: 1132885Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1133885Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &os); 1134885Sahrens if (error != 0) { 1135789Sahrens /* 1136885Sahrens * This is ugly: dmu_objset_open() can return EBUSY if 1137789Sahrens * the objset is held exclusively. Fortunately this hold is 1138789Sahrens * only for a short while, so we retry here. 1139789Sahrens * This avoids user code having to handle EBUSY, 1140885Sahrens * for example for a "zfs list". 1141789Sahrens */ 1142789Sahrens if (error == EBUSY) { 1143789Sahrens delay(1); 1144789Sahrens goto retry; 1145789Sahrens } 1146789Sahrens if (error == ENOENT) 1147885Sahrens error = ESRCH; 1148789Sahrens return (error); 1149789Sahrens } 1150789Sahrens 11511003Slling /* 11521003Slling * A dataset name of maximum length cannot have any snapshots, 11531003Slling * so exit immediately. 11541003Slling */ 11551003Slling if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { 1156885Sahrens dmu_objset_close(os); 11571003Slling return (ESRCH); 1158789Sahrens } 1159789Sahrens 1160885Sahrens error = dmu_snapshot_list_next(os, 1161885Sahrens sizeof (zc->zc_name) - strlen(zc->zc_name), 1162885Sahrens zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie); 1163789Sahrens if (error == ENOENT) 1164789Sahrens error = ESRCH; 1165789Sahrens 1166885Sahrens if (error == 0) 1167885Sahrens error = zfs_ioc_objset_stats(zc); /* fill in the stats */ 1168789Sahrens 1169885Sahrens dmu_objset_close(os); 1170789Sahrens return (error); 1171789Sahrens } 1172789Sahrens 1173789Sahrens static int 11742676Seschrock zfs_set_prop_nvlist(const char *name, dev_t dev, cred_t *cr, nvlist_t *nvl) 1175789Sahrens { 11762676Seschrock nvpair_t *elem; 11772676Seschrock int error; 11782676Seschrock const char *propname; 11792676Seschrock zfs_prop_t prop; 11802676Seschrock uint64_t intval; 11812676Seschrock char *strval; 11822676Seschrock 1183*4543Smarks /* 1184*4543Smarks * First validate permission to set all of the properties 1185*4543Smarks */ 11862676Seschrock elem = NULL; 11872676Seschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 11882676Seschrock propname = nvpair_name(elem); 11892676Seschrock 11902676Seschrock if ((prop = zfs_name_to_prop(propname)) == 11912676Seschrock ZFS_PROP_INVAL) { 11922676Seschrock /* 11932676Seschrock * If this is a user-defined property, it must be a 11942676Seschrock * string, and there is no further validation to do. 11952676Seschrock */ 11962676Seschrock if (!zfs_prop_user(propname) || 11972676Seschrock nvpair_type(elem) != DATA_TYPE_STRING) 11982676Seschrock return (EINVAL); 11992676Seschrock 1200*4543Smarks error = zfs_secpolicy_write_perms(name, 1201*4543Smarks ZFS_DELEG_PERM_USERPROP, cr); 1202*4543Smarks if (error) { 1203*4543Smarks return (EPERM); 1204*4543Smarks } 1205*4543Smarks continue; 12062676Seschrock } 12072676Seschrock 12082676Seschrock /* 1209*4543Smarks * Check permissions for special properties 12102676Seschrock */ 1211*4543Smarks 12122676Seschrock switch (prop) { 12132676Seschrock case ZFS_PROP_ZONED: 12142676Seschrock /* 12152676Seschrock * Disallow setting of 'zoned' from within a local zone. 12162676Seschrock */ 12172676Seschrock if (!INGLOBALZONE(curproc)) 12182676Seschrock return (EPERM); 12192676Seschrock break; 12202676Seschrock 12212676Seschrock case ZFS_PROP_QUOTA: 12222676Seschrock if (error = zfs_dozonecheck(name, cr)) 12232676Seschrock return (error); 12242676Seschrock 12252676Seschrock if (!INGLOBALZONE(curproc)) { 12262676Seschrock uint64_t zoned; 12272676Seschrock char setpoint[MAXNAMELEN]; 12282676Seschrock int dslen; 12292676Seschrock /* 12302676Seschrock * Unprivileged users are allowed to modify the 12312676Seschrock * quota on things *under* (ie. contained by) 12322676Seschrock * the thing they own. 12332676Seschrock */ 12342676Seschrock if (dsl_prop_get_integer(name, "zoned", &zoned, 12352676Seschrock setpoint)) 12362676Seschrock return (EPERM); 12372676Seschrock if (!zoned) /* this shouldn't happen */ 12382676Seschrock return (EPERM); 12392676Seschrock dslen = strlen(name); 12402676Seschrock if (dslen <= strlen(setpoint)) 12412676Seschrock return (EPERM); 12422676Seschrock } 12433886Sahl break; 12443886Sahl 12453886Sahl case ZFS_PROP_COMPRESSION: 12463886Sahl /* 12473886Sahl * If the user specified gzip compression, make sure 12483886Sahl * the SPA supports it. We ignore any errors here since 12493886Sahl * we'll catch them later. 12503886Sahl */ 12513886Sahl if (nvpair_type(elem) == DATA_TYPE_UINT64 && 12523886Sahl nvpair_value_uint64(elem, &intval) == 0 && 12533886Sahl intval >= ZIO_COMPRESS_GZIP_1 && 12543886Sahl intval <= ZIO_COMPRESS_GZIP_9) { 1255*4543Smarks char buf[MAXNAMELEN]; 1256*4543Smarks spa_t *spa; 1257*4543Smarks const char *p; 1258*4543Smarks 12593886Sahl if ((p = strchr(name, '/')) == NULL) { 12603886Sahl p = name; 12613886Sahl } else { 12623886Sahl bcopy(name, buf, p - name); 12633886Sahl buf[p - name] = '\0'; 12643886Sahl p = buf; 12653886Sahl } 12663886Sahl 12673886Sahl if (spa_open(p, &spa, FTAG) == 0) { 12683886Sahl if (spa_version(spa) < 12693886Sahl ZFS_VERSION_GZIP_COMPRESSION) { 12703886Sahl spa_close(spa, FTAG); 12713886Sahl return (ENOTSUP); 12723886Sahl } 12733886Sahl 12743886Sahl spa_close(spa, FTAG); 12753886Sahl } 12763886Sahl } 12773886Sahl break; 12782676Seschrock } 1279*4543Smarks if ((error = zfs_secpolicy_setprop(name, prop, cr)) != 0) 1280*4543Smarks return (error); 1281*4543Smarks } 1282*4543Smarks 1283*4543Smarks elem = NULL; 1284*4543Smarks while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 1285*4543Smarks propname = nvpair_name(elem); 1286*4543Smarks 1287*4543Smarks if ((prop = zfs_name_to_prop(propname)) == 1288*4543Smarks ZFS_PROP_INVAL) { 1289*4543Smarks 1290*4543Smarks VERIFY(nvpair_value_string(elem, &strval) == 0); 1291*4543Smarks error = dsl_prop_set(name, propname, 1, 1292*4543Smarks strlen(strval) + 1, strval); 1293*4543Smarks if (error == 0) 1294*4543Smarks continue; 1295*4543Smarks else 1296*4543Smarks return (error); 1297*4543Smarks } 12982676Seschrock 12992676Seschrock switch (prop) { 13002676Seschrock case ZFS_PROP_QUOTA: 13012676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13022676Seschrock (error = dsl_dir_set_quota(name, 13032676Seschrock intval)) != 0) 13042676Seschrock return (error); 13052676Seschrock break; 13062676Seschrock 13072676Seschrock case ZFS_PROP_RESERVATION: 13082676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13092676Seschrock (error = dsl_dir_set_reservation(name, 13102676Seschrock intval)) != 0) 13112676Seschrock return (error); 13122676Seschrock break; 1313789Sahrens 13142676Seschrock case ZFS_PROP_VOLSIZE: 13152676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13162676Seschrock (error = zvol_set_volsize(name, dev, 13172676Seschrock intval)) != 0) 13182676Seschrock return (error); 13192676Seschrock break; 13202676Seschrock 13212676Seschrock case ZFS_PROP_VOLBLOCKSIZE: 13222676Seschrock if ((error = nvpair_value_uint64(elem, &intval)) != 0 || 13232676Seschrock (error = zvol_set_volblocksize(name, 13242676Seschrock intval)) != 0) 13252676Seschrock return (error); 13262676Seschrock break; 13272676Seschrock 13282676Seschrock default: 13292676Seschrock if (nvpair_type(elem) == DATA_TYPE_STRING) { 13302676Seschrock if (zfs_prop_get_type(prop) != 13312676Seschrock prop_type_string) 13322676Seschrock return (EINVAL); 13332717Seschrock VERIFY(nvpair_value_string(elem, &strval) == 0); 13342717Seschrock if ((error = dsl_prop_set(name, 13352676Seschrock nvpair_name(elem), 1, strlen(strval) + 1, 13362717Seschrock strval)) != 0) 13372717Seschrock return (error); 13382676Seschrock } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { 13392885Sahrens const char *unused; 13402885Sahrens 13412717Seschrock VERIFY(nvpair_value_uint64(elem, &intval) == 0); 13422676Seschrock 13432676Seschrock switch (zfs_prop_get_type(prop)) { 13442676Seschrock case prop_type_number: 13452676Seschrock break; 13462676Seschrock case prop_type_boolean: 13472676Seschrock if (intval > 1) 13482717Seschrock return (EINVAL); 13492676Seschrock break; 13502676Seschrock case prop_type_string: 13512717Seschrock return (EINVAL); 13522676Seschrock case prop_type_index: 13532717Seschrock if (zfs_prop_index_to_string(prop, 13542717Seschrock intval, &unused) != 0) 13552717Seschrock return (EINVAL); 13562676Seschrock break; 13572676Seschrock default: 13582676Seschrock cmn_err(CE_PANIC, "unknown property " 13592676Seschrock "type"); 13602676Seschrock break; 13612676Seschrock } 13622676Seschrock 13632717Seschrock if ((error = dsl_prop_set(name, propname, 13642717Seschrock 8, 1, &intval)) != 0) 13652717Seschrock return (error); 13662676Seschrock } else { 13672676Seschrock return (EINVAL); 13682676Seschrock } 13692676Seschrock break; 13702676Seschrock } 13712676Seschrock } 13722676Seschrock 13732676Seschrock return (0); 1374789Sahrens } 1375789Sahrens 1376789Sahrens static int 13772676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc) 1378789Sahrens { 13792676Seschrock nvlist_t *nvl; 13802676Seschrock int error; 13812676Seschrock zfs_prop_t prop; 1382789Sahrens 13832676Seschrock /* 13842676Seschrock * If zc_value is set, then this is an attempt to inherit a value. 13852676Seschrock * Otherwise, zc_nvlist refers to a list of properties to set. 13862676Seschrock */ 13872676Seschrock if (zc->zc_value[0] != '\0') { 13882676Seschrock if (!zfs_prop_user(zc->zc_value) && 13892676Seschrock ((prop = zfs_name_to_prop(zc->zc_value)) == 13902676Seschrock ZFS_PROP_INVAL || 13912676Seschrock !zfs_prop_inheritable(prop))) 13922676Seschrock return (EINVAL); 13932676Seschrock 13942676Seschrock return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); 13952676Seschrock } 13962676Seschrock 13972676Seschrock if ((error = get_nvlist(zc, &nvl)) != 0) 13982676Seschrock return (error); 13992676Seschrock 14002676Seschrock error = zfs_set_prop_nvlist(zc->zc_name, zc->zc_dev, 14012676Seschrock (cred_t *)(uintptr_t)zc->zc_cred, nvl); 1402*4543Smarks 14032676Seschrock nvlist_free(nvl); 14042676Seschrock return (error); 1405789Sahrens } 1406789Sahrens 1407789Sahrens static int 14084098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc) 14093912Slling { 14103912Slling nvlist_t *nvl; 14113912Slling int error, reset_bootfs = 0; 14123912Slling uint64_t objnum; 1413*4543Smarks uint64_t intval; 14143912Slling zpool_prop_t prop; 14153912Slling nvpair_t *elem; 14163912Slling char *propname, *strval; 14173912Slling spa_t *spa; 14183912Slling vdev_t *rvdev; 14193912Slling char *vdev_type; 14203912Slling objset_t *os; 14213912Slling 14223912Slling if ((error = get_nvlist(zc, &nvl)) != 0) 14233912Slling return (error); 14243912Slling 14253912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { 14263912Slling nvlist_free(nvl); 14273912Slling return (error); 14283912Slling } 14293912Slling 14303912Slling if (spa_version(spa) < ZFS_VERSION_BOOTFS) { 14313912Slling nvlist_free(nvl); 14323912Slling spa_close(spa, FTAG); 14333912Slling return (ENOTSUP); 14343912Slling } 14353912Slling 14363912Slling elem = NULL; 14373912Slling while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 14383912Slling 14393912Slling propname = nvpair_name(elem); 14403912Slling 14413912Slling if ((prop = zpool_name_to_prop(propname)) == 14423912Slling ZFS_PROP_INVAL) { 14433912Slling nvlist_free(nvl); 14443912Slling spa_close(spa, FTAG); 14453912Slling return (EINVAL); 14463912Slling } 14473912Slling 14483912Slling switch (prop) { 1449*4543Smarks case ZPOOL_PROP_DELEGATION: 1450*4543Smarks VERIFY(nvpair_value_uint64(elem, &intval) == 0); 1451*4543Smarks if (intval > 1) 1452*4543Smarks error = EINVAL; 1453*4543Smarks break; 14544451Seschrock case ZPOOL_PROP_BOOTFS: 14553912Slling /* 14563912Slling * A bootable filesystem can not be on a RAIDZ pool 14573912Slling * nor a striped pool with more than 1 device. 14583912Slling */ 14593912Slling rvdev = spa->spa_root_vdev; 14603912Slling vdev_type = 14613912Slling rvdev->vdev_child[0]->vdev_ops->vdev_op_type; 14623912Slling if (strcmp(vdev_type, VDEV_TYPE_RAIDZ) == 0 || 14633912Slling (strcmp(vdev_type, VDEV_TYPE_MIRROR) != 0 && 14643912Slling rvdev->vdev_children > 1)) { 14653912Slling error = ENOTSUP; 14663912Slling break; 14673912Slling } 14683912Slling 14693912Slling reset_bootfs = 1; 14703912Slling 14713912Slling VERIFY(nvpair_value_string(elem, &strval) == 0); 14723912Slling if (strval == NULL || strval[0] == '\0') { 14734451Seschrock objnum = zpool_prop_default_numeric( 14744451Seschrock ZPOOL_PROP_BOOTFS); 14753912Slling break; 14763912Slling } 14773912Slling 14783912Slling if (error = dmu_objset_open(strval, DMU_OST_ZFS, 14793912Slling DS_MODE_STANDARD | DS_MODE_READONLY, &os)) 14803912Slling break; 14813912Slling objnum = dmu_objset_id(os); 14823912Slling dmu_objset_close(os); 14833912Slling break; 14843912Slling } 14853912Slling 14863912Slling if (error) 14873912Slling break; 14883912Slling } 14893912Slling if (error == 0) { 14903912Slling if (reset_bootfs) { 14913912Slling VERIFY(nvlist_remove(nvl, 14924451Seschrock zpool_prop_to_name(ZPOOL_PROP_BOOTFS), 14933912Slling DATA_TYPE_STRING) == 0); 14943912Slling VERIFY(nvlist_add_uint64(nvl, 14954451Seschrock zpool_prop_to_name(ZPOOL_PROP_BOOTFS), 14964451Seschrock objnum) == 0); 14973912Slling } 14983912Slling error = spa_set_props(spa, nvl); 14993912Slling } 15003912Slling 15013912Slling nvlist_free(nvl); 15023912Slling spa_close(spa, FTAG); 15033912Slling 15043912Slling return (error); 15053912Slling } 15063912Slling 15073912Slling static int 15084098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc) 15093912Slling { 15103912Slling spa_t *spa; 15113912Slling int error; 15123912Slling nvlist_t *nvp = NULL; 15133912Slling 15143912Slling if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 15153912Slling return (error); 15163912Slling 15173912Slling error = spa_get_props(spa, &nvp); 15183912Slling 15193912Slling if (error == 0 && zc->zc_nvlist_dst != NULL) 15203912Slling error = put_nvlist(zc, nvp); 15213912Slling else 15223912Slling error = EFAULT; 15233912Slling 15243912Slling spa_close(spa, FTAG); 15253912Slling 15263912Slling if (nvp) 15273912Slling nvlist_free(nvp); 15283912Slling return (error); 15293912Slling } 15303912Slling 15313912Slling static int 1532*4543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) 1533*4543Smarks { 1534*4543Smarks nvlist_t *nvp; 1535*4543Smarks int error; 1536*4543Smarks uint32_t uid; 1537*4543Smarks uint32_t gid; 1538*4543Smarks uint32_t *groups; 1539*4543Smarks uint_t group_cnt; 1540*4543Smarks cred_t *usercred; 1541*4543Smarks 1542*4543Smarks if ((error = get_nvlist(zc, &nvp)) != 0) { 1543*4543Smarks return (error); 1544*4543Smarks } 1545*4543Smarks 1546*4543Smarks if ((error = nvlist_lookup_uint32(nvp, 1547*4543Smarks ZFS_DELEG_PERM_UID, &uid)) != 0) { 1548*4543Smarks nvlist_free(nvp); 1549*4543Smarks return (EPERM); 1550*4543Smarks } 1551*4543Smarks 1552*4543Smarks if ((error = nvlist_lookup_uint32(nvp, 1553*4543Smarks ZFS_DELEG_PERM_GID, &gid)) != 0) { 1554*4543Smarks nvlist_free(nvp); 1555*4543Smarks return (EPERM); 1556*4543Smarks } 1557*4543Smarks 1558*4543Smarks if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, 1559*4543Smarks &groups, &group_cnt)) != 0) { 1560*4543Smarks nvlist_free(nvp); 1561*4543Smarks return (EPERM); 1562*4543Smarks } 1563*4543Smarks usercred = cralloc(); 1564*4543Smarks if ((crsetugid(usercred, uid, gid) != 0) || 1565*4543Smarks (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { 1566*4543Smarks nvlist_free(nvp); 1567*4543Smarks crfree(usercred); 1568*4543Smarks return (EPERM); 1569*4543Smarks } 1570*4543Smarks nvlist_free(nvp); 1571*4543Smarks error = dsl_deleg_access(zc->zc_name, 1572*4543Smarks ZFS_DELEG_PERM_SHAREISCSI, usercred); 1573*4543Smarks crfree(usercred); 1574*4543Smarks return (error); 1575*4543Smarks } 1576*4543Smarks 1577*4543Smarks static int 1578*4543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc) 1579*4543Smarks { 1580*4543Smarks int error; 1581*4543Smarks nvlist_t *fsaclnv = NULL; 1582*4543Smarks cred_t *cr; 1583*4543Smarks 1584*4543Smarks if ((error = get_nvlist(zc, &fsaclnv)) != 0) 1585*4543Smarks return (error); 1586*4543Smarks 1587*4543Smarks /* 1588*4543Smarks * Verify nvlist is constructed correctly 1589*4543Smarks */ 1590*4543Smarks if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { 1591*4543Smarks nvlist_free(fsaclnv); 1592*4543Smarks return (EINVAL); 1593*4543Smarks } 1594*4543Smarks 1595*4543Smarks /* 1596*4543Smarks * If we don't have PRIV_SYS_MOUNT, then validate 1597*4543Smarks * that user is allowed to hand out each permission in 1598*4543Smarks * the nvlist(s) 1599*4543Smarks */ 1600*4543Smarks 1601*4543Smarks cr = (cred_t *)(uintptr_t)zc->zc_cred; 1602*4543Smarks error = secpolicy_zfs(cr); 1603*4543Smarks if (error) { 1604*4543Smarks if (zc->zc_perm_action == B_FALSE) 1605*4543Smarks error = dsl_deleg_can_allow(zc->zc_name, fsaclnv, cr); 1606*4543Smarks else 1607*4543Smarks error = dsl_deleg_can_unallow(zc->zc_name, fsaclnv, cr); 1608*4543Smarks } 1609*4543Smarks 1610*4543Smarks if (error == 0) 1611*4543Smarks error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); 1612*4543Smarks 1613*4543Smarks nvlist_free(fsaclnv); 1614*4543Smarks return (error); 1615*4543Smarks } 1616*4543Smarks 1617*4543Smarks static int 1618*4543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc) 1619*4543Smarks { 1620*4543Smarks nvlist_t *nvp; 1621*4543Smarks int error; 1622*4543Smarks 1623*4543Smarks if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { 1624*4543Smarks error = put_nvlist(zc, nvp); 1625*4543Smarks nvlist_free(nvp); 1626*4543Smarks } 1627*4543Smarks 1628*4543Smarks return (error); 1629*4543Smarks } 1630*4543Smarks 1631*4543Smarks static int 1632789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc) 1633789Sahrens { 16342676Seschrock return (zvol_create_minor(zc->zc_name, zc->zc_dev)); 1635789Sahrens } 1636789Sahrens 1637789Sahrens static int 1638789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc) 1639789Sahrens { 16402676Seschrock return (zvol_remove_minor(zc->zc_name)); 1641789Sahrens } 1642789Sahrens 1643789Sahrens /* 1644789Sahrens * Search the vfs list for a specified resource. Returns a pointer to it 1645789Sahrens * or NULL if no suitable entry is found. The caller of this routine 1646789Sahrens * is responsible for releasing the returned vfs pointer. 1647789Sahrens */ 1648789Sahrens static vfs_t * 1649789Sahrens zfs_get_vfs(const char *resource) 1650789Sahrens { 1651789Sahrens struct vfs *vfsp; 1652789Sahrens struct vfs *vfs_found = NULL; 1653789Sahrens 1654789Sahrens vfs_list_read_lock(); 1655789Sahrens vfsp = rootvfs; 1656789Sahrens do { 1657789Sahrens if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { 1658789Sahrens VFS_HOLD(vfsp); 1659789Sahrens vfs_found = vfsp; 1660789Sahrens break; 1661789Sahrens } 1662789Sahrens vfsp = vfsp->vfs_next; 1663789Sahrens } while (vfsp != rootvfs); 1664789Sahrens vfs_list_unlock(); 1665789Sahrens return (vfs_found); 1666789Sahrens } 1667789Sahrens 1668*4543Smarks /* ARGSUSED */ 1669789Sahrens static void 1670*4543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) 1671789Sahrens { 1672*4543Smarks zfs_create_fs(os, cr, tx); 1673789Sahrens } 1674789Sahrens 1675789Sahrens static int 1676789Sahrens zfs_ioc_create(zfs_cmd_t *zc) 1677789Sahrens { 1678789Sahrens objset_t *clone; 1679789Sahrens int error = 0; 1680*4543Smarks nvlist_t *nvprops = NULL; 1681*4543Smarks void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); 1682789Sahrens dmu_objset_type_t type = zc->zc_objset_type; 1683789Sahrens 1684789Sahrens switch (type) { 1685789Sahrens 1686789Sahrens case DMU_OST_ZFS: 1687789Sahrens cbfunc = zfs_create_cb; 1688789Sahrens break; 1689789Sahrens 1690789Sahrens case DMU_OST_ZVOL: 1691789Sahrens cbfunc = zvol_create_cb; 1692789Sahrens break; 1693789Sahrens 1694789Sahrens default: 16952199Sahrens cbfunc = NULL; 16962199Sahrens } 16972199Sahrens if (strchr(zc->zc_name, '@')) 1698789Sahrens return (EINVAL); 1699789Sahrens 17002676Seschrock if (zc->zc_nvlist_src != NULL && 1701*4543Smarks (error = get_nvlist(zc, &nvprops)) != 0) 17022676Seschrock return (error); 17032676Seschrock 17042676Seschrock if (zc->zc_value[0] != '\0') { 1705789Sahrens /* 1706789Sahrens * We're creating a clone of an existing snapshot. 1707789Sahrens */ 17082676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 17092676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { 1710*4543Smarks nvlist_free(nvprops); 1711789Sahrens return (EINVAL); 17122676Seschrock } 1713789Sahrens 17142676Seschrock error = dmu_objset_open(zc->zc_value, type, 1715789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &clone); 17162676Seschrock if (error) { 1717*4543Smarks nvlist_free(nvprops); 1718789Sahrens return (error); 17192676Seschrock } 1720789Sahrens error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); 1721789Sahrens dmu_objset_close(clone); 1722789Sahrens } else { 17232676Seschrock if (cbfunc == NULL) { 1724*4543Smarks nvlist_free(nvprops); 17252199Sahrens return (EINVAL); 17262676Seschrock } 17272676Seschrock 1728789Sahrens if (type == DMU_OST_ZVOL) { 17292676Seschrock uint64_t volsize, volblocksize; 17302676Seschrock 1731*4543Smarks if (nvprops == NULL || 1732*4543Smarks nvlist_lookup_uint64(nvprops, 17332676Seschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), 17342676Seschrock &volsize) != 0) { 1735*4543Smarks nvlist_free(nvprops); 17362676Seschrock return (EINVAL); 17372676Seschrock } 17382676Seschrock 1739*4543Smarks if ((error = nvlist_lookup_uint64(nvprops, 17402676Seschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 17412676Seschrock &volblocksize)) != 0 && error != ENOENT) { 1742*4543Smarks nvlist_free(nvprops); 17432676Seschrock return (EINVAL); 17442676Seschrock } 17451133Seschrock 17462676Seschrock if (error != 0) 17472676Seschrock volblocksize = zfs_prop_default_numeric( 17482676Seschrock ZFS_PROP_VOLBLOCKSIZE); 17492676Seschrock 17502676Seschrock if ((error = zvol_check_volblocksize( 17512676Seschrock volblocksize)) != 0 || 17522676Seschrock (error = zvol_check_volsize(volsize, 17532676Seschrock volblocksize)) != 0) { 1754*4543Smarks nvlist_free(nvprops); 1755789Sahrens return (error); 17562676Seschrock } 17572676Seschrock } 17581133Seschrock 17592676Seschrock error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, 1760*4543Smarks nvprops); 1761789Sahrens } 17622676Seschrock 17632676Seschrock /* 17642676Seschrock * It would be nice to do this atomically. 17652676Seschrock */ 17662676Seschrock if (error == 0) { 17672676Seschrock if ((error = zfs_set_prop_nvlist(zc->zc_name, 17682676Seschrock zc->zc_dev, (cred_t *)(uintptr_t)zc->zc_cred, 1769*4543Smarks nvprops)) != 0) 17702676Seschrock (void) dmu_objset_destroy(zc->zc_name); 17712676Seschrock } 17722676Seschrock 1773*4543Smarks nvlist_free(nvprops); 1774789Sahrens return (error); 1775789Sahrens } 1776789Sahrens 1777789Sahrens static int 17782199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc) 17792199Sahrens { 17802676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 17812199Sahrens return (EINVAL); 17822199Sahrens return (dmu_objset_snapshot(zc->zc_name, 17832676Seschrock zc->zc_value, zc->zc_cookie)); 17842199Sahrens } 17852199Sahrens 17864007Smmusante int 17872199Sahrens zfs_unmount_snap(char *name, void *arg) 1788789Sahrens { 17892199Sahrens char *snapname = arg; 17902199Sahrens char *cp; 17912417Sahrens vfs_t *vfsp = NULL; 17922199Sahrens 17932199Sahrens /* 17942199Sahrens * Snapshots (which are under .zfs control) must be unmounted 17952199Sahrens * before they can be destroyed. 17962199Sahrens */ 17972199Sahrens 17982199Sahrens if (snapname) { 17992199Sahrens (void) strcat(name, "@"); 18002199Sahrens (void) strcat(name, snapname); 18012199Sahrens vfsp = zfs_get_vfs(name); 18022199Sahrens cp = strchr(name, '@'); 18032199Sahrens *cp = '\0'; 18042417Sahrens } else if (strchr(name, '@')) { 18052199Sahrens vfsp = zfs_get_vfs(name); 18062199Sahrens } 18072199Sahrens 18082199Sahrens if (vfsp) { 18092199Sahrens /* 18102199Sahrens * Always force the unmount for snapshots. 18112199Sahrens */ 18122199Sahrens int flag = MS_FORCE; 1813789Sahrens int err; 1814789Sahrens 18152199Sahrens if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { 18162199Sahrens VFS_RELE(vfsp); 18172199Sahrens return (err); 18182199Sahrens } 18192199Sahrens VFS_RELE(vfsp); 18202199Sahrens if ((err = dounmount(vfsp, flag, kcred)) != 0) 18212199Sahrens return (err); 18222199Sahrens } 18232199Sahrens return (0); 18242199Sahrens } 18252199Sahrens 18262199Sahrens static int 18272199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc) 18282199Sahrens { 18292199Sahrens int err; 1830789Sahrens 18312676Seschrock if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) 18322199Sahrens return (EINVAL); 18332199Sahrens err = dmu_objset_find(zc->zc_name, 18342676Seschrock zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); 18352199Sahrens if (err) 18362199Sahrens return (err); 18372676Seschrock return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); 18382199Sahrens } 18392199Sahrens 18402199Sahrens static int 18412199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc) 18422199Sahrens { 18432199Sahrens if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { 18442199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18452199Sahrens if (err) 18462199Sahrens return (err); 1847789Sahrens } 1848789Sahrens 1849789Sahrens return (dmu_objset_destroy(zc->zc_name)); 1850789Sahrens } 1851789Sahrens 1852789Sahrens static int 1853789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc) 1854789Sahrens { 1855789Sahrens return (dmu_objset_rollback(zc->zc_name)); 1856789Sahrens } 1857789Sahrens 1858789Sahrens static int 1859789Sahrens zfs_ioc_rename(zfs_cmd_t *zc) 1860789Sahrens { 18614490Svb160487 boolean_t recursive = zc->zc_cookie & 1; 18624007Smmusante 18632676Seschrock zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; 18642676Seschrock if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) 1865789Sahrens return (EINVAL); 1866789Sahrens 18674007Smmusante /* 18684007Smmusante * Unmount snapshot unless we're doing a recursive rename, 18694007Smmusante * in which case the dataset code figures out which snapshots 18704007Smmusante * to unmount. 18714007Smmusante */ 18724007Smmusante if (!recursive && strchr(zc->zc_name, '@') != NULL && 1873789Sahrens zc->zc_objset_type == DMU_OST_ZFS) { 18742199Sahrens int err = zfs_unmount_snap(zc->zc_name, NULL); 18752199Sahrens if (err) 18762199Sahrens return (err); 1877789Sahrens } 1878789Sahrens 18794007Smmusante return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); 1880789Sahrens } 1881789Sahrens 1882789Sahrens static int 1883789Sahrens zfs_ioc_recvbackup(zfs_cmd_t *zc) 1884789Sahrens { 1885789Sahrens file_t *fp; 1886789Sahrens int error, fd; 18872885Sahrens offset_t new_off; 1888789Sahrens 18893265Sahrens if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || 18903265Sahrens strchr(zc->zc_value, '@') == NULL) 18913265Sahrens return (EINVAL); 18923265Sahrens 1893789Sahrens fd = zc->zc_cookie; 1894789Sahrens fp = getf(fd); 1895789Sahrens if (fp == NULL) 1896789Sahrens return (EBADF); 18972676Seschrock error = dmu_recvbackup(zc->zc_value, &zc->zc_begin_record, 18982676Seschrock &zc->zc_cookie, (boolean_t)zc->zc_guid, fp->f_vnode, 18992665Snd150628 fp->f_offset); 19002885Sahrens 19012885Sahrens new_off = fp->f_offset + zc->zc_cookie; 19022885Sahrens if (VOP_SEEK(fp->f_vnode, fp->f_offset, &new_off) == 0) 19032885Sahrens fp->f_offset = new_off; 19042885Sahrens 1905789Sahrens releasef(fd); 1906789Sahrens return (error); 1907789Sahrens } 1908789Sahrens 1909789Sahrens static int 1910789Sahrens zfs_ioc_sendbackup(zfs_cmd_t *zc) 1911789Sahrens { 1912789Sahrens objset_t *fromsnap = NULL; 1913789Sahrens objset_t *tosnap; 1914789Sahrens file_t *fp; 1915789Sahrens int error; 1916789Sahrens 1917789Sahrens error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, 1918789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); 1919789Sahrens if (error) 1920789Sahrens return (error); 1921789Sahrens 19222676Seschrock if (zc->zc_value[0] != '\0') { 19232885Sahrens char buf[MAXPATHLEN]; 19242885Sahrens char *cp; 19252885Sahrens 19262885Sahrens (void) strncpy(buf, zc->zc_name, sizeof (buf)); 19272885Sahrens cp = strchr(buf, '@'); 19282885Sahrens if (cp) 19292885Sahrens *(cp+1) = 0; 19302885Sahrens (void) strncat(buf, zc->zc_value, sizeof (buf)); 19312885Sahrens error = dmu_objset_open(buf, DMU_OST_ANY, 1932789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); 1933789Sahrens if (error) { 1934789Sahrens dmu_objset_close(tosnap); 1935789Sahrens return (error); 1936789Sahrens } 1937789Sahrens } 1938789Sahrens 1939789Sahrens fp = getf(zc->zc_cookie); 1940789Sahrens if (fp == NULL) { 1941789Sahrens dmu_objset_close(tosnap); 1942789Sahrens if (fromsnap) 1943789Sahrens dmu_objset_close(fromsnap); 1944789Sahrens return (EBADF); 1945789Sahrens } 1946789Sahrens 1947789Sahrens error = dmu_sendbackup(tosnap, fromsnap, fp->f_vnode); 1948789Sahrens 1949789Sahrens releasef(zc->zc_cookie); 1950789Sahrens if (fromsnap) 1951789Sahrens dmu_objset_close(fromsnap); 1952789Sahrens dmu_objset_close(tosnap); 1953789Sahrens return (error); 1954789Sahrens } 1955789Sahrens 19561544Seschrock static int 19571544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc) 19581544Seschrock { 19591544Seschrock int id, error; 19601544Seschrock 19611544Seschrock error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, 19621544Seschrock &zc->zc_inject_record); 19631544Seschrock 19641544Seschrock if (error == 0) 19651544Seschrock zc->zc_guid = (uint64_t)id; 19661544Seschrock 19671544Seschrock return (error); 19681544Seschrock } 19691544Seschrock 19701544Seschrock static int 19711544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc) 19721544Seschrock { 19731544Seschrock return (zio_clear_fault((int)zc->zc_guid)); 19741544Seschrock } 19751544Seschrock 19761544Seschrock static int 19771544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc) 19781544Seschrock { 19791544Seschrock int id = (int)zc->zc_guid; 19801544Seschrock int error; 19811544Seschrock 19821544Seschrock error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), 19831544Seschrock &zc->zc_inject_record); 19841544Seschrock 19851544Seschrock zc->zc_guid = id; 19861544Seschrock 19871544Seschrock return (error); 19881544Seschrock } 19891544Seschrock 19901544Seschrock static int 19911544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc) 19921544Seschrock { 19931544Seschrock spa_t *spa; 19941544Seschrock int error; 19952676Seschrock size_t count = (size_t)zc->zc_nvlist_dst_size; 19961544Seschrock 19971544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 19981544Seschrock return (error); 19991544Seschrock 20002676Seschrock error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, 20011544Seschrock &count); 20021544Seschrock if (error == 0) 20032676Seschrock zc->zc_nvlist_dst_size = count; 20041544Seschrock else 20052676Seschrock zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); 20061544Seschrock 20071544Seschrock spa_close(spa, FTAG); 20081544Seschrock 20091544Seschrock return (error); 20101544Seschrock } 20111544Seschrock 20121544Seschrock static int 20131544Seschrock zfs_ioc_clear(zfs_cmd_t *zc) 20141544Seschrock { 20151544Seschrock spa_t *spa; 20161544Seschrock vdev_t *vd; 20171544Seschrock int error; 20184451Seschrock uint64_t txg; 20191544Seschrock 20201544Seschrock if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) 20211544Seschrock return (error); 20221544Seschrock 20234451Seschrock txg = spa_vdev_enter(spa); 20241544Seschrock 20252676Seschrock if (zc->zc_guid == 0) { 20261544Seschrock vd = NULL; 20272676Seschrock } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { 20284451Seschrock (void) spa_vdev_exit(spa, NULL, txg, ENODEV); 20291544Seschrock spa_close(spa, FTAG); 20301544Seschrock return (ENODEV); 20311544Seschrock } 20321544Seschrock 20331544Seschrock vdev_clear(spa, vd); 20341544Seschrock 20354451Seschrock (void) spa_vdev_exit(spa, NULL, txg, 0); 20361544Seschrock 20371544Seschrock spa_close(spa, FTAG); 20381544Seschrock 20391544Seschrock return (0); 20401544Seschrock } 20411544Seschrock 20421544Seschrock static int 20432082Seschrock zfs_ioc_promote(zfs_cmd_t *zc) 20442082Seschrock { 20452417Sahrens char *cp; 20462417Sahrens 20472417Sahrens /* 20482417Sahrens * We don't need to unmount *all* the origin fs's snapshots, but 20492417Sahrens * it's easier. 20502417Sahrens */ 20512676Seschrock cp = strchr(zc->zc_value, '@'); 20522417Sahrens if (cp) 20532417Sahrens *cp = '\0'; 20542676Seschrock (void) dmu_objset_find(zc->zc_value, 20552417Sahrens zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); 20562082Seschrock return (dsl_dataset_promote(zc->zc_name)); 20572082Seschrock } 20582082Seschrock 2059*4543Smarks /* 2060*4543Smarks * We don't want to have a hard dependency 2061*4543Smarks * against some special symbols in sharefs 2062*4543Smarks * and nfs. Determine them if needed when 2063*4543Smarks * the first file system is shared. 2064*4543Smarks * Neither sharefs or nfs are unloadable modules. 2065*4543Smarks */ 2066*4543Smarks int (*zexport_fs)(void *arg); 2067*4543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); 2068*4543Smarks 2069*4543Smarks int zfs_share_inited; 2070*4543Smarks ddi_modhandle_t nfs_mod; 2071*4543Smarks ddi_modhandle_t sharefs_mod; 2072*4543Smarks kmutex_t zfs_share_lock; 2073*4543Smarks 2074*4543Smarks static int 2075*4543Smarks zfs_ioc_share(zfs_cmd_t *zc) 2076*4543Smarks { 2077*4543Smarks int error; 2078*4543Smarks int opcode; 2079*4543Smarks 2080*4543Smarks if (zfs_share_inited == 0) { 2081*4543Smarks mutex_enter(&zfs_share_lock); 2082*4543Smarks nfs_mod = ddi_modopen("fs/nfs", KRTLD_MODE_FIRST, &error); 2083*4543Smarks sharefs_mod = ddi_modopen("fs/sharefs", 2084*4543Smarks KRTLD_MODE_FIRST, &error); 2085*4543Smarks if (nfs_mod == NULL || sharefs_mod == NULL) { 2086*4543Smarks mutex_exit(&zfs_share_lock); 2087*4543Smarks return (ENOSYS); 2088*4543Smarks } 2089*4543Smarks if (zexport_fs == NULL && ((zexport_fs = (int (*)(void *)) 2090*4543Smarks ddi_modsym(nfs_mod, "nfs_export", &error)) == NULL)) { 2091*4543Smarks mutex_exit(&zfs_share_lock); 2092*4543Smarks return (ENOSYS); 2093*4543Smarks } 2094*4543Smarks 2095*4543Smarks if (zshare_fs == NULL && ((zshare_fs = 2096*4543Smarks (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) 2097*4543Smarks ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { 2098*4543Smarks mutex_exit(&zfs_share_lock); 2099*4543Smarks return (ENOSYS); 2100*4543Smarks } 2101*4543Smarks zfs_share_inited = 1; 2102*4543Smarks mutex_exit(&zfs_share_lock); 2103*4543Smarks } 2104*4543Smarks 2105*4543Smarks if (error = zexport_fs((void *)(uintptr_t)zc->zc_share.z_exportdata)) 2106*4543Smarks return (error); 2107*4543Smarks 2108*4543Smarks opcode = (zc->zc_share.z_sharetype == B_TRUE) ? 2109*4543Smarks SHAREFS_ADD : SHAREFS_REMOVE; 2110*4543Smarks 2111*4543Smarks error = zshare_fs(opcode, 2112*4543Smarks (void *)(uintptr_t)zc->zc_share.z_sharedata, 2113*4543Smarks zc->zc_share.z_sharemax); 2114*4543Smarks 2115*4543Smarks return (error); 2116*4543Smarks 2117*4543Smarks } 2118*4543Smarks 2119*4543Smarks /* 2120*4543Smarks * pool destroy and pool export don't log the history as part of zfsdev_ioctl, 2121*4543Smarks * but rather zfs_ioc_pool_create, and zfs_ioc_pool_export do the loggin 2122*4543Smarks * of those commands. 2123*4543Smarks */ 2124789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = { 2125*4543Smarks { zfs_ioc_pool_create, zfs_secpolicy_config, pool_name, B_TRUE }, 2126*4543Smarks { zfs_ioc_pool_destroy, zfs_secpolicy_config, pool_name, B_FALSE }, 2127*4543Smarks { zfs_ioc_pool_import, zfs_secpolicy_config, pool_name, B_TRUE }, 2128*4543Smarks { zfs_ioc_pool_export, zfs_secpolicy_config, pool_name, B_FALSE }, 2129*4543Smarks { zfs_ioc_pool_configs, zfs_secpolicy_none, no_name, B_FALSE }, 2130*4543Smarks { zfs_ioc_pool_stats, zfs_secpolicy_read, pool_name, B_FALSE }, 2131*4543Smarks { zfs_ioc_pool_tryimport, zfs_secpolicy_config, no_name, B_FALSE }, 2132*4543Smarks { zfs_ioc_pool_scrub, zfs_secpolicy_config, pool_name, B_TRUE }, 2133*4543Smarks { zfs_ioc_pool_freeze, zfs_secpolicy_config, no_name, B_FALSE }, 2134*4543Smarks { zfs_ioc_pool_upgrade, zfs_secpolicy_config, pool_name, B_TRUE }, 2135*4543Smarks { zfs_ioc_pool_get_history, zfs_secpolicy_config, pool_name, B_FALSE }, 2136*4543Smarks { zfs_ioc_vdev_add, zfs_secpolicy_config, pool_name, B_TRUE }, 2137*4543Smarks { zfs_ioc_vdev_remove, zfs_secpolicy_config, pool_name, B_TRUE }, 2138*4543Smarks { zfs_ioc_vdev_set_state, zfs_secpolicy_config, pool_name, B_TRUE }, 2139*4543Smarks { zfs_ioc_vdev_attach, zfs_secpolicy_config, pool_name, B_TRUE }, 2140*4543Smarks { zfs_ioc_vdev_detach, zfs_secpolicy_config, pool_name, B_TRUE }, 2141*4543Smarks { zfs_ioc_vdev_setpath, zfs_secpolicy_config, pool_name, B_FALSE }, 2142*4543Smarks { zfs_ioc_objset_stats, zfs_secpolicy_read, dataset_name, B_FALSE }, 2143*4543Smarks { zfs_ioc_dataset_list_next, zfs_secpolicy_read, 2144*4543Smarks dataset_name, B_FALSE }, 2145*4543Smarks { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, 2146*4543Smarks dataset_name, B_FALSE }, 2147*4543Smarks { zfs_ioc_set_prop, zfs_secpolicy_none, dataset_name, B_TRUE }, 2148*4543Smarks { zfs_ioc_create_minor, zfs_secpolicy_minor, dataset_name, B_FALSE }, 2149*4543Smarks { zfs_ioc_remove_minor, zfs_secpolicy_minor, dataset_name, B_FALSE }, 2150*4543Smarks { zfs_ioc_create, zfs_secpolicy_create, dataset_name, B_TRUE }, 2151*4543Smarks { zfs_ioc_destroy, zfs_secpolicy_destroy, dataset_name, B_TRUE }, 2152*4543Smarks { zfs_ioc_rollback, zfs_secpolicy_rollback, dataset_name, B_TRUE }, 2153*4543Smarks { zfs_ioc_rename, zfs_secpolicy_rename, dataset_name, B_TRUE }, 2154*4543Smarks { zfs_ioc_recvbackup, zfs_secpolicy_receive, dataset_name, B_TRUE }, 2155*4543Smarks { zfs_ioc_sendbackup, zfs_secpolicy_send, dataset_name, B_TRUE }, 2156*4543Smarks { zfs_ioc_inject_fault, zfs_secpolicy_inject, no_name, B_FALSE }, 2157*4543Smarks { zfs_ioc_clear_fault, zfs_secpolicy_inject, no_name, B_FALSE }, 2158*4543Smarks { zfs_ioc_inject_list_next, zfs_secpolicy_inject, no_name, B_FALSE }, 2159*4543Smarks { zfs_ioc_error_log, zfs_secpolicy_inject, pool_name, B_FALSE }, 2160*4543Smarks { zfs_ioc_clear, zfs_secpolicy_config, pool_name, B_TRUE }, 2161*4543Smarks { zfs_ioc_promote, zfs_secpolicy_promote, dataset_name, B_TRUE }, 2162*4543Smarks { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, dataset_name, B_TRUE }, 2163*4543Smarks { zfs_ioc_snapshot, zfs_secpolicy_snapshot, dataset_name, B_TRUE }, 2164*4543Smarks { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, pool_name, B_FALSE }, 2165*4543Smarks { zfs_ioc_obj_to_path, zfs_secpolicy_config, no_name, B_FALSE }, 2166*4543Smarks { zfs_ioc_pool_set_props, zfs_secpolicy_config, pool_name, B_TRUE }, 2167*4543Smarks { zfs_ioc_pool_get_props, zfs_secpolicy_read, pool_name, B_FALSE }, 2168*4543Smarks { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, dataset_name, B_TRUE }, 2169*4543Smarks { zfs_ioc_get_fsacl, zfs_secpolicy_read, dataset_name, B_FALSE }, 2170*4543Smarks { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, 2171*4543Smarks dataset_name, B_FALSE }, 2172*4543Smarks { zfs_ioc_share, zfs_secpolicy_share, dataset_name, B_FALSE } 2173789Sahrens }; 2174789Sahrens 2175789Sahrens static int 2176789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 2177789Sahrens { 2178789Sahrens zfs_cmd_t *zc; 2179789Sahrens uint_t vec; 21802199Sahrens int error, rc; 2181789Sahrens 2182789Sahrens if (getminor(dev) != 0) 2183789Sahrens return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); 2184789Sahrens 2185789Sahrens vec = cmd - ZFS_IOC; 2186789Sahrens 2187789Sahrens if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) 2188789Sahrens return (EINVAL); 2189789Sahrens 2190789Sahrens zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); 2191789Sahrens 2192789Sahrens error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); 2193789Sahrens 2194789Sahrens if (error == 0) { 2195789Sahrens zc->zc_cred = (uintptr_t)cr; 2196789Sahrens zc->zc_dev = dev; 2197*4543Smarks error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); 2198789Sahrens } 2199789Sahrens 2200789Sahrens /* 2201789Sahrens * Ensure that all pool/dataset names are valid before we pass down to 2202789Sahrens * the lower layers. 2203789Sahrens */ 2204789Sahrens if (error == 0) { 2205789Sahrens zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; 2206789Sahrens switch (zfs_ioc_vec[vec].zvec_namecheck) { 2207789Sahrens case pool_name: 2208789Sahrens if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) 2209789Sahrens error = EINVAL; 2210789Sahrens break; 2211789Sahrens 2212789Sahrens case dataset_name: 2213789Sahrens if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) 2214789Sahrens error = EINVAL; 2215789Sahrens break; 22162856Snd150628 22172856Snd150628 case no_name: 22182856Snd150628 break; 2219789Sahrens } 2220789Sahrens } 2221789Sahrens 2222789Sahrens if (error == 0) 2223789Sahrens error = zfs_ioc_vec[vec].zvec_func(zc); 2224789Sahrens 22252199Sahrens rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); 2226*4543Smarks if (error == 0) { 22272199Sahrens error = rc; 2228*4543Smarks if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) 2229*4543Smarks zfs_log_history(zc); 2230*4543Smarks } 2231789Sahrens 2232789Sahrens kmem_free(zc, sizeof (zfs_cmd_t)); 2233789Sahrens return (error); 2234789Sahrens } 2235789Sahrens 2236789Sahrens static int 2237789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2238789Sahrens { 2239789Sahrens if (cmd != DDI_ATTACH) 2240789Sahrens return (DDI_FAILURE); 2241789Sahrens 2242789Sahrens if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, 2243789Sahrens DDI_PSEUDO, 0) == DDI_FAILURE) 2244789Sahrens return (DDI_FAILURE); 2245789Sahrens 2246789Sahrens zfs_dip = dip; 2247789Sahrens 2248789Sahrens ddi_report_dev(dip); 2249789Sahrens 2250789Sahrens return (DDI_SUCCESS); 2251789Sahrens } 2252789Sahrens 2253789Sahrens static int 2254789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2255789Sahrens { 2256789Sahrens if (spa_busy() || zfs_busy() || zvol_busy()) 2257789Sahrens return (DDI_FAILURE); 2258789Sahrens 2259789Sahrens if (cmd != DDI_DETACH) 2260789Sahrens return (DDI_FAILURE); 2261789Sahrens 2262789Sahrens zfs_dip = NULL; 2263789Sahrens 2264789Sahrens ddi_prop_remove_all(dip); 2265789Sahrens ddi_remove_minor_node(dip, NULL); 2266789Sahrens 2267789Sahrens return (DDI_SUCCESS); 2268789Sahrens } 2269789Sahrens 2270789Sahrens /*ARGSUSED*/ 2271789Sahrens static int 2272789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2273789Sahrens { 2274789Sahrens switch (infocmd) { 2275789Sahrens case DDI_INFO_DEVT2DEVINFO: 2276789Sahrens *result = zfs_dip; 2277789Sahrens return (DDI_SUCCESS); 2278789Sahrens 2279789Sahrens case DDI_INFO_DEVT2INSTANCE: 2280849Sbonwick *result = (void *)0; 2281789Sahrens return (DDI_SUCCESS); 2282789Sahrens } 2283789Sahrens 2284789Sahrens return (DDI_FAILURE); 2285789Sahrens } 2286789Sahrens 2287789Sahrens /* 2288789Sahrens * OK, so this is a little weird. 2289789Sahrens * 2290789Sahrens * /dev/zfs is the control node, i.e. minor 0. 2291789Sahrens * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. 2292789Sahrens * 2293789Sahrens * /dev/zfs has basically nothing to do except serve up ioctls, 2294789Sahrens * so most of the standard driver entry points are in zvol.c. 2295789Sahrens */ 2296789Sahrens static struct cb_ops zfs_cb_ops = { 2297789Sahrens zvol_open, /* open */ 2298789Sahrens zvol_close, /* close */ 2299789Sahrens zvol_strategy, /* strategy */ 2300789Sahrens nodev, /* print */ 2301789Sahrens nodev, /* dump */ 2302789Sahrens zvol_read, /* read */ 2303789Sahrens zvol_write, /* write */ 2304789Sahrens zfsdev_ioctl, /* ioctl */ 2305789Sahrens nodev, /* devmap */ 2306789Sahrens nodev, /* mmap */ 2307789Sahrens nodev, /* segmap */ 2308789Sahrens nochpoll, /* poll */ 2309789Sahrens ddi_prop_op, /* prop_op */ 2310789Sahrens NULL, /* streamtab */ 2311789Sahrens D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 2312789Sahrens CB_REV, /* version */ 23133638Sbillm nodev, /* async read */ 23143638Sbillm nodev, /* async write */ 2315789Sahrens }; 2316789Sahrens 2317789Sahrens static struct dev_ops zfs_dev_ops = { 2318789Sahrens DEVO_REV, /* version */ 2319789Sahrens 0, /* refcnt */ 2320789Sahrens zfs_info, /* info */ 2321789Sahrens nulldev, /* identify */ 2322789Sahrens nulldev, /* probe */ 2323789Sahrens zfs_attach, /* attach */ 2324789Sahrens zfs_detach, /* detach */ 2325789Sahrens nodev, /* reset */ 2326789Sahrens &zfs_cb_ops, /* driver operations */ 2327789Sahrens NULL /* no bus operations */ 2328789Sahrens }; 2329789Sahrens 2330789Sahrens static struct modldrv zfs_modldrv = { 23312676Seschrock &mod_driverops, "ZFS storage pool version " ZFS_VERSION_STRING, 23322676Seschrock &zfs_dev_ops 2333789Sahrens }; 2334789Sahrens 2335789Sahrens static struct modlinkage modlinkage = { 2336789Sahrens MODREV_1, 2337789Sahrens (void *)&zfs_modlfs, 2338789Sahrens (void *)&zfs_modldrv, 2339789Sahrens NULL 2340789Sahrens }; 2341789Sahrens 2342789Sahrens int 2343789Sahrens _init(void) 2344789Sahrens { 2345789Sahrens int error; 2346789Sahrens 2347849Sbonwick spa_init(FREAD | FWRITE); 2348849Sbonwick zfs_init(); 2349849Sbonwick zvol_init(); 2350849Sbonwick 2351849Sbonwick if ((error = mod_install(&modlinkage)) != 0) { 2352849Sbonwick zvol_fini(); 2353849Sbonwick zfs_fini(); 2354849Sbonwick spa_fini(); 2355789Sahrens return (error); 2356849Sbonwick } 2357789Sahrens 2358789Sahrens error = ldi_ident_from_mod(&modlinkage, &zfs_li); 2359789Sahrens ASSERT(error == 0); 2360*4543Smarks mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); 2361789Sahrens 2362789Sahrens return (0); 2363789Sahrens } 2364789Sahrens 2365789Sahrens int 2366789Sahrens _fini(void) 2367789Sahrens { 2368789Sahrens int error; 2369789Sahrens 23701544Seschrock if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) 2371789Sahrens return (EBUSY); 2372789Sahrens 2373789Sahrens if ((error = mod_remove(&modlinkage)) != 0) 2374789Sahrens return (error); 2375789Sahrens 2376789Sahrens zvol_fini(); 2377789Sahrens zfs_fini(); 2378789Sahrens spa_fini(); 2379*4543Smarks if (zfs_share_inited) { 2380*4543Smarks (void) ddi_modclose(nfs_mod); 2381*4543Smarks (void) ddi_modclose(sharefs_mod); 2382*4543Smarks } 2383789Sahrens 2384789Sahrens ldi_ident_release(zfs_li); 2385789Sahrens zfs_li = NULL; 2386*4543Smarks mutex_destroy(&zfs_share_lock); 2387789Sahrens 2388789Sahrens return (error); 2389789Sahrens } 2390789Sahrens 2391789Sahrens int 2392789Sahrens _info(struct modinfo *modinfop) 2393789Sahrens { 2394789Sahrens return (mod_info(&modlinkage, modinfop)); 2395789Sahrens } 2396