summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/zdb/zdb.c46
-rw-r--r--usr/src/cmd/zfs/zfs_main.c213
-rw-r--r--usr/src/cmd/zpool/zpool_main.c17
-rw-r--r--usr/src/common/zfs/zfs_deleg.c1
-rw-r--r--usr/src/common/zfs/zfs_prop.c16
-rw-r--r--usr/src/grub/grub-0.95/stage2/fsys_zfs.c21
-rw-r--r--usr/src/grub/grub-0.95/stage2/zfs-include/zfs.h18
-rw-r--r--usr/src/grub/grub-0.95/stage2/zfs-include/zfs_znode.h5
-rw-r--r--usr/src/lib/libzfs/common/libzfs.h2
-rw-r--r--usr/src/lib/libzfs/common/libzfs_changelist.c6
-rw-r--r--usr/src/lib/libzfs/common/libzfs_dataset.c144
-rw-r--r--usr/src/lib/libzfs/common/libzfs_import.c8
-rw-r--r--usr/src/lib/libzfs/common/libzfs_pool.c8
-rw-r--r--usr/src/lib/libzfs/common/libzfs_status.c2
-rw-r--r--usr/src/lib/libzfs/common/mapfile-vers1
-rw-r--r--usr/src/uts/common/fs/zfs/bplist.c4
-rw-r--r--usr/src/uts/common/fs/zfs/dnode.c2
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_dataset.c2
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_dir.c8
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_synctask.c30
-rw-r--r--usr/src/uts/common/fs/zfs/spa.c22
-rw-r--r--usr/src/uts/common/fs/zfs/spa_history.c33
-rw-r--r--usr/src/uts/common/fs/zfs/spa_misc.c4
-rw-r--r--usr/src/uts/common/fs/zfs/sys/dsl_deleg.h1
-rw-r--r--usr/src/uts/common/fs/zfs/sys/dsl_synctask.h7
-rw-r--r--usr/src/uts/common/fs/zfs/sys/uberblock_impl.h4
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zap.h10
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h1
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zfs_znode.h26
-rw-r--r--usr/src/uts/common/fs/zfs/vdev.c6
-rw-r--r--usr/src/uts/common/fs/zfs/vdev_label.c3
-rw-r--r--usr/src/uts/common/fs/zfs/zap.c10
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_dir.c14
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_ioctl.c167
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vfsops.c99
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_znode.c19
-rw-r--r--usr/src/uts/common/sys/fs/zfs.h70
37 files changed, 749 insertions, 301 deletions
diff --git a/usr/src/cmd/zdb/zdb.c b/usr/src/cmd/zdb/zdb.c
index 23cf656ebe..b4294270c8 100644
--- a/usr/src/cmd/zdb/zdb.c
+++ b/usr/src/cmd/zdb/zdb.c
@@ -367,6 +367,44 @@ dump_zap(objset_t *os, uint64_t object, void *data, size_t size)
zap_cursor_fini(&zc);
}
+/*ARGSUSED*/
+static void
+dump_zpldir(objset_t *os, uint64_t object, void *data, size_t size)
+{
+ zap_cursor_t zc;
+ zap_attribute_t attr;
+ const char *typenames[] = {
+ /* 0 */ "not specified",
+ /* 1 */ "FIFO",
+ /* 2 */ "Character Device",
+ /* 3 */ "3 (invalid)",
+ /* 4 */ "Directory",
+ /* 5 */ "5 (invalid)",
+ /* 6 */ "Block Device",
+ /* 7 */ "7 (invalid)",
+ /* 8 */ "Regular File",
+ /* 9 */ "9 (invalid)",
+ /* 10 */ "Symbolic Link",
+ /* 11 */ "11 (invalid)",
+ /* 12 */ "Socket",
+ /* 13 */ "Door",
+ /* 14 */ "Event Port",
+ /* 15 */ "15 (invalid)",
+ };
+
+ dump_zap_stats(os, object);
+ (void) printf("\n");
+
+ for (zap_cursor_init(&zc, os, object);
+ zap_cursor_retrieve(&zc, &attr) == 0;
+ zap_cursor_advance(&zc)) {
+ (void) printf("\t\t%s = %lld (type: %s)\n",
+ attr.za_name, ZFS_DIRENT_OBJ(attr.za_first_integer),
+ typenames[ZFS_DIRENT_TYPE(attr.za_first_integer)]);
+ }
+ zap_cursor_fini(&zc);
+}
+
static void
dump_spacemap(objset_t *os, space_map_obj_t *smo, space_map_t *sm)
{
@@ -878,7 +916,7 @@ static object_viewer_t *object_viewer[DMU_OT_NUMTYPES] = {
dump_znode, /* ZFS znode */
dump_acl, /* ZFS ACL */
dump_uint8, /* ZFS plain file */
- dump_zap, /* ZFS directory */
+ dump_zpldir, /* ZFS directory */
dump_zap, /* ZFS master node */
dump_zap, /* ZFS delete queue */
dump_uint8, /* zvol object */
@@ -933,13 +971,15 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
aux[0] = '\0';
- if (doi.doi_checksum != ZIO_CHECKSUM_INHERIT || verbosity >= 6)
+ if (doi.doi_checksum != ZIO_CHECKSUM_INHERIT || verbosity >= 6) {
(void) snprintf(aux + strlen(aux), sizeof (aux), " (K=%s)",
zio_checksum_table[doi.doi_checksum].ci_name);
+ }
- if (doi.doi_compress != ZIO_COMPRESS_INHERIT || verbosity >= 6)
+ if (doi.doi_compress != ZIO_COMPRESS_INHERIT || verbosity >= 6) {
(void) snprintf(aux + strlen(aux), sizeof (aux), " (Z=%s)",
zio_compress_table[doi.doi_compress].ci_name);
+ }
(void) printf("%10lld %3u %5s %5s %5s %5s %s%s\n",
(u_longlong_t)object, doi.doi_indirection, iblk, dblk, lsize,
diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c
index fd178add9e..b5a18a0e9a 100644
--- a/usr/src/cmd/zfs/zfs_main.c
+++ b/usr/src/cmd/zfs/zfs_main.c
@@ -57,6 +57,8 @@
libzfs_handle_t *g_zfs;
static FILE *mnttab_file;
+static int first_argc;
+static char **first_argv;
static int zfs_do_clone(int argc, char **argv);
static int zfs_do_create(int argc, char **argv);
@@ -68,6 +70,7 @@ static int zfs_do_mount(int argc, char **argv);
static int zfs_do_rename(int argc, char **argv);
static int zfs_do_rollback(int argc, char **argv);
static int zfs_do_set(int argc, char **argv);
+static int zfs_do_upgrade(int argc, char **argv);
static int zfs_do_snapshot(int argc, char **argv);
static int zfs_do_unmount(int argc, char **argv);
static int zfs_do_share(int argc, char **argv);
@@ -100,6 +103,7 @@ typedef enum {
HELP_DESTROY,
HELP_GET,
HELP_INHERIT,
+ HELP_UPGRADE,
HELP_LIST,
HELP_MOUNT,
HELP_PROMOTE,
@@ -146,6 +150,7 @@ static zfs_command_t command_table[] = {
{ "set", zfs_do_set, HELP_SET },
{ "get", zfs_do_get, HELP_GET },
{ "inherit", zfs_do_inherit, HELP_INHERIT },
+ { "upgrade", zfs_do_upgrade, HELP_UPGRADE },
{ NULL },
{ "mount", zfs_do_mount, HELP_MOUNT },
{ NULL },
@@ -191,6 +196,9 @@ get_usage(zfs_help_t idx)
case HELP_INHERIT:
return (gettext("\tinherit [-r] <property> "
"<filesystem|volume> ...\n"));
+ case HELP_UPGRADE:
+ return (gettext("\tupgrade [-v]\n"
+ "\tupgrade [-r] [-V version] <-a | filesystem ...>\n"));
case HELP_LIST:
return (gettext("\tlist [-rH] [-o property[,property]...] "
"[-t type[,type]...]\n"
@@ -1301,6 +1309,208 @@ zfs_do_inherit(int argc, char **argv)
return (ret);
}
+typedef struct upgrade_cbdata {
+ uint64_t cb_numupgraded;
+ uint64_t cb_numsamegraded;
+ uint64_t cb_numdowngradefailed;
+ uint64_t cb_version;
+ boolean_t cb_newer;
+ boolean_t cb_foundone;
+ char cb_lastfs[ZFS_MAXNAMELEN];
+} upgrade_cbdata_t;
+
+static int
+same_pool(zfs_handle_t *zhp, const char *name)
+{
+ int len1 = strcspn(name, "/@");
+ const char *zhname = zfs_get_name(zhp);
+ int len2 = strcspn(zhname, "/@");
+
+ if (len1 != len2)
+ return (B_FALSE);
+ return (strncmp(name, zhname, len1) != 0);
+}
+
+static int
+upgrade_list_callback(zfs_handle_t *zhp, void *data)
+{
+ upgrade_cbdata_t *cb = data;
+ int version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
+
+ /* list if it's old/new */
+ if ((!cb->cb_newer && version < ZPL_VERSION) ||
+ (cb->cb_newer && version > SPA_VERSION)) {
+ char *str;
+ if (cb->cb_newer) {
+ str = gettext("The following filesystems are "
+ "formatted using a newer software version and\n"
+ "cannot be accessed on the current system.\n\n");
+ } else {
+ str = gettext("The following filesystems are "
+ "out of date, and can be upgraded. After being\n"
+ "upgraded, these filesystems (and any 'zfs send' "
+ "streams generated from\n"
+ "subsequent snapshots) will no longer be "
+ "accessible by older software versions.\n\n");
+ }
+
+ if (!cb->cb_foundone) {
+ (void) puts(str);
+ (void) printf(gettext("VER FILESYSTEM\n"));
+ (void) printf(gettext("--- ------------\n"));
+ cb->cb_foundone = B_TRUE;
+ }
+
+ (void) printf("%2u %s\n", version, zfs_get_name(zhp));
+ }
+
+ return (0);
+}
+
+static int
+upgrade_set_callback(zfs_handle_t *zhp, void *data)
+{
+ upgrade_cbdata_t *cb = data;
+ int version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
+
+ /* upgrade */
+ if (version < cb->cb_version) {
+ char verstr[16];
+ (void) snprintf(verstr, sizeof (verstr), "%u", cb->cb_version);
+ if (cb->cb_lastfs[0] && !same_pool(zhp, cb->cb_lastfs)) {
+ /*
+ * If they did "zfs upgrade -a", then we could
+ * be doing ioctls to different pools. We need
+ * to log this history once to each pool.
+ */
+ zpool_stage_history(g_zfs, first_argc, first_argv,
+ B_TRUE, B_FALSE);
+ }
+ if (zfs_prop_set(zhp, "version", verstr) == 0)
+ cb->cb_numupgraded++;
+ (void) strcpy(cb->cb_lastfs, zfs_get_name(zhp));
+ } else if (version > cb->cb_version) {
+ /* can't downgrade */
+ (void) printf(gettext("%s: can not be downgraded; "
+ "it is already at version %u\n"),
+ zfs_get_name(zhp), version);
+ cb->cb_numdowngradefailed++;
+ } else {
+ cb->cb_numsamegraded++;
+ }
+ return (0);
+}
+
+/*
+ * zfs upgrade
+ * zfs upgrade -v
+ * zfs upgrade [-r] [-V <version>] <-a | filesystem>
+ */
+static int
+zfs_do_upgrade(int argc, char **argv)
+{
+ boolean_t recurse = B_FALSE;
+ boolean_t all = B_FALSE;
+ boolean_t showversions = B_FALSE;
+ int ret;
+ upgrade_cbdata_t cb = { 0 };
+ char c;
+
+ /* check options */
+ while ((c = getopt(argc, argv, "rvV:a")) != -1) {
+ switch (c) {
+ case 'r':
+ recurse = B_TRUE;
+ break;
+ case 'v':
+ showversions = B_TRUE;
+ break;
+ case 'V':
+ if (zfs_prop_string_to_index(ZFS_PROP_VERSION,
+ optarg, &cb.cb_version) != 0) {
+ (void) fprintf(stderr,
+ gettext("invalid version %s\n"), optarg);
+ usage(B_FALSE);
+ }
+ break;
+ case 'a':
+ all = B_TRUE;
+ break;
+ case '?':
+ default:
+ (void) fprintf(stderr, gettext("invalid option '%c'\n"),
+ optopt);
+ usage(B_FALSE);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if ((!all && !argc) && (recurse | cb.cb_version))
+ usage(B_FALSE);
+ if (showversions && (recurse || all || cb.cb_version || argc))
+ usage(B_FALSE);
+ if ((all || argc) && (showversions))
+ usage(B_FALSE);
+ if (all && argc)
+ usage(B_FALSE);
+
+ if (showversions) {
+ /* Show info on available versions. */
+ (void) printf(gettext("The following filesystem versions are "
+ "supported:\n\n"));
+ (void) printf(gettext("VER DESCRIPTION\n"));
+ (void) printf("--- -----------------------------------------"
+ "---------------\n");
+ (void) printf(gettext(" 1 Initial ZFS filesystem version\n"));
+ (void) printf(gettext(" 2 Enhanced directory entries\n"));
+ (void) printf(gettext("\nFor more information on a particular "
+ "version, including supported releases, see:\n\n"));
+ (void) printf("http://www.opensolaris.org/os/community/zfs/"
+ "version/zpl/N\n\n");
+ (void) printf(gettext("Where 'N' is the version number.\n"));
+ ret = 0;
+ } else if (argc || all) {
+ /* Upgrade filesystems */
+ if (cb.cb_version == 0)
+ cb.cb_version = ZPL_VERSION;
+ ret = zfs_for_each(argc, argv, recurse, ZFS_TYPE_FILESYSTEM,
+ NULL, NULL, upgrade_set_callback, &cb, B_TRUE);
+ (void) printf(gettext("%llu filesystems upgraded\n"),
+ cb.cb_numupgraded);
+ if (cb.cb_numsamegraded) {
+ (void) printf(gettext("%llu filesystems already at "
+ "this version\n"),
+ cb.cb_numsamegraded);
+ }
+ if (cb.cb_numdowngradefailed != 0)
+ ret = 1;
+ } else {
+ /* List old-version filesytems */
+ boolean_t found;
+ (void) printf(gettext("This system is currently running "
+ "ZFS filesystem version %llu.\n\n"), ZPL_VERSION);
+
+ ret = zfs_for_each(0, NULL, B_TRUE, ZFS_TYPE_FILESYSTEM,
+ NULL, NULL, upgrade_list_callback, &cb, B_TRUE);
+
+ found = cb.cb_foundone;
+ cb.cb_foundone = B_FALSE;
+ cb.cb_newer = B_TRUE;
+
+ ret = zfs_for_each(0, NULL, B_TRUE, ZFS_TYPE_FILESYSTEM,
+ NULL, NULL, upgrade_list_callback, &cb, B_TRUE);
+
+ if (!cb.cb_foundone && !found) {
+ (void) printf(gettext("All filesystems are "
+ "formatted with the current version.\n"));
+ }
+ }
+
+ return (ret);
+}
+
/*
* list [-rH] [-o property[,property]...] [-t type[,type]...]
* [-s property [-s property]...] [-S property [-S property]...]
@@ -3564,6 +3774,9 @@ main(int argc, char **argv)
opterr = 0;
+ first_argc = argc;
+ first_argv = argv;
+
if ((g_zfs = libzfs_init()) == NULL) {
(void) fprintf(stderr, gettext("internal error: failed to "
"initialize ZFS library\n"));
diff --git a/usr/src/cmd/zpool/zpool_main.c b/usr/src/cmd/zpool/zpool_main.c
index 0bd2146ec5..b0fe69dbc0 100644
--- a/usr/src/cmd/zpool/zpool_main.c
+++ b/usr/src/cmd/zpool/zpool_main.c
@@ -1221,7 +1221,7 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
ZPOOL_CONFIG_POOL_STATE, &state) == 0);
verify(nvlist_lookup_uint64(config,
ZPOOL_CONFIG_VERSION, &version) == 0);
- if (version > ZFS_VERSION) {
+ if (version > SPA_VERSION) {
(void) fprintf(stderr, gettext("cannot import '%s': pool "
"is formatted using a newer ZFS version\n"), name);
return (1);
@@ -3215,6 +3215,8 @@ typedef struct upgrade_cbdata {
int cb_first;
int cb_newer;
int cb_argc;
+ uint64_t cb_numupgraded;
+ uint64_t cb_numsamegraded;
char **cb_argv;
} upgrade_cbdata_t;
@@ -3230,7 +3232,7 @@ upgrade_cb(zpool_handle_t *zhp, void *arg)
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
&version) == 0);
- if (!cbp->cb_newer && version < ZFS_VERSION) {
+ if (!cbp->cb_newer && version < SPA_VERSION) {
if (!cbp->cb_all) {
if (cbp->cb_first) {
(void) printf(gettext("The following pools are "
@@ -3253,7 +3255,7 @@ upgrade_cb(zpool_handle_t *zhp, void *arg)
"'%s'\n"), zpool_get_name(zhp));
}
}
- } else if (cbp->cb_newer && version > ZFS_VERSION) {
+ } else if (cbp->cb_newer && version > SPA_VERSION) {
assert(!cbp->cb_all);
if (cbp->cb_first) {
@@ -3291,7 +3293,7 @@ upgrade_one(zpool_handle_t *zhp, void *data)
" to upgrade.\n"));
return (1);
}
- if (version == ZFS_VERSION) {
+ if (version == SPA_VERSION) {
(void) printf(gettext("Pool '%s' is already formatted "
"using the current version.\n"), zpool_get_name(zhp));
return (0);
@@ -3302,7 +3304,7 @@ upgrade_one(zpool_handle_t *zhp, void *data)
if (!ret) {
(void) printf(gettext("Successfully upgraded '%s' "
"from version %llu to version %llu\n"), zpool_get_name(zhp),
- (u_longlong_t)version, (u_longlong_t)ZFS_VERSION);
+ (u_longlong_t)version, (u_longlong_t)SPA_VERSION);
}
return (ret != 0);
@@ -3360,8 +3362,8 @@ zpool_do_upgrade(int argc, char **argv)
}
}
- (void) printf(gettext("This system is currently running ZFS version "
- "%llu.\n\n"), ZFS_VERSION);
+ (void) printf(gettext("This system is currently running "
+ "ZFS pool version %llu.\n\n"), SPA_VERSION);
cb.cb_first = B_TRUE;
if (showversions) {
(void) printf(gettext("The following versions are "
@@ -3461,6 +3463,7 @@ char *hist_event_table[LOG_END] = {
"replay_full_sync",
"rollback",
"snapshot",
+ "filesystem version upgrade",
};
/*
diff --git a/usr/src/common/zfs/zfs_deleg.c b/usr/src/common/zfs/zfs_deleg.c
index 578d1c6680..d7c3046572 100644
--- a/usr/src/common/zfs/zfs_deleg.c
+++ b/usr/src/common/zfs/zfs_deleg.c
@@ -80,6 +80,7 @@ char *zfs_deleg_perm_tab[] = {
ZFS_DELEG_PERM_SHAREISCSI,
ZFS_DELEG_PERM_XATTR,
ZFS_DELEG_PERM_COPIES,
+ ZFS_DELEG_PERM_VERSION,
NULL
};
diff --git a/usr/src/common/zfs/zfs_prop.c b/usr/src/common/zfs/zfs_prop.c
index 887f20a2e1..96dacf49d8 100644
--- a/usr/src/common/zfs/zfs_prop.c
+++ b/usr/src/common/zfs/zfs_prop.c
@@ -51,6 +51,7 @@
#include <sys/spa.h>
#include <sys/zfs_acl.h>
#include <sys/zfs_ioctl.h>
+#include <sys/zfs_znode.h>
#include "zfs_prop.h"
#include "zfs_deleg.h"
@@ -204,7 +205,10 @@ static prop_desc_t zfs_prop_table[] = {
ZFS_DELEG_PERM_NONE },
{ "delegation", prop_type_boolean, 1, NULL, prop_default,
ZFS_TYPE_POOL, "on | off", "DELEGATION", B_TRUE,
- B_TRUE, ZFS_DELEG_PERM_NONE }
+ B_TRUE, ZFS_DELEG_PERM_NONE },
+ { "version", prop_type_index, 0, NULL, prop_default,
+ ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "1 | 2 | current",
+ "VERSION", B_TRUE, B_TRUE, ZFS_DELEG_PERM_VERSION },
};
#define ZFS_PROP_COUNT ((sizeof (zfs_prop_table))/(sizeof (prop_desc_t)))
@@ -517,6 +521,13 @@ static zfs_index_t copies_table[] = {
{ NULL }
};
+static zfs_index_t version_table[] = {
+ { "1", 1 },
+ { "2", 2 },
+ { "current", ZPL_VERSION },
+ { NULL }
+};
+
static zfs_index_t *
zfs_prop_index_table(zfs_prop_t prop)
{
@@ -533,12 +544,13 @@ zfs_prop_index_table(zfs_prop_t prop)
return (acl_inherit_table);
case ZFS_PROP_COPIES:
return (copies_table);
+ case ZFS_PROP_VERSION:
+ return (version_table);
default:
return (NULL);
}
}
-
/*
* Tables of index types, plus functions to convert between the user view
* (strings) and internal representation (uint64_t).
diff --git a/usr/src/grub/grub-0.95/stage2/fsys_zfs.c b/usr/src/grub/grub-0.95/stage2/fsys_zfs.c
index 1a7150dfc5..b15779b604 100644
--- a/usr/src/grub/grub-0.95/stage2/fsys_zfs.c
+++ b/usr/src/grub/grub-0.95/stage2/fsys_zfs.c
@@ -266,8 +266,8 @@ uberblock_verify(uberblock_phys_t *ub, int offset)
return (-1);
if (uber->ub_magic == UBERBLOCK_MAGIC &&
- uber->ub_version >= ZFS_VERSION_1 &&
- uber->ub_version <= ZFS_VERSION)
+ uber->ub_version >= SPA_VERSION_1 &&
+ uber->ub_version <= SPA_VERSION)
return (0);
return (-1);
@@ -292,11 +292,10 @@ find_bestub(uberblock_phys_t *ub_array, int label)
if (uberblock_verify(&ub_array[i], offset) == 0) {
if (ubbest == NULL) {
ubbest = &ub_array[i];
- } else {
- if (vdev_uberblock_compare(
- &(ub_array[i].ubp_uberblock),
- &(ubbest->ubp_uberblock)) > 0)
- ubbest = &ub_array[i];
+ } else if (vdev_uberblock_compare(
+ &(ub_array[i].ubp_uberblock),
+ &(ubbest->ubp_uberblock)) > 0) {
+ ubbest = &ub_array[i];
}
}
}
@@ -700,13 +699,18 @@ static int
dnode_get_path(dnode_phys_t *mdn, char *path, dnode_phys_t *dn,
char *stack)
{
- uint64_t objnum;
+ uint64_t objnum, version;
char *cname, ch;
if (errnum = dnode_get(mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE,
dn, stack))
return (errnum);
+ if (errnum = zap_lookup(dn, ZPL_VERSION_STR, &version, stack))
+ return (errnum);
+ if (version > ZPL_VERSION)
+ return (-1);
+
if (errnum = zap_lookup(dn, ZFS_ROOT_OBJ, &objnum, stack))
return (errnum);
@@ -730,6 +734,7 @@ dnode_get_path(dnode_phys_t *mdn, char *path, dnode_phys_t *dn,
if (errnum = zap_lookup(dn, cname, &objnum, stack))
return (errnum);
+ objnum = ZFS_DIRENT_OBJ(objnum);
if (errnum = dnode_get(mdn, objnum, 0, dn, stack))
return (errnum);
diff --git a/usr/src/grub/grub-0.95/stage2/zfs-include/zfs.h b/usr/src/grub/grub-0.95/stage2/zfs-include/zfs.h
index c590a2f932..8af94bc497 100644
--- a/usr/src/grub/grub-0.95/stage2/zfs-include/zfs.h
+++ b/usr/src/grub/grub-0.95/stage2/zfs-include/zfs.h
@@ -29,15 +29,15 @@
/*
* On-disk version number.
*/
-#define ZFS_VERSION_1 1ULL
-#define ZFS_VERSION_2 2ULL
-#define ZFS_VERSION_3 3ULL
-#define ZFS_VERSION_4 4ULL
-#define ZFS_VERSION_5 5ULL
-#define ZFS_VERSION_6 6ULL
-#define ZFS_VERSION_7 7ULL
-#define ZFS_VERSION_8 8ULL
-#define ZFS_VERSION ZFS_VERSION_8
+#define SPA_VERSION_1 1ULL
+#define SPA_VERSION_2 2ULL
+#define SPA_VERSION_3 3ULL
+#define SPA_VERSION_4 4ULL
+#define SPA_VERSION_5 5ULL
+#define SPA_VERSION_6 6ULL
+#define SPA_VERSION_7 7ULL
+#define SPA_VERSION_8 8ULL
+#define SPA_VERSION SPA_VERSION_8
/*
* The following are configuration names used in the nvlist describing a pool's
diff --git a/usr/src/grub/grub-0.95/stage2/zfs-include/zfs_znode.h b/usr/src/grub/grub-0.95/stage2/zfs-include/zfs_znode.h
index 0f96269c7a..36887aac49 100644
--- a/usr/src/grub/grub-0.95/stage2/zfs-include/zfs_znode.h
+++ b/usr/src/grub/grub-0.95/stage2/zfs-include/zfs_znode.h
@@ -28,6 +28,11 @@
#define MASTER_NODE_OBJ 1
#define ZFS_ROOT_OBJ "ROOT"
+#define ZPL_VERSION_STR "VERSION"
+
+#define ZPL_VERSION 2ULL
+
+#define ZFS_DIRENT_OBJ(de) BF64_GET(de, 0, 48)
/*
* This is the persistent portion of the znode. It is stored
diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h
index 06ea0a885c..fd51ea23f8 100644
--- a/usr/src/lib/libzfs/common/libzfs.h
+++ b/usr/src/lib/libzfs/common/libzfs.h
@@ -409,8 +409,6 @@ extern int zfs_promote(zfs_handle_t *);
extern const char *zfs_type_to_name(zfs_type_t);
extern void zfs_refresh_properties(zfs_handle_t *);
extern int zfs_name_valid(const char *, zfs_type_t);
-extern int zfs_disable(zfs_handle_t *);
-extern int zfs_enable(zfs_handle_t *);
extern zfs_handle_t *zfs_path_to_zhandle(libzfs_handle_t *, char *, zfs_type_t);
extern boolean_t zfs_dataset_exists(libzfs_handle_t *, const char *,
zfs_type_t);
diff --git a/usr/src/lib/libzfs/common/libzfs_changelist.c b/usr/src/lib/libzfs/common/libzfs_changelist.c
index ad7ce028a1..7a16d015c6 100644
--- a/usr/src/lib/libzfs/common/libzfs_changelist.c
+++ b/usr/src/lib/libzfs/common/libzfs_changelist.c
@@ -126,8 +126,10 @@ changelist_prefix(prop_changelist_t *clp)
(void) zfs_unshare_iscsi(cn->cn_handle);
break;
}
- } else if (zfs_unmount(cn->cn_handle, NULL, clp->cl_flags) != 0)
+ } else if (zfs_unmount(cn->cn_handle, NULL,
+ clp->cl_flags) != 0) {
ret = -1;
+ }
}
return (ret);
@@ -542,6 +544,8 @@ changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int flags)
clp->cl_prop = ZFS_PROP_MOUNTPOINT;
} else if (prop == ZFS_PROP_VOLSIZE) {
clp->cl_prop = ZFS_PROP_MOUNTPOINT;
+ } else if (prop == ZFS_PROP_VERSION) {
+ clp->cl_prop = ZFS_PROP_MOUNTPOINT;
} else {
clp->cl_prop = prop;
}
diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c
index 5cea7c3fea..6990b20dff 100644
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c
@@ -898,6 +898,23 @@ zfs_validate_properties(libzfs_handle_t *hdl, zfs_type_t type, char *pool_name,
* Perform some additional checks for specific properties.
*/
switch (prop) {
+ case ZFS_PROP_VERSION:
+ {
+ int version;
+
+ if (zhp == NULL)
+ break;
+ version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
+ if (intval < version) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "Can not downgrade; already at version %u"),
+ version);
+ (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
+ goto error;
+ }
+ break;
+ }
+
case ZFS_PROP_RECORDSIZE:
case ZFS_PROP_VOLBLOCKSIZE:
/* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */
@@ -1640,6 +1657,7 @@ zfs_coalesce_perm(zfs_handle_t *zhp, zfs_allow_node_t *allownode,
}
return (0);
}
+
/*
* Uggh, this is going to be a bit complicated.
* we have an nvlist coming out of the kernel that
@@ -2259,20 +2277,6 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zfs_source_t *src,
}
break;
- case ZFS_PROP_RECORDSIZE:
- case ZFS_PROP_COMPRESSION:
- case ZFS_PROP_ZONED:
- case ZFS_PROP_CREATION:
- case ZFS_PROP_COMPRESSRATIO:
- case ZFS_PROP_REFERENCED:
- case ZFS_PROP_USED:
- case ZFS_PROP_CREATETXG:
- case ZFS_PROP_AVAILABLE:
- case ZFS_PROP_VOLSIZE:
- case ZFS_PROP_VOLBLOCKSIZE:
- *val = getprop_uint64(zhp, prop, source);
- break;
-
case ZFS_PROP_CANMOUNT:
*val = getprop_uint64(zhp, prop, source);
if (*val == 0)
@@ -2299,10 +2303,20 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zfs_source_t *src,
break;
default:
- zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
- "cannot get non-numeric property"));
- return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP,
- dgettext(TEXT_DOMAIN, "internal error")));
+ switch (zfs_prop_get_type(prop)) {
+ case prop_type_number:
+ case prop_type_boolean:
+ case prop_type_index:
+ *val = getprop_uint64(zhp, prop, source);
+ break;
+
+ case prop_type_string:
+ default:
+ zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
+ "cannot get non-numeric property"));
+ return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP,
+ dgettext(TEXT_DOMAIN, "internal error")));
+ }
}
return (0);
@@ -2360,56 +2374,6 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
*src = ZFS_SRC_NONE;
switch (prop) {
- case ZFS_PROP_ATIME:
- case ZFS_PROP_READONLY:
- case ZFS_PROP_SETUID:
- case ZFS_PROP_ZONED:
- case ZFS_PROP_DEVICES:
- case ZFS_PROP_EXEC:
- case ZFS_PROP_CANMOUNT:
- case ZFS_PROP_XATTR:
- /*
- * Basic boolean values are built on top of
- * get_numeric_property().
- */
- if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
- return (-1);
- nicebool(val, propbuf, proplen);
-
- break;
-
- case ZFS_PROP_AVAILABLE:
- case ZFS_PROP_RECORDSIZE:
- case ZFS_PROP_CREATETXG:
- case ZFS_PROP_REFERENCED:
- case ZFS_PROP_USED:
- case ZFS_PROP_VOLSIZE:
- case ZFS_PROP_VOLBLOCKSIZE:
- case ZFS_PROP_NUMCLONES:
- /*
- * Basic numeric values are built on top of
- * get_numeric_property().
- */
- if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
- return (-1);
- if (literal)
- (void) snprintf(propbuf, proplen, "%llu",
- (u_longlong_t)val);
- else
- zfs_nicenum(val, propbuf, proplen);
- break;
-
- case ZFS_PROP_COMPRESSION:
- case ZFS_PROP_CHECKSUM:
- case ZFS_PROP_SNAPDIR:
- case ZFS_PROP_ACLMODE:
- case ZFS_PROP_ACLINHERIT:
- case ZFS_PROP_COPIES:
- val = getprop_uint64(zhp, prop, &source);
- verify(zfs_prop_index_to_string(prop, val, &strval) == 0);
- (void) strlcpy(propbuf, strval, proplen);
- break;
-
case ZFS_PROP_CREATION:
/*
* 'creation' is a time_t stored in the statistics. We convert
@@ -2468,13 +2432,6 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
break;
- case ZFS_PROP_SHARENFS:
- case ZFS_PROP_SHAREISCSI:
- case ZFS_PROP_ISCSIOPTIONS:
- (void) strlcpy(propbuf, getprop_string(zhp, prop, &source),
- proplen);
- break;
-
case ZFS_PROP_ORIGIN:
(void) strlcpy(propbuf, getprop_string(zhp, prop, &source),
proplen);
@@ -2561,7 +2518,42 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
break;
default:
- abort();
+ switch (zfs_prop_get_type(prop)) {
+ case prop_type_number:
+ if (get_numeric_property(zhp, prop, src,
+ &source, &val) != 0)
+ return (-1);
+ if (literal)
+ (void) snprintf(propbuf, proplen, "%llu",
+ (u_longlong_t)val);
+ else
+ zfs_nicenum(val, propbuf, proplen);
+ break;
+
+ case prop_type_string:
+ (void) strlcpy(propbuf,
+ getprop_string(zhp, prop, &source), proplen);
+ break;
+
+ case prop_type_boolean:
+ if (get_numeric_property(zhp, prop, src,
+ &source, &val) != 0)
+ return (-1);
+ nicebool(val, propbuf, proplen);
+
+ break;
+
+ case prop_type_index:
+ val = getprop_uint64(zhp, prop, &source);
+ if (zfs_prop_index_to_string(prop, val,
+ &strval) != 0)
+ return (-1);
+ (void) strlcpy(propbuf, strval, proplen);
+ break;
+
+ default:
+ abort();
+ }
}
get_source(zhp, src, source, statbuf, statlen);
diff --git a/usr/src/lib/libzfs/common/libzfs_import.c b/usr/src/lib/libzfs/common/libzfs_import.c
index 97031cbe4e..8b000caf5c 100644
--- a/usr/src/lib/libzfs/common/libzfs_import.c
+++ b/usr/src/lib/libzfs/common/libzfs_import.c
@@ -682,8 +682,9 @@ error:
* Return the offset of the given label.
*/
static uint64_t
-label_offset(size_t size, int l)
+label_offset(uint64_t size, int l)
{
+ ASSERT(P2PHASE_TYPED(size, sizeof (vdev_label_t), uint64_t) == 0);
return (l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ?
0 : size - VDEV_LABELS * sizeof (vdev_label_t)));
}
@@ -698,19 +699,20 @@ zpool_read_label(int fd, nvlist_t **config)
struct stat64 statbuf;
int l;
vdev_label_t *label;
- uint64_t state, txg;
+ uint64_t state, txg, size;
*config = NULL;
if (fstat64(fd, &statbuf) == -1)
return (0);
+ size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t);
if ((label = malloc(sizeof (vdev_label_t))) == NULL)
return (-1);
for (l = 0; l < VDEV_LABELS; l++) {
if (pread(fd, label, sizeof (vdev_label_t),
- label_offset(statbuf.st_size, l)) != sizeof (vdev_label_t))
+ label_offset(size, l)) != sizeof (vdev_label_t))
continue;
if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist,
diff --git a/usr/src/lib/libzfs/common/libzfs_pool.c b/usr/src/lib/libzfs/common/libzfs_pool.c
index 9c1d197f4d..daf435126a 100644
--- a/usr/src/lib/libzfs/common/libzfs_pool.c
+++ b/usr/src/lib/libzfs/common/libzfs_pool.c
@@ -534,7 +534,7 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
"cannot add to '%s'"), zhp->zpool_name);
- if (zpool_get_version(zhp) < ZFS_VERSION_SPARES &&
+ if (zpool_get_version(zhp) < SPA_VERSION_SPARES &&
nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
&spares, &nspares) == 0) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be "
@@ -2183,7 +2183,7 @@ zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval)
dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
zhp->zpool_name);
- if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) {
+ if (zpool_get_version(zhp) < SPA_VERSION_BOOTFS) {
zfs_error_aux(zhp->zpool_hdl,
dgettext(TEXT_DOMAIN, "pool must be "
"upgraded to support pool properties"));
@@ -2230,7 +2230,7 @@ zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop)
uint64_t value;
nvlist_t *nvp;
- if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS)
+ if (zpool_get_version(zhp) < SPA_VERSION_BOOTFS)
return (0);
if (zhp->zpool_props == NULL && zpool_get_all_props(zhp))
@@ -2267,7 +2267,7 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *propbuf,
(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
"cannot get property '%s'"), zpool_prop_to_name(prop));
- if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) {
+ if (zpool_get_version(zhp) < SPA_VERSION_BOOTFS) {
zfs_error_aux(zhp->zpool_hdl,
dgettext(TEXT_DOMAIN, "pool must be "
"upgraded to support pool properties"));
diff --git a/usr/src/lib/libzfs/common/libzfs_status.c b/usr/src/lib/libzfs/common/libzfs_status.c
index 97a81c35bb..6e2065ea36 100644
--- a/usr/src/lib/libzfs/common/libzfs_status.c
+++ b/usr/src/lib/libzfs/common/libzfs_status.c
@@ -264,7 +264,7 @@ check_status(nvlist_t *config, boolean_t isimport)
/*
* Outdated, but usable, version
*/
- if (version < ZFS_VERSION)
+ if (version < SPA_VERSION)
return (ZPOOL_STATUS_VERSION_OLDER);
return (ZPOOL_STATUS_OK);
diff --git a/usr/src/lib/libzfs/common/mapfile-vers b/usr/src/lib/libzfs/common/mapfile-vers
index d870f339f8..53e75e9323 100644
--- a/usr/src/lib/libzfs/common/mapfile-vers
+++ b/usr/src/lib/libzfs/common/mapfile-vers
@@ -85,6 +85,7 @@ SUNWprivate_1.1 {
zfs_prop_iter;
zfs_prop_readonly;
zfs_prop_set;
+ zfs_prop_string_to_index;
zfs_prop_to_name;
zfs_prop_user;
zfs_prop_valid_for_type;
diff --git a/usr/src/uts/common/fs/zfs/bplist.c b/usr/src/uts/common/fs/zfs/bplist.c
index 4442b1f28a..ecab27dd1c 100644
--- a/usr/src/uts/common/fs/zfs/bplist.c
+++ b/usr/src/uts/common/fs/zfs/bplist.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -47,7 +47,7 @@ bplist_create(objset_t *mos, int blocksize, dmu_tx_t *tx)
{
int size;
- size = spa_version(dmu_objset_spa(mos)) < ZFS_VERSION_BPLIST_ACCOUNT ?
+ size = spa_version(dmu_objset_spa(mos)) < SPA_VERSION_BPLIST_ACCOUNT ?
BPLIST_SIZE_V0 : sizeof (bplist_phys_t);
return (dmu_object_alloc(mos, DMU_OT_BPLIST, blocksize,
diff --git a/usr/src/uts/common/fs/zfs/dnode.c b/usr/src/uts/common/fs/zfs/dnode.c
index 1fe144d09e..8e3ded7f94 100644
--- a/usr/src/uts/common/fs/zfs/dnode.c
+++ b/usr/src/uts/common/fs/zfs/dnode.c
@@ -1181,7 +1181,7 @@ dnode_diduse_space(dnode_t *dn, int64_t delta)
ASSERT3U(space, >=, -delta); /* no underflow */
}
space += delta;
- if (spa_version(dn->dn_objset->os_spa) < ZFS_VERSION_DNODE_BYTES) {
+ if (spa_version(dn->dn_objset->os_spa) < SPA_VERSION_DNODE_BYTES) {
ASSERT((dn->dn_phys->dn_flags & DNODE_FLAG_USED_BYTES) == 0);
ASSERT3U(P2PHASE(space, 1<<DEV_BSHIFT), ==, 0);
dn->dn_phys->dn_used = space >> DEV_BSHIFT;
diff --git a/usr/src/uts/common/fs/zfs/dsl_dataset.c b/usr/src/uts/common/fs/zfs/dsl_dataset.c
index e5bfe207b2..6a4baa8c76 100644
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c
+++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c
@@ -268,7 +268,7 @@ dsl_dataset_get_snapname(dsl_dataset_t *ds)
return (err);
headphys = headdbuf->db_data;
err = zap_value_search(dp->dp_meta_objset,
- headphys->ds_snapnames_zapobj, ds->ds_object, ds->ds_snapname);
+ headphys->ds_snapnames_zapobj, ds->ds_object, 0, ds->ds_snapname);
dmu_buf_rele(headdbuf, FTAG);
return (err);
}
diff --git a/usr/src/uts/common/fs/zfs/dsl_dir.c b/usr/src/uts/common/fs/zfs/dsl_dir.c
index d15c7772c3..d7fe638d7d 100644
--- a/usr/src/uts/common/fs/zfs/dsl_dir.c
+++ b/usr/src/uts/common/fs/zfs/dsl_dir.c
@@ -126,17 +126,15 @@ dsl_dir_open_obj(dsl_pool_t *dp, uint64_t ddobj,
uint64_t foundobj;
err = zap_lookup(dp->dp_meta_objset,
- dd->dd_parent->dd_phys->
- dd_child_dir_zapobj,
+ dd->dd_parent->dd_phys->dd_child_dir_zapobj,
tail, sizeof (foundobj), 1, &foundobj);
ASSERT(err || foundobj == ddobj);
#endif
(void) strcpy(dd->dd_myname, tail);
} else {
err = zap_value_search(dp->dp_meta_objset,
- dd->dd_parent->dd_phys->
- dd_child_dir_zapobj,
- ddobj, dd->dd_myname);
+ dd->dd_parent->dd_phys->dd_child_dir_zapobj,
+ ddobj, 0, dd->dd_myname);
}
if (err) {
dsl_dir_close(dd->dd_parent, dd);
diff --git a/usr/src/uts/common/fs/zfs/dsl_synctask.c b/usr/src/uts/common/fs/zfs/dsl_synctask.c
index e1b5b49faa..810d449938 100644
--- a/usr/src/uts/common/fs/zfs/dsl_synctask.c
+++ b/usr/src/uts/common/fs/zfs/dsl_synctask.c
@@ -50,6 +50,7 @@ dsl_sync_task_group_create(dsl_pool_t *dp)
list_create(&dstg->dstg_tasks, sizeof (dsl_sync_task_t),
offsetof(dsl_sync_task_t, dst_node));
dstg->dstg_pool = dp;
+ dstg->dstg_cr = CRED();
return (dstg);
}
@@ -68,7 +69,6 @@ dsl_sync_task_create(dsl_sync_task_group_t *dstg,
dst->dst_syncfunc = syncfunc;
dst->dst_arg1 = arg1;
dst->dst_arg2 = arg2;
- dst->dst_cr = CRED();
list_insert_tail(&dstg->dstg_tasks, dst);
dstg->dstg_space += blocks_modified << DST_AVG_BLKSHIFT;
@@ -125,6 +125,16 @@ top:
}
void
+dsl_sync_task_group_nowait(dsl_sync_task_group_t *dstg, dmu_tx_t *tx)
+{
+ uint64_t txg;
+
+ dstg->dstg_nowaiter = B_TRUE;
+ txg = dmu_tx_get_txg(tx);
+ VERIFY(0 == txg_list_add(&dstg->dstg_pool->dp_sync_tasks, dstg, txg));
+}
+
+void
dsl_sync_task_group_destroy(dsl_sync_task_group_t *dstg)
{
dsl_sync_task_t *dst;
@@ -174,12 +184,15 @@ dsl_sync_task_group_sync(dsl_sync_task_group_t *dstg, dmu_tx_t *tx)
for (dst = list_head(&dstg->dstg_tasks); dst;
dst = list_next(&dstg->dstg_tasks, dst)) {
dst->dst_syncfunc(dst->dst_arg1, dst->dst_arg2,
- dst->dst_cr, tx);
+ dstg->dstg_cr, tx);
}
}
rw_exit(&dstg->dstg_pool->dp_config_rwlock);
dsl_dir_tempreserve_clear(tr_cookie, tx);
+
+ if (dstg->dstg_nowaiter)
+ dsl_sync_task_group_destroy(dstg);
}
int
@@ -197,3 +210,16 @@ dsl_sync_task_do(dsl_pool_t *dp,
dsl_sync_task_group_destroy(dstg);
return (err);
}
+
+void
+dsl_sync_task_do_nowait(dsl_pool_t *dp,
+ dsl_checkfunc_t *checkfunc, dsl_syncfunc_t *syncfunc,
+ void *arg1, void *arg2, int blocks_modified, dmu_tx_t *tx)
+{
+ dsl_sync_task_group_t *dstg;
+
+ dstg = dsl_sync_task_group_create(dp);
+ dsl_sync_task_create(dstg, checkfunc, syncfunc,
+ arg1, arg2, blocks_modified);
+ dsl_sync_task_group_nowait(dstg, tx);
+}
diff --git a/usr/src/uts/common/fs/zfs/spa.c b/usr/src/uts/common/fs/zfs/spa.c
index 72015135e7..ba56215562 100644
--- a/usr/src/uts/common/fs/zfs/spa.c
+++ b/usr/src/uts/common/fs/zfs/spa.c
@@ -475,7 +475,7 @@ spa_load(spa_t *spa, nvlist_t *config, spa_load_state_t state, int mosconfig)
* it's not present treat it as the initial version.
*/
if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, &version) != 0)
- version = ZFS_VERSION_INITIAL;
+ version = SPA_VERSION_INITIAL;
(void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG,
&spa->spa_config_txg);
@@ -551,7 +551,7 @@ spa_load(spa_t *spa, nvlist_t *config, spa_load_state_t state, int mosconfig)
/*
* If the pool is newer than the code, we can't open it.
*/
- if (ub->ub_version > ZFS_VERSION) {
+ if (ub->ub_version > SPA_VERSION) {
vdev_set_state(rvd, B_TRUE, VDEV_STATE_CANT_OPEN,
VDEV_AUX_VERSION_NEWER);
error = ENOTSUP;
@@ -707,7 +707,7 @@ spa_load(spa_t *spa, nvlist_t *config, spa_load_state_t state, int mosconfig)
goto out;
}
if (error == 0) {
- ASSERT(spa_version(spa) >= ZFS_VERSION_SPARES);
+ ASSERT(spa_version(spa) >= SPA_VERSION_SPARES);
if (load_nvlist(spa, spa->spa_spares_object,
&spa->spa_sparelist) != 0) {
vdev_set_state(rvd, B_TRUE, VDEV_STATE_CANT_OPEN,
@@ -1089,7 +1089,7 @@ spa_validate_spares(spa_t *spa, nvlist_t *nvroot, uint64_t crtxg, int mode)
* Make sure the pool is formatted with a version that supports hot
* spares.
*/
- if (spa_version(spa) < ZFS_VERSION_SPARES)
+ if (spa_version(spa) < SPA_VERSION_SPARES)
return (ENOTSUP);
/*
@@ -1164,7 +1164,7 @@ spa_create(const char *pool, nvlist_t *nvroot, const char *altroot)
spa_activate(spa);
spa->spa_uberblock.ub_txg = txg - 1;
- spa->spa_uberblock.ub_version = ZFS_VERSION;
+ spa->spa_uberblock.ub_version = SPA_VERSION;
spa->spa_ubsync = spa->spa_uberblock;
/*
@@ -1928,7 +1928,7 @@ spa_vdev_detach(spa_t *spa, uint64_t guid, int replace_done)
}
ASSERT(pvd->vdev_ops != &vdev_spare_ops ||
- spa_version(spa) >= ZFS_VERSION_SPARES);
+ spa_version(spa) >= SPA_VERSION_SPARES);
/*
* Only mirror, replacing, and spare vdevs support detach.
@@ -3052,11 +3052,11 @@ spa_sync(spa_t *spa, uint64_t txg)
tx = dmu_tx_create_assigned(dp, txg);
/*
- * If we are upgrading to ZFS_VERSION_RAIDZ_DEFLATE this txg,
+ * If we are upgrading to SPA_VERSION_RAIDZ_DEFLATE this txg,
* set spa_deflate if we have no raid-z vdevs.
*/
- if (spa->spa_ubsync.ub_version < ZFS_VERSION_RAIDZ_DEFLATE &&
- spa->spa_uberblock.ub_version >= ZFS_VERSION_RAIDZ_DEFLATE) {
+ if (spa->spa_ubsync.ub_version < SPA_VERSION_RAIDZ_DEFLATE &&
+ spa->spa_uberblock.ub_version >= SPA_VERSION_RAIDZ_DEFLATE) {
int i;
for (i = 0; i < rvd->vdev_children; i++) {
@@ -3273,9 +3273,9 @@ spa_upgrade(spa_t *spa)
* future version would result in an unopenable pool, this shouldn't be
* possible.
*/
- ASSERT(spa->spa_uberblock.ub_version <= ZFS_VERSION);
+ ASSERT(spa->spa_uberblock.ub_version <= SPA_VERSION);
- spa->spa_uberblock.ub_version = ZFS_VERSION;
+ spa->spa_uberblock.ub_version = SPA_VERSION;
vdev_config_dirty(spa->spa_root_vdev);
spa_config_exit(spa, FTAG);
diff --git a/usr/src/uts/common/fs/zfs/spa_history.c b/usr/src/uts/common/fs/zfs/spa_history.c
index 7d44242596..f3fc5f3b35 100644
--- a/usr/src/uts/common/fs/zfs/spa_history.c
+++ b/usr/src/uts/common/fs/zfs/spa_history.c
@@ -188,7 +188,7 @@ spa_history_zone()
/*
* Write out a history event.
*/
-void
+static void
spa_history_log_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx)
{
spa_t *spa = arg1;
@@ -203,9 +203,6 @@ spa_history_log_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx)
char *record_packed = NULL;
int ret;
- if (history_str == NULL)
- return;
-
/*
* If we have an older pool that doesn't have a command
* history object, create it now.
@@ -279,6 +276,11 @@ spa_history_log_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx)
nvlist_free(nvrecord);
kmem_free(record_packed, reclen);
dmu_buf_rele(dbp, FTAG);
+
+ if (hap->ha_log_type == LOG_INTERNAL) {
+ kmem_free((void*)hap->ha_history_str, HIS_MAX_RECORD_LEN);
+ kmem_free(hap, sizeof (history_arg_t));
+ }
}
/*
@@ -289,6 +291,8 @@ spa_history_log(spa_t *spa, const char *history_str, history_log_type_t what)
{
history_arg_t ha;
+ ASSERT(what != LOG_INTERNAL);
+
ha.ha_history_str = history_str;
ha.ha_log_type = what;
(void) strlcpy(ha.ha_zone, spa_history_zone(), sizeof (ha.ha_zone));
@@ -388,20 +392,27 @@ void
spa_history_internal_log(history_internal_events_t event, spa_t *spa,
dmu_tx_t *tx, cred_t *cr, const char *fmt, ...)
{
- history_arg_t ha;
+ history_arg_t *hap;
char *str;
va_list adx;
+ hap = kmem_alloc(sizeof (history_arg_t), KM_SLEEP);
str = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP);
va_start(adx, fmt);
(void) vsnprintf(str, HIS_MAX_RECORD_LEN, fmt, adx);
va_end(adx);
- ha.ha_log_type = LOG_INTERNAL;
- ha.ha_history_str = str;
- ha.ha_event = event;
- ha.ha_zone[0] = '\0';
- spa_history_log_sync(spa, &ha, cr, tx);
- kmem_free(str, HIS_MAX_RECORD_LEN);
+ hap->ha_log_type = LOG_INTERNAL;
+ hap->ha_history_str = str;
+ hap->ha_event = event;
+ hap->ha_zone[0] = '\0';
+
+ if (dmu_tx_is_syncing(tx)) {
+ spa_history_log_sync(spa, hap, cr, tx);
+ } else {
+ dsl_sync_task_do_nowait(spa_get_dsl(spa), NULL,
+ spa_history_log_sync, spa, hap, 0, tx);
+ }
+ /* spa_history_log_sync() will free hap and str */
}
diff --git a/usr/src/uts/common/fs/zfs/spa_misc.c b/usr/src/uts/common/fs/zfs/spa_misc.c
index 578f89e333..d2ba6a1079 100644
--- a/usr/src/uts/common/fs/zfs/spa_misc.c
+++ b/usr/src/uts/common/fs/zfs/spa_misc.c
@@ -1016,11 +1016,11 @@ int
spa_max_replication(spa_t *spa)
{
/*
- * As of ZFS_VERSION == ZFS_VERSION_DITTO_BLOCKS, we are able to
+ * As of SPA_VERSION == SPA_VERSION_DITTO_BLOCKS, we are able to
* handle BPs with more than one DVA allocated. Set our max
* replication level accordingly.
*/
- if (spa_version(spa) < ZFS_VERSION_DITTO_BLOCKS)
+ if (spa_version(spa) < SPA_VERSION_DITTO_BLOCKS)
return (1);
return (MIN(SPA_DVAS_PER_BP, spa_max_replication_override));
}
diff --git a/usr/src/uts/common/fs/zfs/sys/dsl_deleg.h b/usr/src/uts/common/fs/zfs/sys/dsl_deleg.h
index 87a8526716..1cc22b3dc8 100644
--- a/usr/src/uts/common/fs/zfs/sys/dsl_deleg.h
+++ b/usr/src/uts/common/fs/zfs/sys/dsl_deleg.h
@@ -71,6 +71,7 @@ extern "C" {
#define ZFS_DELEG_PERM_SHAREISCSI "shareiscsi"
#define ZFS_DELEG_PERM_XATTR "xattr"
#define ZFS_DELEG_PERM_COPIES "copies"
+#define ZFS_DELEG_PERM_VERSION "version"
int dsl_deleg_get(const char *ddname, nvlist_t **nvp);
int dsl_deleg_set(const char *ddname, nvlist_t *nvp, boolean_t unset);
diff --git a/usr/src/uts/common/fs/zfs/sys/dsl_synctask.h b/usr/src/uts/common/fs/zfs/sys/dsl_synctask.h
index 9125c30b42..4995bfe5ac 100644
--- a/usr/src/uts/common/fs/zfs/sys/dsl_synctask.h
+++ b/usr/src/uts/common/fs/zfs/sys/dsl_synctask.h
@@ -46,7 +46,6 @@ typedef struct dsl_sync_task {
dsl_syncfunc_t *dst_syncfunc;
void *dst_arg1;
void *dst_arg2;
- cred_t *dst_cr;
int dst_err;
} dsl_sync_task_t;
@@ -54,9 +53,11 @@ typedef struct dsl_sync_task_group {
txg_node_t dstg_node;
list_t dstg_tasks;
struct dsl_pool *dstg_pool;
+ cred_t *dstg_cr;
uint64_t dstg_txg;
int dstg_err;
int dstg_space;
+ boolean_t dstg_nowaiter;
} dsl_sync_task_group_t;
dsl_sync_task_group_t *dsl_sync_task_group_create(struct dsl_pool *dp);
@@ -64,12 +65,16 @@ void dsl_sync_task_create(dsl_sync_task_group_t *dstg,
dsl_checkfunc_t *, dsl_syncfunc_t *,
void *arg1, void *arg2, int blocks_modified);
int dsl_sync_task_group_wait(dsl_sync_task_group_t *dstg);
+void dsl_sync_task_group_nowait(dsl_sync_task_group_t *dstg, dmu_tx_t *tx);
void dsl_sync_task_group_destroy(dsl_sync_task_group_t *dstg);
void dsl_sync_task_group_sync(dsl_sync_task_group_t *dstg, dmu_tx_t *tx);
int dsl_sync_task_do(struct dsl_pool *dp,
dsl_checkfunc_t *checkfunc, dsl_syncfunc_t *syncfunc,
void *arg1, void *arg2, int blocks_modified);
+void dsl_sync_task_do_nowait(struct dsl_pool *dp,
+ dsl_checkfunc_t *checkfunc, dsl_syncfunc_t *syncfunc,
+ void *arg1, void *arg2, int blocks_modified, dmu_tx_t *tx);
#ifdef __cplusplus
}
diff --git a/usr/src/uts/common/fs/zfs/sys/uberblock_impl.h b/usr/src/uts/common/fs/zfs/sys/uberblock_impl.h
index ab0f2dcf8c..55a0dd5aec 100644
--- a/usr/src/uts/common/fs/zfs/sys/uberblock_impl.h
+++ b/usr/src/uts/common/fs/zfs/sys/uberblock_impl.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -49,7 +49,7 @@ extern "C" {
struct uberblock {
uint64_t ub_magic; /* UBERBLOCK_MAGIC */
- uint64_t ub_version; /* ZFS_VERSION */
+ uint64_t ub_version; /* SPA_VERSION */
uint64_t ub_txg; /* txg of last sync */
uint64_t ub_guid_sum; /* sum of all vdev guids */
uint64_t ub_timestamp; /* UTC time of last sync */
diff --git a/usr/src/uts/common/fs/zfs/sys/zap.h b/usr/src/uts/common/fs/zfs/sys/zap.h
index f89d9385ea..d194705987 100644
--- a/usr/src/uts/common/fs/zfs/sys/zap.h
+++ b/usr/src/uts/common/fs/zfs/sys/zap.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -191,11 +191,13 @@ int zap_count(objset_t *ds, uint64_t zapobj, uint64_t *count);
/*
- * Returns (in name) the name of the entry whose value
+ * Returns (in name) the name of the entry whose (value & mask)
* (za_first_integer) is value, or ENOENT if not found. The string
- * pointed to by name must be at least 256 bytes long.
+ * pointed to by name must be at least 256 bytes long. If mask==0, the
+ * match must be exact (ie, same as mask=-1ULL).
*/
-int zap_value_search(objset_t *os, uint64_t zapobj, uint64_t value, char *name);
+int zap_value_search(objset_t *os, uint64_t zapobj,
+ uint64_t value, uint64_t mask, char *name);
struct zap;
struct zap_leaf;
diff --git a/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h b/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h
index d06915dfb9..912416a838 100644
--- a/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h
@@ -61,6 +61,7 @@ struct zfsvfs {
vnode_t *z_ctldir; /* .zfs directory pointer */
boolean_t z_show_ctldir; /* expose .zfs in the root dir */
boolean_t z_issnap; /* true if this is a snapshot */
+ uint64_t z_version;
#define ZFS_OBJ_MTX_SZ 64
kmutex_t z_hold_mtx[ZFS_OBJ_MTX_SZ]; /* znode hold locks */
};
diff --git a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h
index b53eed9be3..4b731ba320 100644
--- a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h
@@ -54,23 +54,11 @@ extern "C" {
/*
* special attributes for master node.
*/
-
#define ZFS_FSID "FSID"
#define ZFS_UNLINKED_SET "DELETE_QUEUE"
#define ZFS_ROOT_OBJ "ROOT"
-#define ZPL_VERSION_OBJ "VERSION"
-#define ZFS_PROP_BLOCKPERPAGE "BLOCKPERPAGE"
-#define ZFS_PROP_NOGROWBLOCKS "NOGROWBLOCKS"
-
-#define ZFS_FLAG_BLOCKPERPAGE 0x1
-#define ZFS_FLAG_NOGROWBLOCKS 0x2
-
-/*
- * ZPL version - rev'd whenever an incompatible on-disk format change
- * occurs. Independent of SPA/DMU/ZAP versioning.
- */
+#define ZPL_VERSION_STR "VERSION"
-#define ZPL_VERSION 1ULL
#define ZFS_MAX_BLOCKSIZE (SPA_MAXBLOCKSIZE)
@@ -85,14 +73,18 @@ extern "C" {
#define ZFS_MAXNAMELEN (MAXNAMELEN - 1)
/*
+ * Convert mode bits (zp_mode) to BSD-style DT_* values for storing in
+ * the directory entries.
+ */
+#define IFTODT(mode) (((mode) & S_IFMT) >> 12)
+
+/*
* The directory entry has the type (currently unused on Solaris) in the
* top 4 bits, and the object number in the low 48 bits. The "middle"
* 12 bits are unused.
*/
#define ZFS_DIRENT_TYPE(de) BF64_GET(de, 60, 4)
#define ZFS_DIRENT_OBJ(de) BF64_GET(de, 0, 48)
-#define ZFS_DIRENT_MAKE(type, obj) (((uint64_t)type << 60) | obj)
-
/*
* This is the persistent portion of the znode. It is stored
@@ -248,7 +240,7 @@ typedef struct znode {
extern int zfs_init_fs(zfsvfs_t *, znode_t **, cred_t *);
extern void zfs_set_dataprop(objset_t *);
-extern void zfs_create_fs(objset_t *os, cred_t *cr, dmu_tx_t *tx);
+extern void zfs_create_fs(objset_t *os, cred_t *cr, uint64_t, dmu_tx_t *tx);
extern void zfs_time_stamper(znode_t *, uint_t, dmu_tx_t *);
extern void zfs_time_stamper_locked(znode_t *, uint_t, dmu_tx_t *);
extern void zfs_grow_blocksize(znode_t *, uint64_t, dmu_tx_t *);
@@ -263,6 +255,8 @@ extern void zfs_remove_op_tables();
extern int zfs_create_op_tables();
extern int zfs_sync(vfs_t *vfsp, short flag, cred_t *cr);
extern dev_t zfs_cmpldev(uint64_t);
+extern int zfs_get_stats(objset_t *os, nvlist_t *nv);
+extern int zfs_set_version(const char *name, uint64_t newvers);
extern void zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, int txtype,
znode_t *dzp, znode_t *zp, char *name);
diff --git a/usr/src/uts/common/fs/zfs/vdev.c b/usr/src/uts/common/fs/zfs/vdev.c
index 9269311cf4..84b0325f34 100644
--- a/usr/src/uts/common/fs/zfs/vdev.c
+++ b/usr/src/uts/common/fs/zfs/vdev.c
@@ -395,14 +395,14 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id,
* Older versions can only support 1 parity device.
*/
if (nparity == 2 &&
- spa_version(spa) < ZFS_VERSION_RAID6)
+ spa_version(spa) < SPA_VERSION_RAID6)
return (ENOTSUP);
} else {
/*
* We require the parity to be specified for SPAs that
* support multiple parity levels.
*/
- if (spa_version(spa) >= ZFS_VERSION_RAID6)
+ if (spa_version(spa) >= SPA_VERSION_RAID6)
return (EINVAL);
/*
* Otherwise, we default to 1 parity device for RAID-Z.
@@ -1361,7 +1361,7 @@ vdev_validate_spare(vdev_t *vd)
}
if (nvlist_lookup_uint64(label, ZPOOL_CONFIG_VERSION, &version) != 0 ||
- version > ZFS_VERSION ||
+ version > SPA_VERSION ||
nvlist_lookup_uint64(label, ZPOOL_CONFIG_GUID, &guid) != 0 ||
guid != vd->vdev_guid ||
nvlist_lookup_uint64(label, ZPOOL_CONFIG_POOL_STATE, &state) != 0) {
diff --git a/usr/src/uts/common/fs/zfs/vdev_label.c b/usr/src/uts/common/fs/zfs/vdev_label.c
index 7c5487bf1a..0158228a34 100644
--- a/usr/src/uts/common/fs/zfs/vdev_label.c
+++ b/usr/src/uts/common/fs/zfs/vdev_label.c
@@ -153,6 +153,7 @@ uint64_t
vdev_label_offset(uint64_t psize, int l, uint64_t offset)
{
ASSERT(offset < sizeof (vdev_label_t));
+ ASSERT(P2PHASE_TYPED(psize, sizeof (vdev_label_t), uint64_t) == 0);
return (offset + l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ?
0 : psize - VDEV_LABELS * sizeof (vdev_label_t)));
@@ -223,7 +224,7 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
*/
ASSERT(vd->vdev_nparity == 1 ||
(vd->vdev_nparity == 2 &&
- spa_version(spa) >= ZFS_VERSION_RAID6));
+ spa_version(spa) >= SPA_VERSION_RAID6));
/*
* Note that we'll add the nparity tag even on storage pools
diff --git a/usr/src/uts/common/fs/zfs/zap.c b/usr/src/uts/common/fs/zfs/zap.c
index 715de6adf4..7dfe44baba 100644
--- a/usr/src/uts/common/fs/zfs/zap.c
+++ b/usr/src/uts/common/fs/zfs/zap.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -897,17 +897,21 @@ fzap_remove(zap_t *zap, const char *name, dmu_tx_t *tx)
}
int
-zap_value_search(objset_t *os, uint64_t zapobj, uint64_t value, char *name)
+zap_value_search(objset_t *os, uint64_t zapobj, uint64_t value, uint64_t mask,
+ char *name)
{
zap_cursor_t zc;
zap_attribute_t *za;
int err;
+ if (mask == 0)
+ mask = -1ULL;
+
za = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP);
for (zap_cursor_init(&zc, os, zapobj);
(err = zap_cursor_retrieve(&zc, za)) == 0;
zap_cursor_advance(&zc)) {
- if (za->za_first_integer == value) {
+ if ((za->za_first_integer & mask) == (value & mask)) {
(void) strcpy(name, za->za_name);
break;
}
diff --git a/usr/src/uts/common/fs/zfs/zfs_dir.c b/usr/src/uts/common/fs/zfs/zfs_dir.c
index bf459719c5..bcaa6fd4b5 100644
--- a/usr/src/uts/common/fs/zfs/zfs_dir.c
+++ b/usr/src/uts/common/fs/zfs/zfs_dir.c
@@ -516,6 +516,15 @@ zfs_rmnode(znode_t *zp)
VN_RELE(ZTOV(xzp));
}
+static uint64_t
+zfs_dirent(znode_t *zp)
+{
+ uint64_t de = zp->z_id;
+ if (zp->z_zfsvfs->z_version >= ZPL_VERSION_DIRENT_TYPE)
+ de |= IFTODT((zp)->z_phys->zp_mode) << 60;
+ return (de);
+}
+
/*
* Link zp into dl. Can only fail if zp has been unlinked.
*/
@@ -552,10 +561,7 @@ zfs_link_create(zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag)
zfs_time_stamper_locked(dzp, CONTENT_MODIFIED, tx);
mutex_exit(&dzp->z_lock);
- /*
- * MacOS X will fill in the 4-bit object type here.
- */
- value = ZFS_DIRENT_MAKE(0, zp->z_id);
+ value = zfs_dirent(zp);
error = zap_add(zp->z_zfsvfs->z_os, dzp->z_id, dl->dl_name,
8, 1, &value, tx);
ASSERT(error == 0);
diff --git a/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
index 560a943cd7..dcd9853ed8 100644
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
@@ -62,6 +62,7 @@
#include <sys/zfs_ctldir.h>
#include <sys/zvol.h>
#include <sharefs/share.h>
+#include <sys/zfs_znode.h>
#include "zfs_namecheck.h"
#include "zfs_prop.h"
@@ -82,9 +83,9 @@ typedef struct zfs_ioc_vec {
zfs_ioc_func_t *zvec_func;
zfs_secpolicy_func_t *zvec_secpolicy;
enum {
- no_name,
- pool_name,
- dataset_name
+ NO_NAME,
+ POOL_NAME,
+ DATASET_NAME
} zvec_namecheck;
boolean_t zvec_his_log;
} zfs_ioc_vec_t;
@@ -135,6 +136,10 @@ zfs_log_history(zfs_cmd_t *zc)
if (zc->zc_history == NULL)
return;
+ if (zc->zc_history_offset != LOG_CMD_POOL_CREATE &&
+ zc->zc_history_offset != LOG_CMD_NORMAL)
+ return;
+
buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP);
if (copyinstr((void *)(uintptr_t)zc->zc_history,
buf, HIS_MAX_RECORD_LEN, NULL) != 0) {
@@ -154,7 +159,7 @@ zfs_log_history(zfs_cmd_t *zc)
return;
}
- if (spa_version(spa) >= ZFS_VERSION_ZPOOL_HISTORY)
+ if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY)
(void) spa_history_log(spa, buf, zc->zc_history_offset);
spa_close(spa, FTAG);
@@ -521,8 +526,6 @@ zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr)
return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr));
}
-
-
static int
zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr)
{
@@ -847,7 +850,7 @@ zfs_ioc_pool_get_history(zfs_cmd_t *zc)
if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
return (error);
- if (spa_version(spa) < ZFS_VERSION_ZPOOL_HISTORY) {
+ if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) {
spa_close(spa, FTAG);
return (ENOTSUP);
}
@@ -1052,14 +1055,17 @@ retry:
(error = dsl_prop_get_all(os, &nv)) == 0) {
dmu_objset_stats(os, nv);
/*
- * NB: zvol_get_stats() will read the objset contents,
+ * NB: {zpl,zvol}_get_stats() will read the objset contents,
* which we aren't supposed to do with a
* DS_MODE_STANDARD open, because it could be
* inconsistent. So this is a bit of a workaround...
*/
- if (!zc->zc_objset_stats.dds_inconsistent &&
- dmu_objset_type(os) == DMU_OST_ZVOL)
- VERIFY(zvol_get_stats(os, nv) == 0);
+ if (!zc->zc_objset_stats.dds_inconsistent) {
+ if (dmu_objset_type(os) == DMU_OST_ZVOL)
+ VERIFY(zvol_get_stats(os, nv) == 0);
+ else if (dmu_objset_type(os) == DMU_OST_ZFS)
+ (void) zfs_get_stats(os, nv);
+ }
error = put_nvlist(zc, nv);
nvlist_free(nv);
}
@@ -1266,7 +1272,7 @@ zfs_set_prop_nvlist(const char *name, dev_t dev, cred_t *cr, nvlist_t *nvl)
if (spa_open(p, &spa, FTAG) == 0) {
if (spa_version(spa) <
- ZFS_VERSION_GZIP_COMPRESSION) {
+ SPA_VERSION_GZIP_COMPRESSION) {
spa_close(spa, FTAG);
return (ENOTSUP);
}
@@ -1299,8 +1305,7 @@ zfs_set_prop_nvlist(const char *name, dev_t dev, cred_t *cr, nvlist_t *nvl)
switch (prop) {
case ZFS_PROP_QUOTA:
if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
- (error = dsl_dir_set_quota(name,
- intval)) != 0)
+ (error = dsl_dir_set_quota(name, intval)) != 0)
return (error);
break;
@@ -1313,15 +1318,19 @@ zfs_set_prop_nvlist(const char *name, dev_t dev, cred_t *cr, nvlist_t *nvl)
case ZFS_PROP_VOLSIZE:
if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
- (error = zvol_set_volsize(name, dev,
- 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)
+ (error = zvol_set_volblocksize(name, intval)) != 0)
+ return (error);
+ break;
+
+ case ZFS_PROP_VERSION:
+ if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
+ (error = zfs_set_version(name, intval)) != 0)
return (error);
break;
@@ -1355,8 +1364,8 @@ zfs_set_prop_nvlist(const char *name, dev_t dev, cred_t *cr, nvlist_t *nvl)
return (EINVAL);
break;
default:
- cmn_err(CE_PANIC, "unknown property "
- "type");
+ cmn_err(CE_PANIC,
+ "unknown property type");
break;
}
@@ -1427,7 +1436,7 @@ zfs_ioc_pool_set_props(zfs_cmd_t *zc)
return (error);
}
- if (spa_version(spa) < ZFS_VERSION_BOOTFS) {
+ if (spa_version(spa) < SPA_VERSION_BOOTFS) {
nvlist_free(nvl);
spa_close(spa, FTAG);
return (ENOTSUP);
@@ -1669,7 +1678,13 @@ zfs_get_vfs(const char *resource)
static void
zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx)
{
- zfs_create_fs(os, cr, tx);
+ nvlist_t *nvprops = arg;
+ uint64_t version = ZPL_VERSION;
+
+ (void) nvlist_lookup_uint64(nvprops,
+ zfs_prop_to_name(ZFS_PROP_VERSION), &version);
+
+ zfs_create_fs(os, cr, version, tx);
}
static int
@@ -1754,6 +1769,16 @@ zfs_ioc_create(zfs_cmd_t *zc)
nvlist_free(nvprops);
return (error);
}
+ } else if (type == DMU_OST_ZFS) {
+ uint64_t version;
+
+ if (0 == nvlist_lookup_uint64(nvprops,
+ zfs_prop_to_name(ZFS_PROP_VERSION), &version) &&
+ (version < ZPL_VERSION_INITIAL ||
+ version > ZPL_VERSION)) {
+ nvlist_free(nvprops);
+ return (EINVAL);
+ }
}
error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc,
@@ -2122,54 +2147,54 @@ zfs_ioc_share(zfs_cmd_t *zc)
* of those commands.
*/
static zfs_ioc_vec_t zfs_ioc_vec[] = {
- { zfs_ioc_pool_create, zfs_secpolicy_config, pool_name, B_TRUE },
- { zfs_ioc_pool_destroy, zfs_secpolicy_config, pool_name, B_FALSE },
- { zfs_ioc_pool_import, zfs_secpolicy_config, pool_name, B_TRUE },
- { zfs_ioc_pool_export, zfs_secpolicy_config, pool_name, B_FALSE },
- { zfs_ioc_pool_configs, zfs_secpolicy_none, no_name, B_FALSE },
- { zfs_ioc_pool_stats, zfs_secpolicy_read, pool_name, B_FALSE },
- { zfs_ioc_pool_tryimport, zfs_secpolicy_config, no_name, B_FALSE },
- { zfs_ioc_pool_scrub, zfs_secpolicy_config, pool_name, B_TRUE },
- { zfs_ioc_pool_freeze, zfs_secpolicy_config, no_name, B_FALSE },
- { zfs_ioc_pool_upgrade, zfs_secpolicy_config, pool_name, B_TRUE },
- { zfs_ioc_pool_get_history, zfs_secpolicy_config, pool_name, B_FALSE },
- { zfs_ioc_vdev_add, zfs_secpolicy_config, pool_name, B_TRUE },
- { zfs_ioc_vdev_remove, zfs_secpolicy_config, pool_name, B_TRUE },
- { zfs_ioc_vdev_set_state, zfs_secpolicy_config, pool_name, B_TRUE },
- { zfs_ioc_vdev_attach, zfs_secpolicy_config, pool_name, B_TRUE },
- { zfs_ioc_vdev_detach, zfs_secpolicy_config, pool_name, B_TRUE },
- { zfs_ioc_vdev_setpath, zfs_secpolicy_config, pool_name, B_FALSE },
- { zfs_ioc_objset_stats, zfs_secpolicy_read, dataset_name, B_FALSE },
+ { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_TRUE },
+ { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE },
+ { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE },
+ { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE },
+ { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE },
+ { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE },
+ { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE },
+ { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE },
+ { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE },
+ { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE },
+ { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE },
+ { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE },
+ { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE },
+ { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE },
+ { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE },
+ { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE },
+ { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE },
+ { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE },
{ zfs_ioc_dataset_list_next, zfs_secpolicy_read,
- dataset_name, B_FALSE },
+ DATASET_NAME, B_FALSE },
{ zfs_ioc_snapshot_list_next, zfs_secpolicy_read,
- dataset_name, B_FALSE },
- { zfs_ioc_set_prop, zfs_secpolicy_none, dataset_name, B_TRUE },
- { zfs_ioc_create_minor, zfs_secpolicy_minor, dataset_name, B_FALSE },
- { zfs_ioc_remove_minor, zfs_secpolicy_minor, dataset_name, B_FALSE },
- { zfs_ioc_create, zfs_secpolicy_create, dataset_name, B_TRUE },
- { zfs_ioc_destroy, zfs_secpolicy_destroy, dataset_name, B_TRUE },
- { zfs_ioc_rollback, zfs_secpolicy_rollback, dataset_name, B_TRUE },
- { zfs_ioc_rename, zfs_secpolicy_rename, dataset_name, B_TRUE },
- { zfs_ioc_recvbackup, zfs_secpolicy_receive, dataset_name, B_TRUE },
- { zfs_ioc_sendbackup, zfs_secpolicy_send, dataset_name, B_TRUE },
- { zfs_ioc_inject_fault, zfs_secpolicy_inject, no_name, B_FALSE },
- { zfs_ioc_clear_fault, zfs_secpolicy_inject, no_name, B_FALSE },
- { zfs_ioc_inject_list_next, zfs_secpolicy_inject, no_name, B_FALSE },
- { zfs_ioc_error_log, zfs_secpolicy_inject, pool_name, B_FALSE },
- { zfs_ioc_clear, zfs_secpolicy_config, pool_name, B_TRUE },
- { zfs_ioc_promote, zfs_secpolicy_promote, dataset_name, B_TRUE },
- { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, dataset_name, B_TRUE },
- { zfs_ioc_snapshot, zfs_secpolicy_snapshot, dataset_name, B_TRUE },
- { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, pool_name, B_FALSE },
- { zfs_ioc_obj_to_path, zfs_secpolicy_config, no_name, B_FALSE },
- { zfs_ioc_pool_set_props, zfs_secpolicy_config, pool_name, B_TRUE },
- { zfs_ioc_pool_get_props, zfs_secpolicy_read, pool_name, B_FALSE },
- { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, dataset_name, B_TRUE },
- { zfs_ioc_get_fsacl, zfs_secpolicy_read, dataset_name, B_FALSE },
+ DATASET_NAME, B_FALSE },
+ { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE },
+ { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE },
+ { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE },
+ { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE },
+ { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE },
+ { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE },
+ { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE },
+ { zfs_ioc_recvbackup, zfs_secpolicy_receive, DATASET_NAME, B_TRUE },
+ { zfs_ioc_sendbackup, zfs_secpolicy_send, DATASET_NAME, B_TRUE },
+ { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE },
+ { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE },
+ { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE },
+ { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE },
+ { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE },
+ { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE },
+ { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE },
+ { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE },
+ { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE },
+ { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE },
+ { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE },
+ { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE },
+ { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE },
+ { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE },
{ zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi,
- dataset_name, B_FALSE },
- { zfs_ioc_share, zfs_secpolicy_share, dataset_name, B_FALSE }
+ DATASET_NAME, B_FALSE },
+ { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }
};
static int
@@ -2204,17 +2229,17 @@ zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
if (error == 0) {
zc->zc_name[sizeof (zc->zc_name) - 1] = '\0';
switch (zfs_ioc_vec[vec].zvec_namecheck) {
- case pool_name:
+ case POOL_NAME:
if (pool_namecheck(zc->zc_name, NULL, NULL) != 0)
error = EINVAL;
break;
- case dataset_name:
+ case DATASET_NAME:
if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0)
error = EINVAL;
break;
- case no_name:
+ case NO_NAME:
break;
}
}
@@ -2328,7 +2353,7 @@ static struct dev_ops zfs_dev_ops = {
};
static struct modldrv zfs_modldrv = {
- &mod_driverops, "ZFS storage pool version " ZFS_VERSION_STRING,
+ &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING,
&zfs_dev_ops
};
diff --git a/usr/src/uts/common/fs/zfs/zfs_vfsops.c b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
index 40915bfec5..f849bf98de 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
@@ -628,10 +628,33 @@ zfs_domount(vfs_t *vfsp, char *osname, cred_t *cr)
if (error)
goto out;
- zfs_unlinked_drain(zfsvfs);
+ if (!(zfsvfs->z_vfs->vfs_flag & VFS_RDONLY))
+ zfs_unlinked_drain(zfsvfs);
/*
* Parse and replay the intent log.
+ *
+ * Because of ziltest, this must be done after
+ * zfs_unlinked_drain(). (Further note: ziltest doesn't
+ * use readonly mounts, where zfs_unlinked_drain() isn't
+ * called.) This is because ziltest causes spa_sync()
+ * to think it's committed, but actually it is not, so
+ * the intent log contains many txg's worth of changes.
+ *
+ * In particular, if object N is in the unlinked set in
+ * the last txg to actually sync, then it could be
+ * actually freed in a later txg and then reallocated in
+ * a yet later txg. This would write a "create object
+ * N" record to the intent log. Normally, this would be
+ * fine because the spa_sync() would have written out
+ * the fact that object N is free, before we could write
+ * the "create object N" intent log record.
+ *
+ * But when we are in ziltest mode, we advance the "open
+ * txg" without actually spa_sync()-ing the changes to
+ * disk. So we would see that object N is still
+ * allocated and in the unlinked set, and there is an
+ * intent log record saying to allocate it.
*/
zil_replay(zfsvfs->z_os, zfsvfs, &zfsvfs->z_assign,
zfs_replay_vector);
@@ -652,7 +675,6 @@ out:
}
return (error);
-
}
void
@@ -717,7 +739,6 @@ str_to_uint64(char *str, uint64_t *objnum)
return (0);
}
-
/*
* The boot path passed from the boot loader is in the form of
* "rootpool-name/root-filesystem-object-number'. Convert this
@@ -817,13 +838,10 @@ out:
vfs_unlock(vfsp);
ret = (error) ? error : 0;
return (ret);
-
} else if (why == ROOT_REMOUNT) {
-
readonly_changed_cb(vfsp->vfs_data, B_FALSE);
vfsp->vfs_flag |= VFS_REMOUNT;
return (zfs_refresh_properties(vfsp));
-
} else if (why == ROOT_UNMOUNT) {
zfs_unregister_callbacks((zfsvfs_t *)vfsp->vfs_data);
(void) zfs_sync(vfsp, 0, 0);
@@ -873,9 +891,8 @@ zfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
* When doing a remount, we simply refresh our temporary properties
* according to those options set in the current VFS options.
*/
- if (uap->flags & MS_REMOUNT) {
+ if (uap->flags & MS_REMOUNT)
return (zfs_refresh_properties(vfsp));
- }
/*
* Get the objset name (the "special" mount argument).
@@ -1347,6 +1364,70 @@ zfs_busy(void)
return (zfs_active_fs_count != 0);
}
+int
+zfs_get_stats(objset_t *os, nvlist_t *nv)
+{
+ int error;
+ uint64_t val;
+
+ error = zap_lookup(os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 8, 1, &val);
+ if (error == 0)
+ dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_VERSION, val);
+
+ return (error);
+}
+
+int
+zfs_set_version(const char *name, uint64_t newvers)
+{
+ int error;
+ objset_t *os;
+ dmu_tx_t *tx;
+ uint64_t curvers;
+
+ /*
+ * XXX for now, require that the filesystem be unmounted. Would
+ * be nice to find the zfsvfs_t and just update that if
+ * possible.
+ */
+
+ if (newvers < ZPL_VERSION_INITIAL || newvers > ZPL_VERSION)
+ return (EINVAL);
+
+ error = dmu_objset_open(name, DMU_OST_ZFS, DS_MODE_PRIMARY, &os);
+ if (error)
+ return (error);
+
+ error = zap_lookup(os, MASTER_NODE_OBJ, ZPL_VERSION_STR,
+ 8, 1, &curvers);
+ if (error)
+ goto out;
+ if (newvers < curvers) {
+ error = EINVAL;
+ goto out;
+ }
+
+ tx = dmu_tx_create(os);
+ dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, 0, ZPL_VERSION_STR);
+ error = dmu_tx_assign(tx, TXG_WAIT);
+ if (error) {
+ dmu_tx_abort(tx);
+ goto out;
+ }
+ error = zap_update(os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 8, 1,
+ &newvers, tx);
+
+ spa_history_internal_log(LOG_DS_UPGRADE,
+ dmu_objset_spa(os), tx, CRED(),
+ "oldver=%llu newver=%llu dataset = %llu", curvers, newvers,
+ dmu_objset_id(os));
+ dmu_tx_commit(tx);
+
+out:
+ dmu_objset_close(os);
+ return (error);
+}
+
static vfsdef_t vfw = {
VFSDEF_VERSION,
MNTTYPE_ZFS,
@@ -1356,5 +1437,5 @@ static vfsdef_t vfw = {
};
struct modlfs zfs_modlfs = {
- &mod_fsops, "ZFS filesystem version " ZFS_VERSION_STRING, &vfw
+ &mod_fsops, "ZFS filesystem version " SPA_VERSION_STRING, &vfw
};
diff --git a/usr/src/uts/common/fs/zfs/zfs_znode.c b/usr/src/uts/common/fs/zfs/zfs_znode.c
index be7522ee80..8a39bb1602 100644
--- a/usr/src/uts/common/fs/zfs/zfs_znode.c
+++ b/usr/src/uts/common/fs/zfs/zfs_znode.c
@@ -250,7 +250,6 @@ zfs_init_fs(zfsvfs_t *zfsvfs, znode_t **zpp, cred_t *cr)
extern int zfsfstype;
objset_t *os = zfsvfs->z_os;
- uint64_t version = ZPL_VERSION;
int i, error;
dmu_object_info_t doi;
uint64_t fsid_guid;
@@ -269,19 +268,19 @@ zfs_init_fs(zfsvfs_t *zfsvfs, znode_t **zpp, cred_t *cr)
dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); /* root node */
error = dmu_tx_assign(tx, TXG_WAIT);
ASSERT3U(error, ==, 0);
- zfs_create_fs(os, cr, tx);
+ zfs_create_fs(os, cr, ZPL_VERSION, tx);
dmu_tx_commit(tx);
}
- error = zap_lookup(os, MASTER_NODE_OBJ, ZPL_VERSION_OBJ, 8, 1,
- &version);
+ error = zap_lookup(os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 8, 1,
+ &zfsvfs->z_version);
if (error) {
return (error);
- } else if (version != ZPL_VERSION) {
+ } else if (zfsvfs->z_version > ZPL_VERSION) {
(void) printf("Mismatched versions: File system "
"is version %lld on-disk format, which is "
"incompatible with this software version %lld!",
- (u_longlong_t)version, ZPL_VERSION);
+ (u_longlong_t)zfsvfs->z_version, ZPL_VERSION);
return (ENOTSUP);
}
@@ -1040,11 +1039,10 @@ zfs_freesp(znode_t *zp, uint64_t off, uint64_t len, int flag, boolean_t log)
}
void
-zfs_create_fs(objset_t *os, cred_t *cr, dmu_tx_t *tx)
+zfs_create_fs(objset_t *os, cred_t *cr, uint64_t version, dmu_tx_t *tx)
{
zfsvfs_t zfsvfs;
uint64_t moid, doid, roid = 0;
- uint64_t version = ZPL_VERSION;
int error;
znode_t *rootzp = NULL;
vnode_t *vp;
@@ -1066,7 +1064,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, dmu_tx_t *tx)
* Set starting attributes.
*/
- error = zap_update(os, moid, ZPL_VERSION_OBJ, 8, 1, &version, tx);
+ error = zap_update(os, moid, ZPL_VERSION_STR, 8, 1, &version, tx);
ASSERT(error == 0);
/*
@@ -1176,7 +1174,8 @@ zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len)
if (is_xattrdir) {
(void) sprintf(component + 1, "<xattrdir>");
} else {
- error = zap_value_search(osp, pobj, obj, component + 1);
+ error = zap_value_search(osp, pobj, obj,
+ ZFS_DIRENT_OBJ(-1ULL), component + 1);
if (error != 0)
break;
}
diff --git a/usr/src/uts/common/sys/fs/zfs.h b/usr/src/uts/common/sys/fs/zfs.h
index 1023e31c16..5de4a0e83f 100644
--- a/usr/src/uts/common/sys/fs/zfs.h
+++ b/usr/src/uts/common/sys/fs/zfs.h
@@ -97,7 +97,8 @@ typedef enum {
ZPOOL_PROP_BOOTFS,
ZPOOL_PROP_AUTOREPLACE,
ZPOOL_PROP_DELEGATION,
- ZPOOL_PROP_NAME
+ ZFS_PROP_VERSION,
+ ZPOOL_PROP_NAME /* XXX must be last! */
} zfs_prop_t;
typedef zfs_prop_t zpool_prop_t;
@@ -172,45 +173,61 @@ extern zpool_prop_t zpool_prop_iter(zpool_prop_f, void *, boolean_t);
/*
* On-disk version number.
*/
-#define ZFS_VERSION_1 1ULL
-#define ZFS_VERSION_2 2ULL
-#define ZFS_VERSION_3 3ULL
-#define ZFS_VERSION_4 4ULL
-#define ZFS_VERSION_5 5ULL
-#define ZFS_VERSION_6 6ULL
-#define ZFS_VERSION_7 7ULL
-#define ZFS_VERSION_8 8ULL
+#define SPA_VERSION_1 1ULL
+#define SPA_VERSION_2 2ULL
+#define SPA_VERSION_3 3ULL
+#define SPA_VERSION_4 4ULL
+#define SPA_VERSION_5 5ULL
+#define SPA_VERSION_6 6ULL
+#define SPA_VERSION_7 7ULL
+#define SPA_VERSION_8 8ULL
/*
- * When bumping up ZFS_VERSION, make sure GRUB ZFS understand the on-disk
+ * When bumping up SPA_VERSION, make sure GRUB ZFS understand the on-disk
* format change. Go to usr/src/grub/grub-0.95/stage2/{zfs-include/, fsys_zfs*},
* and do the appropriate changes.
*/
-#define ZFS_VERSION ZFS_VERSION_8
-#define ZFS_VERSION_STRING "8"
+#define SPA_VERSION SPA_VERSION_8
+#define SPA_VERSION_STRING "8"
/*
- * Symbolic names for the changes that caused a ZFS_VERSION switch.
+ * Symbolic names for the changes that caused a SPA_VERSION switch.
* Used in the code when checking for presence or absence of a feature.
* Feel free to define multiple symbolic names for each version if there
* were multiple changes to on-disk structures during that version.
*
- * NOTE: When checking the current ZFS_VERSION in your code, be sure
+ * NOTE: When checking the current SPA_VERSION in your code, be sure
* to use spa_version() since it reports the version of the
* last synced uberblock. Checking the in-flight version can
* be dangerous in some cases.
*/
-#define ZFS_VERSION_INITIAL ZFS_VERSION_1
-#define ZFS_VERSION_DITTO_BLOCKS ZFS_VERSION_2
-#define ZFS_VERSION_SPARES ZFS_VERSION_3
-#define ZFS_VERSION_RAID6 ZFS_VERSION_3
-#define ZFS_VERSION_BPLIST_ACCOUNT ZFS_VERSION_3
-#define ZFS_VERSION_RAIDZ_DEFLATE ZFS_VERSION_3
-#define ZFS_VERSION_DNODE_BYTES ZFS_VERSION_3
-#define ZFS_VERSION_ZPOOL_HISTORY ZFS_VERSION_4
-#define ZFS_VERSION_GZIP_COMPRESSION ZFS_VERSION_5
-#define ZFS_VERSION_BOOTFS ZFS_VERSION_6
-#define ZFS_VERSION_SLOGS ZFS_VERSION_7
-#define ZFS_VERSION_DELEGATED_PERMS ZFS_VERSION_8
+#define SPA_VERSION_INITIAL SPA_VERSION_1
+#define SPA_VERSION_DITTO_BLOCKS SPA_VERSION_2
+#define SPA_VERSION_SPARES SPA_VERSION_3
+#define SPA_VERSION_RAID6 SPA_VERSION_3
+#define SPA_VERSION_BPLIST_ACCOUNT SPA_VERSION_3
+#define SPA_VERSION_RAIDZ_DEFLATE SPA_VERSION_3
+#define SPA_VERSION_DNODE_BYTES SPA_VERSION_3
+#define SPA_VERSION_ZPOOL_HISTORY SPA_VERSION_4
+#define SPA_VERSION_GZIP_COMPRESSION SPA_VERSION_5
+#define SPA_VERSION_BOOTFS SPA_VERSION_6
+#define ZFS_VERSION_SLOGS SPA_VERSION_7
+#define ZFS_VERSION_DELEGATED_PERMS SPA_VERSION_8
+
+/*
+ * ZPL version - rev'd whenever an incompatible on-disk format change
+ * occurs. This is independent of SPA/DMU/ZAP versioning. You must
+ * also update the version_table[] and help message in zfs_prop.c.
+ *
+ * When changing, be sure to teach GRUB how to read the new format!
+ * See usr/src/grub/grub-0.95/stage2/{zfs-include/,fsys_zfs*}
+ */
+#define ZPL_VERSION_1 1ULL
+#define ZPL_VERSION_2 2ULL
+#define ZPL_VERSION ZPL_VERSION_2
+#define ZPL_VERSION_STRING "2"
+
+#define ZPL_VERSION_INITIAL ZPL_VERSION_1
+#define ZPL_VERSION_DIRENT_TYPE ZPL_VERSION_2
/*
* The following are configuration names used in the nvlist describing a pool's
@@ -556,6 +573,7 @@ typedef enum history_internal_events {
LOG_DS_REPLAY_FULL_SYNC,
LOG_DS_ROLLBACK,
LOG_DS_SNAPSHOT,
+ LOG_DS_UPGRADE,
LOG_END
} history_internal_events_t;