summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorahrens <none@none>2007-06-29 16:23:19 -0700
committerahrens <none@none>2007-06-29 16:23:19 -0700
commite7437265dc2a4920c197ed4337665539d358b22c (patch)
tree9c7cdf5fccdef976501b70787140cd3fe7260a3e /usr/src
parent5cb4fc8151d97cf08a87f2d1011efed091d169ea (diff)
downloadillumos-joyent-e7437265dc2a4920c197ed4337665539d358b22c.tar.gz
PSARC/2007/328 zfs upgrade
6552536 'zpool status -v' doesn't work with new (type-bearing) directory entries 6559635 can not import pool whose front labels are gone 6572636 need "zfs upgrade" to change ZPL version number 6572637 store object type in directory entries. 6572648 ZPL's delete queue should not be processed if the filesystem is mounted read-only 6572650 ZFS_VERSION should be SPA_VERSION for readability
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;