6377671 zfs mount -a shouldn't bother checking snapshots
6377673 'zfs mount -a' should discover the proper mount order
6378361 'zfs share -a' needs to avoid expensive checks during boot
6378377 zfs_get_stats() is way to expensive
6378388 zfs_for_each() iterates unnecessarily
--- a/usr/src/cmd/fs.d/nfs/share/share.c Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/cmd/fs.d/nfs/share/share.c Mon Jan 30 22:19:55 2006 -0800
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -148,15 +148,17 @@
if (argc - optind > 1)
res = argv[optind + 1];
- switch (shareable(dir)) {
- case 0:
- exit(RET_ERR);
- break;
- case 1:
- break;
- case 2:
- replace = 1;
- break;
+ if (getenv("SHARE_NOINUSE_CHECK") == NULL) {
+ switch (shareable(dir)) {
+ case 0:
+ exit(RET_ERR);
+ break;
+ case 1:
+ break;
+ case 2:
+ replace = 1;
+ break;
+ }
}
ex.ex_path = dir;
--- a/usr/src/cmd/fs.d/nfs/svc/nfs-server Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/cmd/fs.d/nfs/svc/nfs-server Mon Jan 30 22:19:55 2006 -0800
@@ -21,7 +21,7 @@
# CDDL HEADER END
#
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -41,6 +41,16 @@
exit $SMF_EXIT_OK
fi
+ # Share any ZFS filesystems marked for sharing. The environment
+ # variable prevents share(1M) from checking whether each filesystem
+ # is in use, an O(n^2) operation with no purpose at this time
+
+ if [ -x /usr/sbin/zfs ]; then
+ SHARE_NOINUSE_CHECK=1; export SHARE_NOINUSE_CHECK
+ /usr/sbin/zfs share -a
+ unset SHARE_NOINUSE_CHECK
+ fi
+
# If /etc/dfs/dfstab exists and has non-blank or non-commented-out
# lines, then run shareall to export them.
@@ -51,11 +61,6 @@
/usr/sbin/shareall -F nfs
fi
- # Share any ZFS filesystems marked for sharing.
-
- if [ -x /usr/sbin/zfs ]; then
- /usr/sbin/zfs share -a
- fi
# Start up mountd and nfsd if anything is exported.
--- a/usr/src/cmd/zfs/zfs_iter.c Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/cmd/zfs/zfs_iter.c Mon Jan 30 22:19:55 2006 -0800
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -91,11 +91,11 @@
}
/*
- * If 'recurse' is set, and the datasets can have datasets of the
- * appropriate type, then recurse over its children.
+ * Recurse if necessary.
*/
if (cb->cb_recurse && (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM ||
- (cb->cb_types & ZFS_TYPE_SNAPSHOT)))
+ (zfs_get_type(zhp) == ZFS_TYPE_VOLUME && (cb->cb_types &
+ ZFS_TYPE_SNAPSHOT))))
(void) zfs_iter_children(zhp, zfs_callback, data);
if (!dontclose)
--- a/usr/src/cmd/zfs/zfs_main.c Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/cmd/zfs/zfs_main.c Mon Jan 30 22:19:55 2006 -0800
@@ -1770,6 +1770,75 @@
return (err != 0);
}
+typedef struct get_all_cbdata {
+ zfs_handle_t **cb_handles;
+ size_t cb_alloc;
+ size_t cb_used;
+} get_all_cbdata_t;
+
+static int
+get_one_filesystem(zfs_handle_t *zhp, void *data)
+{
+ get_all_cbdata_t *cbp = data;
+
+ /*
+ * Skip any zvols
+ */
+ if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
+ zfs_close(zhp);
+ return (0);
+ }
+
+ if (cbp->cb_alloc == cbp->cb_used) {
+ zfs_handle_t **handles;
+
+ if (cbp->cb_alloc == 0)
+ cbp->cb_alloc = 64;
+ else
+ cbp->cb_alloc *= 2;
+
+ handles = safe_malloc(cbp->cb_alloc * sizeof (void *));
+
+ if (cbp->cb_handles) {
+ bcopy(cbp->cb_handles, handles,
+ cbp->cb_used * sizeof (void *));
+ free(cbp->cb_handles);
+ }
+
+ cbp->cb_handles = handles;
+ }
+
+ cbp->cb_handles[cbp->cb_used++] = zhp;
+
+ return (zfs_iter_filesystems(zhp, get_one_filesystem, data));
+}
+
+static void
+get_all_filesystems(zfs_handle_t ***fslist, size_t *count)
+{
+ get_all_cbdata_t cb = { 0 };
+
+ (void) zfs_iter_root(get_one_filesystem, &cb);
+
+ *fslist = cb.cb_handles;
+ *count = cb.cb_used;
+}
+
+static int
+mountpoint_compare(const void *a, const void *b)
+{
+ zfs_handle_t **za = (zfs_handle_t **)a;
+ zfs_handle_t **zb = (zfs_handle_t **)b;
+ char mounta[MAXPATHLEN];
+ char mountb[MAXPATHLEN];
+
+ verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta,
+ sizeof (mounta), NULL, NULL, 0, FALSE) == 0);
+ verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb,
+ sizeof (mountb), NULL, NULL, 0, FALSE) == 0);
+
+ return (strcmp(mounta, mountb));
+}
/*
* Generic callback for sharing or mounting filesystems. Because the code is so
@@ -1975,13 +2044,30 @@
/* check number of arguments */
if (do_all) {
+ zfs_handle_t **fslist = NULL;
+ size_t i, count = 0;
+
if (argc != 0) {
(void) fprintf(stderr, gettext("too many arguments\n"));
usage(FALSE);
}
- ret = zfs_for_each(argc, argv, TRUE,
- ZFS_TYPE_FILESYSTEM, share_mount_callback, &cb);
+ get_all_filesystems(&fslist, &count);
+
+ if (count == 0)
+ return (0);
+
+ qsort(fslist, count, sizeof (void *), mountpoint_compare);
+
+ for (i = 0; i < count; i++) {
+ if ((ret = share_mount_callback(fslist[i], &cb)) != 0)
+ break;
+ }
+
+ for (i = 0; i < count; i++)
+ zfs_close(fslist[i]);
+
+ free(fslist);
} else if (argc == 0) {
struct mnttab entry;
--- a/usr/src/common/zfs/zfs_prop.c Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/common/zfs/zfs_prop.c Mon Jan 30 22:19:55 2006 -0800
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -212,10 +212,10 @@
/*
* Return the default value for the given property.
*/
-void
-zfs_prop_default_string(zfs_prop_t prop, char *buf, size_t buflen)
+const char *
+zfs_prop_default_string(zfs_prop_t prop)
{
- (void) strncpy(buf, zfs_prop_table[prop].pd_strdefault, buflen);
+ return (zfs_prop_table[prop].pd_strdefault);
}
uint64_t
--- a/usr/src/lib/libzfs/common/libzfs.h Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/lib/libzfs/common/libzfs.h Mon Jan 30 22:19:55 2006 -0800
@@ -183,7 +183,7 @@
int zfs_prop_inherit(zfs_handle_t *, zfs_prop_t);
const char *zfs_prop_values(zfs_prop_t);
int zfs_prop_valid_for_type(zfs_prop_t, int);
-void zfs_prop_default_string(zfs_prop_t prop, char *buf, size_t buflen);
+const char *zfs_prop_default_string(zfs_prop_t prop);
uint64_t zfs_prop_default_numeric(zfs_prop_t);
int zfs_prop_is_string(zfs_prop_t prop);
const char *zfs_prop_column_name(zfs_prop_t);
@@ -201,6 +201,8 @@
extern int zfs_iter_root(zfs_iter_f, void *);
extern int zfs_iter_children(zfs_handle_t *, zfs_iter_f, void *);
extern int zfs_iter_dependents(zfs_handle_t *, zfs_iter_f, void *);
+extern int zfs_iter_filesystems(zfs_handle_t *, zfs_iter_f, void *);
+extern int zfs_iter_snapshots(zfs_handle_t *, zfs_iter_f, void *);
/*
* Functions to create and destroy datasets.
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c Mon Jan 30 22:19:55 2006 -0800
@@ -190,16 +190,24 @@
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
- /*
- * get the generic DMU stats and per-type (zfs, zvol) stats
- */
- if (ioctl(zfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0)
- return (-1);
+ zc.zc_config_src = (uint64_t)(uintptr_t)zfs_malloc(1024);
+ zc.zc_config_src_size = 1024;
+
+ while (ioctl(zfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) {
+ if (errno == ENOMEM) {
+ zc.zc_config_src = (uint64_t)(uintptr_t)
+ zfs_malloc(zc.zc_config_src_size);
+ } else {
+ free((void *)(uintptr_t)zc.zc_config_src);
+ return (-1);
+ }
+ }
bcopy(&zc.zc_objset_stats, &zhp->zfs_dmustats,
sizeof (zc.zc_objset_stats));
- bcopy(&zc.zc_zfs_stats, &zhp->zfs_zplstats, sizeof (zc.zc_zfs_stats));
+ verify(nvlist_unpack((void *)(uintptr_t)zc.zc_config_src,
+ zc.zc_config_src_size, &zhp->zfs_props, 0) == 0);
zhp->zfs_volsize = zc.zc_volsize;
zhp->zfs_volblocksize = zc.zc_volblocksize;
@@ -1041,6 +1049,47 @@
}
/*
+ * True DSL properties are stored in an nvlist. The following two functions
+ * extract them appropriately.
+ */
+static uint64_t
+getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
+{
+ nvlist_t *nv;
+ uint64_t value;
+
+ if (nvlist_lookup_nvlist(zhp->zfs_props,
+ zfs_prop_to_name(prop), &nv) == 0) {
+ verify(nvlist_lookup_uint64(nv, ZFS_PROP_VALUE, &value) == 0);
+ verify(nvlist_lookup_string(nv, ZFS_PROP_SOURCE, source) == 0);
+ } else {
+ value = zfs_prop_default_numeric(prop);
+ *source = "";
+ }
+
+ return (value);
+}
+
+static char *
+getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
+{
+ nvlist_t *nv;
+ char *value;
+
+ if (nvlist_lookup_nvlist(zhp->zfs_props,
+ zfs_prop_to_name(prop), &nv) == 0) {
+ verify(nvlist_lookup_string(nv, ZFS_PROP_VALUE, &value) == 0);
+ verify(nvlist_lookup_string(nv, ZFS_PROP_SOURCE, source) == 0);
+ } else {
+ if ((value = (char *)zfs_prop_default_string(prop)) == NULL)
+ value = "";
+ *source = "";
+ }
+
+ return (value);
+}
+
+/*
* Internal function for getting a numeric property. Both zfs_prop_get() and
* zfs_prop_get_int() are built using this interface.
*
@@ -1065,8 +1114,7 @@
switch (prop) {
case ZFS_PROP_ATIME:
- *source = zhp->zfs_zplstats.zs_atime_setpoint;
- val = zhp->zfs_zplstats.zs_devices;
+ val = getprop_uint64(zhp, prop, source);
if (hasmntopt(&mnt, MNTOPT_ATIME) && !val) {
val = TRUE;
@@ -1077,14 +1125,13 @@
if (src)
*src = ZFS_SRC_TEMPORARY;
}
- return (zhp->zfs_zplstats.zs_atime);
+ return (val);
case ZFS_PROP_AVAILABLE:
return (zhp->zfs_dmustats.dds_available);
case ZFS_PROP_DEVICES:
- *source = zhp->zfs_zplstats.zs_devices_setpoint;
- val = zhp->zfs_zplstats.zs_devices;
+ val = getprop_uint64(zhp, prop, source);
if (hasmntopt(&mnt, MNTOPT_DEVICES) && !val) {
val = TRUE;
@@ -1098,8 +1145,7 @@
return (val);
case ZFS_PROP_EXEC:
- *source = zhp->zfs_zplstats.zs_exec_setpoint;
- val = zhp->zfs_zplstats.zs_exec;
+ val = getprop_uint64(zhp, prop, source);
if (hasmntopt(&mnt, MNTOPT_EXEC) && !val) {
val = TRUE;
@@ -1113,16 +1159,13 @@
return (val);
case ZFS_PROP_RECORDSIZE:
- *source = zhp->zfs_zplstats.zs_recordsize_setpoint;
- return (zhp->zfs_zplstats.zs_recordsize);
-
case ZFS_PROP_COMPRESSION:
- *source = zhp->zfs_dmustats.dds_compression_setpoint;
- return (zhp->zfs_dmustats.dds_compression);
+ case ZFS_PROP_ZONED:
+ val = getprop_uint64(zhp, prop, source);
+ return (val);
case ZFS_PROP_READONLY:
- *source = zhp->zfs_zplstats.zs_readonly_setpoint;
- val = zhp->zfs_zplstats.zs_readonly;
+ val = getprop_uint64(zhp, prop, source);
if (hasmntopt(&mnt, MNTOPT_RO) && !val) {
val = TRUE;
@@ -1169,8 +1212,7 @@
return (zhp->zfs_dmustats.dds_space_refd);
case ZFS_PROP_SETUID:
- *source = zhp->zfs_zplstats.zs_setuid_setpoint;
- val = zhp->zfs_zplstats.zs_setuid;
+ val = getprop_uint64(zhp, prop, source);
if (hasmntopt(&mnt, MNTOPT_SETUID) && !val) {
val = TRUE;
@@ -1189,10 +1231,6 @@
case ZFS_PROP_VOLBLOCKSIZE:
return (zhp->zfs_volblocksize);
- case ZFS_PROP_ZONED:
- *source = zhp->zfs_dmustats.dds_zoned_setpoint;
- return (zhp->zfs_dmustats.dds_zoned);
-
case ZFS_PROP_USED:
return (zhp->zfs_dmustats.dds_space_used);
@@ -1312,58 +1350,53 @@
break;
case ZFS_PROP_COMPRESSION:
+ val = getprop_uint64(zhp, prop, &source);
for (i = 0; compress_table[i].name != NULL; i++) {
- if (compress_table[i].value ==
- zhp->zfs_dmustats.dds_compression)
+ if (compress_table[i].value == val)
break;
}
assert(compress_table[i].name != NULL);
(void) strlcpy(propbuf, compress_table[i].name, proplen);
- source = zhp->zfs_dmustats.dds_compression_setpoint;
break;
case ZFS_PROP_CHECKSUM:
+ val = getprop_uint64(zhp, prop, &source);
for (i = 0; checksum_table[i].name != NULL; i++) {
- if (checksum_table[i].value ==
- zhp->zfs_dmustats.dds_checksum)
+ if (checksum_table[i].value == val)
break;
}
assert(checksum_table[i].name != NULL);
(void) strlcpy(propbuf, checksum_table[i].name, proplen);
- source = zhp->zfs_dmustats.dds_checksum_setpoint;
break;
case ZFS_PROP_SNAPDIR:
+ val = getprop_uint64(zhp, prop, &source);
for (i = 0; snapdir_table[i].name != NULL; i++) {
- if (snapdir_table[i].value ==
- zhp->zfs_zplstats.zs_snapdir)
+ if (snapdir_table[i].value == val)
break;
}
assert(snapdir_table[i].name != NULL);
(void) strlcpy(propbuf, snapdir_table[i].name, proplen);
- source = zhp->zfs_zplstats.zs_snapdir_setpoint;
break;
case ZFS_PROP_ACLMODE:
+ val = getprop_uint64(zhp, prop, &source);
for (i = 0; acl_mode_table[i].name != NULL; i++) {
- if (acl_mode_table[i].value ==
- zhp->zfs_zplstats.zs_acl_mode)
+ if (acl_mode_table[i].value == val)
break;
}
assert(acl_mode_table[i].name != NULL);
(void) strlcpy(propbuf, acl_mode_table[i].name, proplen);
- source = zhp->zfs_zplstats.zs_acl_mode_setpoint;
break;
case ZFS_PROP_ACLINHERIT:
+ val = getprop_uint64(zhp, prop, &source);
for (i = 0; acl_inherit_table[i].name != NULL; i++) {
- if (acl_inherit_table[i].value ==
- zhp->zfs_zplstats.zs_acl_inherit)
+ if (acl_inherit_table[i].value == val)
break;
}
assert(acl_inherit_table[i].name != NULL);
(void) strlcpy(propbuf, acl_inherit_table[i].name, proplen);
- source = zhp->zfs_zplstats.zs_acl_inherit_setpoint;
break;
case ZFS_PROP_CREATION:
@@ -1398,44 +1431,40 @@
* root to any values we return.
*/
root = zhp->zfs_dmustats.dds_altroot;
-
- if (zhp->zfs_zplstats.zs_mountpoint[0] == '\0') {
+ str = getprop_string(zhp, prop, &source);
+
+ if (str[0] == '\0') {
(void) snprintf(propbuf, proplen, "%s/zfs/%s",
root, zhp->zfs_name);
- } else if (zhp->zfs_zplstats.zs_mountpoint[0] == '/') {
- const char *relpath = zhp->zfs_name +
- strlen(zhp->zfs_zplstats.zs_mountpoint_setpoint);
- const char *mntpoint = zhp->zfs_zplstats.zs_mountpoint;
+ } else if (str[0] == '/') {
+ const char *relpath = zhp->zfs_name + strlen(source);
if (relpath[0] == '/')
relpath++;
- if (mntpoint[1] == '\0')
- mntpoint++;
+ if (str[1] == '\0')
+ str++;
if (relpath[0] == '\0')
(void) snprintf(propbuf, proplen, "%s%s",
- root, mntpoint);
+ root, str);
else
(void) snprintf(propbuf, proplen, "%s%s%s%s",
- root, mntpoint,
- relpath[0] == '@' ? "" : "/",
+ root, str, relpath[0] == '@' ? "" : "/",
relpath);
} else {
/* 'legacy' or 'none' */
- (void) strlcpy(propbuf, zhp->zfs_zplstats.zs_mountpoint,
- proplen);
+ (void) strlcpy(propbuf, str, proplen);
}
- source = zhp->zfs_zplstats.zs_mountpoint_setpoint;
break;
case ZFS_PROP_SHARENFS:
- (void) strlcpy(propbuf, zhp->zfs_zplstats.zs_sharenfs, proplen);
- source = zhp->zfs_zplstats.zs_sharenfs_setpoint;
+ (void) strlcpy(propbuf, getprop_string(zhp, prop, &source),
+ proplen);
break;
case ZFS_PROP_ORIGIN:
- (void) strlcpy(propbuf, zhp->zfs_dmustats.dds_clone_of,
+ (void) strlcpy(propbuf, getprop_string(zhp, prop, &source),
proplen);
/*
* If there is no parent at all, return failure to indicate that
@@ -1580,10 +1609,10 @@
}
/*
- * Iterate over all children, datasets and snapshots.
+ * Iterate over all child filesystems
*/
int
-zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data)
+zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
zfs_cmd_t zc = { 0 };
zfs_handle_t *nzhp;
@@ -1617,7 +1646,18 @@
if (errno != ESRCH && errno != ENOENT)
zfs_baderror(errno);
- bzero(&zc, sizeof (zc));
+ return (0);
+}
+
+/*
+ * Iterate over all snapshots
+ */
+int
+zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data)
+{
+ zfs_cmd_t zc = { 0 };
+ zfs_handle_t *nzhp;
+ int ret;
for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
ioctl(zfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT, &zc) == 0;
@@ -1642,6 +1682,20 @@
}
/*
+ * Iterate over all children, snapshots and filesystems
+ */
+int
+zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data)
+{
+ int ret;
+
+ if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0)
+ return (ret);
+
+ return (zfs_iter_snapshots(zhp, func, data));
+}
+
+/*
* Given a complete name, return just the portion that refers to the parent.
* Can return NULL if this is a pool.
*/
@@ -1668,6 +1722,7 @@
zfs_cmd_t zc = { 0 };
char parent[ZFS_MAXNAMELEN];
char *slash;
+ zfs_handle_t *zhp;
/* get parent, and check to see if this is just a pool */
if (parent_name(path, parent, sizeof (parent)) != 0) {
@@ -1692,8 +1747,7 @@
}
/* check to see if the parent dataset exists */
- (void) strlcpy(zc.zc_name, parent, sizeof (zc.zc_name));
- if (ioctl(zfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) {
+ if ((zhp = make_dataset_handle(parent)) == NULL) {
switch (errno) {
case ENOENT:
zfs_error(dgettext(TEXT_DOMAIN,
@@ -1706,20 +1760,24 @@
}
/* we are in a non-global zone, but parent is in the global zone */
- if (getzoneid() != GLOBAL_ZONEID && !zc.zc_objset_stats.dds_zoned) {
+ if (getzoneid() != GLOBAL_ZONEID &&
+ zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
zfs_error(dgettext(TEXT_DOMAIN,
"cannot create '%s': permission denied"), path);
+ zfs_close(zhp);
return (-1);
}
/* make sure parent is a filesystem */
- if (zc.zc_objset_stats.dds_type != DMU_OST_ZFS) {
+ if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
zfs_error(dgettext(TEXT_DOMAIN,
"cannot create '%s': parent is not a filesystem"),
path);
+ zfs_close(zhp);
return (-1);
}
+ zfs_close(zhp);
return (0);
}
--- a/usr/src/lib/libzfs/common/libzfs_impl.h Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/lib/libzfs/common/libzfs_impl.h Mon Jan 30 22:19:55 2006 -0800
@@ -45,7 +45,7 @@
char zfs_name[ZFS_MAXNAMELEN];
zfs_type_t zfs_type;
dmu_objset_stats_t zfs_dmustats;
- zfs_stats_t zfs_zplstats;
+ nvlist_t *zfs_props;
uint64_t zfs_volsize;
uint64_t zfs_volblocksize;
char *zfs_mntopts;
--- a/usr/src/lib/libzfs/spec/libzfs.spec Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/lib/libzfs/spec/libzfs.spec Mon Jan 30 22:19:55 2006 -0800
@@ -80,10 +80,18 @@
version SUNWprivate_1.1
end
+function zfs_iter_filesystems
+version SUNWprivate_1.1
+end
+
function zfs_iter_root
version SUNWprivate_1.1
end
+function zfs_iter_snapshots
+version SUNWprivate_1.1
+end
+
function zfs_mount
version SUNWprivate_1.1
end
--- a/usr/src/lib/libzfs_jni/common/libzfs_jni_property.c Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/lib/libzfs_jni/common/libzfs_jni_property.c Mon Jan 30 22:19:55 2006 -0800
@@ -333,9 +333,7 @@
jobject propValue;
if (convert_str != NULL) {
- char propbuf[ZFS_MAXPROPLEN];
- zfs_prop_default_string(
- prop, propbuf, sizeof (propbuf));
+ char *propbuf = (char *)zfs_prop_default_string(prop);
propValue = convert_str(env, propbuf);
} else {
uint64_t value = zfs_prop_default_numeric(prop);
@@ -406,9 +404,7 @@
jobject propValue;
if (convert_str != NULL) {
- char propbuf[ZFS_MAXPROPLEN];
- zfs_prop_default_string(
- prop, propbuf, sizeof (propbuf));
+ char *propbuf = (char *)zfs_prop_default_string(prop);
propValue = convert_str(env, propbuf);
} else {
uint64_t value = zfs_prop_default_numeric(prop);
--- a/usr/src/uts/common/fs/zfs/dsl_dir.c Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/uts/common/fs/zfs/dsl_dir.c Mon Jan 30 22:19:55 2006 -0800
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -557,15 +557,6 @@
rw_exit(&dd->dd_pool->dp_config_rwlock);
}
- VERIFY(dsl_prop_get_ds_integer(dd, "checksum",
- &dds->dds_checksum, dds->dds_checksum_setpoint) == 0);
-
- VERIFY(dsl_prop_get_ds_integer(dd, "compression",
- &dds->dds_compression, dds->dds_compression_setpoint) == 0);
-
- VERIFY(dsl_prop_get_ds_integer(dd, "zoned",
- &dds->dds_zoned, dds->dds_zoned_setpoint) == 0);
-
spa_altroot(dd->dd_pool->dp_spa, dds->dds_altroot,
sizeof (dds->dds_altroot));
}
--- a/usr/src/uts/common/fs/zfs/dsl_prop.c Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/uts/common/fs/zfs/dsl_prop.c Mon Jan 30 22:19:55 2006 -0800
@@ -20,13 +20,14 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/dmu.h>
+#include <sys/dmu_objset.h>
#include <sys/dmu_tx.h>
#include <sys/dsl_dataset.h>
#include <sys/dsl_dir.h>
@@ -50,7 +51,7 @@
if (zfs_prop_get_type(prop) == prop_type_string) {
if (intsz != 1)
return (EOVERFLOW);
- zfs_prop_default_string(prop, buf, numint);
+ (void) strncpy(buf, zfs_prop_default_string(prop), numint);
} else {
if (intsz != 8 || numint < 1)
return (EOVERFLOW);
@@ -366,3 +367,103 @@
return (err);
}
+
+/*
+ * Iterate over all properties for this dataset and return them in an nvlist.
+ */
+int
+dsl_prop_get_all(objset_t *os, nvlist_t **nvp)
+{
+ dsl_dataset_t *ds = os->os->os_dsl_dataset;
+ dsl_dir_t *dd, *parent;
+ int err = 0;
+ dsl_pool_t *dp;
+ objset_t *mos;
+ zap_cursor_t zc;
+ zap_attribute_t za;
+ char setpoint[MAXNAMELEN];
+ char *tmp;
+ nvlist_t *prop;
+
+ if (dsl_dataset_is_snapshot(ds)) {
+ VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
+ return (0);
+ }
+
+ dd = ds->ds_dir;
+
+ VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
+
+ dp = dd->dd_pool;
+ mos = dp->dp_meta_objset;
+
+ rw_enter(&dp->dp_config_rwlock, RW_READER);
+ while (dd != NULL) {
+ dsl_dir_name(dd, setpoint);
+
+ 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)
+ continue;
+
+ VERIFY(nvlist_alloc(&prop, NV_UNIQUE_NAME,
+ KM_SLEEP) == 0);
+ if (za.za_integer_length == 1) {
+ /*
+ * String property
+ */
+
+ tmp = kmem_alloc(za.za_num_integers, KM_SLEEP);
+ err = zap_lookup(mos,
+ dd->dd_phys->dd_props_zapobj,
+ za.za_name, 1, za.za_num_integers,
+ tmp);
+ if (err != 0) {
+ kmem_free(tmp, za.za_num_integers);
+ break;
+ }
+ VERIFY(nvlist_add_string(prop,
+ ZFS_PROP_VALUE, tmp) == 0);
+ kmem_free(tmp, za.za_num_integers);
+ } else {
+ /*
+ * Integer property
+ */
+ ASSERT(za.za_integer_length == 8);
+ (void) nvlist_add_uint64(prop, ZFS_PROP_VALUE,
+ za.za_first_integer);
+ }
+
+ VERIFY(nvlist_add_string(prop,
+ ZFS_PROP_SOURCE, setpoint) == 0);
+ VERIFY(nvlist_add_nvlist(*nvp, za.za_name,
+ prop) == 0);
+ nvlist_free(prop);
+ }
+ zap_cursor_fini(&zc);
+
+ if (err != ENOENT) {
+ if (dd != ds->ds_dir)
+ dsl_dir_close(dd, FTAG);
+ break;
+ } else {
+ err = 0;
+ }
+
+ /*
+ * Continue to parent.
+ */
+ if (dd->dd_phys->dd_parent_obj == 0)
+ parent = NULL;
+ else
+ parent = dsl_dir_open_obj(dp,
+ dd->dd_phys->dd_parent_obj, NULL, FTAG);
+ if (dd != ds->ds_dir)
+ dsl_dir_close(dd, FTAG);
+ dd = parent;
+ }
+ rw_exit(&dp->dp_config_rwlock);
+
+ return (err);
+}
--- a/usr/src/uts/common/fs/zfs/sys/dmu.h Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/dmu.h Mon Jan 30 22:19:55 2006 -0800
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -553,14 +553,8 @@
uint64_t dds_available;
/*
- * Various properties.
+ * Miscellaneous
*/
- uint64_t dds_compression;
- uint64_t dds_checksum;
- uint64_t dds_zoned;
- char dds_compression_setpoint[MAXNAMELEN];
- char dds_checksum_setpoint[MAXNAMELEN];
- char dds_zoned_setpoint[MAXNAMELEN];
char dds_altroot[MAXPATHLEN];
/* The following are for debugging purposes only */
--- a/usr/src/uts/common/fs/zfs/sys/dsl_prop.h Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/dsl_prop.h Mon Jan 30 22:19:55 2006 -0800
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -64,6 +64,7 @@
uint64_t *valuep, char *setpoint);
int dsl_prop_get_ds_integer(dsl_dir_t *dd, const char *propname,
uint64_t *valuep, char *setpoint);
+int dsl_prop_get_all(objset_t *os, nvlist_t **nvp);
int dsl_prop_set(const char *ddname, const char *propname,
int intsz, int numints, const void *buf);
--- a/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_ioctl.h Mon Jan 30 22:19:55 2006 -0800
@@ -42,31 +42,6 @@
#define ZFS_SNAPDIR_HIDDEN 0
#define ZFS_SNAPDIR_VISIBLE 1
-typedef struct zfs_stats {
- uint64_t zs_atime;
- uint64_t zs_recordsize;
- uint64_t zs_readonly;
- uint64_t zs_devices;
- uint64_t zs_exec;
- uint64_t zs_setuid;
- uint64_t zs_snapdir;
- uint64_t zs_acl_mode;
- uint64_t zs_acl_inherit;
- char zs_mountpoint[MAXPATHLEN];
- char zs_atime_setpoint[MAXNAMELEN];
- char zs_recordsize_setpoint[MAXNAMELEN];
- char zs_readonly_setpoint[MAXNAMELEN];
- char zs_devices_setpoint[MAXNAMELEN];
- char zs_setuid_setpoint[MAXNAMELEN];
- char zs_exec_setpoint[MAXNAMELEN];
- char zs_mountpoint_setpoint[MAXNAMELEN];
- char zs_sharenfs[MAXPATHLEN];
- char zs_sharenfs_setpoint[MAXNAMELEN];
- char zs_snapdir_setpoint[MAXNAMELEN];
- char zs_acl_mode_setpoint[MAXNAMELEN];
- char zs_acl_inherit_setpoint[MAXNAMELEN];
-} zfs_stats_t;
-
#define DMU_BACKUP_VERSION (1ULL)
#define DMU_BACKUP_MAGIC 0x2F5bacbacULL
@@ -141,7 +116,6 @@
uint64_t zc_volsize;
uint64_t zc_volblocksize;
uint64_t zc_objset_type;
- zfs_stats_t zc_zfs_stats;
dmu_object_info_t zc_object_info;
dmu_objset_stats_t zc_objset_stats;
struct drr_begin zc_begin_record;
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c Mon Jan 30 22:19:55 2006 -0800
@@ -640,46 +640,13 @@
static int
-zfs_get_stats(zfs_cmd_t *zc)
-{
- char *name = zc->zc_name;
- zfs_stats_t *zs = &zc->zc_zfs_stats;
- int error;
-
- bzero(zs, sizeof (zfs_stats_t));
-
- if ((error = dsl_prop_get_integer(name, "atime",
- &zs->zs_atime, zs->zs_atime_setpoint)) != 0 ||
- (error = dsl_prop_get_integer(name, "recordsize",
- &zs->zs_recordsize, zs->zs_recordsize_setpoint)) != 0 ||
- (error = dsl_prop_get_integer(name, "readonly",
- &zs->zs_readonly, zs->zs_readonly_setpoint)) != 0 ||
- (error = dsl_prop_get_integer(name, "devices",
- &zs->zs_devices, zs->zs_devices_setpoint)) != 0 ||
- (error = dsl_prop_get_integer(name, "setuid",
- &zs->zs_setuid, zs->zs_setuid_setpoint)) != 0 ||
- (error = dsl_prop_get_integer(name, "exec",
- &zs->zs_exec, zs->zs_exec_setpoint)) != 0 ||
- (error = dsl_prop_get_string(name, "mountpoint", zs->zs_mountpoint,
- sizeof (zs->zs_mountpoint), zs->zs_mountpoint_setpoint)) != 0 ||
- (error = dsl_prop_get_string(name, "sharenfs", zs->zs_sharenfs,
- sizeof (zs->zs_sharenfs), zs->zs_sharenfs_setpoint)) != 0 ||
- (error = dsl_prop_get_integer(name, "aclmode",
- &zs->zs_acl_mode, zs->zs_acl_mode_setpoint)) != 0 ||
- (error = dsl_prop_get_integer(name, "snapdir",
- &zs->zs_snapdir, zs->zs_snapdir_setpoint)) != 0 ||
- (error = dsl_prop_get_integer(name, "aclinherit",
- &zs->zs_acl_inherit, zs->zs_acl_inherit_setpoint)) != 0)
- return (error);
-
- return (0);
-}
-
-static int
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,
@@ -701,16 +668,25 @@
dmu_objset_stats(os, &zc->zc_objset_stats);
- switch (zc->zc_objset_stats.dds_type) {
+ if (zc->zc_config_src != 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);
+ }
+ nvlist_free(nv);
+ }
- case DMU_OST_ZFS:
- error = zfs_get_stats(zc);
- break;
-
- case DMU_OST_ZVOL:
+ if (!error && zc->zc_objset_stats.dds_type == DMU_OST_ZVOL)
error = zvol_get_stats(zc, os);
- break;
- }
dmu_objset_close(os);
return (error);
--- a/usr/src/uts/common/fs/zfs/zvol.c Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/uts/common/fs/zfs/zvol.c Mon Jan 30 22:19:55 2006 -0800
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -165,10 +165,6 @@
if (error == 0)
zc->zc_volblocksize = doi.doi_data_block_size;
- error = dsl_prop_get_integer(zc->zc_name, "readonly",
- &zc->zc_zfs_stats.zs_readonly,
- zc->zc_zfs_stats.zs_readonly_setpoint);
-
return (error);
}
--- a/usr/src/uts/common/sys/fs/zfs.h Mon Jan 30 21:43:33 2006 -0800
+++ b/usr/src/uts/common/sys/fs/zfs.h Mon Jan 30 22:19:55 2006 -0800
@@ -96,12 +96,15 @@
#define ZFS_NPROP_VISIBLE ZFS_PROP_CREATETXG
+#define ZFS_PROP_VALUE "value"
+#define ZFS_PROP_SOURCE "source"
+
/*
* The following functions are shared between libzfs and the kernel.
*/
zfs_prop_t zfs_name_to_prop(const char *);
int zfs_prop_readonly(zfs_prop_t);
-void zfs_prop_default_string(zfs_prop_t, char *, size_t);
+const char *zfs_prop_default_string(zfs_prop_t);
uint64_t zfs_prop_default_numeric(zfs_prop_t);
/*