mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +03:00 
			
		
		
		
	Add "compatibility" property for zpool feature sets
Property to allow sets of features to be specified; for compatibility with specific versions / releases / external systems. Influences the behavior of 'zpool upgrade' and 'zpool create'. Initial man page changes and test cases included. Brief synopsis: zpool create -o compatibility=off|legacy|file[,file...] pool vdev... compatibility = off : disable compatibility mode (enable all features) compatibility = legacy : request that no features be enabled compatibility = file[,file...] : read features from specified files. Only features present in *all* files will be enabled on the resulting pool. Filenames may be absolute, or relative to /etc/zfs/compatibility.d or /usr/share/zfs/compatibility.d (/etc checked first). Only affects zpool create, zpool upgrade and zpool status. ABI changes in libzfs: * New function "zpool_load_compat" to load and parse compat sets. * Add "zpool_compat_status_t" typedef for compatibility parse status. * Add ZPOOL_PROP_COMPATIBILITY to the pool properties enum * Add ZPOOL_STATUS_COMPATIBILITY_ERR to the pool status enum An initial set of base compatibility sets are included in cmd/zpool/compatibility.d, and the Makefile for cmd/zpool is modified to install these in $pkgdatadir/compatibility.d and to create symbolic links to a reasonable set of aliases. Reviewed-by: ericloewe Reviewed-by: Matthew Ahrens <mahrens@delphix.com> Reviewed-by: Richard Laager <rlaager@wiktel.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Colm Buckley <colm@tuatha.org> Closes #11468
This commit is contained in:
		
							parent
							
								
									35ec51796f
								
							
						
					
					
						commit
						658fb8020f
					
				| @ -39,7 +39,7 @@ include $(top_srcdir)/config/CppCheck.am | ||||
| zpoolconfdir = $(sysconfdir)/zfs/zpool.d | ||||
| zpoolexecdir = $(zfsexecdir)/zpool.d | ||||
| 
 | ||||
| EXTRA_DIST = zpool.d/README | ||||
| EXTRA_DIST = zpool.d/README compatibility.d | ||||
| 
 | ||||
| dist_zpoolexec_SCRIPTS = \
 | ||||
| 	zpool.d/dm-deps \
 | ||||
| @ -129,6 +129,48 @@ zpoolconfdefaults = \ | ||||
| 	test_progress \
 | ||||
| 	test_ended | ||||
| 
 | ||||
| zpoolcompatdir = $(pkgdatadir)/compatibility.d | ||||
| 
 | ||||
| dist_zpoolcompat_DATA = \
 | ||||
| 	compatibility.d/compat-2018 \
 | ||||
| 	compatibility.d/compat-2019 \
 | ||||
| 	compatibility.d/compat-2020 \
 | ||||
| 	compatibility.d/compat-2021 \
 | ||||
| 	compatibility.d/freebsd-11.0 \
 | ||||
| 	compatibility.d/freebsd-11.2 \
 | ||||
| 	compatibility.d/freebsd-11.3 \
 | ||||
| 	compatibility.d/freenas-9.10.2 \
 | ||||
| 	compatibility.d/grub2 \
 | ||||
| 	compatibility.d/openzfsonosx-1.7.0 \
 | ||||
| 	compatibility.d/openzfsonosx-1.8.1 \
 | ||||
| 	compatibility.d/openzfsonosx-1.9.3 \
 | ||||
| 	compatibility.d/openzfs-2.0-freebsd \
 | ||||
| 	compatibility.d/openzfs-2.0-linux \
 | ||||
| 	compatibility.d/zol-0.6.5 \
 | ||||
| 	compatibility.d/zol-0.7 \
 | ||||
| 	compatibility.d/zol-0.8 | ||||
| 
 | ||||
| # canonical <- alias symbolic link pairs
 | ||||
| # eg: "2018" is a link to "compat-2018"
 | ||||
| zpoolcompatlinks = \
 | ||||
| 	"compat-2018		2018" \
 | ||||
| 	"compat-2019		2019" \
 | ||||
| 	"compat-2020		2020" \
 | ||||
| 	"compat-2021		2021" \
 | ||||
| 	"freebsd-11.0		freebsd-11.1" \
 | ||||
| 	"freebsd-11.0		freenas-11.0" \
 | ||||
| 	"freebsd-11.2		freenas-11.2" \
 | ||||
| 	"freebsd-11.3		freebsd-11.4" \
 | ||||
| 	"freebsd-11.3		freebsd-12.0" \
 | ||||
| 	"freebsd-11.3		freebsd-12.1" \
 | ||||
| 	"freebsd-11.3		freebsd-12.2" \
 | ||||
| 	"freebsd-11.3		freenas-11.3" \
 | ||||
| 	"freenas-11.0		freenas-11.1" \
 | ||||
| 	"openzfsonosx-1.9.3	openzfsonosx-1.9.4" \
 | ||||
| 	"openzfs-2.0-freebsd	truenas-12.0" \
 | ||||
| 	"zol-0.7		ubuntu-18.04" \
 | ||||
| 	"zol-0.8		ubuntu-20.04" | ||||
| 
 | ||||
| install-data-hook: | ||||
| 	$(MKDIR_P) "$(DESTDIR)$(zpoolconfdir)" | ||||
| 	for f in $(zpoolconfdefaults); do \
 | ||||
| @ -136,3 +178,6 @@ install-data-hook: | ||||
| 	       -L "$(DESTDIR)$(zpoolconfdir)/$${f}" || \
 | ||||
| 	    ln -s "$(zpoolexecdir)/$${f}" "$(DESTDIR)$(zpoolconfdir)"; \
 | ||||
| 	done | ||||
| 	for l in $(zpoolcompatlinks); do \
 | ||||
| 		(cd "$(DESTDIR)$(zpoolcompatdir)"; ln -s $${l} ); \
 | ||||
| 	done | ||||
|  | ||||
							
								
								
									
										12
									
								
								cmd/zpool/compatibility.d/compat-2018
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								cmd/zpool/compatibility.d/compat-2018
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| # Features supported by all Tier 1 platforms as of 2018 | ||||
| async_destroy | ||||
| bookmarks | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| lz4_compress | ||||
| spacemap_histogram | ||||
							
								
								
									
										15
									
								
								cmd/zpool/compatibility.d/compat-2019
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								cmd/zpool/compatibility.d/compat-2019
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| # Features supported by all Tier 1 platforms as of 2019 | ||||
| async_destroy | ||||
| bookmarks | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| lz4_compress | ||||
| multi_vdev_crash_dump | ||||
| sha512 | ||||
| skein | ||||
| spacemap_histogram | ||||
							
								
								
									
										15
									
								
								cmd/zpool/compatibility.d/compat-2020
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								cmd/zpool/compatibility.d/compat-2020
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| # Features supported by all Tier 1 platforms as of 2020 | ||||
| async_destroy | ||||
| bookmarks | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| lz4_compress | ||||
| multi_vdev_crash_dump | ||||
| sha512 | ||||
| skein | ||||
| spacemap_histogram | ||||
							
								
								
									
										19
									
								
								cmd/zpool/compatibility.d/compat-2021
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								cmd/zpool/compatibility.d/compat-2021
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| # Features supported by all Tier 1 platforms as of 2021 | ||||
| async_destroy | ||||
| bookmarks | ||||
| device_removal | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| lz4_compress | ||||
| multi_vdev_crash_dump | ||||
| obsolete_counts | ||||
| sha512 | ||||
| skein | ||||
| spacemap_histogram | ||||
| spacemap_v2 | ||||
| zpool_checkpoint | ||||
							
								
								
									
										15
									
								
								cmd/zpool/compatibility.d/freebsd-11.0
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								cmd/zpool/compatibility.d/freebsd-11.0
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| # Features supported by FreeBSD 11.0 | ||||
| async_destroy | ||||
| bookmarks | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| lz4_compress | ||||
| multi_vdev_crash_dump | ||||
| sha512 | ||||
| skein | ||||
| spacemap_histogram | ||||
							
								
								
									
										18
									
								
								cmd/zpool/compatibility.d/freebsd-11.2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								cmd/zpool/compatibility.d/freebsd-11.2
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| # Features supported by FreeBSD 11.2 | ||||
| async_destroy | ||||
| bookmarks | ||||
| device_removal | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| lz4_compress | ||||
| multi_vdev_crash_dump | ||||
| obsolete_counts | ||||
| sha512 | ||||
| skein | ||||
| spacemap_histogram | ||||
| zpool_checkpoint | ||||
							
								
								
									
										19
									
								
								cmd/zpool/compatibility.d/freebsd-11.3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								cmd/zpool/compatibility.d/freebsd-11.3
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| # Features supported by FreeBSD 11.3 | ||||
| async_destroy | ||||
| bookmarks | ||||
| device_removal | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| lz4_compress | ||||
| multi_vdev_crash_dump | ||||
| obsolete_counts | ||||
| sha512 | ||||
| skein | ||||
| spacemap_histogram | ||||
| spacemap_v2 | ||||
| zpool_checkpoint | ||||
							
								
								
									
										13
									
								
								cmd/zpool/compatibility.d/freenas-9.10.2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								cmd/zpool/compatibility.d/freenas-9.10.2
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| # Features supported by FreeNAS 9.10.2 | ||||
| async_destroy | ||||
| bookmarks | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| lz4_compress | ||||
| multi_vdev_crash_dump | ||||
| spacemap_histogram | ||||
							
								
								
									
										12
									
								
								cmd/zpool/compatibility.d/grub2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								cmd/zpool/compatibility.d/grub2
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| # Features which are supported by GRUB2 | ||||
| async_destroy | ||||
| bookmarks | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| lz4_compress | ||||
| spacemap_histogram | ||||
							
								
								
									
										33
									
								
								cmd/zpool/compatibility.d/openzfs-2.0-freebsd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								cmd/zpool/compatibility.d/openzfs-2.0-freebsd
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| # Features supported by OpenZFS 2.0 on FreeBSD | ||||
| allocation_classes | ||||
| async_destroy | ||||
| bookmark_v2 | ||||
| bookmark_written | ||||
| bookmarks | ||||
| device_rebuild | ||||
| device_removal | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| encryption | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| large_dnode | ||||
| livelist | ||||
| log_spacemap | ||||
| lz4_compress | ||||
| multi_vdev_crash_dump | ||||
| obsolete_counts | ||||
| project_quota | ||||
| redacted_datasets | ||||
| redaction_bookmarks | ||||
| resilver_defer | ||||
| sha512 | ||||
| skein | ||||
| spacemap_histogram | ||||
| spacemap_v2 | ||||
| userobj_accounting | ||||
| zpool_checkpoint | ||||
| zstd_compress | ||||
							
								
								
									
										34
									
								
								cmd/zpool/compatibility.d/openzfs-2.0-linux
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								cmd/zpool/compatibility.d/openzfs-2.0-linux
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| # Features supported by OpenZFS 2.0 on Linux | ||||
| allocation_classes | ||||
| async_destroy | ||||
| bookmark_v2 | ||||
| bookmark_written | ||||
| bookmarks | ||||
| device_rebuild | ||||
| device_removal | ||||
| edonr | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| encryption | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| large_dnode | ||||
| livelist | ||||
| log_spacemap | ||||
| lz4_compress | ||||
| multi_vdev_crash_dump | ||||
| obsolete_counts | ||||
| project_quota | ||||
| redacted_datasets | ||||
| redaction_bookmarks | ||||
| resilver_defer | ||||
| sha512 | ||||
| skein | ||||
| spacemap_histogram | ||||
| spacemap_v2 | ||||
| userobj_accounting | ||||
| zpool_checkpoint | ||||
| zstd_compress | ||||
							
								
								
									
										16
									
								
								cmd/zpool/compatibility.d/openzfsonosx-1.7.0
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								cmd/zpool/compatibility.d/openzfsonosx-1.7.0
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| # Features supported by OpenZFSonOSX 1.7.0 | ||||
| async_destroy | ||||
| bookmarks | ||||
| edonr | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| lz4_compress | ||||
| multi_vdev_crash_dump | ||||
| sha512 | ||||
| skein | ||||
| spacemap_histogram | ||||
							
								
								
									
										21
									
								
								cmd/zpool/compatibility.d/openzfsonosx-1.8.1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								cmd/zpool/compatibility.d/openzfsonosx-1.8.1
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| # Features supported by OpenZFSonOSX 1.8.1 | ||||
| async_destroy | ||||
| bookmarks | ||||
| device_removal | ||||
| edonr | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| encryption | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| lz4_compress | ||||
| multi_vdev_crash_dump | ||||
| obsolete_counts | ||||
| sha512 | ||||
| skein | ||||
| spacemap_histogram | ||||
| spacemap_v2 | ||||
| zpool_checkpoint | ||||
							
								
								
									
										27
									
								
								cmd/zpool/compatibility.d/openzfsonosx-1.9.3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								cmd/zpool/compatibility.d/openzfsonosx-1.9.3
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| # Features supported by OpenZFSonOSX 1.9.3 | ||||
| allocation_classes | ||||
| async_destroy | ||||
| bookmark_v2 | ||||
| bookmarks | ||||
| device_removal | ||||
| edonr | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| encryption | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| large_dnode | ||||
| lz4_compress | ||||
| multi_vdev_crash_dump | ||||
| obsolete_counts | ||||
| project_quota | ||||
| resilver_defer | ||||
| sha512 | ||||
| skein | ||||
| spacemap_histogram | ||||
| spacemap_v2 | ||||
| userobj_accounting | ||||
| zpool_checkpoint | ||||
							
								
								
									
										12
									
								
								cmd/zpool/compatibility.d/zol-0.6.5
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								cmd/zpool/compatibility.d/zol-0.6.5
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| # Features supported by ZFSonLinux v0.6.5 | ||||
| async_destroy | ||||
| bookmarks | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| lz4_compress | ||||
| spacemap_histogram | ||||
							
								
								
									
										18
									
								
								cmd/zpool/compatibility.d/zol-0.7
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								cmd/zpool/compatibility.d/zol-0.7
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| # Features supported by ZFSonLinux v0.7 | ||||
| async_destroy | ||||
| bookmarks | ||||
| edonr | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| large_dnode | ||||
| lz4_compress | ||||
| multi_vdev_crash_dump | ||||
| sha512 | ||||
| skein | ||||
| spacemap_histogram | ||||
| userobj_accounting | ||||
							
								
								
									
										27
									
								
								cmd/zpool/compatibility.d/zol-0.8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								cmd/zpool/compatibility.d/zol-0.8
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| # Features supported by ZFSonLinux v0.8 | ||||
| allocation_classes | ||||
| async_destroy | ||||
| bookmark_v2 | ||||
| bookmarks | ||||
| device_removal | ||||
| edonr | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| encryption | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| large_dnode | ||||
| lz4_compress | ||||
| multi_vdev_crash_dump | ||||
| obsolete_counts | ||||
| project_quota | ||||
| resilver_defer | ||||
| sha512 | ||||
| skein | ||||
| spacemap_histogram | ||||
| spacemap_v2 | ||||
| userobj_accounting | ||||
| zpool_checkpoint | ||||
| @ -31,6 +31,7 @@ | ||||
|  * Copyright (c) 2017 Open-E, Inc. All Rights Reserved. | ||||
|  * Copyright (c) 2017, Intel Corporation. | ||||
|  * Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com> | ||||
|  * Copyright (c) 2021, Colm Buckley <colm@tuatha.org> | ||||
|  */ | ||||
| 
 | ||||
