diff options
Diffstat (limited to 'usr/src')
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; | 
