summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/fs')
-rw-r--r--usr/src/uts/common/fs/zfs/dmu.c20
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_prop.c38
-rw-r--r--usr/src/uts/common/fs/zfs/sys/spa.h4
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zfs_acl.h10
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h48
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zvol.h71
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_acl.c14
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_ctldir.c4
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_ioctl.c553
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vfsops.c2
-rw-r--r--usr/src/uts/common/fs/zfs/zvol.c79
11 files changed, 530 insertions, 313 deletions
diff --git a/usr/src/uts/common/fs/zfs/dmu.c b/usr/src/uts/common/fs/zfs/dmu.c
index 8db58a884d..81536337ed 100644
--- a/usr/src/uts/common/fs/zfs/dmu.c
+++ b/usr/src/uts/common/fs/zfs/dmu.c
@@ -1796,17 +1796,16 @@ dmu_object_size_from_db(dmu_buf_t *db, uint32_t *blksize, u_longlong_t *nblk512)
* human-readable format.
*/
int
-spa_bookmark_name(spa_t *spa, zbookmark_t *zb, char *dsname, size_t dslen,
- char *objname, size_t objlen, char *range, size_t rangelen)
+spa_bookmark_name(spa_t *spa, zbookmark_t *zb, nvlist_t *nvl)
{
dsl_pool_t *dp;
dsl_dataset_t *ds = NULL;
objset_t *os = NULL;
dnode_t *dn = NULL;
int err, shift;
-
- if (dslen < MAXNAMELEN || objlen < 32 || rangelen < 64)
- return (ENOSPC);
+ char dsname[MAXNAMELEN];
+ char objname[32];
+ char range[64];
dp = spa_get_dsl(spa);
if (zb->zb_objset != 0) {
@@ -1832,9 +1831,9 @@ spa_bookmark_name(spa_t *spa, zbookmark_t *zb, char *dsname, size_t dslen,
if (zb->zb_object == DMU_META_DNODE_OBJECT) {
- (void) strncpy(objname, "mdn", objlen);
+ (void) strncpy(objname, "mdn", sizeof (objname));
} else {
- (void) snprintf(objname, objlen, "%lld",
+ (void) snprintf(objname, sizeof (objname), "%lld",
(longlong_t)zb->zb_object);
}
@@ -1844,10 +1843,15 @@ spa_bookmark_name(spa_t *spa, zbookmark_t *zb, char *dsname, size_t dslen,
shift = (dn->dn_datablkshift?dn->dn_datablkshift:SPA_MAXBLOCKSHIFT) +
zb->zb_level * (dn->dn_indblkshift - SPA_BLKPTRSHIFT);
- (void) snprintf(range, rangelen, "%llu-%llu",
+ (void) snprintf(range, sizeof (range), "%llu-%llu",
(u_longlong_t)(zb->zb_blkid << shift),
(u_longlong_t)((zb->zb_blkid+1) << shift));
+ if ((err = nvlist_add_string(nvl, ZPOOL_ERR_DATASET, dsname)) != 0 ||
+ (err = nvlist_add_string(nvl, ZPOOL_ERR_OBJECT, objname)) != 0 ||
+ (err = nvlist_add_string(nvl, ZPOOL_ERR_RANGE, range)) != 0)
+ goto out;
+
out:
if (dn)
dnode_rele(dn, FTAG);
diff --git a/usr/src/uts/common/fs/zfs/dsl_prop.c b/usr/src/uts/common/fs/zfs/dsl_prop.c
index 0ad81ed920..5c615dad92 100644
--- a/usr/src/uts/common/fs/zfs/dsl_prop.c
+++ b/usr/src/uts/common/fs/zfs/dsl_prop.c
@@ -67,10 +67,13 @@ dsl_prop_get_impl(dsl_dir_t *dd, const char *propname,
int intsz, int numint, void *buf, char *setpoint)
{
int err = ENOENT;
+ zfs_prop_t prop;
if (setpoint)
setpoint[0] = '\0';
+ prop = zfs_name_to_prop(propname);
+
/*
* Note: dd may be NULL, therefore we shouldn't dereference it
* ouside this loop.
@@ -85,6 +88,13 @@ dsl_prop_get_impl(dsl_dir_t *dd, const char *propname,
dsl_dir_name(dd, setpoint);
break;
}
+
+ /*
+ * Break out of this loop for non-inheritable properties.
+ */
+ if (prop != ZFS_PROP_INVAL &&
+ !zfs_prop_inheritable(prop))
+ break;
}
if (err == ENOENT)
err = dodefault(propname, intsz, numint, buf);
@@ -403,7 +413,8 @@ dsl_prop_get_all(objset_t *os, nvlist_t **nvp)
zap_attribute_t za;
char setpoint[MAXNAMELEN];
char *tmp;
- nvlist_t *prop;
+ nvlist_t *propval;
+ zfs_prop_t prop;
if (dsl_dataset_is_snapshot(ds)) {
VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
@@ -422,10 +433,19 @@ dsl_prop_get_all(objset_t *os, nvlist_t **nvp)
for (zap_cursor_init(&zc, mos, dd->dd_phys->dd_props_zapobj);
(err = zap_cursor_retrieve(&zc, &za)) == 0;
zap_cursor_advance(&zc)) {
- if (nvlist_lookup_nvlist(*nvp, za.za_name, &prop) == 0)
+ /*
+ * Skip non-inheritable properties.
+ */
+ if ((prop = zfs_name_to_prop(za.za_name)) !=
+ ZFS_PROP_INVAL && !zfs_prop_inheritable(prop) &&
+ dd != ds->ds_dir)
+ continue;
+
+ if (nvlist_lookup_nvlist(*nvp, za.za_name,
+ &propval) == 0)
continue;
- VERIFY(nvlist_alloc(&prop, NV_UNIQUE_NAME,
+ VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME,
KM_SLEEP) == 0);
if (za.za_integer_length == 1) {
/*
@@ -440,7 +460,7 @@ dsl_prop_get_all(objset_t *os, nvlist_t **nvp)
kmem_free(tmp, za.za_num_integers);
break;
}
- VERIFY(nvlist_add_string(prop,
+ VERIFY(nvlist_add_string(propval,
ZFS_PROP_VALUE, tmp) == 0);
kmem_free(tmp, za.za_num_integers);
} else {
@@ -448,15 +468,15 @@ dsl_prop_get_all(objset_t *os, nvlist_t **nvp)
* Integer property
*/
ASSERT(za.za_integer_length == 8);
- (void) nvlist_add_uint64(prop, ZFS_PROP_VALUE,
- za.za_first_integer);
+ (void) nvlist_add_uint64(propval,
+ ZFS_PROP_VALUE, za.za_first_integer);
}
- VERIFY(nvlist_add_string(prop,
+ VERIFY(nvlist_add_string(propval,
ZFS_PROP_SOURCE, setpoint) == 0);
VERIFY(nvlist_add_nvlist(*nvp, za.za_name,
- prop) == 0);
- nvlist_free(prop);
+ propval) == 0);
+ nvlist_free(propval);
}
zap_cursor_fini(&zc);
diff --git a/usr/src/uts/common/fs/zfs/sys/spa.h b/usr/src/uts/common/fs/zfs/sys/spa.h
index 829c025af2..4f2eb50d1f 100644
--- a/usr/src/uts/common/fs/zfs/sys/spa.h
+++ b/usr/src/uts/common/fs/zfs/sys/spa.h
@@ -439,8 +439,8 @@ extern int spa_get_errlog(spa_t *spa, void *uaddr, size_t *count);
extern void spa_errlog_rotate(spa_t *spa);
extern void spa_errlog_drain(spa_t *spa);
extern void spa_errlog_sync(spa_t *spa, uint64_t txg);
-extern int spa_bookmark_name(spa_t *spa, struct zbookmark *zb, char *ds,
- size_t dsname, char *obj, size_t objname, char *range, size_t rangelen);
+extern int spa_bookmark_name(spa_t *spa, struct zbookmark *zb,
+ nvlist_t *nvl);
extern void spa_get_errlists(spa_t *spa, avl_tree_t *last, avl_tree_t *scrub);
/* Initialization and termination */
diff --git a/usr/src/uts/common/fs/zfs/sys/zfs_acl.h b/usr/src/uts/common/fs/zfs/sys/zfs_acl.h
index 34057e83c9..e3a653c5fa 100644
--- a/usr/src/uts/common/fs/zfs/sys/zfs_acl.h
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_acl.h
@@ -77,11 +77,11 @@ typedef struct zfs_acl {
* whereas acl_inherit has secure instead of groupmask.
*/
-#define DISCARD 0
-#define NOALLOW 1
-#define GROUPMASK 2
-#define PASSTHROUGH 3
-#define SECURE 4
+#define ZFS_ACL_DISCARD 0
+#define ZFS_ACL_NOALLOW 1
+#define ZFS_ACL_GROUPMASK 2
+#define ZFS_ACL_PASSTHROUGH 3
+#define ZFS_ACL_SECURE 4
struct znode;
diff --git a/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h b/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h
index a8f1f4ed89..b4f834e186 100644
--- a/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h
@@ -31,6 +31,7 @@
#include <sys/cred.h>
#include <sys/dmu.h>
#include <sys/zio.h>
+#include <sys/zvol.h>
#ifdef __cplusplus
extern "C" {
@@ -115,29 +116,29 @@ typedef struct zinject_record {
typedef struct zfs_cmd {
char zc_name[MAXPATHLEN];
- char zc_prop_name[MAXNAMELEN];
- char zc_prop_value[MAXPATHLEN];
- char zc_root[MAXPATHLEN];
- char zc_filename[MAXNAMELEN];
- uint32_t zc_intsz;
- uint32_t zc_numints;
+ char zc_value[MAXPATHLEN];
uint64_t zc_guid;
- uint64_t zc_config_src; /* really (char *) */
- uint64_t zc_config_src_size;
- uint64_t zc_config_dst; /* really (char *) */
- uint64_t zc_config_dst_size;
+ uint64_t zc_nvlist_src; /* really (char *) */
+ uint64_t zc_nvlist_src_size;
+ uint64_t zc_nvlist_dst; /* really (char *) */
+ uint64_t zc_nvlist_dst_size;
uint64_t zc_cookie;
uint64_t zc_cred;
uint64_t zc_dev;
- uint64_t zc_volsize;
- uint64_t zc_volblocksize;
uint64_t zc_objset_type;
dmu_objset_stats_t zc_objset_stats;
+ zvol_stats_t zc_vol_stats;
struct drr_begin zc_begin_record;
zinject_record_t zc_inject_record;
zbookmark_t zc_bookmark;
} zfs_cmd_t;
+typedef struct zfs_create_data {
+ cred_t *zc_cred;
+ dev_t zc_dev;
+ nvlist_t *zc_props;
+} zfs_create_data_t;
+
#define ZVOL_MAX_MINOR (1 << 16)
#define ZFS_MIN_MINOR (ZVOL_MAX_MINOR + 1)
@@ -145,30 +146,9 @@ typedef struct zfs_cmd {
extern dev_info_t *zfs_dip;
-extern int zfs_secpolicy_write(const char *dataset, const char *, cred_t *cr);
+extern int zfs_secpolicy_write(const char *dataset, cred_t *cr);
extern int zfs_busy(void);
-extern int zvol_check_volsize(zfs_cmd_t *zc, uint64_t blocksize);
-extern int zvol_check_volblocksize(zfs_cmd_t *zc);
-extern int zvol_get_stats(zfs_cmd_t *zc, objset_t *os);
-extern void zvol_create_cb(objset_t *os, void *arg, dmu_tx_t *tx);
-extern int zvol_create_minor(zfs_cmd_t *zc);
-extern int zvol_remove_minor(zfs_cmd_t *zc);
-extern int zvol_set_volsize(zfs_cmd_t *zc);
-extern int zvol_set_volblocksize(zfs_cmd_t *zc);
-extern int zvol_open(dev_t *devp, int flag, int otyp, cred_t *cr);
-extern int zvol_close(dev_t dev, int flag, int otyp, cred_t *cr);
-extern int zvol_strategy(buf_t *bp);
-extern int zvol_read(dev_t dev, uio_t *uiop, cred_t *cr);
-extern int zvol_write(dev_t dev, uio_t *uiop, cred_t *cr);
-extern int zvol_aread(dev_t dev, struct aio_req *aio, cred_t *cr);
-extern int zvol_awrite(dev_t dev, struct aio_req *aio, cred_t *cr);
-extern int zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr,
- int *rvalp);
-extern int zvol_busy(void);
-extern void zvol_init(void);
-extern void zvol_fini(void);
-
#endif /* _KERNEL */
#ifdef __cplusplus
diff --git a/usr/src/uts/common/fs/zfs/sys/zvol.h b/usr/src/uts/common/fs/zfs/sys/zvol.h
new file mode 100644
index 0000000000..9ddbfc2e21
--- /dev/null
+++ b/usr/src/uts/common/fs/zfs/sys/zvol.h
@@ -0,0 +1,71 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_ZVOL_H
+#define _SYS_ZVOL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/zfs_context.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct zvol_stats {
+ uint64_t zv_volsize;
+ uint64_t zv_volblocksize;
+} zvol_stats_t;
+
+#ifdef _KERNEL
+extern int zvol_check_volsize(uint64_t volsize, uint64_t blocksize);
+extern int zvol_check_volblocksize(uint64_t volblocksize);
+extern int zvol_get_stats(objset_t *os, zvol_stats_t *zvs);
+extern void zvol_create_cb(objset_t *os, void *arg, dmu_tx_t *tx);
+extern int zvol_create_minor(const char *, dev_t);
+extern int zvol_remove_minor(const char *);
+extern int zvol_set_volsize(const char *, dev_t, uint64_t);
+extern int zvol_set_volblocksize(const char *, uint64_t);
+
+extern int zvol_open(dev_t *devp, int flag, int otyp, cred_t *cr);
+extern int zvol_close(dev_t dev, int flag, int otyp, cred_t *cr);
+extern int zvol_strategy(buf_t *bp);
+extern int zvol_read(dev_t dev, uio_t *uiop, cred_t *cr);
+extern int zvol_write(dev_t dev, uio_t *uiop, cred_t *cr);
+extern int zvol_aread(dev_t dev, struct aio_req *aio, cred_t *cr);
+extern int zvol_awrite(dev_t dev, struct aio_req *aio, cred_t *cr);
+extern int zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr,
+ int *rvalp);
+extern int zvol_busy(void);
+extern void zvol_init(void);
+extern void zvol_fini(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_ZVOL_H */
diff --git a/usr/src/uts/common/fs/zfs/zfs_acl.c b/usr/src/uts/common/fs/zfs/zfs_acl.c
index 310ff9c917..430625b84f 100644
--- a/usr/src/uts/common/fs/zfs/zfs_acl.c
+++ b/usr/src/uts/common/fs/zfs/zfs_acl.c
@@ -788,7 +788,7 @@ zfs_acl_chmod(znode_t *zp, uint64_t mode, zfs_acl_t *aclp,
}
- if (zfsvfs->z_acl_mode == DISCARD) {
+ if (zfsvfs->z_acl_mode == ZFS_ACL_DISCARD) {
zfs_ace_remove(aclp, i);
continue;
}
@@ -820,7 +820,7 @@ zfs_acl_chmod(znode_t *zp, uint64_t mode, zfs_acl_t *aclp,
* This is only applicable when the acl_mode
* property == groupmask.
*/
- if (zfsvfs->z_acl_mode == GROUPMASK) {
+ if (zfsvfs->z_acl_mode == ZFS_ACL_GROUPMASK) {
reuse_deny = zfs_reuse_deny(acep, i);
@@ -902,7 +902,7 @@ zfs_acl_chmod_setattr(znode_t *zp, uint64_t mode, dmu_tx_t *tx)
static void
zfs_securemode_update(zfsvfs_t *zfsvfs, ace_t *acep)
{
- if ((zfsvfs->z_acl_inherit == SECURE) &&
+ if ((zfsvfs->z_acl_inherit == ZFS_ACL_SECURE) &&
(acep->a_type == ALLOW))
acep->a_access_mask &= ~SECURE_CLEAR;
}
@@ -924,10 +924,10 @@ zfs_acl_inherit(znode_t *zp, zfs_acl_t *paclp)
i = j = 0;
pace_cnt = paclp->z_acl_count;
pacep = paclp->z_acl;
- if (zfsvfs->z_acl_inherit != DISCARD) {
+ if (zfsvfs->z_acl_inherit != ZFS_ACL_DISCARD) {
for (i = 0; i != pace_cnt; i++) {
- if (zfsvfs->z_acl_inherit == NOALLOW &&
+ if (zfsvfs->z_acl_inherit == ZFS_ACL_NOALLOW &&
pacep[i].a_type == ALLOW)
continue;
@@ -941,12 +941,12 @@ zfs_acl_inherit(znode_t *zp, zfs_acl_t *paclp)
}
aclp = zfs_acl_alloc(ace_cnt + OGE_PAD);
- if (ace_cnt && zfsvfs->z_acl_inherit != DISCARD) {
+ if (ace_cnt && zfsvfs->z_acl_inherit != ZFS_ACL_DISCARD) {
acep = aclp->z_acl;
pacep = paclp->z_acl;
for (i = 0; i != pace_cnt; i++) {
- if (zfsvfs->z_acl_inherit == NOALLOW &&
+ if (zfsvfs->z_acl_inherit == ZFS_ACL_NOALLOW &&
pacep[i].a_type == ALLOW)
continue;
diff --git a/usr/src/uts/common/fs/zfs/zfs_ctldir.c b/usr/src/uts/common/fs/zfs/zfs_ctldir.c
index e890530701..cb0807aa56 100644
--- a/usr/src/uts/common/fs/zfs/zfs_ctldir.c
+++ b/usr/src/uts/common/fs/zfs/zfs_ctldir.c
@@ -513,7 +513,7 @@ zfsctl_snapdir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm,
err = zfsctl_snapshot_zname(sdvp, snm, MAXNAMELEN, from);
if (err)
return (err);
- err = zfs_secpolicy_write(from, NULL, cr);
+ err = zfs_secpolicy_write(from, cr);
if (err)
return (err);
@@ -558,7 +558,7 @@ zfsctl_snapdir_remove(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr)
err = zfsctl_snapshot_zname(dvp, name, MAXNAMELEN, snapname);
if (err)
return (err);
- err = zfs_secpolicy_write(snapname, NULL, cr);
+ err = zfs_secpolicy_write(snapname, cr);
if (err)
return (err);
diff --git a/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
index 029138ff3a..e51c1587df 100644
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
@@ -58,6 +58,7 @@
#include <sys/zfs_ctldir.h>
#include "zfs_namecheck.h"
+#include "zfs_prop.h"
extern struct modlfs zfs_modlfs;
@@ -68,7 +69,7 @@ ldi_ident_t zfs_li = NULL;
dev_info_t *zfs_dip;
typedef int zfs_ioc_func_t(zfs_cmd_t *);
-typedef int zfs_secpolicy_func_t(const char *, const char *, cred_t *);
+typedef int zfs_secpolicy_func_t(const char *, cred_t *);
typedef struct zfs_ioc_vec {
zfs_ioc_func_t *zvec_func;
@@ -122,7 +123,7 @@ __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
*/
/* ARGSUSED */
static int
-zfs_secpolicy_none(const char *unused1, const char *unused2, cred_t *cr)
+zfs_secpolicy_none(const char *unused1, cred_t *cr)
{
return (0);
}
@@ -133,7 +134,7 @@ zfs_secpolicy_none(const char *unused1, const char *unused2, cred_t *cr)
*/
/* ARGSUSED */
static int
-zfs_secpolicy_read(const char *dataset, const char *unused, cred_t *cr)
+zfs_secpolicy_read(const char *dataset, cred_t *cr)
{
if (INGLOBALZONE(curproc) ||
zone_dataset_visible(dataset, NULL))
@@ -184,9 +185,8 @@ zfs_dozonecheck(const char *dataset, cred_t *cr)
* Policy for dataset write operations (create children, set properties, etc).
* Requires SYS_MOUNT privilege, and must be writable in the local zone.
*/
-/* ARGSUSED */
int
-zfs_secpolicy_write(const char *dataset, const char *unused, cred_t *cr)
+zfs_secpolicy_write(const char *dataset, cred_t *cr)
{
int error;
@@ -201,7 +201,7 @@ zfs_secpolicy_write(const char *dataset, const char *unused, cred_t *cr)
* create, destroy, snapshot, clone, restore.
*/
static int
-zfs_secpolicy_parent(const char *dataset, const char *unused, cred_t *cr)
+zfs_secpolicy_parent(const char *dataset, cred_t *cr)
{
char parentname[MAXNAMELEN];
char *cp;
@@ -221,65 +221,7 @@ zfs_secpolicy_parent(const char *dataset, const char *unused, cred_t *cr)
}
- return (zfs_secpolicy_write(parentname, unused, cr));
-}
-
-/*
- * Policy for dataset write operations (create children, set properties, etc).
- * Requires SYS_MOUNT privilege, and must be writable in the local zone.
- */
-static int
-zfs_secpolicy_setprop(const char *dataset, const char *prop, cred_t *cr)
-{
- int error;
-
- if (error = zfs_dozonecheck(dataset, cr))
- return (error);
-
- if (strcmp(prop, "zoned") == 0) {
- /*
- * Disallow setting of 'zoned' from within a local zone.
- */
- if (!INGLOBALZONE(curproc))
- return (EPERM);
- }
-
- return (secpolicy_zfs(cr));
-}
-
-/*
- * Security policy for setting the quota. This is the same as
- * zfs_secpolicy_write, except that the local zone may not change the quota at
- * the zone-property setpoint.
- */
-/* ARGSUSED */
-static int
-zfs_secpolicy_quota(const char *dataset, const char *unused, cred_t *cr)
-{
- int error;
-
- if (error = zfs_dozonecheck(dataset, cr))
- return (error);
-
- if (!INGLOBALZONE(curproc)) {
- uint64_t zoned;
- char setpoint[MAXNAMELEN];
- int dslen;
- /*
- * Unprivileged users are allowed to modify the quota
- * on things *under* (ie. contained by) the thing they
- * own.
- */
- if (dsl_prop_get_integer(dataset, "zoned", &zoned, setpoint))
- return (EPERM);
- if (!zoned) /* this shouldn't happen */
- return (EPERM);
- dslen = strlen(dataset);
- if (dslen <= strlen(setpoint))
- return (EPERM);
- }
-
- return (secpolicy_zfs(cr));
+ return (zfs_secpolicy_write(parentname, cr));
}
/*
@@ -288,7 +230,7 @@ zfs_secpolicy_quota(const char *dataset, const char *unused, cred_t *cr)
*/
/* ARGSUSED */
static int
-zfs_secpolicy_config(const char *unused, const char *unused2, cred_t *cr)
+zfs_secpolicy_config(const char *unused, cred_t *cr)
{
if (secpolicy_sys_config(cr, B_FALSE) != 0)
return (EPERM);
@@ -301,7 +243,7 @@ zfs_secpolicy_config(const char *unused, const char *unused2, cred_t *cr)
*/
/* ARGSUSED */
static int
-zfs_secpolicy_inject(const char *unused, const char *unused2, cred_t *cr)
+zfs_secpolicy_inject(const char *unused, cred_t *cr)
{
return (secpolicy_zinject(cr));
}
@@ -310,7 +252,7 @@ zfs_secpolicy_inject(const char *unused, const char *unused2, cred_t *cr)
* Returns the nvlist as specified by the user in the zfs_cmd_t.
*/
static int
-get_config(zfs_cmd_t *zc, nvlist_t **nvp)
+get_nvlist(zfs_cmd_t *zc, nvlist_t **nvp)
{
char *packed;
size_t size;
@@ -318,16 +260,14 @@ get_config(zfs_cmd_t *zc, nvlist_t **nvp)
nvlist_t *config = NULL;
/*
- * Read in and unpack the user-supplied nvlist. By this point, we know
- * that the user has the SYS_CONFIG privilege, so allocating arbitrary
- * sized regions of memory should not be a problem.
+ * Read in and unpack the user-supplied nvlist.
*/
- if ((size = zc->zc_config_src_size) == 0)
+ if ((size = zc->zc_nvlist_src_size) == 0)
return (EINVAL);
packed = kmem_alloc(size, KM_SLEEP);
- if ((error = xcopyin((void *)(uintptr_t)zc->zc_config_src, packed,
+ if ((error = xcopyin((void *)(uintptr_t)zc->zc_nvlist_src, packed,
size)) != 0) {
kmem_free(packed, size);
return (error);
@@ -345,16 +285,39 @@ get_config(zfs_cmd_t *zc, nvlist_t **nvp)
}
static int
+put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl)
+{
+ char *packed = NULL;
+ size_t size;
+ int error;
+
+ VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0);
+
+ if (size > zc->zc_nvlist_dst_size) {
+ error = ENOMEM;
+ } else {
+ VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
+ KM_SLEEP) == 0);
+ error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst,
+ size);
+ kmem_free(packed, size);
+ }
+
+ zc->zc_nvlist_dst_size = size;
+ return (error);
+}
+
+static int
zfs_ioc_pool_create(zfs_cmd_t *zc)
{
int error;
nvlist_t *config;
- if ((error = get_config(zc, &config)) != 0)
+ if ((error = get_nvlist(zc, &config)) != 0)
return (error);
- error = spa_create(zc->zc_name, config, zc->zc_root[0] == '\0' ?
- NULL : zc->zc_root);
+ error = spa_create(zc->zc_name, config, zc->zc_value[0] == '\0' ?
+ NULL : zc->zc_value);
nvlist_free(config);
@@ -374,7 +337,7 @@ zfs_ioc_pool_import(zfs_cmd_t *zc)
nvlist_t *config;
uint64_t guid;
- if ((error = get_config(zc, &config)) != 0)
+ if ((error = get_nvlist(zc, &config)) != 0)
return (error);
if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 ||
@@ -382,7 +345,7 @@ zfs_ioc_pool_import(zfs_cmd_t *zc)
error = EINVAL;
else
error = spa_import(zc->zc_name, config,
- zc->zc_root[0] == '\0' ? NULL : zc->zc_root);
+ zc->zc_value[0] == '\0' ? NULL : zc->zc_value);
nvlist_free(config);
@@ -399,25 +362,13 @@ static int
zfs_ioc_pool_configs(zfs_cmd_t *zc)
{
nvlist_t *configs;
- char *packed = NULL;
- size_t size = 0;
int error;
if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL)
return (EEXIST);
- VERIFY(nvlist_pack(configs, &packed, &size, NV_ENCODE_NATIVE,
- KM_SLEEP) == 0);
+ error = put_nvlist(zc, configs);
- if (size > zc->zc_config_dst_size)
- error = ENOMEM;
- else
- error = xcopyout(packed, (void *)(uintptr_t)zc->zc_config_dst,
- size);
-
- zc->zc_config_dst_size = size;
-
- kmem_free(packed, size);
nvlist_free(configs);
return (error);
@@ -427,27 +378,14 @@ static int
zfs_ioc_pool_stats(zfs_cmd_t *zc)
{
nvlist_t *config;
- char *packed = NULL;
- size_t size = 0;
int error;
int ret = 0;
- error = spa_get_stats(zc->zc_name, &config, zc->zc_root,
- sizeof (zc->zc_root));
+ error = spa_get_stats(zc->zc_name, &config, zc->zc_value,
+ sizeof (zc->zc_value));
if (config != NULL) {
- VERIFY(nvlist_pack(config, &packed, &size,
- NV_ENCODE_NATIVE, KM_SLEEP) == 0);
-
- if (size > zc->zc_config_dst_size)
- ret = ENOMEM;
- else if (xcopyout(packed, (void *)(uintptr_t)zc->zc_config_dst,
- size))
- ret = EFAULT;
-
- zc->zc_config_dst_size = size;
-
- kmem_free(packed, size);
+ ret = put_nvlist(zc, config);
nvlist_free(config);
/*
@@ -471,11 +409,9 @@ static int
zfs_ioc_pool_tryimport(zfs_cmd_t *zc)
{
nvlist_t *tryconfig, *config;
- char *packed = NULL;
- size_t size = 0;
int error;
- if ((error = get_config(zc, &tryconfig)) != 0)
+ if ((error = get_nvlist(zc, &tryconfig)) != 0)
return (error);
config = spa_tryimport(tryconfig);
@@ -485,18 +421,7 @@ zfs_ioc_pool_tryimport(zfs_cmd_t *zc)
if (config == NULL)
return (EINVAL);
- VERIFY(nvlist_pack(config, &packed, &size, NV_ENCODE_NATIVE,
- KM_SLEEP) == 0);
-
- if (size > zc->zc_config_dst_size)
- error = ENOMEM;
- else
- error = xcopyout(packed, (void *)(uintptr_t)zc->zc_config_dst,
- size);
-
- zc->zc_config_dst_size = size;
-
- kmem_free(packed, size);
+ error = put_nvlist(zc, config);
nvlist_free(config);
return (error);
@@ -555,7 +480,7 @@ zfs_ioc_vdev_add(zfs_cmd_t *zc)
if (error != 0)
return (error);
- if ((error = get_config(zc, &config)) == 0) {
+ if ((error = get_nvlist(zc, &config)) == 0) {
error = spa_vdev_add(spa, config);
nvlist_free(config);
}
@@ -619,7 +544,7 @@ zfs_ioc_vdev_attach(zfs_cmd_t *zc)
if (error != 0)
return (error);
- if ((error = get_config(zc, &config)) == 0) {
+ if ((error = get_nvlist(zc, &config)) == 0) {
error = spa_vdev_attach(spa, zc->zc_guid, config, replacing);
nvlist_free(config);
}
@@ -648,7 +573,7 @@ static int
zfs_ioc_vdev_setpath(zfs_cmd_t *zc)
{
spa_t *spa;
- char *path = zc->zc_prop_value;
+ char *path = zc->zc_value;
uint64_t guid = zc->zc_guid;
int error;
@@ -668,8 +593,6 @@ zfs_ioc_objset_stats(zfs_cmd_t *zc)
objset_t *os = NULL;
int error;
nvlist_t *nv;
- size_t sz;
- char *buf;
retry:
error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
@@ -691,27 +614,16 @@ retry:
dmu_objset_stats(os, &zc->zc_objset_stats);
- if (zc->zc_config_src != NULL &&
+ if (zc->zc_nvlist_dst != NULL &&
(error = dsl_prop_get_all(os, &nv)) == 0) {
- VERIFY(nvlist_size(nv, &sz, NV_ENCODE_NATIVE) == 0);
- if (sz > zc->zc_config_src_size) {
- zc->zc_config_src_size = sz;
- error = ENOMEM;
- } else {
- buf = kmem_alloc(sz, KM_SLEEP);
- VERIFY(nvlist_pack(nv, &buf, &sz,
- NV_ENCODE_NATIVE, 0) == 0);
- error = xcopyout(buf,
- (void *)(uintptr_t)zc->zc_config_src, sz);
- kmem_free(buf, sz);
- }
+ error = put_nvlist(zc, nv);
nvlist_free(nv);
}
if (!error && zc->zc_objset_stats.dds_type == DMU_OST_ZVOL)
- error = zvol_get_stats(zc, os);
+ error = zvol_get_stats(os, &zc->zc_vol_stats);
- spa_altroot(dmu_objset_spa(os), zc->zc_root, sizeof (zc->zc_root));
+ spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value));
dmu_objset_close(os);
return (error);
@@ -818,46 +730,215 @@ retry:
}
static int
-zfs_ioc_set_prop(zfs_cmd_t *zc)
+zfs_set_prop_nvlist(const char *name, dev_t dev, cred_t *cr, nvlist_t *nvl)
{
- return (dsl_prop_set(zc->zc_name, zc->zc_prop_name,
- zc->zc_intsz, zc->zc_numints, zc->zc_prop_value));
-}
+ nvpair_t *elem;
+ int error;
+ const char *propname;
+ zfs_prop_t prop;
+ uint64_t intval;
+ char *strval;
+
+ elem = NULL;
+ while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
+ propname = nvpair_name(elem);
+
+ if ((prop = zfs_name_to_prop(propname)) ==
+ ZFS_PROP_INVAL) {
+ /*
+ * If this is a user-defined property, it must be a
+ * string, and there is no further validation to do.
+ */
+ if (!zfs_prop_user(propname) ||
+ nvpair_type(elem) != DATA_TYPE_STRING)
+ return (EINVAL);
+
+ VERIFY(nvpair_value_string(elem, &strval) == 0);
+ error = dsl_prop_set(name, propname, 1,
+ strlen(strval) + 1, strval);
+ if (error == 0)
+ continue;
+ else
+ break;
+ }
-static int
-zfs_ioc_set_quota(zfs_cmd_t *zc)
-{
- return (dsl_dir_set_quota(zc->zc_name, zc->zc_cookie));
-}
+ /*
+ * Check permissions for special properties.
+ */
+ switch (prop) {
+ case ZFS_PROP_ZONED:
+ /*
+ * Disallow setting of 'zoned' from within a local zone.
+ */
+ if (!INGLOBALZONE(curproc))
+ return (EPERM);
+ break;
-static int
-zfs_ioc_set_reservation(zfs_cmd_t *zc)
-{
- return (dsl_dir_set_reservation(zc->zc_name, zc->zc_cookie));
-}
+ case ZFS_PROP_QUOTA:
+ if (error = zfs_dozonecheck(name, cr))
+ return (error);
-static int
-zfs_ioc_set_volsize(zfs_cmd_t *zc)
-{
- return (zvol_set_volsize(zc));
+ if (!INGLOBALZONE(curproc)) {
+ uint64_t zoned;
+ char setpoint[MAXNAMELEN];
+ int dslen;
+ /*
+ * Unprivileged users are allowed to modify the
+ * quota on things *under* (ie. contained by)
+ * the thing they own.
+ */
+ if (dsl_prop_get_integer(name, "zoned", &zoned,
+ setpoint))
+ return (EPERM);
+ if (!zoned) /* this shouldn't happen */
+ return (EPERM);
+ dslen = strlen(name);
+ if (dslen <= strlen(setpoint))
+ return (EPERM);
+ }
+ }
+
+ switch (prop) {
+ case ZFS_PROP_QUOTA:
+ if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
+ (error = dsl_dir_set_quota(name,
+ intval)) != 0)
+ return (error);
+ break;
+
+ case ZFS_PROP_RESERVATION:
+ if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
+ (error = dsl_dir_set_reservation(name,
+ intval)) != 0)
+ return (error);
+ break;
+
+ case ZFS_PROP_VOLSIZE:
+ if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
+ (error = zvol_set_volsize(name, dev,
+ intval)) != 0)
+ return (error);
+ break;
+
+ case ZFS_PROP_VOLBLOCKSIZE:
+ if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
+ (error = zvol_set_volblocksize(name,
+ intval)) != 0)
+ return (error);
+ break;
+
+ default:
+ if (nvpair_type(elem) == DATA_TYPE_STRING) {
+ if (zfs_prop_get_type(prop) !=
+ prop_type_string)
+ return (EINVAL);
+ ASSERT(nvpair_value_string(elem, &strval) == 0);
+ error = dsl_prop_set(name,
+ nvpair_name(elem), 1, strlen(strval) + 1,
+ strval);
+ } else if (nvpair_type(elem) == DATA_TYPE_UINT64) {
+ ASSERT(nvpair_value_uint64(elem, &intval) == 0);
+
+ switch (zfs_prop_get_type(prop)) {
+ case prop_type_number:
+ break;
+ case prop_type_boolean:
+ if (intval > 1)
+ error = EINVAL;
+ break;
+ case prop_type_string:
+ error = EINVAL;
+ break;
+ case prop_type_index:
+ switch (prop) {
+ case ZFS_PROP_CHECKSUM:
+ if (intval >=
+ ZIO_CHECKSUM_FUNCTIONS)
+ error = EINVAL;
+ break;
+ case ZFS_PROP_COMPRESSION:
+ if (intval >=
+ ZIO_COMPRESS_FUNCTIONS)
+ error = EINVAL;
+ break;
+ case ZFS_PROP_SNAPDIR:
+ if (intval >
+ ZFS_SNAPDIR_VISIBLE)
+ error = EINVAL;
+ break;
+ case ZFS_PROP_ACLMODE:
+ if (intval >
+ ZFS_ACL_PASSTHROUGH)
+ error = EINVAL;
+ break;
+ case ZFS_PROP_ACLINHERIT:
+ if (intval > ZFS_ACL_SECURE ||
+ intval == ZFS_ACL_GROUPMASK)
+ error = EINVAL;
+ break;
+ default:
+ cmn_err(CE_PANIC,
+ "unknown index property");
+ }
+ break;
+ default:
+ cmn_err(CE_PANIC, "unknown property "
+ "type");
+ break;
+ }
+
+ error = dsl_prop_set(name, propname, 8, 1,
+ &intval);
+ } else {
+ return (EINVAL);
+ }
+ break;
+ }
+ }
+
+ return (0);
}
static int
-zfs_ioc_set_volblocksize(zfs_cmd_t *zc)
+zfs_ioc_set_prop(zfs_cmd_t *zc)
{
- return (zvol_set_volblocksize(zc));
+ nvlist_t *nvl;
+ int error;
+ zfs_prop_t prop;
+
+ /*
+ * If zc_value is set, then this is an attempt to inherit a value.
+ * Otherwise, zc_nvlist refers to a list of properties to set.
+ */
+ if (zc->zc_value[0] != '\0') {
+ if (!zfs_prop_user(zc->zc_value) &&
+ ((prop = zfs_name_to_prop(zc->zc_value)) ==
+ ZFS_PROP_INVAL ||
+ !zfs_prop_inheritable(prop)))
+ return (EINVAL);
+
+ return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL));
+ }
+
+ if ((error = get_nvlist(zc, &nvl)) != 0)
+ return (error);
+
+ error = zfs_set_prop_nvlist(zc->zc_name, zc->zc_dev,
+ (cred_t *)(uintptr_t)zc->zc_cred, nvl);
+ nvlist_free(nvl);
+ return (error);
}
static int
zfs_ioc_create_minor(zfs_cmd_t *zc)
{
- return (zvol_create_minor(zc));
+ return (zvol_create_minor(zc->zc_name, zc->zc_dev));
}
static int
zfs_ioc_remove_minor(zfs_cmd_t *zc)
{
- return (zvol_remove_minor(zc));
+ return (zvol_remove_minor(zc->zc_name));
}
/*
@@ -888,7 +969,7 @@ zfs_get_vfs(const char *resource)
static void
zfs_create_cb(objset_t *os, void *arg, dmu_tx_t *tx)
{
- zfs_cmd_t *zc = arg;
+ zfs_create_data_t *zc = arg;
zfs_create_fs(os, (cred_t *)(uintptr_t)zc->zc_cred, tx);
}
@@ -897,6 +978,7 @@ zfs_ioc_create(zfs_cmd_t *zc)
{
objset_t *clone;
int error = 0;
+ zfs_create_data_t cbdata = { 0 };
void (*cbfunc)(objset_t *os, void *arg, dmu_tx_t *tx);
dmu_objset_type_t type = zc->zc_objset_type;
@@ -916,47 +998,93 @@ zfs_ioc_create(zfs_cmd_t *zc)
if (strchr(zc->zc_name, '@'))
return (EINVAL);
- if (zc->zc_filename[0] != '\0') {
+ if (zc->zc_nvlist_src != NULL &&
+ (error = get_nvlist(zc, &cbdata.zc_props)) != 0)
+ return (error);
+
+ cbdata.zc_cred = (cred_t *)(uintptr_t)zc->zc_cred;
+ cbdata.zc_dev = (dev_t)zc->zc_dev;
+
+ if (zc->zc_value[0] != '\0') {
/*
* We're creating a clone of an existing snapshot.
*/
- zc->zc_filename[sizeof (zc->zc_filename) - 1] = '\0';
- if (dataset_namecheck(zc->zc_filename, NULL, NULL) != 0)
+ zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
+ if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) {
+ nvlist_free(cbdata.zc_props);
return (EINVAL);
+ }
- error = dmu_objset_open(zc->zc_filename, type,
+ error = dmu_objset_open(zc->zc_value, type,
DS_MODE_STANDARD | DS_MODE_READONLY, &clone);
- if (error)
+ if (error) {
+ nvlist_free(cbdata.zc_props);
return (error);
+ }
error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL);
dmu_objset_close(clone);
} else {
- if (cbfunc == NULL)
+ if (cbfunc == NULL) {
+ nvlist_free(cbdata.zc_props);
return (EINVAL);
- /*
- * We're creating a new dataset.
- */
- if (type == DMU_OST_ZVOL) {
-
- if ((error = zvol_check_volblocksize(zc)) != 0)
- return (error);
+ }
- if ((error = zvol_check_volsize(zc,
- zc->zc_volblocksize)) != 0)
+ if (type == DMU_OST_ZVOL) {
+ uint64_t volsize, volblocksize;
+
+ if (cbdata.zc_props == NULL ||
+ nvlist_lookup_uint64(cbdata.zc_props,
+ zfs_prop_to_name(ZFS_PROP_VOLSIZE),
+ &volsize) != 0) {
+ nvlist_free(cbdata.zc_props);
+ return (EINVAL);
+ }
+
+ if ((error = nvlist_lookup_uint64(cbdata.zc_props,
+ zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
+ &volblocksize)) != 0 && error != ENOENT) {
+ nvlist_free(cbdata.zc_props);
+ return (EINVAL);
+ }
+
+ if (error != 0)
+ volblocksize = zfs_prop_default_numeric(
+ ZFS_PROP_VOLBLOCKSIZE);
+
+ if ((error = zvol_check_volblocksize(
+ volblocksize)) != 0 ||
+ (error = zvol_check_volsize(volsize,
+ volblocksize)) != 0) {
+ nvlist_free(cbdata.zc_props);
return (error);
+ }
}
- error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, zc);
+
+ error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc,
+ &cbdata);
}
+
+ /*
+ * It would be nice to do this atomically.
+ */
+ if (error == 0) {
+ if ((error = zfs_set_prop_nvlist(zc->zc_name,
+ zc->zc_dev, (cred_t *)(uintptr_t)zc->zc_cred,
+ cbdata.zc_props)) != 0)
+ (void) dmu_objset_destroy(zc->zc_name);
+ }
+
+ nvlist_free(cbdata.zc_props);
return (error);
}
static int
zfs_ioc_snapshot(zfs_cmd_t *zc)
{
- if (snapshot_namecheck(zc->zc_prop_value, NULL, NULL) != 0)
+ if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0)
return (EINVAL);
return (dmu_objset_snapshot(zc->zc_name,
- zc->zc_prop_value, zc->zc_cookie));
+ zc->zc_value, zc->zc_cookie));
}
static int
@@ -1004,13 +1132,13 @@ zfs_ioc_destroy_snaps(zfs_cmd_t *zc)
{
int err;
- if (snapshot_namecheck(zc->zc_prop_value, NULL, NULL) != 0)
+ if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0)
return (EINVAL);
err = dmu_objset_find(zc->zc_name,
- zfs_unmount_snap, zc->zc_prop_value, DS_FIND_CHILDREN);
+ zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN);
if (err)
return (err);
- return (dmu_snapshots_destroy(zc->zc_name, zc->zc_prop_value));
+ return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value));
}
static int
@@ -1034,8 +1162,8 @@ zfs_ioc_rollback(zfs_cmd_t *zc)
static int
zfs_ioc_rename(zfs_cmd_t *zc)
{
- zc->zc_prop_value[sizeof (zc->zc_prop_value) - 1] = '\0';
- if (dataset_namecheck(zc->zc_prop_value, NULL, NULL) != 0)
+ zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
+ if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0)
return (EINVAL);
if (strchr(zc->zc_name, '@') != NULL &&
@@ -1045,7 +1173,7 @@ zfs_ioc_rename(zfs_cmd_t *zc)
return (err);
}
- return (dmu_objset_rename(zc->zc_name, zc->zc_prop_value));
+ return (dmu_objset_rename(zc->zc_name, zc->zc_value));
}
static int
@@ -1058,8 +1186,8 @@ zfs_ioc_recvbackup(zfs_cmd_t *zc)
fp = getf(fd);
if (fp == NULL)
return (EBADF);
- error = dmu_recvbackup(zc->zc_filename, &zc->zc_begin_record,
- &zc->zc_cookie, (boolean_t)zc->zc_numints, fp->f_vnode,
+ error = dmu_recvbackup(zc->zc_value, &zc->zc_begin_record,
+ &zc->zc_cookie, (boolean_t)zc->zc_guid, fp->f_vnode,
fp->f_offset);
releasef(fd);
return (error);
@@ -1078,8 +1206,8 @@ zfs_ioc_sendbackup(zfs_cmd_t *zc)
if (error)
return (error);
- if (zc->zc_prop_value[0] != '\0') {
- error = dmu_objset_open(zc->zc_prop_value, DMU_OST_ANY,
+ if (zc->zc_value[0] != '\0') {
+ error = dmu_objset_open(zc->zc_value, DMU_OST_ANY,
DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap);
if (error) {
dmu_objset_close(tosnap);
@@ -1143,17 +1271,17 @@ zfs_ioc_error_log(zfs_cmd_t *zc)
{
spa_t *spa;
int error;
- size_t count = (size_t)zc->zc_config_dst_size;
+ size_t count = (size_t)zc->zc_nvlist_dst_size;
if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
return (error);
- error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_config_dst,
+ error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst,
&count);
if (error == 0)
- zc->zc_config_dst_size = count;
+ zc->zc_nvlist_dst_size = count;
else
- zc->zc_config_dst_size = spa_get_errlog_size(spa);
+ zc->zc_nvlist_dst_size = spa_get_errlog_size(spa);
spa_close(spa, FTAG);
@@ -1172,9 +1300,9 @@ zfs_ioc_clear(zfs_cmd_t *zc)
spa_config_enter(spa, RW_WRITER, FTAG);
- if (zc->zc_prop_value[0] == '\0')
+ if (zc->zc_guid == 0) {
vd = NULL;
- else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) {
+ } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) {
spa_config_exit(spa, FTAG);
spa_close(spa, FTAG);
return (ENODEV);
@@ -1194,14 +1322,17 @@ zfs_ioc_bookmark_name(zfs_cmd_t *zc)
{
spa_t *spa;
int error;
+ nvlist_t *nvl;
if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
return (error);
- error = spa_bookmark_name(spa, &zc->zc_bookmark,
- zc->zc_prop_name, sizeof (zc->zc_prop_name), zc->zc_prop_value,
- sizeof (zc->zc_prop_value), zc->zc_filename,
- sizeof (zc->zc_filename));
+ VERIFY(nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) == 0);
+
+ error = spa_bookmark_name(spa, &zc->zc_bookmark, nvl);
+ if (error == 0)
+ error = put_nvlist(zc, nvl);
+ nvlist_free(nvl);
spa_close(spa, FTAG);
@@ -1217,10 +1348,10 @@ zfs_ioc_promote(zfs_cmd_t *zc)
* We don't need to unmount *all* the origin fs's snapshots, but
* it's easier.
*/
- cp = strchr(zc->zc_prop_value, '@');
+ cp = strchr(zc->zc_value, '@');
if (cp)
*cp = '\0';
- (void) dmu_objset_find(zc->zc_prop_value,
+ (void) dmu_objset_find(zc->zc_value,
zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS);
return (dsl_dataset_promote(zc->zc_name));
}
@@ -1246,11 +1377,7 @@ static zfs_ioc_vec_t zfs_ioc_vec[] = {
{ zfs_ioc_objset_stats, zfs_secpolicy_read, dataset_name },
{ zfs_ioc_dataset_list_next, zfs_secpolicy_read, dataset_name },
{ zfs_ioc_snapshot_list_next, zfs_secpolicy_read, dataset_name },
- { zfs_ioc_set_prop, zfs_secpolicy_setprop, dataset_name },
- { zfs_ioc_set_quota, zfs_secpolicy_quota, dataset_name },
- { zfs_ioc_set_reservation, zfs_secpolicy_write, dataset_name },
- { zfs_ioc_set_volsize, zfs_secpolicy_config, dataset_name },
- { zfs_ioc_set_volblocksize, zfs_secpolicy_config, dataset_name },
+ { zfs_ioc_set_prop, zfs_secpolicy_write, dataset_name },
{ zfs_ioc_create_minor, zfs_secpolicy_config, dataset_name },
{ zfs_ioc_remove_minor, zfs_secpolicy_config, dataset_name },
{ zfs_ioc_create, zfs_secpolicy_parent, dataset_name },
@@ -1292,8 +1419,7 @@ zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
if (error == 0) {
zc->zc_cred = (uintptr_t)cr;
zc->zc_dev = dev;
- error = zfs_ioc_vec[vec].zvec_secpolicy(zc->zc_name,
- zc->zc_prop_name, cr);
+ error = zfs_ioc_vec[vec].zvec_secpolicy(zc->zc_name, cr);
}
/*
@@ -1421,7 +1547,8 @@ static struct dev_ops zfs_dev_ops = {
};
static struct modldrv zfs_modldrv = {
- &mod_driverops, "ZFS storage pool version 1", &zfs_dev_ops
+ &mod_driverops, "ZFS storage pool version " ZFS_VERSION_STRING,
+ &zfs_dev_ops
};
static struct modlinkage modlinkage = {
diff --git a/usr/src/uts/common/fs/zfs/zfs_vfsops.c b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
index 5abaaa174f..04ada0c8d0 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
@@ -1237,5 +1237,5 @@ static vfsdef_t vfw = {
};
struct modlfs zfs_modlfs = {
- &mod_fsops, "ZFS filesystem version 1", &vfw
+ &mod_fsops, "ZFS filesystem version " ZFS_VERSION_STRING, &vfw
};
diff --git a/usr/src/uts/common/fs/zfs/zvol.c b/usr/src/uts/common/fs/zfs/zvol.c
index 66a8327b51..0b83bd7bd0 100644
--- a/usr/src/uts/common/fs/zfs/zvol.c
+++ b/usr/src/uts/common/fs/zfs/zvol.c
@@ -116,27 +116,27 @@ zvol_size_changed(zvol_state_t *zv, dev_t dev)
}
int
-zvol_check_volsize(zfs_cmd_t *zc, uint64_t blocksize)
+zvol_check_volsize(uint64_t volsize, uint64_t blocksize)
{
- if (zc->zc_volsize == 0)
+ if (volsize == 0)
return (EINVAL);
- if (zc->zc_volsize % blocksize != 0)
+ if (volsize % blocksize != 0)
return (EINVAL);
#ifdef _ILP32
- if (zc->zc_volsize - 1 > SPEC_MAXOFFSET_T)
+ if (volsize - 1 > SPEC_MAXOFFSET_T)
return (EOVERFLOW);
#endif
return (0);
}
int
-zvol_check_volblocksize(zfs_cmd_t *zc)
+zvol_check_volblocksize(uint64_t volblocksize)
{
- if (zc->zc_volblocksize < SPA_MINBLOCKSIZE ||
- zc->zc_volblocksize > SPA_MAXBLOCKSIZE ||
- !ISP2(zc->zc_volblocksize))
+ if (volblocksize < SPA_MINBLOCKSIZE ||
+ volblocksize > SPA_MAXBLOCKSIZE ||
+ !ISP2(volblocksize))
return (EDOM);
return (0);
@@ -151,12 +151,12 @@ zvol_readonly_changed_cb(void *arg, uint64_t newval)
}
int
-zvol_get_stats(zfs_cmd_t *zc, objset_t *os)
+zvol_get_stats(objset_t *os, zvol_stats_t *zvs)
{
int error;
dmu_object_info_t doi;
- error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &zc->zc_volsize);
+ error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &zvs->zv_volsize);
if (error)
return (error);
@@ -164,7 +164,7 @@ zvol_get_stats(zfs_cmd_t *zc, objset_t *os)
error = dmu_object_info(os, ZVOL_OBJ, &doi);
if (error == 0)
- zc->zc_volblocksize = doi.doi_data_block_size;
+ zvs->zv_volblocksize = doi.doi_data_block_size;
return (error);
}
@@ -187,7 +187,7 @@ zvol_minor_alloc(void)
}
static zvol_state_t *
-zvol_minor_lookup(char *name)
+zvol_minor_lookup(const char *name)
{
minor_t minor;
zvol_state_t *zv;
@@ -208,10 +208,26 @@ zvol_minor_lookup(char *name)
void
zvol_create_cb(objset_t *os, void *arg, dmu_tx_t *tx)
{
- zfs_cmd_t *zc = arg;
+ zfs_create_data_t *zc = arg;
int error;
+ uint64_t volblocksize, volsize;
- error = dmu_object_claim(os, ZVOL_OBJ, DMU_OT_ZVOL, zc->zc_volblocksize,
+ VERIFY(nvlist_lookup_uint64(zc->zc_props,
+ zfs_prop_to_name(ZFS_PROP_VOLSIZE), &volsize) == 0);
+ if (nvlist_lookup_uint64(zc->zc_props,
+ zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), &volblocksize) != 0)
+ volblocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
+
+ /*
+ * These properites must be removed from the list so the generic
+ * property setting step won't apply to them.
+ */
+ VERIFY(nvlist_remove_all(zc->zc_props,
+ zfs_prop_to_name(ZFS_PROP_VOLSIZE)) == 0);
+ (void) nvlist_remove_all(zc->zc_props,
+ zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE));
+
+ error = dmu_object_claim(os, ZVOL_OBJ, DMU_OT_ZVOL, volblocksize,
DMU_OT_NONE, 0, tx);
ASSERT(error == 0);
@@ -219,7 +235,7 @@ zvol_create_cb(objset_t *os, void *arg, dmu_tx_t *tx)
DMU_OT_NONE, 0, tx);
ASSERT(error == 0);
- error = zap_update(os, ZVOL_ZAP_OBJ, "size", 8, 1, &zc->zc_volsize, tx);
+ error = zap_update(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize, tx);
ASSERT(error == 0);
}
@@ -284,10 +300,8 @@ zil_replay_func_t *zvol_replay_vector[TX_MAX_TYPE] = {
* Create a minor node for the specified volume.
*/
int
-zvol_create_minor(zfs_cmd_t *zc)
+zvol_create_minor(const char *name, dev_t dev)
{
- char *name = zc->zc_name;
- dev_t dev = zc->zc_dev;
zvol_state_t *zv;
objset_t *os;
uint64_t volsize;
@@ -377,7 +391,8 @@ zvol_create_minor(zfs_cmd_t *zc)
return (EAGAIN);
}
- (void) ddi_prop_update_string(minor, zfs_dip, ZVOL_PROP_NAME, name);
+ (void) ddi_prop_update_string(minor, zfs_dip, ZVOL_PROP_NAME,
+ (char *)name);
(void) sprintf(chrbuf, "%uc,raw", minor);
@@ -431,14 +446,14 @@ zvol_create_minor(zfs_cmd_t *zc)
* Remove minor node for the specified volume.
*/
int
-zvol_remove_minor(zfs_cmd_t *zc)
+zvol_remove_minor(const char *name)
{
zvol_state_t *zv;
char namebuf[30];
mutex_enter(&zvol_state_lock);
- if ((zv = zvol_minor_lookup(zc->zc_name)) == NULL) {
+ if ((zv = zvol_minor_lookup(name)) == NULL) {
mutex_exit(&zvol_state_lock);
return (ENXIO);
}
@@ -472,23 +487,23 @@ zvol_remove_minor(zfs_cmd_t *zc)
}
int
-zvol_set_volsize(zfs_cmd_t *zc)
+zvol_set_volsize(const char *name, dev_t dev, uint64_t volsize)
{
zvol_state_t *zv;
- dev_t dev = zc->zc_dev;
dmu_tx_t *tx;
int error;
dmu_object_info_t doi;
mutex_enter(&zvol_state_lock);
- if ((zv = zvol_minor_lookup(zc->zc_name)) == NULL) {
+ if ((zv = zvol_minor_lookup(name)) == NULL) {
mutex_exit(&zvol_state_lock);
return (ENXIO);
}
if ((error = dmu_object_info(zv->zv_objset, ZVOL_OBJ, &doi)) != 0 ||
- (error = zvol_check_volsize(zc, doi.doi_data_block_size)) != 0) {
+ (error = zvol_check_volsize(volsize,
+ doi.doi_data_block_size)) != 0) {
mutex_exit(&zvol_state_lock);
return (error);
}
@@ -500,7 +515,7 @@ zvol_set_volsize(zfs_cmd_t *zc)
tx = dmu_tx_create(zv->zv_objset);
dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
- dmu_tx_hold_free(tx, ZVOL_OBJ, zc->zc_volsize, DMU_OBJECT_END);
+ dmu_tx_hold_free(tx, ZVOL_OBJ, volsize, DMU_OBJECT_END);
error = dmu_tx_assign(tx, TXG_WAIT);
if (error) {
dmu_tx_abort(tx);
@@ -509,16 +524,16 @@ zvol_set_volsize(zfs_cmd_t *zc)
}
error = zap_update(zv->zv_objset, ZVOL_ZAP_OBJ, "size", 8, 1,
- &zc->zc_volsize, tx);
+ &volsize, tx);
if (error == 0) {
- error = dmu_free_range(zv->zv_objset, ZVOL_OBJ, zc->zc_volsize,
+ error = dmu_free_range(zv->zv_objset, ZVOL_OBJ, volsize,
DMU_OBJECT_END, tx);
}
dmu_tx_commit(tx);
if (error == 0) {
- zv->zv_volsize = zc->zc_volsize;
+ zv->zv_volsize = volsize;
zvol_size_changed(zv, dev);
}
@@ -528,7 +543,7 @@ zvol_set_volsize(zfs_cmd_t *zc)
}
int
-zvol_set_volblocksize(zfs_cmd_t *zc)
+zvol_set_volblocksize(const char *name, uint64_t volblocksize)
{
zvol_state_t *zv;
dmu_tx_t *tx;
@@ -536,7 +551,7 @@ zvol_set_volblocksize(zfs_cmd_t *zc)
mutex_enter(&zvol_state_lock);
- if ((zv = zvol_minor_lookup(zc->zc_name)) == NULL) {
+ if ((zv = zvol_minor_lookup(name)) == NULL) {
mutex_exit(&zvol_state_lock);
return (ENXIO);
}
@@ -553,7 +568,7 @@ zvol_set_volblocksize(zfs_cmd_t *zc)
dmu_tx_abort(tx);
} else {
error = dmu_object_set_blocksize(zv->zv_objset, ZVOL_OBJ,
- zc->zc_volblocksize, 0, tx);
+ volblocksize, 0, tx);
if (error == ENOTSUP)
error = EBUSY;
dmu_tx_commit(tx);