| #include <assert.h> | ||||
| @ -124,6 +125,9 @@ static int zpool_do_version(int, char **); | ||||
| 
 | ||||
| static int zpool_do_wait(int, char **); | ||||
| 
 | ||||
| static zpool_compat_status_t zpool_do_load_compat( | ||||
|     const char *, boolean_t *); | ||||
| 
 | ||||
| /*
 | ||||
|  * These libumem hooks provide a reasonable set of defaults for the allocator's | ||||
|  * debugging facilities. | ||||
| @ -782,6 +786,8 @@ add_prop_list(const char *propname, char *propval, nvlist_t **props, | ||||
| 
 | ||||
| 	if (poolprop) { | ||||
| 		const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION); | ||||
| 		const char *fname = | ||||
| 		    zpool_prop_to_name(ZPOOL_PROP_COMPATIBILITY); | ||||
| 
 | ||||
| 		if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL && | ||||
| 		    !zpool_prop_feature(propname)) { | ||||
| @ -804,6 +810,19 @@ add_prop_list(const char *propname, char *propval, nvlist_t **props, | ||||
| 			return (2); | ||||
| 		} | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * compatibility property and version should not be specified | ||||
| 		 * at the same time. | ||||
| 		 */ | ||||
| 		if ((prop == ZPOOL_PROP_COMPATIBILITY && | ||||
| 		    nvlist_exists(proplist, vname)) || | ||||
| 		    (prop == ZPOOL_PROP_VERSION && | ||||
| 		    nvlist_exists(proplist, fname))) { | ||||
| 			(void) fprintf(stderr, gettext("'compatibility' and " | ||||
| 			    "'version' properties cannot be specified " | ||||
| 			    "together\n")); | ||||
| 			return (2); | ||||
| 		} | ||||
| 
 | ||||
| 		if (zpool_prop_feature(propname)) | ||||
| 			normnm = propname; | ||||
| @ -1374,13 +1393,15 @@ zpool_do_create(int argc, char **argv) | ||||
| { | ||||
| 	boolean_t force = B_FALSE; | ||||
| 	boolean_t dryrun = B_FALSE; | ||||
| 	boolean_t enable_all_pool_feat = B_TRUE; | ||||
| 	boolean_t enable_pool_features = B_TRUE; | ||||
| 
 | ||||
| 	int c; | ||||
| 	nvlist_t *nvroot = NULL; | ||||
| 	char *poolname; | ||||
| 	char *tname = NULL; | ||||
| 	int ret = 1; | ||||
| 	char *altroot = NULL; | ||||
| 	char *compat = NULL; | ||||
| 	char *mountpoint = NULL; | ||||
| 	nvlist_t *fsprops = NULL; | ||||
| 	nvlist_t *props = NULL; | ||||
| @ -1396,7 +1417,7 @@ zpool_do_create(int argc, char **argv) | ||||
| 			dryrun = B_TRUE; | ||||
| 			break; | ||||
| 		case 'd': | ||||
| 			enable_all_pool_feat = B_FALSE; | ||||
| 			enable_pool_features = B_FALSE; | ||||
| 			break; | ||||
| 		case 'R': | ||||
| 			altroot = optarg; | ||||
| @ -1434,11 +1455,14 @@ zpool_do_create(int argc, char **argv) | ||||
| 				ver = strtoull(propval, &end, 10); | ||||
| 				if (*end == '\0' && | ||||
| 				    ver < SPA_VERSION_FEATURES) { | ||||
| 					enable_all_pool_feat = B_FALSE; | ||||
| 					enable_pool_features = B_FALSE; | ||||
| 				} | ||||
| 			} | ||||
| 			if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT) | ||||
| 				altroot = propval; | ||||
| 			if (zpool_name_to_prop(optarg) == | ||||
| 			    ZPOOL_PROP_COMPATIBILITY) | ||||
| 				compat = propval; | ||||
| 			break; | ||||
| 		case 'O': | ||||
| 			if ((propval = strchr(optarg, '=')) == NULL) { | ||||
| @ -1632,10 +1656,26 @@ zpool_do_create(int argc, char **argv) | ||||
| 		ret = 0; | ||||
| 	} else { | ||||
| 		/*
 | ||||
| 		 * Hand off to libzfs. | ||||
| 		 * Load in feature set. | ||||
| 		 * Note: if compatibility property not given, we'll have | ||||
| 		 * NULL, which means 'all features'. | ||||
| 		 */ | ||||
| 		spa_feature_t i; | ||||
| 		for (i = 0; i < SPA_FEATURES; i++) { | ||||
| 		boolean_t requested_features[SPA_FEATURES]; | ||||
| 		if (zpool_do_load_compat(compat, requested_features) != | ||||
| 		    ZPOOL_COMPATIBILITY_OK) | ||||
| 			goto errout; | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * props contains list of features to enable. | ||||
| 		 * For each feature: | ||||
| 		 *  - remove it if feature@name=disabled | ||||
| 		 *  - leave it there if feature@name=enabled | ||||
| 		 *  - add it if: | ||||
| 		 *    - enable_pool_features (ie: no '-d' or '-o version') | ||||
| 		 *    - it's supported by the kernel module | ||||
| 		 *    - it's in the requested feature set | ||||
| 		 */ | ||||
| 		for (spa_feature_t i = 0; i < SPA_FEATURES; i++) { | ||||
| 			char propname[MAXPATHLEN]; | ||||
| 			char *propval; | ||||
| 			zfeature_info_t *feat = &spa_feature_table[i]; | ||||
| @ -1643,18 +1683,14 @@ zpool_do_create(int argc, char **argv) | ||||
| 			(void) snprintf(propname, sizeof (propname), | ||||
| 			    "feature@%s", feat->fi_uname); | ||||
| 
 | ||||
| 			/*
 | ||||
| 			 * Only features contained in props will be enabled: | ||||
| 			 * remove from the nvlist every ZFS_FEATURE_DISABLED | ||||
| 			 * value and add every missing ZFS_FEATURE_ENABLED if | ||||
| 			 * enable_all_pool_feat is set. | ||||
| 			 */ | ||||
| 			if (!nvlist_lookup_string(props, propname, &propval)) { | ||||
| 				if (strcmp(propval, ZFS_FEATURE_DISABLED) == 0) | ||||
| 					(void) nvlist_remove_all(props, | ||||
| 					    propname); | ||||
| 			} else if (enable_all_pool_feat && | ||||
| 			    feat->fi_zfs_mod_supported) { | ||||
| 			} else if ( | ||||
| 			    enable_pool_features && | ||||
| 			    feat->fi_zfs_mod_supported && | ||||
| 			    requested_features[i]) { | ||||
| 				ret = add_prop_list(propname, | ||||
| 				    ZFS_FEATURE_ENABLED, &props, B_TRUE); | ||||
| 				if (ret != 0) | ||||
| @ -2674,8 +2710,15 @@ show_import(nvlist_t *config) | ||||
| 
 | ||||
| 	case ZPOOL_STATUS_FEAT_DISABLED: | ||||
| 		printf_color(ANSI_BOLD, gettext("status: ")); | ||||
| 		printf_color(ANSI_YELLOW, gettext("Some supported features are " | ||||
| 		    "not enabled on the pool.\n")); | ||||
| 		printf_color(ANSI_YELLOW, gettext("Some supported and " | ||||
| 		    "requested features are not enabled on the pool.\n")); | ||||
| 		break; | ||||
| 
 | ||||
| 	case ZPOOL_STATUS_COMPATIBILITY_ERR: | ||||
| 		printf_color(ANSI_BOLD, gettext("status: ")); | ||||
| 		printf_color(ANSI_YELLOW, gettext("Error reading or parsing " | ||||
| 		    "the file(s) indicated by the 'compatibility'\n" | ||||
| 		    "property.\n")); | ||||
| 		break; | ||||
| 
 | ||||
| 	case ZPOOL_STATUS_UNSUP_FEAT_READ: | ||||
| @ -2767,6 +2810,12 @@ show_import(nvlist_t *config) | ||||
| 			    "imported using its name or numeric identifier, " | ||||
| 			    "though\n\tsome features will not be available " | ||||
| 			    "without an explicit 'zpool upgrade'.\n")); | ||||
| 		} else if (reason == ZPOOL_STATUS_COMPATIBILITY_ERR) { | ||||
| 			(void) printf(gettext(" action: The pool can be " | ||||
| 			    "imported using its name or numeric\n\tidentifier, " | ||||
| 			    "though the file(s) indicated by its " | ||||
| 			    "'compatibility'\n\tproperty cannot be parsed at " | ||||
| 			    "this time.\n")); | ||||
| 		} else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) { | ||||
| 			(void) printf(gettext(" action: The pool can be " | ||||
| 			    "imported using its name or numeric " | ||||
| @ -7942,7 +7991,8 @@ status_callback(zpool_handle_t *zhp, void *data) | ||||
| 	if (cbp->cb_explain && | ||||
| 	    (reason == ZPOOL_STATUS_OK || | ||||
| 	    reason == ZPOOL_STATUS_VERSION_OLDER || | ||||
| 	    reason == ZPOOL_STATUS_FEAT_DISABLED)) { | ||||
| 	    reason == ZPOOL_STATUS_FEAT_DISABLED || | ||||
| 	    reason == ZPOOL_STATUS_COMPATIBILITY_ERR)) { | ||||
| 		if (!cbp->cb_allpools) { | ||||
| 			(void) printf(gettext("pool '%s' is healthy\n"), | ||||
| 			    zpool_get_name(zhp)); | ||||
| @ -8117,9 +8167,10 @@ status_callback(zpool_handle_t *zhp, void *data) | ||||
| 
 | ||||
| 	case ZPOOL_STATUS_FEAT_DISABLED: | ||||
| 		printf_color(ANSI_BOLD, gettext("status: ")); | ||||
| 		printf_color(ANSI_YELLOW, gettext("Some supported features are " | ||||
| 		    "not enabled on the pool. The pool can\n\tstill be used, " | ||||
| 		    "but some features are unavailable.\n")); | ||||
| 		printf_color(ANSI_YELLOW, gettext("Some supported and " | ||||
| 		    "requested features are not enabled on the pool.\n\t" | ||||
| 		    "The pool can still be used, but some features are " | ||||
| 		    "unavailable.\n")); | ||||
| 		printf_color(ANSI_BOLD, gettext("action: ")); | ||||
| 		printf_color(ANSI_YELLOW, gettext("Enable all features using " | ||||
| 		    "'zpool upgrade'. Once this is done,\n\tthe pool may no " | ||||
| @ -8127,6 +8178,19 @@ status_callback(zpool_handle_t *zhp, void *data) | ||||
| 		    "the features. See zpool-features(5) for details.\n")); | ||||
| 		break; | ||||
| 
 | ||||
| 	case ZPOOL_STATUS_COMPATIBILITY_ERR: | ||||
| 		printf_color(ANSI_BOLD, gettext("status: ")); | ||||
| 		printf_color(ANSI_YELLOW, gettext("This pool has a " | ||||
| 		    "compatibility list specified, but it could not be\n\t" | ||||
| 		    "read/parsed at this time. The pool can still be used, " | ||||
| 		    "but this\n\tshould be investigated.\n")); | ||||
| 		printf_color(ANSI_BOLD, gettext("action: ")); | ||||
| 		printf_color(ANSI_YELLOW, gettext("Check the value of the " | ||||
| 		    "'compatibility' property against the\n\t" | ||||
| 		    "appropriate file in " ZPOOL_SYSCONF_COMPAT_D " or " | ||||
| 		    ZPOOL_DATA_COMPAT_D ".\n")); | ||||
| 		break; | ||||
| 
 | ||||
| 	case ZPOOL_STATUS_UNSUP_FEAT_READ: | ||||
| 		printf_color(ANSI_BOLD, gettext("status: ")); | ||||
| 		printf_color(ANSI_YELLOW, gettext("The pool cannot be accessed " | ||||
| @ -8625,6 +8689,16 @@ upgrade_enable_all(zpool_handle_t *zhp, int *countp) | ||||
| 	boolean_t firstff = B_TRUE; | ||||
| 	nvlist_t *enabled = zpool_get_features(zhp); | ||||
| 
 | ||||
| 	char compat[ZFS_MAXPROPLEN]; | ||||
| 	if (zpool_get_prop(zhp, ZPOOL_PROP_COMPATIBILITY, compat, | ||||
| 	    ZFS_MAXPROPLEN, NULL, B_FALSE) != 0) | ||||
| 		compat[0] = '\0'; | ||||
| 
 | ||||
| 	boolean_t requested_features[SPA_FEATURES]; | ||||
| 	if (zpool_do_load_compat(compat, requested_features) != | ||||
| 	    ZPOOL_COMPATIBILITY_OK) | ||||
| 		return (-1); | ||||
| 
 | ||||
| 	count = 0; | ||||
| 	for (i = 0; i < SPA_FEATURES; i++) { | ||||
| 		const char *fname = spa_feature_table[i].fi_uname; | ||||
| @ -8633,7 +8707,7 @@ upgrade_enable_all(zpool_handle_t *zhp, int *countp) | ||||
| 		if (!spa_feature_table[i].fi_zfs_mod_supported) | ||||
| 			continue; | ||||
| 
 | ||||
| 		if (!nvlist_exists(enabled, fguid)) { | ||||
| 		if (!nvlist_exists(enabled, fguid) && requested_features[i]) { | ||||
| 			char *propname; | ||||
| 			verify(-1 != asprintf(&propname, "feature@%s", fname)); | ||||
| 			ret = zpool_set_prop(zhp, propname, | ||||
| @ -8855,7 +8929,7 @@ upgrade_one(zpool_handle_t *zhp, void *data) | ||||
| 			printnl = B_TRUE; | ||||
| 		} else if (cur_version == SPA_VERSION) { | ||||
| 			(void) printf(gettext("Pool '%s' already has all " | ||||
| 			    "supported features enabled.\n"), | ||||
| 			    "supported and requested features enabled.\n"), | ||||
| 			    zpool_get_name(zhp)); | ||||
| 		} | ||||
| 	} | ||||
| @ -9016,8 +9090,8 @@ zpool_do_upgrade(int argc, char **argv) | ||||
| 				(void) printf(gettext("All pools are already " | ||||
| 				    "formatted using feature flags.\n\n")); | ||||
| 				(void) printf(gettext("Every feature flags " | ||||
| 				    "pool already has all supported features " | ||||
| 				    "enabled.\n")); | ||||
| 				    "pool already has all supported and " | ||||
| 				    "requested features enabled.\n")); | ||||
| 			} else { | ||||
| 				(void) printf(gettext("All pools are already " | ||||
| 				    "formatted with version %llu or higher.\n"), | ||||
| @ -9043,7 +9117,7 @@ zpool_do_upgrade(int argc, char **argv) | ||||
| 
 | ||||
| 		if (cb.cb_first) { | ||||
| 			(void) printf(gettext("Every feature flags pool has " | ||||
| 			    "all supported features enabled.\n")); | ||||
| 			    "all supported and requested features enabled.\n")); | ||||
| 		} else { | ||||
| 			(void) printf(gettext("\n")); | ||||
| 		} | ||||
| @ -10347,6 +10421,39 @@ zpool_do_version(int argc, char **argv) | ||||
| 	return (0); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Do zpool_load_compat() and print error message on failure | ||||
|  */ | ||||
| static zpool_compat_status_t | ||||
| zpool_do_load_compat(const char *compat, boolean_t *list) | ||||
| { | ||||
| 	char badword[ZFS_MAXPROPLEN]; | ||||
| 	char badfile[MAXPATHLEN]; | ||||
| 	zpool_compat_status_t ret; | ||||
| 
 | ||||
| 	switch (ret = zpool_load_compat(compat, list, badword, badfile)) { | ||||
| 	case ZPOOL_COMPATIBILITY_OK: | ||||
| 		break; | ||||
| 	case ZPOOL_COMPATIBILITY_READERR: | ||||
| 		(void) fprintf(stderr, gettext("error reading compatibility " | ||||
| 		    "file '%s'\n"), badfile); | ||||
| 		break; | ||||
| 	case ZPOOL_COMPATIBILITY_BADFILE: | ||||
| 		(void) fprintf(stderr, gettext("compatibility file '%s' " | ||||
| 		    "too large or not newline-terminated\n"), badfile); | ||||
| 		break; | ||||
| 	case ZPOOL_COMPATIBILITY_BADWORD: | ||||
| 		(void) fprintf(stderr, gettext("unknown feature '%s' in " | ||||
| 		    "compatibility file '%s'\n"), badword, badfile); | ||||
| 		break; | ||||
| 	case ZPOOL_COMPATIBILITY_NOFILES: | ||||
| 		(void) fprintf(stderr, gettext("no compatibility files " | ||||
| 		    "specified\n")); | ||||
| 		break; | ||||
| 	} | ||||
| 	return (ret); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| main(int argc, char **argv) | ||||
| { | ||||
|  | ||||
| @ -44,6 +44,7 @@ AM_CPPFLAGS += -DLIBEXECDIR=\"$(libexecdir)\" | ||||
| AM_CPPFLAGS += -DRUNSTATEDIR=\"$(runstatedir)\" | ||||
| AM_CPPFLAGS += -DSBINDIR=\"$(sbindir)\" | ||||
| AM_CPPFLAGS += -DSYSCONFDIR=\"$(sysconfdir)\" | ||||
| AM_CPPFLAGS += -DPKGDATADIR=\"$(pkgdatadir)\" | ||||
| AM_CPPFLAGS += $(DEBUG_CPPFLAGS) | ||||
| AM_CPPFLAGS += $(CODE_COVERAGE_CPPFLAGS) | ||||
| if BUILD_LINUX | ||||
|  | ||||
| @ -28,6 +28,7 @@ | ||||
|  * Copyright 2016 Nexenta Systems, Inc. | ||||
|  * Copyright (c) 2017 Open-E, Inc. All Rights Reserved. | ||||
|  * Copyright (c) 2019 Datto Inc. | ||||
|  * Copyright (c) 2021, Colm Buckley <colm@tuatha.org> | ||||
|  */ | ||||
| 
 | ||||
| #ifndef	_LIBZFS_H | ||||
| @ -391,6 +392,7 @@ typedef enum { | ||||
| 	ZPOOL_STATUS_REBUILDING,	/* device being rebuilt */ | ||||
| 	ZPOOL_STATUS_REBUILD_SCRUB,	/* recommend scrubbing the pool */ | ||||
| 	ZPOOL_STATUS_NON_NATIVE_ASHIFT,	/* (e.g. 512e dev with ashift of 9) */ | ||||
| 	ZPOOL_STATUS_COMPATIBILITY_ERR,	/* bad 'compatibility' property */ | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Finally, the following indicates a healthy pool. | ||||
| @ -912,6 +914,20 @@ int zfs_smb_acl_rename(libzfs_handle_t *, char *, char *, char *, char *); | ||||
| extern int zpool_enable_datasets(zpool_handle_t *, const char *, int); | ||||
| extern int zpool_disable_datasets(zpool_handle_t *, boolean_t); | ||||
| 
 | ||||
| /*
 | ||||
|  * Parse a features file for -o compatibility | ||||
|  */ | ||||
| typedef enum { | ||||
| 	ZPOOL_COMPATIBILITY_OK, | ||||
| 	ZPOOL_COMPATIBILITY_READERR, | ||||
| 	ZPOOL_COMPATIBILITY_BADFILE, | ||||
| 	ZPOOL_COMPATIBILITY_BADWORD, | ||||
| 	ZPOOL_COMPATIBILITY_NOFILES | ||||
| } zpool_compat_status_t; | ||||
| 
 | ||||
| extern zpool_compat_status_t zpool_load_compat(const char *, | ||||
|     boolean_t *, char *, char *); | ||||
| 
 | ||||
| #ifdef __FreeBSD__ | ||||
| 
 | ||||
| /*
 | ||||
|  | ||||
| @ -27,10 +27,10 @@ | ||||
|  * Copyright (c) 2014 Integros [integros.com] | ||||
|  * Copyright (c) 2017, Intel Corporation. | ||||
|  * Copyright (c) 2019 Datto Inc. | ||||
|  * Portions Copyright 2010 Robert Milkowski | ||||
|  * Copyright (c) 2021, Colm Buckley <colm@tuatha.org> | ||||
|  */ | ||||
| 
 | ||||
| /* Portions Copyright 2010 Robert Milkowski */ | ||||
| 
 | ||||
| #ifndef	_SYS_FS_ZFS_H | ||||
| #define	_SYS_FS_ZFS_H | ||||
| 
 | ||||
| @ -246,6 +246,7 @@ typedef enum { | ||||
| 	ZPOOL_PROP_CHECKPOINT, | ||||
| 	ZPOOL_PROP_LOAD_GUID, | ||||
| 	ZPOOL_PROP_AUTOTRIM, | ||||
| 	ZPOOL_PROP_COMPATIBILITY, | ||||
| 	ZPOOL_NUM_PROPS | ||||
| } zpool_prop_t; | ||||
| 
 | ||||
| @ -733,6 +734,7 @@ typedef struct zpool_load_policy { | ||||
| #define	ZPOOL_CONFIG_ALLOCATION_BIAS	"alloc_bias"	/* not stored on disk */ | ||||
| #define	ZPOOL_CONFIG_EXPANSION_TIME	"expansion_time"	/* not stored */ | ||||
| #define	ZPOOL_CONFIG_REBUILD_STATS	"org.openzfs:rebuild_stats" | ||||
| #define	ZPOOL_CONFIG_COMPATIBILITY	"compatibility" | ||||
| 
 | ||||
| /*
 | ||||
|  * The persistent vdev state is stored as separate values rather than a single | ||||
| @ -845,6 +847,19 @@ typedef struct zpool_load_policy { | ||||
|  */ | ||||
| #define	ZPOOL_CACHE_BOOT	"/boot/zfs/zpool.cache" | ||||
| #define	ZPOOL_CACHE		"/etc/zfs/zpool.cache" | ||||
| /*
 | ||||
|  * Settings for zpool compatibility features files | ||||
|  */ | ||||
| #define	ZPOOL_SYSCONF_COMPAT_D	SYSCONFDIR "/zfs/compatibility.d" | ||||
| #define	ZPOOL_DATA_COMPAT_D	PKGDATADIR "/compatibility.d" | ||||
| #define	ZPOOL_COMPAT_MAXSIZE	16384 | ||||
| 
 | ||||
| /*
 | ||||
|  * Hard-wired compatibility settings | ||||
|  */ | ||||
| #define	ZPOOL_COMPAT_LEGACY	"legacy" | ||||
| #define	ZPOOL_COMPAT_OFF	"off" | ||||
| 
 | ||||
| /*
 | ||||
|  * vdev states are ordered from least to most healthy. | ||||
|  * A vdev that's CANT_OPEN or below is considered unusable. | ||||
|  | ||||
| @ -424,6 +424,8 @@ struct spa { | ||||
| 	int		spa_waiters;		/* number of waiting threads */ | ||||
| 	boolean_t	spa_waiters_cancel;	/* waiters should return */ | ||||
| 
 | ||||
| 	char		*spa_compatibility;	/* compatibility file(s) */ | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * spa_refcount & spa_config_lock must be the last elements | ||||
| 	 * because zfs_refcount_t changes size based on compilation options. | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -28,6 +28,7 @@ | ||||
|  * Copyright (c) 2017 Open-E, Inc. All Rights Reserved. | ||||
|  * Copyright (c) 2017, Intel Corporation. | ||||
|  * Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com> | ||||
|  * Copyright (c) 2021, Colm Buckley <colm@tuatha.org> | ||||
|  */ | ||||
| 
 | ||||
| #include <errno.h> | ||||
| @ -44,8 +45,12 @@ | ||||
| #include <sys/zfs_ioctl.h> | ||||
| #include <sys/zfs_sysfs.h> | ||||
| #include <sys/vdev_disk.h> | ||||
| #include <sys/types.h> | ||||
| #include <dlfcn.h> | ||||
| #include <libzutil.h> | ||||
| #include <fcntl.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #include "zfs_namecheck.h" | ||||
| #include "zfs_prop.h" | ||||
| #include "libzfs_impl.h" | ||||
| @ -302,6 +307,7 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, | ||||
| 		case ZPOOL_PROP_ALTROOT: | ||||
| 		case ZPOOL_PROP_CACHEFILE: | ||||
| 		case ZPOOL_PROP_COMMENT: | ||||
| 		case ZPOOL_PROP_COMPATIBILITY: | ||||
| 			if (zhp->zpool_props != NULL || | ||||
| 			    zpool_get_all_props(zhp) == 0) { | ||||
| 				(void) strlcpy(buf, | ||||
| @ -462,6 +468,8 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname, | ||||
| 	char *slash, *check; | ||||
| 	struct stat64 statbuf; | ||||
| 	zpool_handle_t *zhp; | ||||
| 	char badword[ZFS_MAXPROPLEN]; | ||||
| 	char badfile[MAXPATHLEN]; | ||||
| 
 | ||||
| 	if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) { | ||||
| 		(void) no_memory(hdl); | ||||
| @ -671,6 +679,39 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname, | ||||
| 			*slash = '/'; | ||||
| 			break; | ||||
| 
 | ||||
| 		case ZPOOL_PROP_COMPATIBILITY: | ||||
| 			switch (zpool_load_compat(strval, NULL, | ||||
| 			    badword, badfile)) { | ||||
| 			case ZPOOL_COMPATIBILITY_OK: | ||||
| 				break; | ||||
| 			case ZPOOL_COMPATIBILITY_READERR: | ||||
| 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, | ||||
| 				    "error reading feature file '%s'"), | ||||
| 				    badfile); | ||||
| 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf); | ||||
| 				goto error; | ||||
| 			case ZPOOL_COMPATIBILITY_BADFILE: | ||||
| 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, | ||||
| 				    "feature file '%s' too large or not " | ||||
| 				    "newline-terminated"), | ||||
| 				    badfile); | ||||
| 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf); | ||||
| 				goto error; | ||||
| 			case ZPOOL_COMPATIBILITY_BADWORD: | ||||
| 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, | ||||
| 				    "unknown feature '%s' in feature " | ||||
| 				    "file '%s'"), | ||||
| 				    badword, badfile); | ||||
| 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf); | ||||
| 				goto error; | ||||
| 			case ZPOOL_COMPATIBILITY_NOFILES: | ||||
| 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, | ||||
| 				    "no feature files specified")); | ||||
| 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf); | ||||
| 				goto error; | ||||
| 			} | ||||
| 			break; | ||||
| 
 | ||||
| 		case ZPOOL_PROP_COMMENT: | ||||
| 			for (check = strval; *check != '\0'; check++) { | ||||
| 				if (!isprint(*check)) { | ||||
| @ -4663,3 +4704,190 @@ zpool_get_bootenv(zpool_handle_t *zhp, nvlist_t **nvlp) | ||||
| 
 | ||||
| 	return (error); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Attempt to read and parse feature file(s) (from "compatibility" property). | ||||
|  * Files contain zpool feature names, comma or whitespace-separated. | ||||
|  * Comments (# character to next newline) are discarded. | ||||
|  * | ||||
|  * Arguments: | ||||
|  *  compatibility : string containing feature filenames | ||||
|  *  features : either NULL or pointer to array of boolean | ||||
|  *  badtoken : either NULL or pointer to char[ZFS_MAXPROPLEN] | ||||
|  *  badfile : either NULL or pointer to char[MAXPATHLEN] | ||||
|  * | ||||
|  * compatibility is NULL (unset), "", "off", "legacy", or list of | ||||
|  * comma-separated filenames. filenames should either be absolute, | ||||
|  * or relative to: | ||||
|  *   1) ZPOOL_SYSCONF_COMPAT_D (eg: /etc/zfs/compatibility.d) or | ||||
|  *   2) ZPOOL_DATA_COMPAT_D (eg: /usr/share/zfs/compatibility.d). | ||||
|  * (Unset), "" or "off" => enable all features | ||||
|  * "legacy" => disable all features | ||||
|  * Any feature names read from files which match unames in spa_feature_table | ||||
|  * will have the corresponding boolean set in the features array (if non-NULL). | ||||
|  * If more than one feature set specified, only features present in *all* of | ||||
|  * them will be set. | ||||
|  * | ||||
|  * An unreadable filename will be strlcpy'd to badfile (if non-NULL). | ||||
|  * An unrecognized feature will be strlcpy'd to badtoken (if non-NULL). | ||||
|  * | ||||
|  * Return values: | ||||
|  *   ZPOOL_COMPATIBILITY_OK : files read and parsed ok | ||||
|  *   ZPOOL_COMPATIBILITY_READERR : file could not be opened / mmap'd | ||||
|  *   ZPOOL_COMPATIBILITY_BADFILE : file too big or not a text file | ||||
|  *   ZPOOL_COMPATIBILITY_BADWORD : file contains invalid feature name | ||||
|  *   ZPOOL_COMPATIBILITY_NOFILES  : no file names found | ||||
|  */ | ||||
| zpool_compat_status_t | ||||
| zpool_load_compat(const char *compatibility, | ||||
|     boolean_t *features, char *badtoken, char *badfile) | ||||
| { | ||||
| 	int sdirfd, ddirfd, featfd; | ||||
| 	int i; | ||||
| 	struct stat fs; | ||||
| 	char *fc;			/* mmap of file */ | ||||
| 	char *ps, *ls, *ws;		/* strtok state */ | ||||
| 	char *file, *line, *word; | ||||
| 	char filenames[ZFS_MAXPROPLEN]; | ||||
| 	int filecount = 0; | ||||
| 
 | ||||
| 	/* special cases (unset), "" and "off" => enable all features */ | ||||
| 	if (compatibility == NULL || compatibility[0] == '\0' || | ||||
| 	    strcmp(compatibility, ZPOOL_COMPAT_OFF) == 0) { | ||||
| 		if (features != NULL) | ||||
| 			for (i = 0; i < SPA_FEATURES; i++) | ||||
| 				features[i] = B_TRUE; | ||||
| 		return (ZPOOL_COMPATIBILITY_OK); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Final special case "legacy" => disable all features */ | ||||
| 	if (strcmp(compatibility, ZPOOL_COMPAT_LEGACY) == 0) { | ||||
| 		if (features != NULL) | ||||
| 			for (i = 0; i < SPA_FEATURES; i++) | ||||
| 				features[i] = B_FALSE; | ||||
| 		return (ZPOOL_COMPATIBILITY_OK); | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Start with all true; will be ANDed with results from each file | ||||
| 	 */ | ||||
| 	if (features != NULL) | ||||
| 		for (i = 0; i < SPA_FEATURES; i++) | ||||
| 			features[i] = B_TRUE; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * We ignore errors from the directory open() | ||||
| 	 * as they're only needed if the filename is relative | ||||
| 	 * which will be checked during the openat(). | ||||
| 	 */ | ||||
| #ifdef O_PATH | ||||
| 	sdirfd = open(ZPOOL_SYSCONF_COMPAT_D, O_DIRECTORY | O_PATH); | ||||
| 	ddirfd = open(ZPOOL_DATA_COMPAT_D, O_DIRECTORY | O_PATH); | ||||
| #else | ||||
| 	sdirfd = open(ZPOOL_SYSCONF_COMPAT_D, O_DIRECTORY | O_RDONLY); | ||||
| 	ddirfd = open(ZPOOL_DATA_COMPAT_D, O_DIRECTORY | O_RDONLY); | ||||
| #endif | ||||
| 
 | ||||
| 	(void) strlcpy(filenames, compatibility, ZFS_MAXPROPLEN); | ||||
| 	file = strtok_r(filenames, ",", &ps); | ||||
| 	while (file != NULL) { | ||||
| 		boolean_t features_local[SPA_FEATURES]; | ||||
| 
 | ||||
| 		/* try sysconfdir first, then datadir */ | ||||
| 		if ((featfd = openat(sdirfd, file, 0, O_RDONLY)) < 0) | ||||
| 			featfd = openat(ddirfd, file, 0, O_RDONLY); | ||||
| 
 | ||||
| 		if (featfd < 0 || fstat(featfd, &fs) < 0) { | ||||
| 			(void) close(featfd); | ||||
| 			(void) close(sdirfd); | ||||
| 			(void) close(ddirfd); | ||||
| 			if (badfile != NULL) | ||||
| 				(void) strlcpy(badfile, file, MAXPATHLEN); | ||||
| 			return (ZPOOL_COMPATIBILITY_READERR); | ||||
| 		} | ||||
| 
 | ||||
| 		/* Too big or too small */ | ||||
| 		if (fs.st_size < 1 || fs.st_size > ZPOOL_COMPAT_MAXSIZE) { | ||||
| 			(void) close(featfd); | ||||
| 			(void) close(sdirfd); | ||||
| 			(void) close(ddirfd); | ||||
| 			if (badfile != NULL) | ||||
| 				(void) strlcpy(badfile, file, MAXPATHLEN); | ||||
| 			return (ZPOOL_COMPATIBILITY_BADFILE); | ||||
| 		} | ||||
| 
 | ||||
| 		/* private mmap() so we can strtok safely */ | ||||
| 		fc = (char *)mmap(NULL, fs.st_size, | ||||
| 		    PROT_READ|PROT_WRITE, MAP_PRIVATE, featfd, 0); | ||||
| 		(void) close(featfd); | ||||
| 
 | ||||
| 		if (fc < 0) { | ||||
| 			(void) close(sdirfd); | ||||
| 			(void) close(ddirfd); | ||||
| 			if (badfile != NULL) | ||||
| 				(void) strlcpy(badfile, file, MAXPATHLEN); | ||||
| 			return (ZPOOL_COMPATIBILITY_READERR); | ||||
| 		} | ||||
| 
 | ||||
| 		/* Text file sanity check - last char should be newline */ | ||||
| 		if (fc[fs.st_size - 1] != '\n') { | ||||
| 			(void) munmap((void *) fc, fs.st_size); | ||||
| 			(void) close(sdirfd); | ||||
| 			(void) close(ddirfd); | ||||
| 			if (badfile != NULL) | ||||
| 				(void) strlcpy(badfile, file, MAXPATHLEN); | ||||
| 			return (ZPOOL_COMPATIBILITY_BADFILE); | ||||
| 		} | ||||
| 
 | ||||
| 		/* replace with NUL to ensure we have a delimiter */ | ||||
| 		fc[fs.st_size - 1] = '\0'; | ||||
| 
 | ||||
| 		for (i = 0; i < SPA_FEATURES; i++) | ||||
| 			features_local[i] = B_FALSE; | ||||
| 
 | ||||
| 		line = strtok_r(fc, "\n", &ls); | ||||
| 		while (line != NULL) { | ||||
| 			/* discard comments */ | ||||
| 			*(strchrnul(line, '#')) = '\0'; | ||||
| 
 | ||||
| 			word = strtok_r(line, ", \t", &ws); | ||||
| 			while (word != NULL) { | ||||
| 				/* Find matching feature name */ | ||||
| 				for (i = 0; i < SPA_FEATURES; i++) { | ||||
| 					zfeature_info_t *fi = | ||||
| 					    &spa_feature_table[i]; | ||||
| 					if (strcmp(word, fi->fi_uname) == 0) { | ||||
| 						features_local[i] = B_TRUE; | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
| 				if (i == SPA_FEATURES) { | ||||
| 					if (badtoken != NULL) | ||||
| 						(void) strlcpy(badtoken, word, | ||||
| 						    ZFS_MAXPROPLEN); | ||||
| 					if (badfile != NULL) | ||||
| 						(void) strlcpy(badfile, file, | ||||
| 						    MAXPATHLEN); | ||||
| 					(void) munmap((void *) fc, fs.st_size); | ||||
| 					(void) close(sdirfd); | ||||
| 					(void) close(ddirfd); | ||||
| 					return (ZPOOL_COMPATIBILITY_BADWORD); | ||||
| 				} | ||||
| 				word = strtok_r(NULL, ", \t", &ws); | ||||
| 			} | ||||
| 			line = strtok_r(NULL, "\n", &ls); | ||||
| 		} | ||||
| 		(void) munmap((void *) fc, fs.st_size); | ||||
| 		if (features != NULL) { | ||||
| 			for (i = 0; i < SPA_FEATURES; i++) | ||||
| 				features[i] &= features_local[i]; | ||||
| 		} | ||||
| 		filecount++; | ||||
| 		file = strtok_r(NULL, ",", &ps); | ||||
| 	} | ||||
| 	(void) close(sdirfd); | ||||
| 	(void) close(ddirfd); | ||||
| 	if (filecount == 0) | ||||
| 		return (ZPOOL_COMPATIBILITY_NOFILES); | ||||
| 	return (ZPOOL_COMPATIBILITY_OK); | ||||
| } | ||||
|  | ||||
| @ -23,6 +23,7 @@ | ||||
|  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. | ||||
|  * Copyright (c) 2012 by Delphix. All rights reserved. | ||||
|  * Copyright (c) 2013 Steven Hartland. All rights reserved. | ||||
|  * Copyright (c) 2021, Colm Buckley <colm@tuatha.org> | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
| @ -87,6 +88,7 @@ static char *zfs_msgid_table[] = { | ||||
| 	 *	ZPOOL_STATUS_REMOVED_DEV | ||||
| 	 *	ZPOOL_STATUS_REBUILDING | ||||
| 	 *	ZPOOL_STATUS_REBUILD_SCRUB | ||||
| 	 *	ZPOOL_STATUS_COMPATIBILITY_ERR | ||||
| 	 *	ZPOOL_STATUS_OK | ||||
| 	 */ | ||||
| }; | ||||
| @ -218,7 +220,8 @@ find_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t), | ||||
|  * only picks the most damaging of all the current errors to report. | ||||
|  */ | ||||
| static zpool_status_t | ||||
| check_status(nvlist_t *config, boolean_t isimport, zpool_errata_t *erratap) | ||||
| check_status(nvlist_t *config, boolean_t isimport, | ||||
|     zpool_errata_t *erratap, const char *compat) | ||||
| { | ||||
| 	nvlist_t *nvroot; | ||||
| 	vdev_stat_t *vs; | ||||
| @ -471,9 +474,16 @@ check_status(nvlist_t *config, boolean_t isimport, zpool_errata_t *erratap) | ||||
| 			    ZPOOL_CONFIG_FEATURE_STATS); | ||||
| 		} | ||||
| 
 | ||||
| 		/* check against all features, or limited set? */ | ||||
| 		boolean_t pool_features[SPA_FEATURES]; | ||||
| 
 | ||||
| 		if (zpool_load_compat(compat, pool_features, NULL, NULL) != | ||||
| 		    ZPOOL_COMPATIBILITY_OK) | ||||
| 			return (ZPOOL_STATUS_COMPATIBILITY_ERR); | ||||
| 		for (i = 0; i < SPA_FEATURES; i++) { | ||||
| 			zfeature_info_t *fi = &spa_feature_table[i]; | ||||
| 			if (!nvlist_exists(feat, fi->fi_guid)) | ||||
| 			if (pool_features[i] && | ||||
| 			    !nvlist_exists(feat, fi->fi_guid)) | ||||
| 				return (ZPOOL_STATUS_FEAT_DISABLED); | ||||
| 		} | ||||
| 	} | ||||
| @ -484,7 +494,18 @@ check_status(nvlist_t *config, boolean_t isimport, zpool_errata_t *erratap) | ||||
| zpool_status_t | ||||
| zpool_get_status(zpool_handle_t *zhp, char **msgid, zpool_errata_t *errata) | ||||
| { | ||||
| 	zpool_status_t ret = check_status(zhp->zpool_config, B_FALSE, errata); | ||||
| 	/*
 | ||||
| 	 * pass in the desired feature set, as | ||||
| 	 * it affects check for disabled features | ||||
| 	 */ | ||||
| 	char compatibility[ZFS_MAXPROPLEN]; | ||||
| 	if (zpool_get_prop(zhp, ZPOOL_PROP_COMPATIBILITY, compatibility, | ||||
| 	    ZFS_MAXPROPLEN, NULL, B_FALSE) != 0) | ||||
| 		compatibility[0] = '\0'; | ||||
| 
 | ||||
| 	zpool_status_t ret = check_status(zhp->zpool_config, B_FALSE, errata, | ||||
| 	    compatibility); | ||||
| 
 | ||||
| 	if (msgid != NULL) { | ||||
| 		if (ret >= NMSGID) | ||||
| 			*msgid = NULL; | ||||
| @ -497,7 +518,7 @@ zpool_get_status(zpool_handle_t *zhp, char **msgid, zpool_errata_t *errata) | ||||
| zpool_status_t | ||||
| zpool_import_status(nvlist_t *config, char **msgid, zpool_errata_t *errata) | ||||
| { | ||||
| 	zpool_status_t ret = check_status(config, B_TRUE, errata); | ||||
| 	zpool_status_t ret = check_status(config, B_TRUE, errata, NULL); | ||||
| 
 | ||||
| 	if (ret >= NMSGID) | ||||
| 		*msgid = NULL; | ||||
|  | ||||
| @ -24,6 +24,7 @@ | ||||
|  * Copyright (c) 2012, 2018 by Delphix. All rights reserved. | ||||
|  * Copyright 2015 RackTop Systems. | ||||
|  * Copyright (c) 2016, Intel Corporation. | ||||
|  * Copyright (c) 2021, Colm Buckley <colm@tuatha.org> | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
| @ -552,12 +553,14 @@ get_configs(libpc_handle_t *hdl, pool_list_t *pl, boolean_t active_ok, | ||||
| 				 *	pool guid | ||||
| 				 *	name | ||||
| 				 *	comment (if available) | ||||
| 				 *	compatibility features (if available) | ||||
| 				 *	pool state | ||||
| 				 *	hostid (if available) | ||||
| 				 *	hostname (if available) | ||||
| 				 */ | ||||
| 				uint64_t state, version; | ||||
| 				char *comment = NULL; | ||||
| 				char *compatibility = NULL; | ||||
| 
 | ||||
| 				version = fnvlist_lookup_uint64(tmp, | ||||
| 				    ZPOOL_CONFIG_VERSION); | ||||
| @ -577,6 +580,13 @@ get_configs(libpc_handle_t *hdl, pool_list_t *pl, boolean_t active_ok, | ||||
| 					fnvlist_add_string(config, | ||||
| 					    ZPOOL_CONFIG_COMMENT, comment); | ||||
| 
 | ||||
| 				if (nvlist_lookup_string(tmp, | ||||
| 				    ZPOOL_CONFIG_COMPATIBILITY, | ||||
| 				    &compatibility) == 0) | ||||
| 					fnvlist_add_string(config, | ||||
| 					    ZPOOL_CONFIG_COMPATIBILITY, | ||||
| 					    compatibility); | ||||
| 
 | ||||
| 				state = fnvlist_lookup_uint64(tmp, | ||||
| 				    ZPOOL_CONFIG_POOL_STATE); | ||||
| 				fnvlist_add_uint64(config, | ||||
|  | ||||
| @ -16,6 +16,7 @@ | ||||
| .\" Portions Copyright [yyyy] [name of copyright owner] | ||||
| .\" Copyright (c) 2019, Klara Inc. | ||||
| .\" Copyright (c) 2019, Allan Jude | ||||
| .\" Copyright (c) 2021, Colm Buckley <colm@tuatha.org> | ||||
| .TH ZPOOL-FEATURES 5 "Aug 24, 2020" OpenZFS | ||||
| .SH NAME | ||||
| zpool\-features \- ZFS pool feature descriptions | ||||
| @ -26,7 +27,8 @@ ZFS pool on\-disk format versions are specified via "features" which replace | ||||
| the old on\-disk format numbers (the last supported on\-disk format number is | ||||
| 28). To enable a feature on a pool use the \fBupgrade\fR subcommand of the | ||||
| zpool(8) command, or set the \fBfeature@\fR\fIfeature_name\fR property | ||||
| to \fBenabled\fR. | ||||
| to \fBenabled\fR. Please also see the \fB"Compatibility feature sets"\fR | ||||
| section for information on how sets of features may be enabled together. | ||||
| .sp | ||||
| .LP | ||||
| The pool format does not affect file system version compatibility or the ability | ||||
| @ -140,6 +142,61 @@ read\-only mode. | ||||
| Some features depend on other features being enabled in order to function | ||||
| properly. Enabling a feature will automatically enable any features it | ||||
| depends on. | ||||
| 
 | ||||
| .SS "Compatibility feature sets" | ||||
| .sp | ||||
| .LP | ||||
| It is sometimes necessary for a pool to maintain compatibility with a | ||||
| specific on\-disk format, by enabling and disabling particular features. The | ||||
| \fBcompatibility\fR feature facilitates this by allowing feature sets to | ||||
| be read from text files. When set to \fBoff\fR (the default); compatibility | ||||
| feature sets are disabled (ie: all features are enabled); when set to | ||||
| \fBlegacy\fR; no features are enabled. When set to a comma\-separated list | ||||
| of filenames (each filename may either be an absolute path, or relative to | ||||
| \fB/etc/zfs/compatibility.d\fR or \fB/usr/share/zfs/compatibility.d\fR) | ||||
| the lists of requested features are read from those files, separated by | ||||
| whitespace and/or commas. Only features present in all files are enabled. | ||||
| .LP | ||||
| Simple sanity checks are applied to the files; they must be between 1 and | ||||
| 16,384 bytes in size, and must end with a newline character. | ||||
| .LP | ||||
| The requested features are applied when a pool is created using | ||||
| \fBzpool create \-o compatibility=...\fR and controls which features are | ||||
| enabled when using \fBzpool upgrade\fR. \fBzpool status\fR | ||||
| will not show a warning about disabled features which are not part | ||||
| of the requested feature set. | ||||
| .LP | ||||
| By convention, compatibility files in \fB/usr/share/zfs/compatibility.d\fR | ||||
| are provided by the distribution package, and include feature sets | ||||
| supported by important versions of popular distribtions, and feature | ||||
| sets commonly supported at the start of each year.  Compatibility files | ||||
| in \fB/etc/zfs/compatibility.d\fR, if present, will take precedence over | ||||
| files with the same name in \fB/usr/share/zfs/compatibility.d\fR. | ||||
| .LP | ||||
| Compatibility files may include comments; any text from \fB#\fR to the end | ||||
| of the line is ignored. | ||||
| .LP | ||||
| \fBExample:\fR | ||||
| .EX | ||||
| # \fBcat /usr/share/zfs/compatibility.d/grub2\fR | ||||
| # Features which are supported by GRUB2 | ||||
| async_destroy | ||||
| bookmarks | ||||
| embedded_data | ||||
| empty_bpobj | ||||
| enabled_txg | ||||
| extensible_dataset | ||||
| filesystem_limits | ||||
| hole_birth | ||||
| large_blocks | ||||
| lz4_compress | ||||
| spacemap_histogram | ||||
| 
 | ||||
| # \fBzpool create \-o compatibility=grub2 bootpool vdev\fR | ||||
| .EE | ||||
| .LP | ||||
| See \fBzpool\-create(8)\fR and \fBzpool\-upgrade(8)\fR for more information | ||||
| on how these commands are affected by feature sets. | ||||
| .SH FEATURES | ||||
| .sp | ||||
| .LP | ||||
|  | ||||
| @ -26,6 +26,7 @@ | ||||
| .\" Copyright (c) 2018 George Melikov. All Rights Reserved. | ||||
| .\" Copyright 2017 Nexenta Systems, Inc. | ||||
| .\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved. | ||||
| .\" Copyright (c) 2021, Colm Buckley <colm@tuatha.org> | ||||
| .\" | ||||
| .Dd August 9, 2019 | ||||
| .Dt ZPOOL-CREATE 8 | ||||
| @ -40,6 +41,7 @@ | ||||
| .Op Fl m Ar mountpoint | ||||
| .Oo Fl o Ar property Ns = Ns Ar value Oc Ns ... | ||||
| .Oo Fl o Ar feature@feature Ns = Ns Ar value Oc | ||||
| .Op Fl o Ar compatibility Ns = Ns Ar off | legacy | file Bq , Ns Ar file Ns ... | ||||
| .Oo Fl O Ar file-system-property Ns = Ns Ar value Oc Ns ... | ||||
| .Op Fl R Ar root | ||||
| .Ar pool vdev Ns ... | ||||
| @ -52,6 +54,7 @@ | ||||
| .Op Fl m Ar mountpoint | ||||
| .Oo Fl o Ar property Ns = Ns Ar value Oc Ns ... | ||||
| .Oo Fl o Ar feature@feature Ns = Ns Ar value Oc Ns ... | ||||
| .Op Fl o Ar compatibility Ns = Ns Ar off | legacy | file Bq , Ns Ar file Ns ... | ||||
| .Oo Fl O Ar file-system-property Ns = Ns Ar value Oc Ns ... | ||||
| .Op Fl R Ar root | ||||
| .Op Fl t Ar tname | ||||
| @ -135,9 +138,14 @@ This can be overridden with the | ||||
| .Fl m | ||||
| option. | ||||
| .Pp | ||||
| By default all supported features are enabled on the new pool unless the | ||||
| By default all supported features are enabled on the new pool. The | ||||
| .Fl d | ||||
| option is specified. | ||||
| option or the | ||||
| .Fl o Ar compatibility | ||||
| property (eg: | ||||
| .Fl o Ar compatibility=2020 | ||||
| ) can be used to restrict the features that are enabled, so that the | ||||
| pool can be imported on other releases of the ZFS software. | ||||
| .Bl -tag -width Ds | ||||
| .It Fl d | ||||
| Do not enable any features on the new pool. | ||||
| @ -179,6 +187,10 @@ Sets the given pool properties. | ||||
| See the | ||||
| .Xr zpoolprops | ||||
| manual page for a list of valid properties that can be set. | ||||
| .It Fl o Ar compatibility Ns = Ns Ar off | legacy | file Bq , Ns Ar file Ns ... | ||||
| Specifies compatibility feature sets. See | ||||
| .Xr zpool-features 5 | ||||
| for more information about compatibility feature sets. | ||||
| .It Fl o Ar feature@feature Ns = Ns Ar value | ||||
| Sets the given pool feature. See the | ||||
| .Xr zpool-features 5 | ||||
|  | ||||
| @ -26,6 +26,7 @@ | ||||
| .\" Copyright (c) 2018 George Melikov. All Rights Reserved. | ||||
| .\" Copyright 2017 Nexenta Systems, Inc. | ||||
| .\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved. | ||||
| .\" Copyright (c) 2021, Colm Buckley <colm@tuatha.org> | ||||
| .\" | ||||
| .Dd August 9, 2019 | ||||
| .Dt ZPOOL-UPGRADE 8 | ||||
| @ -54,7 +55,11 @@ formatted using a legacy ZFS version number. | ||||
| These pools can continue to be used, but some features may not be available. | ||||
| Use | ||||
| .Nm zpool Cm upgrade Fl a | ||||
| to enable all features on all pools. | ||||
| to enable all features on all pools. (If a pool has specified compatibility | ||||
| feature sets using the | ||||
| .Fl o Ar compatibility | ||||
| property, only the features present in all requested compatibility sets will | ||||
| be enabled on that pool.) | ||||
| .It Xo | ||||
| .Nm zpool | ||||
| .Cm upgrade | ||||
| @ -70,7 +75,11 @@ for a description of feature flags features supported by the current software. | ||||
| .Op Fl V Ar version | ||||
| .Fl a Ns | Ns Ar pool Ns ... | ||||
| .Xc | ||||
| Enables all supported features on the given pool. | ||||
| Enables all supported features on the given pool. (If the pool has specified | ||||
| compatibility feature sets using the | ||||
| .Fl o Ar compatibility | ||||
| property, only the features present in all requested compatibility sets will be | ||||
| enabled.) | ||||
| Once this is done, the pool will no longer be accessible on systems that do not | ||||
| support feature flags. | ||||
| See | ||||
| @ -79,7 +88,8 @@ for details on compatibility with systems that support feature flags, but do not | ||||
| support all features enabled on the pool. | ||||
| .Bl -tag -width Ds | ||||
| .It Fl a | ||||
| Enables all supported features on all pools. | ||||
| Enables all supported features (from specified compatibility sets, if any) on all | ||||
| pools. | ||||
| .It Fl V Ar version | ||||
| Upgrade to the specified legacy version. | ||||
| If the | ||||
|  | ||||
| @ -26,6 +26,7 @@ | ||||
| .\" Copyright (c) 2018 George Melikov. All Rights Reserved. | ||||
| .\" Copyright 2017 Nexenta Systems, Inc. | ||||
| .\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved. | ||||
| .\" Copyright (c) 2021, Colm Buckley <colm@tuatha.org> | ||||
| .\" | ||||
| .Dd August 9, 2019 | ||||
| .Dt ZPOOLPROPS 8 | ||||
| @ -285,6 +286,24 @@ A text string consisting of printable ASCII characters that will be stored | ||||
| such that it is available even if the pool becomes faulted. | ||||
| An administrator can provide additional information about a pool using this | ||||
| property. | ||||
| .It Sy compatibility Ns = Ns Ar off | legacy | file Bq , Ns Ar file Ns ... | ||||
| Specifies that the pool maintain compatibility with specific feature sets. | ||||
| When set to | ||||
| .Sy off | ||||
| (or unset); compatibility is disabled (all features are enabled); when set to | ||||
| .Sy legacy Ns ; | ||||
| no features are enabled. When set to a comma-separated list of | ||||
| filenames (each filename may either be an absolute path, or relative to | ||||
| .Pa /etc/zfs/compatibility.d or Pa /usr/share/zfs/compatibility.d Ns ) | ||||
| the lists of requested features are read from those files, separated by | ||||
| whitespace and/or commas. Only features present in all files are enabled. | ||||
| 
 | ||||
| See | ||||
| .Xr zpool-features 5 Ns , | ||||
| .Xr zpool-create 8 | ||||
| and | ||||
| .Xr zpool-upgrade 8 | ||||
| for more information on the operation of compatibility feature sets. | ||||
| .It Sy dedupditto Ns = Ns Ar number | ||||
| This property is deprecated and no longer has any effect. | ||||
| .It Sy delegation Ns = Ns Sy on Ns | Ns Sy off | ||||
|  | ||||
| @ -22,6 +22,7 @@ | ||||
|  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | ||||
|  * Copyright 2011 Nexenta Systems, Inc. All rights reserved. | ||||
|  * Copyright (c) 2012, 2018 by Delphix. All rights reserved. | ||||
|  * Copyright (c) 2021, Colm Buckley <colm@tuatha.org> | ||||
|  */ | ||||
| 
 | ||||
| #include <sys/zio.h> | ||||
| @ -71,6 +72,9 @@ zpool_prop_init(void) | ||||
| 	    PROP_DEFAULT, ZFS_TYPE_POOL, "<file> | none", "CACHEFILE"); | ||||
| 	zprop_register_string(ZPOOL_PROP_COMMENT, "comment", NULL, | ||||
| 	    PROP_DEFAULT, ZFS_TYPE_POOL, "<comment-string>", "COMMENT"); | ||||
| 	zprop_register_string(ZPOOL_PROP_COMPATIBILITY, "compatibility", | ||||
| 	    "off", PROP_DEFAULT, ZFS_TYPE_POOL, | ||||
| 	    "<file[,file...]> | off | legacy", "COMPATIBILITY"); | ||||
| 
 | ||||
| 	/* readonly number properties */ | ||||
| 	zprop_register_number(ZPOOL_PROP_SIZE, "size", 0, PROP_READONLY, | ||||
|  | ||||
| @ -32,6 +32,7 @@ | ||||
|  * Copyright (c) 2017, 2019, Datto Inc. All rights reserved. | ||||
|  * Copyright 2017 Joyent, Inc. | ||||
|  * Copyright (c) 2017, Intel Corporation. | ||||
|  * Copyright (c) 2021, Colm Buckley <colm@tuatha.org> | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
| @ -377,6 +378,11 @@ spa_prop_get_config(spa_t *spa, nvlist_t **nvp) | ||||
| 		    0, ZPROP_SRC_LOCAL); | ||||
| 	} | ||||
| 
 | ||||
| 	if (spa->spa_compatibility != NULL) { | ||||
| 		spa_prop_add_list(*nvp, ZPOOL_PROP_COMPATIBILITY, | ||||
| 		    spa->spa_compatibility, 0, ZPROP_SRC_LOCAL); | ||||
| 	} | ||||
| 
 | ||||
| 	if (spa->spa_root != NULL) | ||||
| 		spa_prop_add_list(*nvp, ZPOOL_PROP_ALTROOT, spa->spa_root, | ||||
| 		    0, ZPROP_SRC_LOCAL); | ||||
| @ -1669,6 +1675,10 @@ spa_unload(spa_t *spa) | ||||
| 		spa_strfree(spa->spa_comment); | ||||
| 		spa->spa_comment = NULL; | ||||
| 	} | ||||
| 	if (spa->spa_compatibility != NULL) { | ||||
| 		spa_strfree(spa->spa_compatibility); | ||||
| 		spa->spa_compatibility = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	spa_config_exit(spa, SCL_ALL, spa); | ||||
| } | ||||
| @ -3249,6 +3259,7 @@ spa_ld_parse_config(spa_t *spa, spa_import_type_t type) | ||||
| 	vdev_t *rvd; | ||||
| 	uint64_t pool_guid; | ||||
| 	char *comment; | ||||
| 	char *compatibility; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Versioning wasn't explicitly added to the label until later, so if | ||||
| @ -3297,6 +3308,11 @@ spa_ld_parse_config(spa_t *spa, spa_import_type_t type) | ||||
| 	if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0) | ||||
| 		spa->spa_comment = spa_strdup(comment); | ||||
| 
 | ||||
| 	ASSERT(spa->spa_compatibility == NULL); | ||||
| 	if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMPATIBILITY, | ||||
| 	    &compatibility) == 0) | ||||
| 		spa->spa_compatibility = spa_strdup(compatibility); | ||||
| 
 | ||||
| 	(void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG, | ||||
| 	    &spa->spa_config_txg); | ||||
| 
 | ||||
| @ -8668,6 +8684,20 @@ spa_sync_props(void *arg, dmu_tx_t *tx) | ||||
| 			spa_history_log_internal(spa, "set", tx, | ||||
| 			    "%s=%s", nvpair_name(elem), strval); | ||||
| 			break; | ||||
| 		case ZPOOL_PROP_COMPATIBILITY: | ||||
| 			strval = fnvpair_value_string(elem); | ||||
| 			if (spa->spa_compatibility != NULL) | ||||
| 				spa_strfree(spa->spa_compatibility); | ||||
| 			spa->spa_compatibility = spa_strdup(strval); | ||||
| 			/*
 | ||||
| 			 * Dirty the configuration on vdevs as above. | ||||
| 			 */ | ||||
| 			if (tx->tx_txg != TXG_INITIAL) | ||||
| 				vdev_config_dirty(spa->spa_root_vdev); | ||||
| 			spa_history_log_internal(spa, "set", tx, | ||||
| 			    "%s=%s", nvpair_name(elem), strval); | ||||
| 			break; | ||||
| 
 | ||||
| 		default: | ||||
| 			/*
 | ||||
| 			 * Set pool property values in the poolprops mos object. | ||||
|  | ||||
| @ -24,6 +24,7 @@ | ||||
|  * Copyright 2011 Nexenta Systems, Inc. All rights reserved. | ||||
|  * Copyright (c) 2011, 2020 by Delphix. All rights reserved. | ||||
|  * Copyright 2017 Joyent, Inc. | ||||
|  * Copyright (c) 2021, Colm Buckley <colm@tuatha.org> | ||||
|  */ | ||||
| 
 | ||||
| #include <sys/spa.h> | ||||
| @ -446,6 +447,9 @@ spa_config_generate(spa_t *spa, vdev_t *vd, uint64_t txg, int getstats) | ||||
| 	if (spa->spa_comment != NULL) | ||||
| 		fnvlist_add_string(config, ZPOOL_CONFIG_COMMENT, | ||||
| 		    spa->spa_comment); | ||||
| 	if (spa->spa_compatibility != NULL) | ||||
| 		fnvlist_add_string(config, ZPOOL_CONFIG_COMPATIBILITY, | ||||
| 		    spa->spa_compatibility); | ||||
| 
 | ||||
| 	hostid = spa_get_hostid(spa); | ||||
| 	if (hostid != 0) | ||||
|  | ||||
| @ -457,6 +457,7 @@ systemctl --system daemon-reload >/dev/null || true | ||||
| %{_udevdir}/vdev_id | ||||
| %{_udevdir}/zvol_id | ||||
| %{_udevdir}/rules.d/* | ||||
| %{_datadir}/%{name}/compatibility.d | ||||
| %if ! 0%{?_systemd} || 0%{?_initramfs} | ||||
| # Files needed for sysvinit and initramfs-tools | ||||
| %{_sysconfdir}/%{name}/zfs-functions | ||||
| @ -503,7 +504,10 @@ systemctl --system daemon-reload >/dev/null || true | ||||
| %doc AUTHORS COPYRIGHT LICENSE NOTICE README.md | ||||
| 
 | ||||
| %files test | ||||
| %{_datadir}/%{name} | ||||
| %{_datadir}/%{name}/zfs-tests | ||||
| %{_datadir}/%{name}/test-runner | ||||
| %{_datadir}/%{name}/runfiles | ||||
| %{_datadir}/%{name}/*.sh | ||||
| 
 | ||||
| %files dracut | ||||
| %doc contrib/dracut/README.dracut.markdown | ||||
|  | ||||
| @ -34,6 +34,7 @@ export ZEDLET_ETC_DIR=$$CMD_DIR/zed/zed.d | ||||
| export ZEDLET_LIBEXEC_DIR=$$CMD_DIR/zed/zed.d | ||||
| export ZPOOL_SCRIPT_DIR=$$CMD_DIR/zpool/zpool.d | ||||
| export ZPOOL_SCRIPTS_PATH=$$CMD_DIR/zpool/zpool.d | ||||
| export ZPOOL_COMPAT_DIR=$$CMD_DIR/zpool/compatibility.d | ||||
| export CONTRIB_DIR=@abs_top_builddir@/contrib | ||||
| export LIB_DIR=@abs_top_builddir@/lib | ||||
| export SYSCONF_DIR=@abs_top_builddir@/etc | ||||
|  | ||||
| @ -344,7 +344,8 @@ tests = ['zpool_create_001_pos', 'zpool_create_002_pos', | ||||
|     'zpool_create_draid_003_pos', 'zpool_create_draid_004_pos', | ||||
|     'zpool_create_features_001_pos', 'zpool_create_features_002_pos', | ||||
|     'zpool_create_features_003_pos', 'zpool_create_features_004_neg', | ||||
|     'zpool_create_features_005_pos', | ||||
|     'zpool_create_features_005_pos', 'zpool_create_features_006_pos', | ||||
|     'zpool_create_features_007_pos', 'zpool_create_features_008_pos', | ||||
|     'create-o_ashift', 'zpool_create_tempname', 'zpool_create_dryrun_output'] | ||||
| tags = ['functional', 'cli_root', 'zpool_create'] | ||||
| 
 | ||||
| @ -468,7 +469,8 @@ tests = ['zpool_split_cliargs', 'zpool_split_devices', | ||||
| tags = ['functional', 'cli_root', 'zpool_split'] | ||||
| 
 | ||||
| [tests/functional/cli_root/zpool_status] | ||||
| tests = ['zpool_status_001_pos', 'zpool_status_002_pos'] | ||||
| tests = ['zpool_status_001_pos', 'zpool_status_002_pos', | ||||
|     'zpool_status_features_001_pos'] | ||||
| tags = ['functional', 'cli_root', 'zpool_status'] | ||||
| 
 | ||||
| [tests/functional/cli_root/zpool_sync] | ||||
| @ -491,7 +493,7 @@ tests = ['zpool_upgrade_001_pos', 'zpool_upgrade_002_pos', | ||||
|     'zpool_upgrade_003_pos', 'zpool_upgrade_004_pos', | ||||
|     'zpool_upgrade_005_neg', 'zpool_upgrade_006_neg', | ||||
|     'zpool_upgrade_007_pos', 'zpool_upgrade_008_pos', | ||||
|     'zpool_upgrade_009_neg'] | ||||
|     'zpool_upgrade_009_neg', 'zpool_upgrade_features_001_pos'] | ||||
| tags = ['functional', 'cli_root', 'zpool_upgrade'] | ||||
| 
 | ||||
| [tests/functional/cli_root/zpool_wait] | ||||
|  | ||||
| @ -37,6 +37,7 @@ | ||||
| export ZEDLET_ETC_DIR=${ZEDLET_ETC_DIR:-@sysconfdir@/zfs/zed.d} | ||||
| export ZEDLET_LIBEXEC_DIR=${ZEDLET_LIBEXEC_DIR:-@zfsexecdir@/zed.d} | ||||
| export ZPOOL_SCRIPT_DIR=${ZPOOL_SCRIPT_DIR:-@sysconfdir@/zfs/zpool.d} | ||||
| export ZPOOL_COMPAT_DIR=${ZPOOL_COMPAT_DIR:-@datadir@/zfs/compatibility.d} | ||||
| 
 | ||||
| # Define run length constants | ||||
| export RT_LONG="3" | ||||
|  | ||||
| @ -36,6 +36,9 @@ dist_pkgdata_SCRIPTS = \ | ||||
| 	zpool_create_features_003_pos.ksh \
 | ||||
| 	zpool_create_features_004_neg.ksh \
 | ||||
| 	zpool_create_features_005_pos.ksh \
 | ||||
| 	zpool_create_features_006_pos.ksh \
 | ||||
| 	zpool_create_features_007_pos.ksh \
 | ||||
| 	zpool_create_features_008_pos.ksh \
 | ||||
| 	create-o_ashift.ksh \
 | ||||
| 	zpool_create_tempname.ksh \
 | ||||
| 	zpool_create_dryrun_output.ksh | ||||
|  | ||||
| @ -107,3 +107,84 @@ function save_dump_dev | ||||
| 	fi | ||||
| 	echo $dumpdev | ||||
| } | ||||
| 
 | ||||
| # | ||||
| # Verify a pools enabled features match the provided feature set. | ||||
| # $1, pool name | ||||
| # $2, feature set(s) | ||||
| # | ||||
| # check_feature_set $TESTPOOL set1 set2 set3 ... | ||||
| # | ||||
| function check_feature_set | ||||
| { | ||||
| 	typeset pool=$1 | ||||
| 	typeset feature_set=$2 | ||||
| 	shift | ||||
| 
 | ||||
| 	for set in "$@"; do | ||||
| 		if test -e "$ZPOOL_COMPAT_DIR/$set"; then | ||||
| 			file="$ZPOOL_COMPAT_DIR/$set" | ||||
| 		else | ||||
| 			log_fail "Missing feature file: $ZPOOL_COMPAT_DIR/$set" | ||||
| 		fi | ||||
| 	done | ||||
| 
 | ||||
| 	# | ||||
| 	# Create a temporary file which contains all features which are | ||||
| 	# common to the listed feature sets.  This is used for comparison | ||||
| 	# below to determine which features should be enabled. | ||||
| 	# | ||||
| 	typeset tmpfile=$(mktemp) | ||||
| 
 | ||||
| 	while read line; do | ||||
| 		typeset flag=1 | ||||
| 
 | ||||
| 		if [[ "$line" == "#*" ]]; then | ||||
| 			continue | ||||
| 		fi | ||||
| 
 | ||||
| 		for set in "$@"; do | ||||
| 			if ! grep -q "$line" $ZPOOL_COMPAT_DIR/$set; then | ||||
| 				flag=0 | ||||
| 				break; | ||||
| 			fi | ||||
| 		done | ||||
| 
 | ||||
| 		if [[ $flag -eq 1 ]]; then | ||||
| 			echo "$line" >>$tmpfile | ||||
| 		fi | ||||
| 	done <"$file" | ||||
| 
 | ||||
| 	# | ||||
| 	# Verify every enabled feature appears in the merged feature set. | ||||
| 	# Verify every disabled feature does not. | ||||
| 	# | ||||
| 	for feature in $(zpool get all $pool | \ | ||||
| 	    awk '$2 ~ /feature@/ { print $2 }'); do | ||||
| 		state=$(get_pool_prop $feature $pool) | ||||
| 		name=$(cut -d'@' -f2 <<<"$feature") | ||||
| 
 | ||||
| 		if [[ "$state" = "enabled" || "$state" = "active" ]]; then | ||||
| 			if ! grep -q $name $tmpfile; then | ||||
| 				cat $tmpfile | ||||
| 				rm -f $tmpfile | ||||
| 				log_fail "Enabled feature $name not " \ | ||||
| 				    "in feature set file" | ||||
| 			fi | ||||
| 		elif [[ "$state" = "disabled" ]]; then | ||||
| 			if grep -q $name $tmpfile; then | ||||
| 				cat $tmpfile | ||||
| 				rm -f $tmpfile | ||||
| 				log_fail "Disabled feature $name is " \ | ||||
| 				    "in feature set file" | ||||
| 			fi | ||||
| 		else | ||||
| 			rm -f $tmpfile | ||||
| 			log_fail "Feature $name in unknown state $state" | ||||
| 		fi | ||||
| 	done | ||||
| 
 | ||||
| 	log_note "Checked all features" | ||||
| 
 | ||||
| 	rm -f $tmpfile | ||||
| } | ||||
|  | ||||
| @ -0,0 +1,58 @@ | ||||
| #!/bin/ksh -p | ||||
| # | ||||
| # CDDL HEADER START | ||||
| # | ||||
| # The contents of this file are subject to the terms of the | ||||
| # Common Development and Distribution License (the "License"). | ||||
| # You may not use this file except in compliance with the License. | ||||
| # | ||||
| # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | ||||
| # or http://www.opensolaris.org/os/licensing. | ||||
| # See the License for the specific language governing permissions | ||||
| # and limitations under the License. | ||||
| # | ||||
| # When distributing Covered Code, include this CDDL HEADER in each | ||||
| # file and include the License file at usr/src/OPENSOLARIS.LICENSE. | ||||
| # If applicable, add the following below this CDDL HEADER, with the | ||||
| # fields enclosed by brackets "[]" replaced with your own identifying | ||||
| # information: Portions Copyright [yyyy] [name of copyright owner] | ||||
| # | ||||
| # CDDL HEADER END | ||||
| # | ||||
| 
 | ||||
| # | ||||
| # Copyright (c) 2021 Lawrence Livermore National Security, LLC. | ||||
| # | ||||
| 
 | ||||
| . $STF_SUITE/include/libtest.shlib | ||||
| 
 | ||||
| # | ||||
| # DESCRIPTION: | ||||
| #	Verify '-o compatibility' reserved values 'off, legacy' | ||||
| # | ||||
| # STRATEGY: | ||||
| #	1. Create a pool with '-o compatibility=off' | ||||
| #	2. Create a pool with '-o compatibility=legacy' | ||||
| #	3. Cannot create a pool with '-o compatibility=unknown' | ||||
| # | ||||
| 
 | ||||
| verify_runnable "global" | ||||
| 
 | ||||
| function cleanup | ||||
| { | ||||
| 	datasetexists $TESTPOOL && log_must zpool destroy $TESTPOOL | ||||
| } | ||||
| 
 | ||||
| log_onexit cleanup | ||||
| 
 | ||||
| log_assert "verify '-o compatibility' reserved values 'off, legacy'" | ||||
| 
 | ||||
| log_must zpool create -f -o compatibility=off $TESTPOOL $DISKS | ||||
| log_must zpool destroy -f $TESTPOOL | ||||
| 
 | ||||
| log_must zpool create -f -o compatibility=legacy $TESTPOOL $DISKS | ||||
| log_must zpool destroy -f $TESTPOOL | ||||
| 
 | ||||
| log_mustnot zpool create -f -o compatibility=unknown $TESTPOOL $DISKS | ||||
| 
 | ||||
| log_pass "verify '-o compatibility' reserved values 'off, legacy'" | ||||
| @ -0,0 +1,54 @@ | ||||
| #!/bin/ksh -p | ||||
| # | ||||
| # CDDL HEADER START | ||||
| # | ||||
| # The contents of this file are subject to the terms of the | ||||
| # Common Development and Distribution License (the "License"). | ||||
| # You may not use this file except in compliance with the License. | ||||
| # | ||||
| # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | ||||
| # or http://www.opensolaris.org/os/licensing. | ||||
| # See the License for the specific language governing permissions | ||||
| # and limitations under the License. | ||||
| # | ||||
| # When distributing Covered Code, include this CDDL HEADER in each | ||||
| # file and include the License file at usr/src/OPENSOLARIS.LICENSE. | ||||
| # If applicable, add the following below this CDDL HEADER, with the | ||||
| # fields enclosed by brackets "[]" replaced with your own identifying | ||||
| # information: Portions Copyright [yyyy] [name of copyright owner] | ||||
| # | ||||
| # CDDL HEADER END | ||||
| # | ||||
| 
 | ||||
| # | ||||
| # Copyright (c) 2021 Lawrence Livermore National Security, LLC. | ||||
| # | ||||
| 
 | ||||
| . $STF_SUITE/include/libtest.shlib | ||||
| . $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib | ||||
| 
 | ||||
| # | ||||
| # DESCRIPTION: | ||||
| #	Verify pools can be created with the expected feature set enabled. | ||||
| # | ||||
| # STRATEGY: | ||||
| #	1. Create a pool with a known feature set. | ||||
| #	2. Verify only those features are active/enabled. | ||||
| # | ||||
| 
 | ||||
| verify_runnable "global" | ||||
| 
 | ||||
| function cleanup | ||||
| { | ||||
| 	datasetexists $TESTPOOL && log_must zpool destroy $TESTPOOL | ||||
| } | ||||
| 
 | ||||
| log_onexit cleanup | ||||
| 
 | ||||
| log_assert "creates a pool with a specified feature set enabled" | ||||
| 
 | ||||
| log_must zpool create -f -o compatibility=compat-2020 $TESTPOOL $DISKS | ||||
| check_feature_set $TESTPOOL compat-2020 | ||||
| log_must zpool destroy -f $TESTPOOL | ||||
| 
 | ||||
| log_pass "creates a pool with a specified feature set enabled" | ||||
| @ -0,0 +1,54 @@ | ||||
| #!/bin/ksh -p | ||||
| # | ||||
| # CDDL HEADER START | ||||
| # | ||||
| # The contents of this file are subject to the terms of the | ||||
| # Common Development and Distribution License (the "License"). | ||||
| # You may not use this file except in compliance with the License. | ||||
| # | ||||
| # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | ||||
| # or http://www.opensolaris.org/os/licensing. | ||||
| # See the License for the specific language governing permissions | ||||
| # and limitations under the License. | ||||
| # | ||||
| # When distributing Covered Code, include this CDDL HEADER in each | ||||
| # file and include the License file at usr/src/OPENSOLARIS.LICENSE. | ||||
| # If applicable, add the following below this CDDL HEADER, with the | ||||
| # fields enclosed by brackets "[]" replaced with your own identifying | ||||
| # information: Portions Copyright [yyyy] [name of copyright owner] | ||||
| # | ||||
| # CDDL HEADER END | ||||
| # | ||||
| 
 | ||||
| # | ||||
| # Copyright (c) 2021 Lawrence Livermore National Security, LLC. | ||||
| # | ||||
| 
 | ||||
| . $STF_SUITE/include/libtest.shlib | ||||
| . $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib | ||||
| 
 | ||||
| # | ||||
| # DESCRIPTION: | ||||
| #	Verify pools can be created with multiple feature sets. | ||||
| # | ||||
| # STRATEGY: | ||||
| #	1. Create a pool with multiple feature sets. | ||||
| #	2. Verify only the features common to both sets are enabled. | ||||
| # | ||||
| 
 | ||||
| verify_runnable "global" | ||||
| 
 | ||||
| function cleanup | ||||
| { | ||||
| 	datasetexists $TESTPOOL && log_must zpool destroy $TESTPOOL | ||||
| } | ||||
| 
 | ||||
| log_onexit cleanup | ||||
| 
 | ||||
| log_assert "creates a pool with multiple feature sets enabled" | ||||
| 
 | ||||
| log_must zpool create -f -o compatibility=freebsd-11.0,zol-0.8 $TESTPOOL $DISKS | ||||
| check_feature_set $TESTPOOL freebsd-11.0 zol-0.8 | ||||
| log_must zpool destroy -f $TESTPOOL | ||||
| 
 | ||||
| log_pass "creates a pool with multiple feature sets enabled" | ||||
| @ -57,6 +57,7 @@ typeset -a properties=( | ||||
|     "leaked" | ||||
|     "multihost" | ||||
|     "autotrim" | ||||
|     "compatibility" | ||||
|     "feature@async_destroy" | ||||
|     "feature@empty_bpobj" | ||||
|     "feature@lz4_compress" | ||||
|  | ||||
| @ -3,4 +3,5 @@ dist_pkgdata_SCRIPTS = \ | ||||
| 	setup.ksh \
 | ||||
| 	cleanup.ksh \
 | ||||
| 	zpool_status_001_pos.ksh \
 | ||||
| 	zpool_status_002_pos.ksh | ||||
| 	zpool_status_002_pos.ksh \
 | ||||
| 	zpool_status_features_001_pos.ksh | ||||
|  | ||||
| @ -0,0 +1,63 @@ | ||||
| #!/bin/ksh -p | ||||
| # | ||||
| # CDDL HEADER START | ||||
| # | ||||
| # The contents of this file are subject to the terms of the | ||||
| # Common Development and Distribution License (the "License"). | ||||
| # You may not use this file except in compliance with the License. | ||||
| # | ||||
| # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | ||||
| # or http://www.opensolaris.org/os/licensing. | ||||
| # See the License for the specific language governing permissions | ||||
| # and limitations under the License. | ||||
| # | ||||
| # When distributing Covered Code, include this CDDL HEADER in each | ||||
| # file and include the License file at usr/src/OPENSOLARIS.LICENSE. | ||||
| # If applicable, add the following below this CDDL HEADER, with the | ||||
| # fields enclosed by brackets "[]" replaced with your own identifying | ||||
| # information: Portions Copyright [yyyy] [name of copyright owner] | ||||
| # | ||||
| # CDDL HEADER END | ||||
| # | ||||
| 
 | ||||
| # | ||||
| # Copyright (c) 2021 Lawrence Livermore National Security, LLC. | ||||
| # | ||||
| 
 | ||||
| . $STF_SUITE/include/libtest.shlib | ||||
| . $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib | ||||
| 
 | ||||
| # | ||||
| # DESCRIPTION: | ||||
| #	Verify zpool status only recommends upgrading the pool when | ||||
| #	the enabled features don't match those in the feature set. | ||||
| # | ||||
| # STRATEGY: | ||||
| #	1. Create a pool with a known feature set. | ||||
| #	2. Verify there is no `zpool status` notice to upgrade the pool. | ||||
| #	3. Set the pool compatibility to a newer feature set. | ||||
| #	4. Verify there is a `zpool status` notice to upgrade the pool. | ||||
| # | ||||
| 
 | ||||
| verify_runnable "global" | ||||
| 
 | ||||
| function cleanup | ||||
| { | ||||
| 	datasetexists $TESTPOOL1 && log_must zpool destroy $TESTPOOL1 | ||||
| 	rm -f $FILEDEV | ||||
| } | ||||
| 
 | ||||
| FILEDEV="$TEST_BASE_DIR/filedev.$$" | ||||
| 
 | ||||
| log_onexit cleanup | ||||
| 
 | ||||
| log_assert "check 'zpool status' upgrade notice" | ||||
| 
 | ||||
| log_must truncate -s $MINVDEVSIZE $FILEDEV | ||||
| log_must zpool create -f -o compatibility=compat-2018 $TESTPOOL1 $FILEDEV | ||||
| log_mustnot check_pool_status $TESTPOOL1 "status" "features are not enabled" | ||||
| 
 | ||||
| log_must zpool set compatibility=compat-2020 $TESTPOOL1 | ||||
| log_must check_pool_status $TESTPOOL1 "status" "features are not enabled" | ||||
| 
 | ||||
| log_pass "check 'zpool status' upgrade notice" | ||||
| @ -12,7 +12,8 @@ dist_pkgdata_SCRIPTS = \ | ||||
| 	zpool_upgrade_006_neg.ksh \
 | ||||
| 	zpool_upgrade_007_pos.ksh \
 | ||||
| 	zpool_upgrade_008_pos.ksh \
 | ||||
| 	zpool_upgrade_009_neg.ksh | ||||
| 	zpool_upgrade_009_neg.ksh \
 | ||||
| 	zpool_upgrade_features_001_pos.ksh | ||||
| 
 | ||||
| dist_pkgdata_DATA = \
 | ||||
| 	zpool_upgrade.cfg \
 | ||||
|  | ||||
| @ -0,0 +1,67 @@ | ||||
| #!/bin/ksh -p | ||||
| # | ||||
| # CDDL HEADER START | ||||
| # | ||||
| # The contents of this file are subject to the terms of the | ||||
| # Common Development and Distribution License (the "License"). | ||||
| # You may not use this file except in compliance with the License. | ||||
| # | ||||
| # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | ||||
| # or http://www.opensolaris.org/os/licensing. | ||||
| # See the License for the specific language governing permissions | ||||
| # and limitations under the License. | ||||
| # | ||||
| # When distributing Covered Code, include this CDDL HEADER in each | ||||
| # file and include the License file at usr/src/OPENSOLARIS.LICENSE. | ||||
| # If applicable, add the following below this CDDL HEADER, with the | ||||
| # fields enclosed by brackets "[]" replaced with your own identifying | ||||
| # information: Portions Copyright [yyyy] [name of copyright owner] | ||||
| # | ||||
| # CDDL HEADER END | ||||
| # | ||||
| 
 | ||||
| # | ||||
| # Copyright (c) 2021 Lawrence Livermore National Security, LLC. | ||||
| # | ||||
| 
 | ||||
| . $STF_SUITE/include/libtest.shlib | ||||
| . $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib | ||||
| 
 | ||||
| # | ||||
| # DESCRIPTION: | ||||
| #	Verify pools can be upgraded to known feature sets. | ||||
| # | ||||
| # STRATEGY: | ||||
| #	1. Create a pool with a known feature set. | ||||
| #	2. Verify only those features are active/enabled. | ||||
| #	3. Upgrade the pool to a newer feature set. | ||||
| #	4. Verify only those features are active/enabled. | ||||
| # | ||||
| 
 | ||||
| verify_runnable "global" | ||||
| 
 | ||||
| function cleanup | ||||
| { | ||||
| 	datasetexists $TESTPOOL1 && log_must zpool destroy $TESTPOOL1 | ||||
| 	rm -f $FILEDEV | ||||
| } | ||||
| 
 | ||||
| FILEDEV="$TEST_BASE_DIR/filedev.$$" | ||||
| 
 | ||||
| log_onexit cleanup | ||||
| 
 | ||||
| log_assert "verify pools can be upgraded to known feature sets." | ||||
| 
 | ||||
| log_must truncate -s $MINVDEVSIZE $FILEDEV | ||||
| log_must zpool create -f -o compatibility=compat-2018 $TESTPOOL1 $FILEDEV | ||||
| check_feature_set $TESTPOOL1 compat-2018 | ||||
| log_mustnot check_pool_status $TESTPOOL1 "status" "features are not enabled" | ||||
| 
 | ||||
| log_must zpool set compatibility=compat-2020 $TESTPOOL1 | ||||
| log_must check_pool_status $TESTPOOL1 "status" "features are not enabled" | ||||
| 
 | ||||
| log_must zpool upgrade $TESTPOOL1 | ||||
| check_feature_set $TESTPOOL1 compat-2020 | ||||
| log_mustnot check_pool_status $TESTPOOL1 "status" "features are not enabled" | ||||
| 
 | ||||
| log_pass "verify pools can be upgraded to known feature sets." | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Colm
						Colm