aboutsummaryrefslogtreecommitdiff
path: root/tests/zfs-tests/tests/functional/cli_root
diff options
context:
space:
mode:
Diffstat (limited to 'tests/zfs-tests/tests/functional/cli_root')
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/Makefile.am66
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/cli_common.kshlib90
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am17
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_002_pos.ksh51
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_003_pos.ksh72
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_004_pos.ksh93
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_005_pos.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_006_pos.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh83
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_pos.ksh104
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh272
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_checksum.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress.ksh119
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress_zstd.ksh114
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_display_block.ksh128
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_object_range_neg.ksh72
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_object_range_pos.ksh171
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_objset_id.ksh96
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs/Makefile.am7
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs/zfs_001_neg.ksh82
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs/zfs_002_pos.ksh123
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs/zfs_003_neg.ksh68
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/Makefile.am5
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_bookmark/cleanup.ksh31
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_bookmark/setup.ksh35
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_bookmark/zfs_bookmark_cliargs.ksh238
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_change-key/Makefile.am12
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_change-key/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_change-key/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_child.ksh91
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_clones.ksh80
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_format.ksh72
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_inherit.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_load.ksh58
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_location.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_pbkdf2iters.ksh75
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_clone/Makefile.am17
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/setup.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_001_neg.ksh126
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_002_pos.ksh89
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_003_pos.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_004_pos.ksh87
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_005_pos.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_006_pos.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_007_pos.ksh85
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_008_neg.ksh80
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_009_neg.ksh80
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_010_pos.ksh229
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_deeply_nested.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_encrypted.ksh83
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_rm_nested.ksh77
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_copies/Makefile.am14
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/cleanup.ksh44
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/setup.ksh31
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.cfg37
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib158
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_001_pos.ksh116
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_002_pos.ksh119
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_003_pos.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_004_neg.ksh58
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_005_neg.ksh80
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_006_pos.ksh77
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_create/Makefile.am27
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/cleanup.ksh30
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_create/properties.kshlib73
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/setup.ksh32
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create.cfg65
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_001_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_002_pos.ksh93
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_003_pos.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_004_pos.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_005_pos.ksh85
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_006_pos.ksh84
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_007_pos.ksh91
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_008_neg.ksh113
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_009_neg.ksh130
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_010_neg.ksh149
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_011_pos.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_012_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_013_pos.ksh82
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_014_pos.ksh59
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib54
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_crypt_combos.ksh99
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_dryrun.ksh169
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_encrypted.ksh136
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_verbose.ksh165
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_destroy/Makefile.am29
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_clone_livelist_condense_and_disable.ksh125
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_clone_livelist_condense_races.ksh117
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg39
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_001_pos.ksh235
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_002_pos.ksh95
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_003_pos.ksh156
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_004_pos.ksh126
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_005_neg.ksh204
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_006_neg.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_007_neg.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_008_pos.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_009_pos.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_010_pos.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_011_pos.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_012_pos.ksh75
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_013_neg.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_014_pos.ksh79
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_015_pos.ksh161
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_016_pos.ksh186
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_clone_livelist.ksh164
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib174
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_dev_removal.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_dev_removal_condense.ksh94
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_diff/.gitignore1
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_diff/Makefile.am17
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_diff/cleanup.ksh19
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_diff/setup.ksh21
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_diff/socket.c58
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_changes.ksh96
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_cliargs.ksh80
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_encrypted.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_timestamp.ksh104
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_types.ksh134
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_get/Makefile.am18
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_001_pos.ksh163
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_002_pos.ksh97
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_003_pos.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_004_pos.ksh227
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_005_neg.ksh156
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_006_neg.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_007_neg.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_008_pos.ksh117
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_009_pos.ksh112
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_010_neg.ksh59
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib106
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib84
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/Makefile.am5
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/cleanup.ksh29
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/setup.ksh31
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/zfs_ids_to_path_001_pos.ksh96
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_inherit/Makefile.am8
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_inherit/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_inherit/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_001_neg.ksh82
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_002_neg.ksh107
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_003_pos.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_mountpoint.ksh62
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_jail/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_jail/cleanup.ksh30
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_jail/jail.conf9
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_jail/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_jail/zfs_jail_001_pos.ksh84
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_load-key/Makefile.am14
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_load-key/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_load-key/setup.ksh32
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key.cfg26
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key.ksh85
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_all.ksh77
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib101
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_file.ksh58
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_location.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_noop.ksh54
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_recursive.ksh66
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_mount/Makefile.am27
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/setup.ksh32
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.cfg39
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib134
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_001_pos.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_002_pos.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_003_pos.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_004_pos.ksh83
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_005_pos.ksh99
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_006_pos.ksh147
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_007_pos.ksh163
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_008_pos.ksh97
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_009_neg.ksh111
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_010_neg.ksh75
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_011_neg.ksh81
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_012_pos.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_001_pos.ksh202
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_fail.ksh105
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_mountpoints.ksh162
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_encrypted.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_remount.ksh171
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_test_race.ksh116
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_multi_mount.ksh109
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_program/Makefile.am5
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_program/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_program/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_program/zfs_program_json.ksh148
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_promote/Makefile.am16
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/setup.ksh32
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote.cfg43
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_001_pos.ksh127
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_002_pos.ksh102
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_003_pos.ksh134
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_004_pos.ksh140
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_005_pos.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_006_neg.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_007_neg.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_008_pos.ksh84
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_encryptionroot.ksh93
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_property/Makefile.am5
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_property/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_property/setup.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_property/zfs_written_property_001_pos.ksh230
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_receive/Makefile.am31
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/cleanup.ksh33
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/receive-o-x_props_override.ksh320
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/setup.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_-e.ksh106
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_001_pos.ksh176
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_002_pos.ksh108
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_003_pos.ksh93
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_004_neg.ksh110
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_005_neg.ksh99
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_006_pos.ksh108
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_007_neg.ksh84
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_008_pos.ksh148
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_009_neg.ksh118
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_pos.ksh177
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_011_pos.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_012_pos.ksh83
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_013_pos.ksh75
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_014_pos.ksh122
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_015_pos.ksh83
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_016_pos.ksh85
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_from_encrypted.ksh83
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_from_zstd.ksh112
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_raw.ksh94
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_raw_-d.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_raw_incremental.ksh96
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh77
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_receive/zstd_test_data.txt1
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_rename/Makefile.am25
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/cleanup.ksh43
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/setup.ksh49
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.cfg39
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib129
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_001_pos.ksh109
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_002_pos.ksh92
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_003_pos.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_004_neg.ksh112
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_005_neg.ksh91
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_006_pos.ksh85
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_007_pos.ksh155
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_008_pos.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_009_neg.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_010_neg.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_011_pos.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_012_neg.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_013_pos.ksh85
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_014_neg.ksh110
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_encrypted_child.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_mountpoint.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_to_encrypted.ksh53
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_reservation/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_reservation/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_reservation/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_001_pos.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_002_pos.ksh88
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_rollback/Makefile.am12
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rollback/cleanup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rollback/setup.ksh31
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback.cfg45
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_001_pos.ksh174
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_002_pos.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_003_neg.ksh84
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_004_neg.ksh86
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib321
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_send/Makefile.am19
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/cleanup.ksh33
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send-b.ksh102
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send.cfg32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_001_pos.ksh127
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_002_pos.ksh139
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_003_pos.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_004_neg.ksh109
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_005_pos.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos.ksh202
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_007_pos.ksh100
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted_unloaded.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_raw.ksh79
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_sparse.ksh83
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_set/Makefile.am35
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/cache_001_pos.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/cache_002_neg.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_001_pos.ksh123
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_002_pos.ksh161
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_003_pos.ksh111
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_004_pos.ksh96
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/checksum_001_pos.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/compression_001_pos.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_001_pos.ksh100
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_002_pos.ksh98
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_003_pos.ksh145
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/onoffs_001_pos.ksh108
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/property_alias_001_pos.ksh142
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/readonly_001_pos.ksh160
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/reservation_001_neg.ksh101
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/ro_props_001_pos.ksh124
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/share_mount_001_neg.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/snapdir_001_pos.ksh112
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_001_pos.ksh84
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_002_pos.ksh120
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_003_neg.ksh82
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_004_pos.ksh101
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/version_001_neg.ksh91
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_001_neg.ksh87
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_002_neg.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_003_neg.ksh77
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib376
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_feature_activation.ksh98
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_keylocation.ksh101
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_share/Makefile.am20
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share.cfg32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_001_pos.ksh160
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_002_pos.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_003_pos.ksh110
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_004_pos.ksh96
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_005_pos.ksh93
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_006_pos.ksh105
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_007_neg.ksh85
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_008_neg.ksh74
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_009_neg.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_010_neg.ksh60
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_011_pos.ksh89
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_012_pos.ksh85
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_concurrent_shares.ksh201
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/Makefile.am16
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/setup.ksh32
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot.cfg42
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_001_neg.ksh117
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_002_neg.ksh98
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_003_neg.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_004_neg.ksh96
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_005_neg.ksh96
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_006_pos.ksh124
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_007_neg.ksh137
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_008_neg.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_009_pos.ksh115
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/Makefile.am10
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/setup.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfeature_set_unsupported.ksh54
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_get_unsupported.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_set_unsupported.ksh54
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_sysfs_live.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_get_unsupported.ksh55
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_set_unsupported.ksh54
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/Makefile.am7
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unload-key/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unload-key/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unload-key/zfs_unload-key.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unload-key/zfs_unload-key_all.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unload-key/zfs_unload-key_recursive.ksh72
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_unmount/Makefile.am20
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/setup.ksh32
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.cfg39
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib77
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_001_pos.ksh117
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_002_pos.ksh98
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_003_pos.ksh109
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_004_pos.ksh99
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_005_pos.ksh117
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_006_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_007_neg.ksh110
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_008_neg.ksh146
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_009_pos.ksh142
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_all_001_pos.ksh203
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_nested.ksh193
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_unload_keys.ksh79
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_unshare/Makefile.am11
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/setup.ksh39
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_001_pos.ksh177
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_002_pos.ksh185
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_003_pos.ksh94
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_004_neg.ksh84
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_005_neg.ksh60
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_006_pos.ksh92
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_007_pos.ksh68
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/Makefile.am14
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/cleanup.ksh33
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/setup.ksh42
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib194
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_001_pos.ksh139
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_002_pos.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_003_pos.ksh104
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_004_pos.ksh108
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_005_pos.ksh108
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_006_neg.ksh58
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_007_neg.ksh59
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_wait/Makefile.am8
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_wait/cleanup.ksh20
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_wait/setup.ksh21
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_wait/zfs_wait.kshlib80
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_wait/zfs_wait_deleteq.ksh57
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool/Makefile.am8
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool/zpool_001_neg.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool/zpool_002_pos.ksh112
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool/zpool_003_pos.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool/zpool_colors.ksh91
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_add/Makefile.am21
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/add-o_ashift.ksh85
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/add_nested_replacing_spare.ksh110
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/add_prop_ashift.ksh94
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/cleanup.ksh35
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/setup.ksh37
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.cfg39
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.kshlib111
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_001_pos.ksh116
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_002_pos.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_003_pos.ksh97
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_004_pos.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_005_pos.ksh91
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_006_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_007_neg.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_008_neg.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_009_neg.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh210
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_attach/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_attach/attach-o_ashift.ksh100
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_attach/cleanup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_attach/setup.ksh35
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_attach/zpool_attach_001_neg.ksh83
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_clear/Makefile.am11
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_clear/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_clear/setup.ksh32
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear.cfg33
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_001_pos.ksh207
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_002_neg.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_003_neg.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_readonly.ksh71
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_create/Makefile.am40
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/cleanup.ksh37
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/create-o_ashift.ksh135
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/setup.ksh37
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.cfg66
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.shlib109
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_001_pos.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_002_pos.ksh128
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_003_pos.ksh95
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_004_pos.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_005_pos.ksh124
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_006_pos.ksh137
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_007_neg.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_008_pos.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_009_neg.ksh87
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_010_neg.ksh82
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_011_neg.ksh131
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_012_neg.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_014_neg.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_015_neg.ksh91
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_016_pos.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_017_neg.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_018_pos.ksh98
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_019_pos.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_020_pos.ksh103
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_021_pos.ksh93
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_022_pos.ksh95
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_023_neg.ksh97
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_024_pos.ksh152
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_crypt_combos.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_encrypted.ksh100
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_001_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_002_pos.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_003_pos.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_004_neg.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh93
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_tempname.ksh70
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_destroy/Makefile.am8
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy.cfg37
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_001_pos.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_002_pos.ksh117
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_003_neg.ksh57
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_detach/Makefile.am5
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_detach/cleanup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_detach/setup.ksh35
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_detach/zpool_detach_001_neg.ksh70
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_events/Makefile.am13
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_events/cleanup.ksh19
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_events/setup.ksh21
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events.cfg16
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events.kshlib39
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_clear.ksh58
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_cliargs.ksh89
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_errors.ksh152
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_follow.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_poolname.ksh74
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_expand/Makefile.am12
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_expand/cleanup.ksh35
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_expand/setup.ksh46
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand.cfg37
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_001_pos.ksh167
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_002_pos.ksh168
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_003_neg.ksh138
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_004_pos.ksh100
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_005_pos.ksh99
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_export/Makefile.am11
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_export/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_export/setup.ksh37
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.cfg59
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_001_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_002_pos.ksh81
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_003_neg.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_004_pos.ksh103
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_get/Makefile.am12
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_get/cleanup.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_get/setup.ksh37
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg104
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_001_pos.ksh61
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_002_pos.ksh97
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_003_pos.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_004_neg.ksh61
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_005_pos.ksh78
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_parsable.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_history/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_history/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_history/setup.ksh35
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_001_neg.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_002_pos.ksh53
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_import/Makefile.am48
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/Makefile.am5
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/cryptv0.dat.bz2bin0 -> 94716 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/missing_ivset.dat.bz2bin0 -> 167066 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/unclean_export.dat.bz2bin0 -> 14161 bytes
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/cleanup.ksh50
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_added.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_removed.ksh145
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_replaced.ksh160
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_mirror_attached.ksh72
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_mirror_detached.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_shared_device.ksh113
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/import_devices_missing.ksh122
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/import_paths_changed.ksh98
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_config_changed.ksh261
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_device_replaced.ksh181
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/setup.ksh56
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.cfg64
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.kshlib356
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_001_pos.ksh138
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_002_pos.ksh142
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_003_pos.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_004_pos.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_005_pos.ksh85
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_006_pos.ksh83
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_007_pos.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_008_pos.ksh91
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_009_neg.ksh103
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_010_pos.ksh92
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_011_neg.ksh81
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_012_pos.ksh211
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_013_neg.ksh74
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_014_pos.ksh91
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_015_pos.ksh54
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_all_001_pos.ksh168
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_encrypted.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_encrypted_load.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_errata3.ksh103
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_errata4.ksh143
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_001_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_002_neg.ksh87
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_003_pos.ksh106
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_001_pos.ksh203
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_002_pos.ksh197
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_003_pos.ksh237
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_rename_001_pos.ksh174
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_initialize/Makefile.am17
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/cleanup.ksh31
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib43
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_attach_detach_add_remove.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_import_export.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_offline_export_import_online.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_online_offline.ksh74
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_split.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_neg.ksh60
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_pos.ksh52
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_suspend_resume.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_unsupported_vdevs.ksh74
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_checksums.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_initialized.ksh89
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/Makefile.am9
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/labelclear.cfg28
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_active.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_exported.ksh74
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_removed.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_valid.ksh94
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_offline/Makefile.am7
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_offline/cleanup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_offline/setup.ksh35
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_001_pos.ksh124
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_002_neg.ksh96
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_003_pos.ksh111
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_online/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_online/cleanup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_online/setup.ksh35
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_001_pos.ksh124
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_002_neg.ksh75
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_remove/Makefile.am10
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_remove/cleanup.ksh38
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_remove/setup.ksh37
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove.cfg31
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_001_neg.ksh95
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_002_pos.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_003_pos.ksh71
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_reopen/Makefile.am15
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_reopen/cleanup.ksh37
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_reopen/setup.ksh30
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen.cfg43
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen.shlib124
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_001_pos.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_002_pos.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_003_pos.ksh100
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_004_pos.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_005_pos.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_006_neg.ksh43
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_007_pos.ksh67
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_replace/Makefile.am7
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_replace/cleanup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_replace/replace-o_ashift.ksh101
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_replace/replace_prop_ashift.ksh97
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_replace/setup.ksh35
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_replace/zpool_replace_001_neg.ksh83
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_resilver/Makefile.am9
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_resilver/cleanup.ksh33
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_resilver/setup.ksh39
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver.cfg30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_bad_args.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_restart.ksh86
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_scrub/Makefile.am16
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/setup.ksh44
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg35
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_001_neg.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_002_pos.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_003_pos.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_004_pos.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_005_pos.ksh57
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_encrypted_unloaded.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_multiple_copies.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_offline_device.ksh133
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_print_repairing.ksh74
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_set/Makefile.am9
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_001_pos.ksh60
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_002_neg.ksh124
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_003_neg.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_ashift.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_features.ksh75
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_split/Makefile.am18
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_split/cleanup.ksh19
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_split/setup.ksh17
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split.cfg18
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_cliargs.ksh80
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_devices.ksh101
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_encryption.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_indirect.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_props.ksh95
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_resilver.ksh105
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_vdevs.ksh150
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_wholedisk.ksh84
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_status/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_status/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_status/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_001_pos.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_002_pos.ksh67
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_sync/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_sync/cleanup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_sync/setup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_sync/zpool_sync_001_pos.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_sync/zpool_sync_002_neg.ksh44
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_trim/Makefile.am24
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/setup.ksh43
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib43
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_attach_detach_add_remove.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_import_export.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_multiple.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_neg.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_offline_export_import_online.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_online_offline.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_partial.ksh114
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_rate.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_rate_neg.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_secure.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_split.ksh60
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_start_and_cancel_neg.ksh56
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_start_and_cancel_pos.ksh48
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_suspend_resume.ksh74
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_unsupported_vdevs.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_checksums.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_trimmed.ksh81
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/Makefile.am19
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/Makefile.am54
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-broken-mirror1.dat.bz2bin0 -> 8871 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-broken-mirror2.dat.bz2bin0 -> 29281 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1.dat.bz2bin0 -> 31464 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v10.dat.bz2bin0 -> 31549 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v11.dat.bz2bin0 -> 29695 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v12.dat.bz2bin0 -> 29786 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v13.dat.bz2bin0 -> 30554 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v14.dat.bz2bin0 -> 30605 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v15.dat.bz2bin0 -> 33172 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1mirror1.dat.bz2bin0 -> 32989 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1mirror2.dat.bz2bin0 -> 32965 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1mirror3.dat.bz2bin0 -> 32956 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1raidz1.dat.bz2bin0 -> 28792 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1raidz2.dat.bz2bin0 -> 28480 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1raidz3.dat.bz2bin0 -> 28779 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1stripe1.dat.bz2bin0 -> 20361 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1stripe2.dat.bz2bin0 -> 20251 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1stripe3.dat.bz2bin0 -> 32498 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2.dat.bz2bin0 -> 32492 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2mirror1.dat.bz2bin0 -> 44185 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2mirror2.dat.bz2bin0 -> 44155 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2mirror3.dat.bz2bin0 -> 44170 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2raidz1.dat.bz2bin0 -> 45894 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2raidz2.dat.bz2bin0 -> 49452 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2raidz3.dat.bz2bin0 -> 44503 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2stripe1.dat.bz2bin0 -> 35305 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2stripe2.dat.bz2bin0 -> 28513 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2stripe3.dat.bz2bin0 -> 35344 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3.dat.bz2bin0 -> 27124 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3hotspare1.dat.bz2bin0 -> 42097 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3hotspare2.dat.bz2bin0 -> 35584 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3hotspare3.dat.bz2bin0 -> 19501 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3mirror1.dat.bz2bin0 -> 28160 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3mirror2.dat.bz2bin0 -> 28149 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3mirror3.dat.bz2bin0 -> 28166 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz1.dat.bz2bin0 -> 29077 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz2.dat.bz2bin0 -> 29340 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz21.dat.bz2bin0 -> 28067 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz22.dat.bz2bin0 -> 27999 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz23.dat.bz2bin0 -> 28046 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz3.dat.bz2bin0 -> 29120 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3stripe1.dat.bz2bin0 -> 26174 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3stripe2.dat.bz2bin0 -> 24408 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3stripe3.dat.bz2bin0 -> 26213 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v4.dat.bz2bin0 -> 39824 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v5.dat.bz2bin0 -> 44358 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v6.dat.bz2bin0 -> 42006 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v7.dat.bz2bin0 -> 38100 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v8.dat.bz2bin0 -> 38287 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v9.dat.bz2bin0 -> 33474 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v999.dat.bz2bin0 -> 31807 bytes
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-vBROKEN.dat.bz2bin0 -> 26328 bytes
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/cleanup.ksh39
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/setup.ksh38
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.cfg161
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib140
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_001_pos.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_002_pos.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_003_pos.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_004_pos.ksh83
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_005_neg.ksh54
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_006_neg.ksh57
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_007_pos.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_008_pos.ksh80
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_009_neg.ksh66
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_wait/Makefile.am22
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/cleanup.ksh20
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/Makefile.am11
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/cleanup.ksh20
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_rebuild.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_replace.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_replace_cancel.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_resilver.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_scrub_basic.ksh49
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_scrub_cancel.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_scrub_flag.ksh52
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/setup.ksh23
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib124
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_discard.ksh87
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_freeing.ksh112
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_initialize_basic.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_initialize_cancel.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_initialize_flag.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_multiple.ksh83
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_no_activity.ksh52
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_remove.ksh85
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_remove_cancel.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_basic.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_cancel.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_flag.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_usage.ksh47
805 files changed, 58422 insertions, 0 deletions
diff --git a/tests/zfs-tests/tests/functional/cli_root/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/Makefile.am
new file mode 100644
index 000000000000..c01ecee89640
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/Makefile.am
@@ -0,0 +1,66 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root
+dist_pkgdata_DATA = \
+ cli_common.kshlib
+
+SUBDIRS = \
+ zdb \
+ zfs \
+ zfs_bookmark \
+ zfs_change-key \
+ zfs_clone \
+ zfs_copies \
+ zfs_create \
+ zfs_destroy \
+ zfs_diff \
+ zfs_get \
+ zfs_ids_to_path \
+ zfs_inherit \
+ zfs_jail \
+ zfs_load-key \
+ zfs_mount \
+ zfs_program \
+ zfs_promote \
+ zfs_property \
+ zfs_receive \
+ zfs_rename \
+ zfs_reservation \
+ zfs_rollback \
+ zfs_send \
+ zfs_set \
+ zfs_share \
+ zfs_snapshot \
+ zfs_sysfs \
+ zfs_unload-key \
+ zfs_unmount \
+ zfs_unshare \
+ zfs_upgrade \
+ zfs_wait \
+ zpool \
+ zpool_add \
+ zpool_attach \
+ zpool_clear \
+ zpool_create \
+ zpool_destroy \
+ zpool_detach \
+ zpool_events \
+ zpool_expand \
+ zpool_export \
+ zpool_get \
+ zpool_history \
+ zpool_import \
+ zpool_initialize \
+ zpool_labelclear \
+ zpool_offline \
+ zpool_online \
+ zpool_remove \
+ zpool_reopen \
+ zpool_replace \
+ zpool_resilver \
+ zpool_scrub \
+ zpool_set \
+ zpool_split \
+ zpool_status \
+ zpool_sync \
+ zpool_trim \
+ zpool_upgrade \
+ zpool_wait
diff --git a/tests/zfs-tests/tests/functional/cli_root/cli_common.kshlib b/tests/zfs-tests/tests/functional/cli_root/cli_common.kshlib
new file mode 100644
index 000000000000..4788de598663
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/cli_common.kshlib
@@ -0,0 +1,90 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Get the checksum and size of the file.
+#
+function get_cksum # <file path>
+{
+ return $(cksum $1 | awk '{print $1 $2}')
+}
+
+#
+# Compare the check sum of target files with the original file
+#
+
+function compare_cksum #<orig_data> <target_data1>...<target_datan>
+{
+ typeset orig_data=$1
+ typeset orig_sum=$(get_cksum $orig_data)
+ typeset target_sum=""
+ typeset bad_data_list=""
+ typeset -i bad_count=0
+
+ shift
+ for data in $@; do
+ if [[ ! -e $data ]]; then
+ bad_data_list="$bad_data_list $data"
+ (( bad_count +=1 ))
+ continue
+ fi
+
+ target_sum=$(get_cksum $data)
+ if [[ $target_sum != $orig_sum ]]; then
+ bad_data_list="$bad_data_list $data"
+ (( bad_count +=1 ))
+ fi
+ done
+
+ [[ $bad_data_list != "" ]] && \
+ log_fail "Data corruptions appear during send->receive." \
+ "There are total $bad_count corruptions. They are:\n"\
+ "$bad_data_list"
+}
+
+#
+# Check the received dataset exists or not
+#
+function receive_check #<dataset1>...<datasetn>
+{
+ typeset bad_rst_tgts=""
+
+ for dataset in $@; do
+ ! datasetexists $dataset && \
+ bad_rst_tgts="$bad_rst_tgts $dataset"
+ done
+
+ if [[ $bad_rst_tgts != "" ]]; then
+ log_fail "Restoring fails. The specified datasets"\
+ "$bad_rst_tgts are not being received."
+ fi
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am
new file mode 100644
index 000000000000..18420efcb26a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am
@@ -0,0 +1,17 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zdb
+dist_pkgdata_SCRIPTS = \
+ zdb_002_pos.ksh \
+ zdb_003_pos.ksh \
+ zdb_004_pos.ksh \
+ zdb_005_pos.ksh \
+ zdb_006_pos.ksh \
+ zdb_args_neg.ksh \
+ zdb_args_pos.ksh \
+ zdb_block_size_histogram.ksh \
+ zdb_checksum.ksh \
+ zdb_decompress.ksh \
+ zdb_decompress_zstd.ksh \
+ zdb_object_range_neg.ksh \
+ zdb_object_range_pos.ksh \
+ zdb_display_block.ksh \
+ zdb_objset_id.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_002_pos.ksh
new file mode 100755
index 000000000000..ec7e1dcab9c9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_002_pos.ksh
@@ -0,0 +1,51 @@
+#!/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2015 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# zdb will accurately count the feature refcount for pools with and without
+# features enabled.
+#
+# Strategy:
+# 1. Create a pool, and collect zdb output for the pool.
+# 2. Verify there are no 'feature refcount mismatch' messages.
+# 3. Repeat for a pool with features disabled.
+#
+
+log_assert "Verify zdb accurately counts feature refcounts."
+log_onexit cleanup
+
+typeset errstr="feature refcount mismatch"
+typeset tmpfile="$TEST_BASE_DIR/zdb-feature-mismatch"
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+ grep "$errstr" $tmpfile
+ rm -f $tmpfile
+}
+
+for opt in '' -d; do
+ log_must zpool create -f $opt $TESTPOOL ${DISKS%% *}
+ log_must eval "zdb $TESTPOOL >$tmpfile"
+ grep -q "$errstr" $tmpfile && \
+ log_fail "Found feature refcount mismatches in zdb output."
+ destroy_pool $TESTPOOL
+done
+
+log_pass "zdb accurately counts feature refcounts."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_003_pos.ksh
new file mode 100755
index 000000000000..36f1929dd193
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_003_pos.ksh
@@ -0,0 +1,72 @@
+#!/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2017 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# zdb will not produce redundant dumps of configurations
+#
+# Strategy:
+# 1. Create a pool with two vdevs
+# 2. Copy label 1 from the first vdev to the second vdev
+# 3. Collect zdb -l output for both vdevs
+# 4. Verify that the correct number of configs is dumped for each
+#
+
+log_assert "Verify zdb does not produce redundant dumps of configurations"
+log_onexit cleanup
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+ if is_freebsd ; then
+ log_must sysctl kern.geom.debugflags=$saved_debugflags
+ fi
+}
+
+if is_freebsd ; then
+ # FreeBSD won't allow writing to an in-use device without this set
+ saved_debugflags=$(sysctl -n kern.geom.debugflags)
+ log_must sysctl kern.geom.debugflags=16
+fi
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+config_count=(1 2)
+set -A DISK $DISKS
+
+default_mirror_setup_noexit $DISKS
+
+DEVS=$(get_pool_devices ${TESTPOOL} ${DEV_RDSKDIR})
+log_note "$DEVS"
+[[ -n $DEVS ]] && set -A DISK $DEVS
+
+log_must dd if=/dev/${DISK[0]} of=/dev/${DISK[1]} bs=1K count=256 conv=notrunc
+
+for x in 0 1 ; do
+ config_count=$(zdb -l $DEV_RDSKDIR/${DISK[$x]} | grep -c features_for_read)
+ (( $? != 0)) && log_fail "failed to get config_count from DISK[$x]"
+ log_note "vdev $x: message_count $config_count"
+ [ $config_count -ne ${config_count[$x]} ] && \
+ log_fail "zdb produces an incorrect number of configuration dumps."
+done
+
+cleanup
+
+log_pass "zdb produces unique dumps of configurations."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_004_pos.ksh
new file mode 100755
index 000000000000..2c6e6e9be070
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_004_pos.ksh
@@ -0,0 +1,93 @@
+#!/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2017 by Lawrence Livermore National Security, LLC.
+# Copyright (c) 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# zdb will not produce redundant dumps of uberblocks
+#
+# Strategy:
+# 1. Create a pool with two vdevs, A and B
+# 2. Offline vdev A
+# 3. Do some I/O
+# 4. Export the pool
+# 5. Copy label 1 from vdev A to vdev B
+# 6. Collect zdb -lu output for vdev B
+# 7. Verify labels 0 and 1 have unique Uberblocks, but 2 and 3 have none
+#
+
+log_assert "Verify zdb produces unique dumps of uberblocks"
+log_onexit cleanup
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+ for DISK in $DISKS; do
+ zpool labelclear -f $DEV_RDSKDIR/$DISK
+ done
+ if is_freebsd; then
+ log_must sysctl kern.geom.debugflags=$saved_debugflags
+ fi
+}
+
+if is_freebsd; then
+ # FreeBSD won't allow writing to an in-use device without this set
+ saved_debugflags=$(sysctl -n kern.geom.debugflags)
+ log_must sysctl kern.geom.debugflags=16
+fi
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+set -A DISK $DISKS
+WHOLE_DISK=${DISK[0]}
+
+default_mirror_setup_noexit $DISKS
+DEVS=$(get_pool_devices ${TESTPOOL} ${DEV_RDSKDIR})
+[[ -n $DEVS ]] && set -A DISK $DEVS
+
+log_must zpool offline $TESTPOOL $WHOLE_DISK
+log_must dd if=/dev/urandom of=$TESTDIR/testfile bs=1K count=2
+log_must zpool export $TESTPOOL
+
+log_must dd if=$DEV_RDSKDIR/${DISK[0]} of=$DEV_RDSKDIR/${DISK[1]} bs=1K count=256 conv=notrunc
+
+ubs=$(zdb -lu ${DISK[1]} | grep -e LABEL -e Uberblock -e 'labels = ')
+log_note "vdev 1: ubs $ubs"
+
+ub_dump_counts=$(zdb -lu ${DISK[1]} | \
+ awk ' /LABEL/ {label=$NF; blocks[label]=0};
+ /Uberblock/ {blocks[label]++};
+ END {print blocks[0],blocks[1],blocks[2],blocks[3]}')
+(( $? != 0)) && log_fail "failed to get ub_dump_counts from DISK[1]"
+log_note "vdev 1: ub_dump_counts $ub_dump_counts"
+
+set -A dump_count $ub_dump_counts
+for label in 0 1 2 3; do
+ if [[ $label -lt 2 ]]; then
+ [[ ${dump_count[$label]} -eq 0 ]] && \
+ log_fail "zdb incorrectly dumps duplicate uberblocks"
+ else
+ [[ ${dump_count[$label]} -ne 0 ]] && \
+ log_fail "zdb incorrectly dumps duplicate uberblocks"
+ fi
+done
+
+cleanup
+
+log_pass "zdb produces unique dumps of uberblocks"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_005_pos.ksh
new file mode 100755
index 000000000000..74975dbb0dde
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_005_pos.ksh
@@ -0,0 +1,78 @@
+#!/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2017 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# zdb -l exit codes are correct
+#
+# Strategy:
+# 1. Create a pool
+# 2. Overwrite label 0 on vdev[1] with dd
+# 3. Create an empty file
+# 3. Run zdb -l on vdev[0] and verify exit value 0
+# 4. Run zdb -l on vdev[1] and verify exit value 1
+# 5. Run zdb -l on the empty file and verify exit value 2
+#
+
+log_assert "Verify zdb -l exit codes are correct"
+log_onexit cleanup
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -f $TEMPFILE
+ if is_freebsd ; then
+ log_must sysctl kern.geom.debugflags=$saved_debugflags
+ fi
+}
+
+if is_freebsd ; then
+ # FreeBSD won't allow writing to an in-use device without this set
+ saved_debugflags=$(sysctl -n kern.geom.debugflags)
+ log_must sysctl kern.geom.debugflags=16
+fi
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+set -A DISK $DISKS
+
+default_mirror_setup_noexit $DISKS
+DEVS=$(get_pool_devices ${TESTPOOL} ${DEV_RDSKDIR})
+log_note "$DEVS"
+[[ -n $DEVS ]] && set -A DISK $DEVS
+
+log_must dd if=/dev/zero of=$DEV_RDSKDIR/${DISK[1]} bs=1K count=256 conv=notrunc
+log_must truncate -s 0 $TEMPFILE
+
+zdb -l $DEV_RDSKDIR/${DISK[0]}
+[[ $? -ne 0 ]] &&
+ log_fail "zdb -l exit codes are incorrect."
+
+zdb -l $DEV_RDSKDIR/${DISK[1]}
+[[ $? -ne 1 ]] &&
+ log_fail "zdb -l exit codes are incorrect."
+
+zdb -l $TEMPFILE
+[[ $? -ne 2 ]] &&
+ log_fail "zdb -l exit codes are incorrect."
+
+cleanup
+
+log_pass "zdb -l exit codes are correct."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_006_pos.ksh
new file mode 100755
index 000000000000..97b00e9e1996
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_006_pos.ksh
@@ -0,0 +1,64 @@
+#!/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Nutanix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# zdb -d will work on imported/exported pool with pool/dataset argument
+#
+# Strategy:
+# 1. Create a pool
+# 2. Run zdb -d with pool and dataset arguments.
+# 3. Export the pool
+# 4. Run zdb -ed with pool and dataset arguments.
+#
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+ for DISK in $DISKS; do
+ zpool labelclear -f $DEV_RDSKDIR/$DISK
+ done
+}
+
+log_assert "Verify zdb -d works on imported/exported pool with pool/dataset argument"
+log_onexit cleanup
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+default_mirror_setup_noexit $DISKS
+log_must zfs snap $TESTPOOL/$TESTFS@snap
+
+log_must zdb -d $TESTPOOL
+log_must zdb -d $TESTPOOL/
+log_must zdb -d $TESTPOOL/$TESTFS
+log_must zdb -d $TESTPOOL/$TESTFS@snap
+
+log_must zpool export $TESTPOOL
+
+log_must zdb -ed $TESTPOOL
+log_must zdb -ed $TESTPOOL/
+log_must zdb -ed $TESTPOOL/$TESTFS
+log_must zdb -ed $TESTPOOL/$TESTFS@snap
+
+log_must zpool import $TESTPOOL
+
+cleanup
+
+log_pass "zdb -d works on imported/exported pool with pool/dataset argument"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh
new file mode 100755
index 000000000000..1b0219780adc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh
@@ -0,0 +1,83 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# A badly formed parameter passed to zdb(1) should
+# return an error.
+#
+# STRATEGY:
+# 1. Create an array containing bad zdb parameters.
+# 2. For each element, execute the sub-command.
+# 3. Verify it returns an error.
+#
+
+verify_runnable "global"
+
+set -A args "create" "add" "destroy" "import fakepool" \
+ "export fakepool" "create fakepool" "add fakepool" \
+ "create mirror" "create raidz" \
+ "create mirror fakepool" "create raidz fakepool" \
+ "create raidz1 fakepool" "create raidz2 fakepool" \
+ "create fakepool mirror" "create fakepool raidz" \
+ "create fakepool raidz1" "create fakepool raidz2" \
+ "add fakepool mirror" "add fakepool raidz" \
+ "add fakepool raidz1" "add fakepool raidz2" \
+ "add mirror fakepool" "add raidz fakepool" \
+ "add raidz1 fakepool" "add raidz2 fakepool" \
+ "setvprop" "blah blah" "-%" "--?" "-*" "-=" \
+ "-a" "-f" "-g" "-j" "-n" "-o" "-p" "-p /tmp" "-r" \
+ "-t" "-w" "-z" "-E" "-H" "-I" "-J" "-K" \
+ "-N" "-Q" "-R" "-T" "-W"
+
+log_assert "Execute zdb using invalid parameters."
+
+log_onexit cleanup
+
+function cleanup
+{
+ default_cleanup_noexit
+}
+
+function test_imported_pool
+{
+ for i in ${args[@]}; do
+ log_mustnot zdb $i $TESTPOOL
+ done
+}
+
+default_mirror_setup_noexit $DISKS
+
+test_imported_pool
+
+log_pass "Badly formed zdb parameters fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_pos.ksh
new file mode 100755
index 000000000000..4c2fc15ec025
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_pos.ksh
@@ -0,0 +1,104 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# ZDB allows a large number of possible inputs
+# and combinations of those inputs. Test for non-zero
+# exit values. These input options are based on the zdb
+# man page
+#
+# STRATEGY:
+# 1. Create an array containing value zdb parameters.
+# 2. For each element, execute the sub-command.
+# 3. Verify it does not return a error.
+#
+
+verify_runnable "global"
+
+log_assert "Execute zdb using valid parameters."
+
+log_onexit cleanup
+
+function cleanup
+{
+ default_cleanup_noexit
+}
+
+function test_imported_pool
+{
+ typeset -a args=("-A" "-b" "-C" "-c" "-d" "-D" "-G" "-h" "-i" "-L" \
+ "-M" "-P" "-s" "-v" "-Y" "-y")
+ for i in ${args[@]}; do
+ log_must eval "zdb $i $TESTPOOL >/dev/null"
+ done
+}
+
+function test_exported_pool
+{
+ log_must zpool export $TESTPOOL
+ typeset -a args=("-A" "-b" "-C" "-c" "-d" "-D" "-F" "-G" "-h" "-i" "-L" "-M" \
+ "-P" "-s" "-v" "-X" "-Y" "-y")
+ for i in ${args[@]}; do
+ log_must eval "zdb -e $i $TESTPOOL >/dev/null"
+ done
+ log_must zpool import $TESTPOOL
+}
+
+function test_vdev
+{
+ typeset -a args=("-A" "-q" "-u" "-Aqu")
+ VDEVS=$(get_pool_devices ${TESTPOOL} ${DEV_RDSKDIR})
+ log_note $VDEVS
+ set -A VDEV_ARRAY $VDEVS
+ for i in ${args[@]}; do
+ log_must eval "zdb -l $i ${VDEV_ARRAY[0]} >/dev/null"
+ done
+}
+
+function test_metaslab
+{
+ typeset -a args=("-A" "-L" "-P" "-Y")
+ for i in ${args[@]}; do
+ log_must eval "zdb -m $i $TESTPOOL >/dev/null"
+ done
+}
+
+default_mirror_setup_noexit $DISKS
+
+test_imported_pool
+test_exported_pool
+test_vdev
+test_metaslab
+
+log_pass "Valid zdb parameters pass as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh
new file mode 100755
index 000000000000..0c949f9839e1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh
@@ -0,0 +1,272 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2017 by Delphix. All rights reserved.
+# Copyright (c) 2020 by Lawrence Livermore National Security LLC.
+
+. $STF_SUITE/include/libtest.shlib
+
+
+#
+# DESCRIPTION:
+# Create a pool and populate it with files of various
+# recordsizes
+#
+# STRATEGY:
+# 1. Create pool
+# 2. Populate it
+# 3. Run zdb -Pbbb on pool
+# 4. Verify variance on blocksizes
+#
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+SPA_MAXBLOCKSHIFT=24
+
+function histo_populate_test_pool
+{
+ if [ $# -ne 1 ]; then
+ log_note "histo_populate_test_pool: insufficient parameters"
+ log_fail "hptp: 1 requested $# received"
+ fi
+ typeset pool=$1
+
+ set -A recordsizes
+ typeset -i min_rsbits=9 #512
+ typeset -i max_rsbits=SPA_MAXBLOCKSHIFT #16 MiB
+ typeset -i sum_filesizes=0
+ re_number='^[0-9]+$'
+
+ let histo_pool_size=$(get_pool_prop size ${pool})
+ if [[ ! ${histo_pool_size} =~ ${re_number} ]]; then
+ log_fail "histo_pool_size is not numeric ${pool_size}"
+ fi
+ let max_pool_record_size=$(get_prop recordsize ${pool})
+ if [[ ! ${max_pool_record_size} =~ ${re_number} ]]; then
+ log_fail "hptp: max_pool_record_size is not numeric ${max_pool_record_size}"
+ fi
+
+ sum_filesizes=$(echo "2^21"|bc)
+ ((min_pool_size=12*sum_filesizes))
+ if [ ${histo_pool_size} -lt ${min_pool_size} ]; then
+ log_note "hptp: Your pool size ${histo_pool_size}"
+ log_fail "hptp: is less than minimum ${min_pool_size}"
+ fi
+ this_ri=min_rsbits
+ file_num=0
+ total_count=0
+ ###################
+ # generate 10% + 20% + 30% + 31% = 91% of the filespace
+ # attempting to use 100% will lead to no space left on device
+ # Heuristic testing showed that 91% was the practical upper
+ # bound on the default 4G zpool (mirrored) that is used in
+ # testing.
+ #
+ # In order to expedite testing, we will only fill 2G (of 4G)
+ # of the test pool. You may want to modify this for
+ # standalone testing.
+ #
+ # In filling only 50% of the pool, we create one object on
+ # each "pass" below to achieve multiple objects per record
+ # size. Creating one file per object would lead to
+ # excessive file creation time.
+ ###################
+ # for pass in 10 20 30 31 # 91%
+ for pass in 20 20 10 # 50%
+ do
+ ((thiscount=(((histo_pool_size*pass)/100)/sum_filesizes)))
+
+ ((total_count+=thiscount))
+ for rb in $(seq ${min_rsbits} ${max_rsbits})
+ do
+ this_rs=$(echo "2^${rb}" | bc)
+ if [ ${this_rs} -gt ${max_pool_record_size} ]; then
+ continue
+ fi
+
+ if [ ! -d /${pool}/B_${this_rs} ]; then
+ zfs create ${pool}/B_${this_rs}
+ zfs set recordsize=${this_rs} \
+ ${pool}/B_${this_rs}
+ fi
+ ####################
+ # Create the files in the devices and datasets
+ # of the right size. The files are filled
+ # with random data to defeat the compression
+ #
+ # Note that the dd output is suppressed unless
+ # there are errors
+ ####################
+
+ dd if=/dev/urandom \
+ of=/${pool}/B_${this_rs}/file_${filenum} \
+ bs=${this_rs} count=${thiscount} \
+ iflag=fullblock 2>&1 | \
+ egrep -v -e "records in" -e "records out" \
+ -e "bytes.*copied"
+ ((filenum+=1))
+ done
+ done
+
+ ####################
+ # Testing showed that on some devices, unless the pool is
+ # synchronized, that the block counts will be below the
+ # anticipated sizes since not all of the blocks will be flushed
+ # to the device. This 'sync' command prevents that from
+ # happening.
+ ####################
+ log_must zpool sync ${pool}
+}
+function histo_check_test_pool
+{
+ if [ $# -ne 1 ]; then
+ log_note "histo_check_test_pool: insufficient parameters"
+ log_fail "hctp: 1 requested $# received"
+ fi
+ typeset pool=$1
+
+ set -A recordsizes
+ set -A recordcounts
+ typeset -i rb
+ typeset -i min_rsbits=9 #512
+ typeset -i max_rsbits=SPA_MAXBLOCKSHIFT+1
+ typeset -i this_rs
+ typeset -i this_ri
+ typeset -i sum_filesizes=0
+ typeset dumped
+ typeset stripped
+
+ let histo_check_pool_size=$(get_pool_prop size ${pool})
+ if [[ ! ${histo_check_pool_size} =~ ${re_number} ]]; then
+ log_fail "histo_check_pool_size is not numeric ${histo_check_pool_size}"
+ fi
+ let max_pool_record_size=$(get_prop recordsize ${pool})
+ if [[ ! ${max_pool_record_size} =~ ${re_number} ]]; then
+ log_fail "hctp: max_pool_record_size is not numeric ${max_pool_record_size}"
+ fi
+
+ dumped="${TEST_BASE_DIR}/${pool}_dump.txt"
+ stripped="${TEST_BASE_DIR}/${pool}_stripped.txt"
+
+ zdb -Pbbb ${pool} | \
+ tee ${dumped} | \
+ sed -e '1,/^block[ ][ ]*psize[ ][ ]*lsize.*$/d' \
+ -e '/^size[ ]*Count/d' -e '/^$/,$d' \
+ > ${stripped}
+
+ sum_filesizes=$(echo "2^21"|bc)
+
+ ###################
+ # generate 10% + 20% + 30% + 31% = 91% of the filespace
+ # attempting to use 100% will lead to no space left on device
+ # attempting to use 100% will lead to no space left on device
+ # Heuristic testing showed that 91% was the practical upper
+ # bound on the default 4G zpool (mirrored) that is used in
+ # testing.
+ #
+ # In order to expedite testing, we will only fill 2G (of 4G)
+ # of the test pool. You may want to modify this for
+ # standalone testing.
+ #
+ # In filling only 50% of the pool, we create one object on
+ # each "pass" below to achieve multiple objects per record
+ # size. Creating one file per object would lead to
+ # excessive file creation time.
+ ###################
+ # for pass in 10 20 30 31 # 91%
+ for pass in 20 20 10 # 50%
+ do
+ ((thiscount=(((histo_check_pool_size*pass)/100)/sum_filesizes)))
+
+ for rb in $(seq ${min_rsbits} ${max_rsbits})
+ do
+ blksize=$(echo "2^$rb"|bc)
+ if [ $blksize -le $max_pool_record_size ]; then
+ ((recordcounts[$blksize]+=thiscount))
+ fi
+ done
+ done
+
+ ###################
+ # compare the above computed counts for blocks against
+ # lsize count. Since some devices have a minimum hardware
+ # blocksize > 512, we cannot compare against the asize count.
+ # E.G., if the HWBlocksize = 4096, then the asize counts for
+ # 512, 1024 and 2048 will be zero and rolled up into the
+ # 4096 blocksize count for asize. For verification we stick
+ # to just lsize counts.
+ #
+ # The max_variance is hard-coded here at 10%. testing so far
+ # has shown this to be in the range of 2%-8% so we leave a
+ # generous allowance... This might need changes in the future
+ ###################
+ let max_variance=10
+ let fail_value=0
+ let error_count=0
+ log_note "Comparisons for ${pool}"
+ log_note "Bsize is the blocksize, Count is predicted value"
+ log_note "Bsize\tCount\tpsize\tlsize\tasize"
+ while read -r blksize pc pl pm lc ll lm ac al am
+ do
+ if [ $blksize -gt $max_pool_record_size ]; then
+ continue
+ fi
+ log_note \
+ "$blksize\t${recordcounts[${blksize}]}\t$pc\t$lc\t$ac"
+
+ ###################
+ # get the computer record count and compute the
+ # difference percentage in integer arithmetic
+ ###################
+ rc=${recordcounts[${blksize}]}
+ ((rclc=(rc-lc)<0?lc-rc:rc-lc)) # absolute value
+ ((dp=(rclc*100)/rc))
+
+ ###################
+ # Check against the allowed variance
+ ###################
+ if [ $dp -gt ${max_variance} ]; then
+ log_note \
+ "Expected variance < ${max_variance}% observed ${dp}%"
+ if [ ${dp} -gt ${fail_value} ]; then
+ fail_value=${dp}
+ ((error_count++))
+ fi
+ fi
+ done < ${stripped}
+ if [ ${fail_value} -gt 0 ]; then
+ if [ ${error_count} -eq 1 ]; then
+ log_note "hctp: There was ${error_count} error"
+ else
+ log_note "hctp:There were a total of ${error_count} errors"
+ fi
+ log_fail \
+ "hctp: Max variance of ${max_variance}% exceeded, saw ${fail_value}%"
+ fi
+}
+
+log_assert "Verify zdb -Pbbb (block histogram) works as expected"
+log_onexit cleanup
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+default_mirror_setup_noexit $DISKS
+
+histo_populate_test_pool $TESTPOOL
+
+histo_check_test_pool $TESTPOOL
+
+log_pass "Histogram for zdb"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_checksum.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_checksum.ksh
new file mode 100755
index 000000000000..eeff6575f0f4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_checksum.ksh
@@ -0,0 +1,64 @@
+#!/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2019 by Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# zdb -c will display the same checksum as -ddddddbbbbbb
+#
+# Strategy:
+# 1. Create a pool
+# 2. Write some data to a file
+# 3. Run zdb -ddddddbbbbbb against the file
+# 4. Record the checksum and DVA of L0 block 0
+# 5. Run zdb -R with :c flag and match the checksum
+
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_assert "Verify zdb -R generates the correct checksum."
+log_onexit cleanup
+init_data=$TESTDIR/file1
+write_count=8
+blksize=131072
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+default_mirror_setup_noexit $DISKS
+file_write -o create -w -f $init_data -b $blksize -c $write_count
+
+# get object number of file
+listing=$(ls -i $init_data)
+set -A array $listing
+obj=${array[0]}
+log_note "file $init_data has object number $obj"
+
+output=$(zdb -ddddddbbbbbb $TESTPOOL/$TESTFS $obj 2> /dev/null \
+ |grep -m 1 "L0 DVA" |head -n1)
+dva=$(sed -Ene 's/^.+DVA\[0\]=<([^>]+)>.*$/\1/p' <<< "$output")
+log_note "block 0 of $init_data has a DVA of $dva"
+cksum_expected=$(sed -Ene 's/^.+ cksum=([a-z0-9:]+)$/\1/p' <<< "$output")
+log_note "expecting cksum $cksum_expected"
+output=$(zdb -R $TESTPOOL $dva:c 2> /dev/null)
+result=$(grep $cksum_expected <<< "$output")
+(( $? != 0 )) && log_fail "zdb -R failed to print the correct checksum"
+
+log_pass "zdb -R generates the correct checksum"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress.ksh
new file mode 100755
index 000000000000..1ebcbfb44953
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress.ksh
@@ -0,0 +1,119 @@
+#!/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2019 by Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# zdb -R pool <DVA>:d will display the correct data and length
+#
+# Strategy:
+# 1. Create a pool, set compression to lzjb
+# 2. Write some identifiable data to a file
+# 3. Run zdb -ddddddbbbbbb against the file
+# 4. Record the DVA, lsize, and psize of L0 block 0
+# 5. Run zdb -R with :d flag and match the data
+# 6. Run zdb -R with :dr flags and match the lsize/psize
+# 7. Run zdb -R with :dr flags and match the lsize
+# 8. Run zdb -R with :dr flags and match the psize
+#
+
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_assert "Verify zdb -R :d flag (decompress) works as expected"
+log_onexit cleanup
+init_data=$TESTDIR/file1
+write_count=256
+blksize=4096
+pattern="_match__pattern_"
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+default_mirror_setup_noexit $DISKS
+log_must zfs set recordsize=$blksize $TESTPOOL/$TESTFS
+log_must zfs set compression=lzjb $TESTPOOL/$TESTFS
+
+# 16 chars 256 times = 4k = block size
+typeset four_k=""
+for i in {1..$write_count}
+do
+ four_k=$four_k$pattern
+done
+
+# write the 4k block 256 times
+for i in {1..$write_count}
+do
+ echo $four_k >> $init_data
+done
+
+sync_pool $TESTPOOL true
+
+# get object number of file
+listing=$(ls -i $init_data)
+set -A array $listing
+obj=${array[0]}
+log_note "file $init_data has object number $obj"
+
+output=$(zdb -ddddddbbbbbb $TESTPOOL/$TESTFS $obj 2> /dev/null \
+ |grep -m 1 "L0 DVA" |head -n1)
+dva=$(sed -Ene 's/^.+DVA\[0\]=<([^>]+)>.*$/\1/p' <<< "$output")
+log_note "block 0 of $init_data has a DVA of $dva"
+
+# use the length reported by zdb -ddddddbbbbbb
+size_str=$(sed -Ene 's/^.+ size=([^ ]+) .*$/\1/p' <<< "$output")
+log_note "block size $size_str"
+
+vdev=$(echo "$dva" |awk '{split($0,array,":")} END{print array[1]}')
+offset=$(echo "$dva" |awk '{split($0,array,":")} END{print array[2]}')
+output=$(zdb -R $TESTPOOL $vdev:$offset:$size_str:d 2> /dev/null)
+echo $output |grep $pattern > /dev/null
+(( $? != 0 )) && log_fail "zdb -R :d failed to decompress the data properly"
+
+output=$(zdb -R $TESTPOOL $vdev:$offset:$size_str:dr 2> /dev/null)
+echo $output |grep $four_k > /dev/null
+(( $? != 0 )) && log_fail "zdb -R :dr failed to decompress the data properly"
+
+output=$(zdb -R $TESTPOOL $vdev:$offset:$size_str:dr 2> /dev/null)
+result=${#output}
+(( $result != $blksize)) && log_fail \
+"zdb -R failed to decompress the data to the length (${#output} != $size_str)"
+
+# decompress using lsize
+lsize=$(echo $size_str |awk '{split($0,array,"/")} END{print array[1]}')
+psize=$(echo $size_str |awk '{split($0,array,"/")} END{print array[2]}')
+output=$(zdb -R $TESTPOOL $vdev:$offset:$lsize:dr 2> /dev/null)
+result=${#output}
+(( $result != $blksize)) && log_fail \
+"zdb -R failed to decompress the data (length ${#output} != $blksize)"
+
+# Specifying psize will decompress successfully , but not always to full
+# lsize since zdb has to guess lsize incrementally.
+output=$(zdb -R $TESTPOOL $vdev:$offset:$psize:dr 2> /dev/null)
+result=${#output}
+# convert psize to decimal
+psize_orig=$psize
+psize=${psize%?}
+psize=$((16#$psize))
+(( $result < $psize)) && log_fail \
+"zdb -R failed to decompress the data with psize $psize_orig\
+ (length ${#output} < $psize)"
+
+log_pass "zdb -R :d flag (decompress) works as expected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress_zstd.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress_zstd.ksh
new file mode 100755
index 000000000000..238d49560461
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress_zstd.ksh
@@ -0,0 +1,114 @@
+#!/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2020 The FreeBSD Foundation [1]
+#
+# [1] Portions of this software were developed by Allan Jude
+# under sponsorship from the FreeBSD Foundation.
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# zdb -Z pool <objid> will display the ZSTD compression header
+# This will contain the actual length of the compressed data, as well as
+# the version of ZSTD used to compress the block, and the compression level
+#
+# Strategy:
+# 1. Create a pool, set compression to zstd-<random level>
+# 2. Write some identifiable data to a file
+# 3. Run zdb -Zddddddbbbbbb against the file
+# 4. Record the DVA, lsize, and psize, and ZSTD header of L0 block 0
+# 5. Check that the ZSTD length is less than psize
+# 6. Check that the ZSTD level matches the level we requested
+# 7. Run zdb -R with :dr flags and confirm the size and content match
+#
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_assert "Verify zdb -Z (read ZSTD header) works as expected"
+log_onexit cleanup
+src_data="$STF_SUITE/tests/functional/cli_root/zfs_receive/zstd_test_data.txt"
+init_data=$TESTDIR/file1
+write_count=128
+blksize=131072
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+random_level=$((RANDOM%19 + 1))
+
+default_mirror_setup_noexit $DISKS
+log_must zfs set recordsize=$blksize $TESTPOOL/$TESTFS
+log_must zfs set compression=zstd-$random_level $TESTPOOL/$TESTFS
+
+# write the 1k of text 128 times
+for i in {1..$write_count}
+do
+ cat $src_data >> $init_data
+done
+
+sync_pool $TESTPOOL true
+
+# get object number of file
+listing=$(ls -i $init_data)
+set -A array $listing
+obj=${array[0]}
+log_note "file $init_data has object number $obj"
+
+output=$(zdb -Zddddddbbbbbb $TESTPOOL/$TESTFS $obj 2> /dev/null \
+ |grep -m 1 "L0 DVA" |head -n1)
+dva=$(sed -Ene 's/^.+DVA\[0\]=<([^>]+)>.*$/\1/p' <<< "$output")
+log_note "block 0 of $init_data has a DVA of $dva"
+
+# use the length reported by zdb -ddddddbbbbbb
+size_str=$(sed -Ene 's/^.+ size=([^ ]+) .*$/\1/p' <<< "$output")
+# convert sizes to decimal
+lsize=$(echo $size_str |awk '{split($0,array,"/")} END{print array[1]}')
+lsize_orig=$lsize
+lsize=${lsize%?}
+lsize_bytes=$((16#$lsize))
+psize=$(echo $size_str |awk '{split($0,array,"/")} END{print array[2]}')
+psize_orig=$psize
+psize=${psize%?}
+psize_bytes=$((16#$psize))
+log_note "block size $size_str"
+
+# Get the ZSTD header reported by zdb -Z
+zstd_str=$(sed -Ene 's/^.+ ZSTD:size=([^:]+):version=([^:]+):level=([^:]+):.*$/\1:\2:\3/p' <<< "$output")
+zstd_size=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[1]}')
+log_note "ZSTD compressed size $zstd_size"
+(( $psize_bytes < $zstd_size )) && log_fail \
+"zdb -Z failed: physical block size was less than header content length ($psize_bytes < $zstd_size)"
+
+zstd_version=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[2]}')
+log_note "ZSTD version $zstd_version"
+
+zstd_level=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[3]}')
+log_note "ZSTD level $zstd_level"
+(( $zstd_level != $random_level )) && log_fail \
+"zdb -Z failed: compression level did not match header level ($zstd_level < $random_level)"
+
+vdev=$(echo "$dva" |awk '{split($0,array,":")} END{print array[1]}')
+offset=$(echo "$dva" |awk '{split($0,array,":")} END{print array[2]}')
+# Check the first 1024 bytes
+output=$(ZDB_NO_ZLE="true" zdb -R $TESTPOOL $vdev:$offset:$size_str:dr 2> /dev/null)
+outsize=$(wc -c <<< "$output")
+(( $outsize != $blksize )) && log_fail \
+"zdb -Z failed to decompress the data to the expected length ($outsize != $lsize_bytes)"
+cmp $init_data - <<< "$output"
+(( $? != 0 )) && log_fail "zdb -R :dr failed to decompress the data properly"
+
+log_pass "zdb -Z flag (ZSTD compression header) works as expected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_display_block.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_display_block.ksh
new file mode 100755
index 000000000000..5cc4575851f7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_display_block.ksh
@@ -0,0 +1,128 @@
+#!/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2019 by Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# zdb -R pool <DVA>:b will display the block
+#
+# Strategy:
+# 1. Create a pool, set compression to lzjb
+# 2. Write some identifiable data to a file
+# 3. Run zdb -ddddddbbbbbb against the file
+# 4. Record the DVA of the first L1 block;
+# record the first L0 block display; and
+# record the 2nd L0 block display.
+# 5. Run zdb -R with :bd displays first L0
+# 6. Run zdb -R with :b80d displays 2nd L0
+# 7. Run zdb -R with :db80 displays 2nd L0
+# 8. Run zdb -R with :id flag displays indirect block
+# (similar to zdb -ddddddbbbbbb output)
+# 9. Run zdb -R with :id flag and .0 vdev
+#
+
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_assert "Verify zdb -R :b flag (block display) works as expected"
+log_onexit cleanup
+init_data=$TESTDIR/file1
+write_count=256
+blksize=4096
+
+# only read 256 128 byte block pointers in L1 (:i flag)
+# 256 x 128 = 32k / 0x8000
+l1_read_size="8000"
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+default_mirror_setup_noexit $DISKS
+log_must zfs set recordsize=$blksize $TESTPOOL/$TESTFS
+log_must zfs set compression=lzjb $TESTPOOL/$TESTFS
+
+file_write -d R -o create -w -f $init_data -b $blksize -c $write_count
+sync_pool $TESTPOOL true
+
+# get object number of file
+listing=$(ls -i $init_data)
+set -A array $listing
+obj=${array[0]}
+log_note "file $init_data has object number $obj"
+
+output=$(zdb -ddddddbbbbbb $TESTPOOL/$TESTFS $obj 2> /dev/null \
+ |grep -m 1 "L1 DVA" |head -n1)
+dva=$(sed -Ene 's/^.+DVA\[0\]=<([^>]+)>.*/\1/p' <<< "$output")
+log_note "first L1 block $init_data has a DVA of $dva"
+output=$(zdb -ddddddbbbbbb $TESTPOOL/$TESTFS $obj 2> /dev/null \
+ |grep -m 1 "L0 DVA" |head -n1)
+blk_out0=${output##*>}
+blk_out0=${blk_out0##+([[:space:]])}
+
+output=$(zdb -ddddddbbbbbb $TESTPOOL/$TESTFS $obj 2> /dev/null \
+ |grep -m 1 "1000 L0 DVA" |head -n1)
+blk_out1=${output##*>}
+blk_out1=${blk_out1##+([[:space:]])}
+
+output=$(export ZDB_NO_ZLE=\"true\"; zdb -R $TESTPOOL $dva:bd\
+ 2> /dev/null)
+output=${output##*>}
+output=${output##+([[:space:]])}
+if [ "$output" != "$blk_out0" ]; then
+ log_fail "zdb -R :bd (block 0 display/decompress) failed"
+fi
+
+output=$(export ZDB_NO_ZLE=\"true\"; zdb -R $TESTPOOL $dva:db80\
+ 2> /dev/null)
+output=${output##*>}
+output=${output##+([[:space:]])}
+if [ "$output" != "$blk_out1" ]; then
+ log_fail "zdb -R :db80 (block 1 display/decompress) failed"
+fi
+
+output=$(export ZDB_NO_ZLE=\"true\"; zdb -R $TESTPOOL $dva:b80d\
+ 2> /dev/null)
+output=${output##*>}
+output=${output##+([[:space:]])}
+if [ "$output" != "$blk_out1" ]; then
+ log_fail "zdb -R :b80d (block 1 display/decompress) failed"
+fi
+
+vdev=$(echo "$dva" |awk '{split($0,array,":")} END{print array[1]}')
+offset=$(echo "$dva" |awk '{split($0,array,":")} END{print array[2]}')
+output=$(export ZDB_NO_ZLE=\"true\";\
+ zdb -R $TESTPOOL $vdev:$offset:$l1_read_size:id 2> /dev/null)
+block_cnt=$(echo "$output" | grep 'L0' | wc -l)
+if [ $block_cnt -ne $write_count ]; then
+ log_fail "zdb -R :id (indirect block display) failed"
+fi
+
+# read from specific half of mirror
+vdev="$vdev.0"
+log_note "Reading from DVA $vdev:$offset:$l1_read_size"
+output=$(export ZDB_NO_ZLE=\"true\";\
+ zdb -R $TESTPOOL $vdev:$offset:$l1_read_size:id 2> /dev/null)
+block_cnt=$(echo "$output" | grep 'L0' | wc -l)
+if [ $block_cnt -ne $write_count ]; then
+ log_fail "zdb -R 0.0:offset:length:id (indirect block display) failed"
+fi
+
+log_pass "zdb -R :b flag (block display) works as expected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_object_range_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_object_range_neg.ksh
new file mode 100755
index 000000000000..430180788044
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_object_range_neg.ksh
@@ -0,0 +1,72 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2020 Lawrence Livermore National Security, LLC.
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# A badly formed object range parameter passed to zdb -dd should
+# return an error.
+#
+# Strategy:
+# 1. Create a pool
+# 2. Run zdb -dd with assorted invalid object range arguments and
+# confirm it fails as expected
+# 3. Run zdb -dd with an invalid object identifier and
+# confirm it fails as expected
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_assert "Execute zdb using invalid object range parameters."
+log_onexit cleanup
+verify_runnable "both"
+verify_disk_count "$DISKS" 2
+default_mirror_setup_noexit $DISKS
+
+log_must zpool sync
+
+set -A bad_flags a b c e g h i j k l n o p q r s t u v w x y \
+ B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
+ 0 1 2 3 4 5 6 7 8 9 _ - + % . , :
+
+typeset -i i=0
+while [[ $i -lt ${#bad_flags[*]} ]]; do
+ log_mustnot zdb -dd $TESTPOOL 0:1:${bad_flags[i]}
+ log_mustnot zdb -dd $TESTPOOL 0:1:A-${bad_flags[i]}
+ ((i = i + 1))
+done
+
+set -A bad_ranges ":" "::" ":::" ":0" "0:" "0:1:" "0:1::" "0::f" "0a:1" \
+ "a0:1" "a:1" "0:a" "0:1a" "0:a1" "a:b0" "a:0b" "0:1:A-" "1:0" \
+ "0:1:f:f" "0:1:f:"
+
+i=0
+while [[ $i -lt ${#bad_ranges[*]} ]]; do
+ log_mustnot zdb -dd $TESTPOOL ${bad_ranges[i]}
+ ((i = i + 1))
+done
+
+# Specifying a non-existent object identifier returns an error
+obj_id_highest=$(zdb -P -dd $TESTPOOL/$TESTFS 2>/dev/null |
+ egrep "^ +-?([0-9]+ +){7}" | sort -n | tail -n 1 | awk '{print $1}')
+obj_id_invalid=$(( $obj_id_highest + 1 ))
+log_mustnot zdb -dd $TESTPOOL/$TESTFS $obj_id_invalid
+
+log_pass "Badly formed zdb object range parameters fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_object_range_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_object_range_pos.ksh
new file mode 100755
index 000000000000..b7f47d11ad2f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_object_range_pos.ksh
@@ -0,0 +1,171 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2020 Lawrence Livermore National Security, LLC.
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# Object range parameters passed to zdb -dd work correctly.
+#
+# Strategy:
+# 1. Create a pool
+# 2. Create some files
+# 3. Run zdb -dd with assorted object range arguments and verify output
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+#
+# Print objects in @dataset with identifiers greater than or equal to
+# @begin and less than or equal to @end, without using object range
+# parameters.
+#
+function get_object_list_range
+{
+ dataset=$1
+ begin=$2
+ end=$3
+ get_object_list $dataset |
+ while read line; do
+ obj=$(echo $line | awk '{print $1}')
+ if [[ $obj -ge $begin && $obj -le $end ]] ; then
+ echo "$line"
+ elif [[ $obj -gt $end ]] ; then
+ break
+ fi
+ done
+}
+
+#
+# Print just the list of objects from 'zdb -dd' with leading whitespace
+# trimmed, discarding other zdb output, sorted by object identifier.
+# Caller must pass in the dataset argument at minimum.
+#
+function get_object_list
+{
+ zdb -P -dd $@ 2>/dev/null |
+ egrep "^ +-?([0-9]+ +){7}" |
+ sed 's/^[[:space:]]*//' |
+ sort -n
+}
+
+log_assert "Verify zdb -dd object range arguments work correctly."
+log_onexit cleanup
+verify_runnable "both"
+verify_disk_count "$DISKS" 2
+default_mirror_setup_noexit $DISKS
+
+for x in $(seq 0 7); do
+ touch $TESTDIR/file$x
+ mkdir $TESTDIR/dir$x
+done
+
+log_must zpool sync
+
+# Get list of all objects, but filter out user/group objects which don't
+# appear when using object or object range arguments
+all_objects=$(get_object_list $TESTPOOL/$TESTFS | grep -v 'used$')
+
+# Range 0:-1 gets all objects
+expected=$all_objects
+actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1)
+log_must test "\n$actual\n" == "\n$expected\n"
+
+# Range 0:-1:A gets all objects
+expected=$all_objects
+actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1:A)
+log_must test "\n$actual\n" == "\n$expected\n"
+
+# Range 0:-1:f must output all file objects
+expected=$(grep "ZFS plain file" <<< $all_objects)
+actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1:f)
+log_must test "\n$actual\n" == "\n$expected\n"
+
+# Range 0:-1:d must output all directory objects
+expected=$(grep "ZFS directory" <<< $all_objects)
+actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1:d)
+log_must test "\n$actual\n" == "\n$expected\n"
+
+# Range 0:-1:df must output all directory and file objects
+expected=$(grep -e "ZFS directory" -e "ZFS plain file" <<< $all_objects)
+actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1:df)
+log_must test "\n$actual\n" == "\n$expected\n"
+
+# Range 0:-1:A-f-d must output all non-files and non-directories
+expected=$(grep -v -e "ZFS plain file" -e "ZFS directory" <<< $all_objects)
+actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1:A-f-d)
+log_must test "\n$actual\n" == "\n$expected\n"
+
+# Specifying multiple ranges works
+set -A obj_ids $(ls -i $TESTDIR | awk '{print $1}' | sort -n)
+start1=${obj_ids[0]}
+end1=${obj_ids[5]}
+start2=${obj_ids[8]}
+end2=${obj_ids[13]}
+expected=$(get_object_list_range $TESTPOOL/$TESTFS $start1 $end1;
+ get_object_list_range $TESTPOOL/$TESTFS $start2 $end2)
+actual=$(get_object_list $TESTPOOL/$TESTFS $start1:$end1 $start2:$end2)
+log_must test "\n$actual\n" == "\n$expected\n"
+
+# Combining ranges with individual object IDs works
+expected=$(get_object_list_range $TESTPOOL/$TESTFS $start1 $end1;
+ get_object_list $TESTPOOL/$TESTFS $start2 $end2)
+actual=$(get_object_list $TESTPOOL/$TESTFS $start1:$end1 $start2 $end2)
+log_must test "\n$actual\n" == "\n$expected\n"
+
+# Hex conversion must work for ranges and individual object identifiers
+# (this test uses expected result from previous test).
+start1_hex=$(printf "0x%x" $start1)
+end1_hex=$(printf "0x%x" $end1)
+start2_hex=$(printf "0x%x" $start2)
+end2_hex=$(printf "0x%x" $end2)
+actual=$(get_object_list $TESTPOOL/$TESTFS $start1_hex:$end1_hex \
+ $start2_hex $end2_hex)
+log_must test "\n$actual\n" == "\n$expected\n"
+
+# Specifying individual object IDs works
+objects="$start1 $end1 $start2 $end2"
+expected="$objects"
+actual=$(get_object_list $TESTPOOL/$TESTFS $objects | awk '{print $1}' | xargs)
+log_must test "$actual" == "$expected"
+
+# Get all objects in the meta-objset to test m (spacemap) and z (zap) flags
+all_mos_objects=$(get_object_list $TESTPOOL 0:-1)
+
+# Range 0:-1:m must output all space map objects
+expected=$(grep "SPA space map" <<< $all_mos_objects)
+actual=$(get_object_list $TESTPOOL 0:-1:m)
+log_must test "\n$actual\n" == "\n$expected\n"
+
+# Range 0:-1:z must output all zap objects
+expected=$(grep "zap" <<< $all_mos_objects)
+actual=$(get_object_list $TESTPOOL 0:-1:z)
+log_must test "\n$actual\n" == "\n$expected\n"
+
+# Range 0:-1:A-m-z must output all non-space maps and non-zaps
+expected=$(grep -v -e "zap" -e "SPA space map" <<< $all_mos_objects)
+actual=$(get_object_list $TESTPOOL 0:-1:A-m-z)
+log_must test "\n$actual\n" == "\n$expected\n"
+
+# Range 0:-1:mz must output all space maps and zaps
+expected=$(grep -e "SPA space map" -e "zap" <<< $all_mos_objects)
+actual=$(get_object_list $TESTPOOL 0:-1:mz)
+log_must test "\n$actual\n" == "\n$expected\n"
+
+log_pass "zdb -dd object range arguments work correctly"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_objset_id.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_objset_id.ksh
new file mode 100755
index 000000000000..f0c1076c97bd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_objset_id.ksh
@@ -0,0 +1,96 @@
+#!/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2020 by Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# zdb -d pool/<objset id> will display the dataset
+#
+# Strategy:
+# 1. Create a pool
+# 2. Write some data to a file
+# 3. Get the inode number (object number) of the file
+# 4. Run zdb -d to get the objset ID of the dataset
+# 5. Run zdb -dddddd pool/objsetID objectID (decimal)
+# 6. Confirm names
+# 7. Run zdb -dddddd pool/objsetID objectID (hex)
+# 8. Confirm names
+# 9. Obtain objsetID from /proc/spl/kstat/zfs/testpool/obset-0x<ID>
+# (linux only)
+# 10. Run zdb -dddddd pool/objsetID (hex)
+# 11. Match name from zdb against proc entry
+#
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_assert "Verify zdb -d <pool>/<objset ID> generates the correct names."
+log_onexit cleanup
+init_data=$TESTDIR/file1
+write_count=8
+blksize=131072
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+default_mirror_setup_noexit $DISKS
+file_write -o create -w -f $init_data -b $blksize -c $write_count
+
+# get object number of file
+listing=$(ls -i $init_data)
+set -A array $listing
+obj=${array[0]}
+log_note "file $init_data has object number $obj"
+
+output=$(zdb -d $TESTPOOL/$TESTFS)
+objset_id=$(echo $output | awk '{split($0,array,",")} END{print array[2]}' |
+ awk '{split($0,array," ")} END{print array[2]}')
+objset_hex=$(printf "0x%X" $objset_id)
+log_note "objset $TESTPOOL/$TESTFS has objset ID $objset_id ($objset_hex)"
+
+for id in "$objset_id" "$objset_hex"
+do
+ log_note "zdb -dddddd $TESTPOOL/$id $obj"
+ output=$(zdb -dddddd $TESTPOOL/$id $obj)
+ reason="($TESTPOOL/$TESTFS not in zdb output)"
+ echo $output |grep "$TESTPOOL/$TESTFS" > /dev/null
+ (( $? != 0 )) && log_fail \
+ "zdb -dddddd $TESTPOOL/$id $obj failed $reason"
+ reason="(file1 not in zdb output)"
+ echo $output |grep "file1" > /dev/null
+ (( $? != 0 )) && log_fail \
+ "zdb -dddddd $TESTPOOL/$id $obj failed $reason"
+ obj=$(printf "0x%X" $obj)
+done
+
+if is_linux; then
+ output=$(ls -1 /proc/spl/kstat/zfs/$TESTPOOL |grep objset- |tail -1)
+ objset_hex=${output#*-}
+ name_from_proc=$(cat /proc/spl/kstat/zfs/$TESTPOOL/$output |
+ grep dataset_name | awk '{split($0,array," ")} END{print array[3]}')
+ log_note "checking zdb output for $name_from_proc"
+ reason="(name $name_from_proc from proc not in zdb output)"
+ log_note "zdb -dddddd $TESTPOOL/$objset_hex"
+ output=$(zdb -dddddd $TESTPOOL/$objset_hex)
+ echo $output |grep "$name_from_proc" > /dev/null
+ (( $? != 0 )) && log_fail \
+ "zdb -dddddd $TESTPOOL/$objset_hex failed $reason"
+fi
+
+log_pass "zdb -d <pool>/<objset ID> generates the correct names."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs/Makefile.am
new file mode 100644
index 000000000000..8b0ee276a3b0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs/Makefile.am
@@ -0,0 +1,7 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_001_neg.ksh \
+ zfs_002_pos.ksh \
+ zfs_003_neg.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_001_neg.ksh
new file mode 100755
index 000000000000..c6e45c80dd30
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_001_neg.ksh
@@ -0,0 +1,82 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Try each zfs(1) sub-command without parameters to make sure
+# it returns an error.
+#
+# STRATEGY:
+# 1. Create an array of parameters
+# 2. For each parameter in the array, execute the sub-command
+# 3. Verify an error is returned.
+#
+
+verify_runnable "both"
+
+
+set -A args "" "create" "create -s" "create -V" "create -s -V" \
+ "destroy" "destroy -f" "destroy -r" "destroy -R" "destroy -rRf" \
+ "snapshot" "snapshot -r" \
+ "rollback" "rollback -r" "rollback -R" "rollback -f" "rollback -rRf" \
+ "clone" "clone -p" "promote" "rename" "rename -p" "rename -r" "list blah" \
+ "set" "get" "get -rHp" "get -o" "get -s" \
+ "inherit" "inherit -r" "quota=" \
+ "set reservation=" "set atime=" "set checksum=" "set compression=" \
+ "set type=" "set creation=" "set used=" "set available=" "set referenced=" \
+ "set compressratio=" "set mounted=" "set origin=" "set quota=" \
+ "set reservation=" "set volsize=" " set volblocksize=" "set recordsize=" \
+ "set mountpoint=" "set devices=" "set exec=" "set setuid=" "set readonly=" \
+ "set snapdir=" "set aclmode=" "set aclinherit=" \
+ "set quota=blah" "set reservation=blah" "set atime=blah" "set checksum=blah" \
+ "set compression=blah" \
+ "upgrade blah" "mount blah" "mount -o" \
+ "umount blah" "unmount" "unmount blah" "unmount -f" \
+ "share" "unshare" "send" "send -i" "receive" "receive -d" "receive -vnF" \
+ "recv" "recv -d" "recv -vnF" "allow" "unallow" \
+ "blah blah" "-%" "--" "--?" "-*" "-="
+if is_freebsd; then
+ args+=("set jailed=")
+else
+ args+=("set zoned=")
+fi
+
+log_assert "Badly-formed zfs sub-command should return an error."
+
+typeset -i i=0
+while (( $i < ${#args[*]} )); do
+ log_mustnot zfs ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "Badly formed zfs sub-commands fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_002_pos.ksh
new file mode 100755
index 000000000000..b475960c9dea
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_002_pos.ksh
@@ -0,0 +1,123 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# With ZFS_ABORT set, all zfs commands should be able to abort and generate a
+# core file.
+#
+# STRATEGY:
+# 1. Create an array of zfs command
+# 2. Execute each command in the array
+# 3. Verify the command aborts and generate a core file
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ unset ZFS_ABORT
+
+ if is_freebsd && [[ -n $savedcorefile ]]; then
+ sysctl kern.corefile=$savedcorefile
+ fi
+
+ if [[ -d $corepath ]]; then
+ rm -rf $corepath
+ fi
+ for ds in $fs1 $fs $ctr; do
+ if datasetexists $ds; then
+ log_must zfs destroy -rRf $ds
+ fi
+ done
+}
+
+log_assert "With ZFS_ABORT set, all zfs commands can abort and generate a " \
+ "core file."
+log_onexit cleanup
+
+# Preparation work for testing
+savedcorefile=""
+corepath=$TESTDIR/core
+corefile=$corepath/core.zfs
+if [[ -d $corepath ]]; then
+ rm -rf $corepath
+fi
+log_must mkdir $corepath
+
+ctr=$TESTPOOL/$TESTCTR
+log_must zfs create $ctr
+
+fs=$ctr/$TESTFS
+fs1=$ctr/$TESTFS1
+snap=$fs@$TESTSNAP
+clone=$ctr/$TESTCLONE
+streamf=$corepath/s.$$
+
+typeset cmds=("create $fs" "list $fs" "snapshot $snap" "set snapdir=hidden $fs" \
+ "get snapdir $fs" "rollback $snap" "inherit snapdir $fs" \
+ "rename $fs $fs-new" "rename $fs-new $fs" "unmount $fs" \
+ "mount $fs" "share $fs" "unshare $fs" "send $snap \>$streamf" \
+ "receive $fs1 \<$streamf" "clone $snap $clone" "promote $clone" \
+ "promote $fs" "destroy -rRf $fs")
+
+typeset badparams=("" "create" "destroy" "snapshot" "rollback" "clone" \
+ "promote" "rename" "list -*" "set" "get -*" "inherit" "mount -A" \
+ "unmount" "share" "unshare" "send" "receive")
+
+if is_linux; then
+ ulimit -c unlimited
+ echo "$corefile" >/proc/sys/kernel/core_pattern
+ echo 0 >/proc/sys/kernel/core_uses_pid
+ export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
+elif is_freebsd; then
+ ulimit -c unlimited
+ savedcorefile=$(sysctl -n kern.corefile)
+ log_must sysctl kern.corefile=$corepath/core.%N
+else
+ log_must coreadm -p ${corepath}/core.%f
+fi
+
+log_must export ZFS_ABORT=yes
+
+for subcmd in "${cmds[@]}" "${badparams[@]}"; do
+ zfs $subcmd >/dev/null 2>&1 && log_fail "$subcmd passed incorrectly."
+ if [[ ! -e $corefile ]]; then
+ log_fail "zfs $subcmd cannot generate core file with " \
+ "ZFS_ABORT set."
+ fi
+ log_must rm -f $corefile
+done
+
+log_pass "With ZFS_ABORT set, zfs command can abort and generate core file " \
+ "as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_003_neg.ksh
new file mode 100755
index 000000000000..0438bae8f6ce
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs/zfs_003_neg.ksh
@@ -0,0 +1,68 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# zfs command will failed with unexpected scenarios:
+# (1) ZFS_DEV cannot be opened
+# (2) MNTTAB cannot be opened
+#
+# STRATEGY:
+# 1. Create an array of zfs command
+# 2. Execute each command in the array
+# 3. Verify the command aborts and generate a core file
+#
+
+verify_runnable "global"
+
+log_assert "zfs fails with unexpected scenario."
+
+#verify zfs failed if ZFS_DEV cannot be opened
+ZFS_DEV=/dev/zfs
+
+if is_linux; then
+ # On Linux, we use /proc/self/mounts, which cannot be moved.
+ MNTTAB=
+fi
+
+for file in $ZFS_DEV $MNTTAB; do
+ if [[ -e $file ]]; then
+ mv $file ${file}.bak
+ fi
+ for cmd in "" "list" "get all" "mount"; do
+ log_mustnot eval "zfs $cmd >/dev/null 2>&1"
+ done
+ mv ${file}.bak $file
+done
+
+log_pass "zfs fails with unexpected scenario as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/Makefile.am
new file mode 100644
index 000000000000..e71fbc85ca84
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/Makefile.am
@@ -0,0 +1,5 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_bookmark
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_bookmark_cliargs.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/cleanup.ksh
new file mode 100755
index 000000000000..f84ac43e67c9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/cleanup.ksh
@@ -0,0 +1,31 @@
+#!/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 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+log_must zfs destroy "$TESTPOOL/$TESTFS/child"
+log_must zfs destroy "$TESTPOOL/${TESTFS}_with_suffix"
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/setup.ksh
new file mode 100755
index 000000000000..40953415c6b9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/setup.ksh
@@ -0,0 +1,35 @@
+#!/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 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup_noexit $DISK
+log_must zfs create "$TESTPOOL/$TESTFS/child"
+log_must zfs create "$TESTPOOL/${TESTFS}_with_suffix"
+log_must zfs create "$TESTPOOL/$TESTFS/recv"
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/zfs_bookmark_cliargs.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/zfs_bookmark_cliargs.ksh
new file mode 100755
index 000000000000..10e93337abf8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_bookmark/zfs_bookmark_cliargs.ksh
@@ -0,0 +1,238 @@
+#!/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 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+# Copyright 2019, 2020 by Christian Schwarz. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs bookmark' should work with both full and short arguments.
+#
+# STRATEGY:
+# 1. Create initial snapshot
+#
+# 2. Verify we can create a bookmark specifying snapshot and bookmark full paths
+# 3. Verify we can create a bookmark specifying the short snapshot name
+# 4. Verify we can create a bookmark specifying the short bookmark name
+# 5. Verify at least a full dataset path is required and both snapshot and
+# bookmark name must be valid
+#
+# 6. Verify we can copy a bookmark by specifying the source bookmark and new
+# bookmark full paths.
+# 7. Verify we can copy a bookmark specifying the short source name
+# 8. Verify we can copy a bookmark specifying the short new name
+# 9. Verify two short paths are not allowed, and test empty paths
+# 10. Verify we cannot copy a bookmark if the new bookmark already exists
+# 11. Verify that copying a bookmark only works if new and source name
+# have the same dataset
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if snapexists "$DATASET@$TESTSNAP"; then
+ log_must zfs destroy "$DATASET@$TESTSNAP"
+ fi
+ if bkmarkexists "$DATASET#$TESTBM"; then
+ log_must zfs destroy "$DATASET#$TESTBM"
+ fi
+ if bkmarkexists "$DATASET#$TESTBMCOPY"; then
+ log_must zfs destroy "$DATASET#$TESTBMCOPY"
+ fi
+}
+
+log_assert "'zfs bookmark' should work only when passed valid arguments."
+log_onexit cleanup
+
+DATASET="$TESTPOOL/$TESTFS"
+DATASET_TWO="$TESTPOOL/${TESTFS}_two"
+TESTSNAP='snapshot'
+TESTSNAP2='snapshot2'
+TESTBM='bookmark'
+TESTBMCOPY='bookmark_copy'
+
+
+# Create initial snapshot
+log_must zfs snapshot "$DATASET@$TESTSNAP"
+
+#
+# Bookmark creation tests
+#
+
+# Verify we can create a bookmark specifying snapshot and bookmark full paths
+log_must zfs bookmark "$DATASET@$TESTSNAP" "$DATASET#$TESTBM"
+log_must eval "bkmarkexists $DATASET#$TESTBM"
+log_must zfs destroy "$DATASET#$TESTBM"
+
+# Verify we can create a bookmark specifying the snapshot name
+log_must zfs bookmark "@$TESTSNAP" "$DATASET#$TESTBM"
+log_must eval "bkmarkexists $DATASET#$TESTBM"
+log_must zfs destroy "$DATASET#$TESTBM"
+
+# Verify we can create a bookmark specifying the bookmark name
+log_must zfs bookmark "$DATASET@$TESTSNAP" "#$TESTBM"
+log_must eval "bkmarkexists $DATASET#$TESTBM"
+log_must zfs destroy "$DATASET#$TESTBM"
+
+# Verify at least a full dataset path is required and both snapshot and
+# bookmark name must be valid
+log_mustnot zfs bookmark "@$TESTSNAP" "#$TESTBM"
+log_mustnot zfs bookmark "$TESTSNAP" "#$TESTBM"
+log_mustnot zfs bookmark "@$TESTSNAP" "$TESTBM"
+log_mustnot zfs bookmark "$TESTSNAP" "$TESTBM"
+log_mustnot zfs bookmark "$TESTSNAP" "$DATASET#$TESTBM"
+log_mustnot zfs bookmark "$DATASET" "$TESTBM"
+log_mustnot zfs bookmark "$DATASET@" "$TESTBM"
+log_mustnot zfs bookmark "$DATASET" "#$TESTBM"
+log_mustnot zfs bookmark "$DATASET@" "#$TESTBM"
+log_mustnot zfs bookmark "$DATASET@$TESTSNAP" "$TESTBM"
+log_mustnot zfs bookmark "@" "#$TESTBM"
+log_mustnot zfs bookmark "@" "#"
+log_mustnot zfs bookmark "@$TESTSNAP" "#"
+log_mustnot zfs bookmark "@$TESTSNAP" "$DATASET#"
+log_mustnot zfs bookmark "@$TESTSNAP" "$DATASET"
+log_mustnot zfs bookmark "$TESTSNAP" "$DATASET#"
+log_mustnot zfs bookmark "$TESTSNAP" "$DATASET"
+log_mustnot eval "bkmarkexists $DATASET#$TESTBM"
+
+# Verify that we can create a bookmarks on another origin filesystem
+log_must zfs clone "$DATASET@$TESTSNAP" "$DATASET_TWO"
+log_must zfs bookmark "$DATASET@$TESTSNAP" "$DATASET_TWO#$TESTBM"
+log_must eval "destroy_dataset $DATASET_TWO"
+
+# Verify that we can cannot create bookmarks on a non-origin filesystem
+log_must zfs create "$DATASET_TWO"
+log_mustnot_expect "source is not an ancestor of the new bookmark's dataset" zfs bookmark "$DATASET@$TESTSNAP" "$DATASET_TWO#$TESTBM"
+log_must zfs destroy "$DATASET_TWO"
+
+# Verify that we can create bookmarks of snapshots on the pool dataset
+log_must zfs snapshot "$TESTPOOL@$TESTSNAP"
+log_must zfs bookmark "$TESTPOOL@$TESTSNAP" "$TESTPOOL#$TESTBM"
+log_must zfs destroy "$TESTPOOL#$TESTBM"
+log_must zfs destroy "$TESTPOOL@$TESTSNAP"
+
+#
+# Bookmark copying tests
+#
+
+# create the source bookmark
+log_must zfs bookmark "$DATASET@$TESTSNAP" "$DATASET#$TESTBM"
+
+# Verify we can copy a bookmark by specifying the source bookmark
+# and new bookmark full paths.
+log_must eval "bkmarkexists $DATASET#$TESTBM"
+log_must zfs bookmark "$DATASET#$TESTBM" "$DATASET#$TESTBMCOPY"
+log_must eval "bkmarkexists $DATASET#$TESTBMCOPY"
+## validate destroy once (should be truly independent bookmarks)
+log_must zfs destroy "$DATASET#$TESTBM"
+log_mustnot eval "bkmarkexists $DATASET#$TESTBM"
+log_must eval "bkmarkexists $DATASET#$TESTBMCOPY"
+log_must zfs destroy "$DATASET#$TESTBMCOPY"
+log_mustnot eval "bkmarkexists $DATASET#$TESTBMCOPY"
+log_mustnot eval "bkmarkexists $DATASET#$TESTBM"
+## recreate the source bookmark
+log_must zfs bookmark "$DATASET@$TESTSNAP" "$DATASET#$TESTBM"
+
+# Verify we can copy a bookmark specifying the short source name
+log_must zfs bookmark "#$TESTBM" "$DATASET#$TESTBMCOPY"
+log_must eval "bkmarkexists $DATASET#$TESTBMCOPY"
+log_must zfs destroy "$DATASET#$TESTBMCOPY"
+
+# Verify we can copy a bookmark specifying the short bookmark name
+log_must zfs bookmark "$DATASET#$TESTBM" "#$TESTBMCOPY"
+log_must eval "bkmarkexists $DATASET#$TESTBMCOPY"
+log_must zfs destroy "$DATASET#$TESTBMCOPY"
+
+# Verify two short paths are not allowed, and test empty paths
+log_mustnot zfs bookmark "#$TESTBM" "#$TESTBMCOPY"
+log_mustnot zfs bookmark "#$TESTBM" "#"
+log_mustnot zfs bookmark "#" "#$TESTBMCOPY"
+log_mustnot zfs bookmark "#" "#"
+log_mustnot zfs bookmark "#" ""
+log_mustnot zfs bookmark "" "#"
+log_mustnot zfs bookmark "" ""
+
+# Verify that we can copy bookmarks on another origin filesystem
+log_must zfs clone "$DATASET@$TESTSNAP" "$DATASET_TWO"
+log_must zfs bookmark "$DATASET#$TESTBM" "$DATASET_TWO#$TESTBMCOPY"
+log_must zfs destroy "$DATASET_TWO"
+
+# Verify that we can cannot create bookmarks on another non-origin filesystem
+log_must zfs create "$DATASET_TWO"
+log_mustnot_expect "source is not an ancestor of the new bookmark's dataset" zfs bookmark "$DATASET#$TESTBM" "$DATASET_TWO#$TESTBMCOPY"
+log_must zfs destroy "$DATASET_TWO"
+
+# Verify that we can copy bookmarks on the pool dataset
+log_must zfs snapshot "$TESTPOOL@$TESTSNAP"
+log_must zfs bookmark "$TESTPOOL@$TESTSNAP" "$TESTPOOL#$TESTBM"
+log_must zfs bookmark "$TESTPOOL#$TESTBM" "$TESTPOOL#$TESTBMCOPY"
+log_must zfs destroy "$TESTPOOL#$TESTBM"
+log_must zfs destroy "$TESTPOOL#$TESTBMCOPY"
+log_must zfs destroy "$TESTPOOL@$TESTSNAP"
+
+# Verify that copied 'normal' bookmarks are independent of the source bookmark
+log_must zfs bookmark "$DATASET#$TESTBM" "$DATASET#$TESTBMCOPY"
+log_must zfs destroy "$DATASET#$TESTBM"
+log_must eval "zfs send $DATASET@$TESTSNAP > $TEST_BASE_DIR/zfstest_datastream.$$"
+log_must eval "destroy_dataset $TESTPOOL/$TESTFS/recv"
+log_must eval "zfs recv -o mountpoint=none $TESTPOOL/$TESTFS/recv < $TEST_BASE_DIR/zfstest_datastream.$$"
+log_must zfs snapshot "$DATASET@$TESTSNAP2"
+log_must eval "zfs send -i \#$TESTBMCOPY $DATASET@$TESTSNAP2 > $TEST_BASE_DIR/zfstest_datastream.$$"
+log_must eval "zfs recv $TESTPOOL/$TESTFS/recv < $TEST_BASE_DIR/zfstest_datastream.$$"
+# cleanup
+log_must eval "destroy_dataset $DATASET@$TESTSNAP2"
+log_must zfs destroy "$DATASET#$TESTBMCOPY"
+log_must zfs bookmark "$DATASET@$TESTSNAP" "$DATASET#$TESTBM"
+
+# Verify that copied redaction bookmarks are independent of the source bookmark
+## create redaction bookmark
+log_must zfs destroy "$DATASET#$TESTBM"
+log_must zfs destroy "$DATASET@$TESTSNAP"
+log_must eval "echo secret > $TESTDIR/secret"
+log_must zfs snapshot "$DATASET@$TESTSNAP"
+log_must eval "echo redacted > $TESTDIR/secret"
+log_must zfs snapshot "$DATASET@$TESTSNAP2" # TESTSNAP2 is the redaction snapshot
+log_must zfs list -t all -o name,createtxg,guid,mountpoint,written
+log_must zfs redact "$DATASET@$TESTSNAP" "$TESTBM" "$DATASET@$TESTSNAP2"
+# ensure our primitive for testing whether a bookmark is a redaction bookmark works
+log_must eval "zfs get all $DATASET#$TESTBM | grep redact_snaps"
+## copy the redaction bookmark
+log_must zfs bookmark "$DATASET#$TESTBM" "#$TESTBMCOPY"
+log_mustnot eval "zfs get all $DATASET#$TESTBMCOPY | grep redact_snaps"
+log_must eval "zfs send --redact "$TESTBMCOPY" -i $DATASET@$TESTSNAP $DATASET@$TESTSNAP2 2>&1 | head -n 100 | grep 'not a redaction bookmark'"
+# try the above again after destroying the source bookmark, preventive measure for future work
+log_must zfs destroy "$DATASET#$TESTBM"
+log_mustnot eval "zfs get all $DATASET#$TESTBMCOPY | grep redact_snaps"
+log_must eval "zfs send --redact "$TESTBMCOPY" -i $DATASET@$TESTSNAP $DATASET@$TESTSNAP2 2>&1 | head -n 100 | grep 'not a redaction bookmark'"
+## cleanup
+log_must eval "destroy_dataset $DATASET@$TESTSNAP2"
+log_must zfs destroy "$DATASET#$TESTBMCOPY"
+log_must eval "destroy_dataset $DATASET@$TESTSNAP"
+log_must zfs snapshot "$DATASET@$TESTSNAP"
+log_must zfs bookmark "$DATASET@$TESTSNAP" "$DATASET#$TESTBM"
+
+log_pass "'zfs bookmark' works as expected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/Makefile.am
new file mode 100644
index 000000000000..72d6e4700e17
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/Makefile.am
@@ -0,0 +1,12 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_change-key
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_change-key.ksh \
+ zfs_change-key_child.ksh \
+ zfs_change-key_clones.ksh \
+ zfs_change-key_inherit.ksh \
+ zfs_change-key_format.ksh \
+ zfs_change-key_load.ksh \
+ zfs_change-key_location.ksh \
+ zfs_change-key_pbkdf2iters.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key.ksh
new file mode 100755
index 000000000000..781caae5b5c0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key.ksh
@@ -0,0 +1,62 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs change-key' should change the key material.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Attempt to change the key
+# 3. Unmount the dataset and unload its key
+# 4. Attempt to load the old key
+# 5. Verify the key is not loaded
+# 6. Attempt to load the new key
+# 7. Verify the key is loaded
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS1
+}
+log_onexit cleanup
+
+log_assert "'zfs change-key' should change the key material"
+
+log_must eval "echo $PASSPHRASE1 | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS1"
+log_must eval "echo $PASSPHRASE2 | zfs change-key $TESTPOOL/$TESTFS1"
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+
+log_mustnot eval "echo $PASSPHRASE1 | zfs load-key $TESTPOOL/$TESTFS1"
+log_must key_unavailable $TESTPOOL/$TESTFS1
+
+log_must eval "echo $PASSPHRASE2 | zfs load-key $TESTPOOL/$TESTFS1"
+log_must key_available $TESTPOOL/$TESTFS1
+
+log_pass "'zfs change-key' changes the key material"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_child.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_child.ksh
new file mode 100755
index 000000000000..a886ab8a7793
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_child.ksh
@@ -0,0 +1,91 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs change-key' should promote an encrypted child to an encryption root.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Create an encrypted child dataset
+# 3. Create an unencrypted child dataset
+# 4. Attempt to change the key without any flags
+# 5. Attempt to change the key specifying keylocation
+# 6. Attempt to change the key specifying keyformat
+# 7. Verify the new encryption root can unload and load its key
+# 8. Recreate the child dataset
+# 9. Attempt to change the key specifying both the keylocation and keyformat
+# 10. Verify the new encryption root can unload and load its key
+# 11. Verify the unencrytped child is still accessible normally
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+}
+
+log_onexit cleanup
+
+log_assert "'zfs change-key' should promote an encrypted child to an" \
+ "encryption root"
+
+log_must eval "echo $PASSPHRASE1 | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS1"
+log_must zfs create $TESTPOOL/$TESTFS1/child
+log_must zfs create -o encryption=off $TESTPOOL/$TESTFS1/child2
+
+log_mustnot eval "echo $PASSPHRASE2 | zfs change-key" \
+ "$TESTPOOL/$TESTFS1/child"
+
+log_mustnot eval "echo $PASSPHRASE2 | zfs change-key -o keylocation=prompt" \
+ "$TESTPOOL/$TESTFS1/child"
+
+log_must eval "echo $PASSPHRASE2 | zfs change-key -o keyformat=passphrase" \
+ "$TESTPOOL/$TESTFS1/child"
+
+log_must zfs unmount $TESTPOOL/$TESTFS1/child
+log_must zfs unload-key $TESTPOOL/$TESTFS1/child
+log_must key_unavailable $TESTPOOL/$TESTFS1/child
+
+log_must eval "echo $PASSPHRASE2 | zfs load-key $TESTPOOL/$TESTFS1/child"
+log_must key_available $TESTPOOL/$TESTFS1/child
+
+log_must zfs destroy $TESTPOOL/$TESTFS1/child
+log_must zfs create $TESTPOOL/$TESTFS1/child
+
+log_must eval "echo $PASSPHRASE2 | zfs change-key -o keyformat=passphrase" \
+ "-o keylocation=prompt $TESTPOOL/$TESTFS1/child"
+
+log_must zfs unmount $TESTPOOL/$TESTFS1/child
+log_must zfs unload-key $TESTPOOL/$TESTFS1/child
+log_must key_unavailable $TESTPOOL/$TESTFS1/child
+
+log_must eval "echo $PASSPHRASE2 | zfs load-key $TESTPOOL/$TESTFS1/child"
+log_must key_available $TESTPOOL/$TESTFS1/child
+log_must zfs unmount $TESTPOOL/$TESTFS1/child2
+log_must zfs mount $TESTPOOL/$TESTFS1/child2
+
+log_pass "'zfs change-key' promotes an encrypted child to an encryption root"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_clones.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_clones.ksh
new file mode 100755
index 000000000000..497fb99c8102
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_clones.ksh
@@ -0,0 +1,80 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs change-key' should correctly update encryption roots with clones.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Create an encryption root child of the first dataset
+# 3. Clone the child encryption root twice
+# 4. Add inheriting children to the encryption root and each of the clones
+# 5. Verify the encryption roots
+# 6. Have the child encryption root inherit from its parent
+# 7. Verify the encryption root for all datasets is now the parent dataset
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -Rf $TESTPOOL/$TESTFS1
+}
+
+log_onexit cleanup
+
+log_assert "'zfs change-key' should correctly update encryption " \
+ "roots with clones"
+
+log_must eval "echo $PASSPHRASE1 | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS1"
+log_must eval "echo $PASSPHRASE2 | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS1/child"
+log_must zfs snapshot $TESTPOOL/$TESTFS1/child@1
+log_must zfs clone $TESTPOOL/$TESTFS1/child@1 $TESTPOOL/$TESTFS1/clone1
+log_must zfs clone $TESTPOOL/$TESTFS1/child@1 $TESTPOOL/$TESTFS1/clone2
+log_must zfs create $TESTPOOL/$TESTFS1/child/A
+log_must zfs create $TESTPOOL/$TESTFS1/clone1/B
+log_must zfs create $TESTPOOL/$TESTFS1/clone2/C
+
+log_must verify_encryption_root $TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/child $TESTPOOL/$TESTFS1/child
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/clone1 $TESTPOOL/$TESTFS1/child
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/clone2 $TESTPOOL/$TESTFS1/child
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/child/A $TESTPOOL/$TESTFS1/child
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/clone1/B $TESTPOOL/$TESTFS1/child
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/clone2/C $TESTPOOL/$TESTFS1/child
+
+log_must zfs change-key -i $TESTPOOL/$TESTFS1/child
+
+log_must verify_encryption_root $TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/child $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/clone1 $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/clone2 $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/child/A $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/clone1/B $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/clone2/C $TESTPOOL/$TESTFS1
+
+log_pass "'zfs change-key' correctly updates encryption roots with clones"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_format.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_format.ksh
new file mode 100755
index 000000000000..6344b8d05a20
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_format.ksh
@@ -0,0 +1,72 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+# Copyright (c) 2019 DilOS
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs change-key -o' should change the key format.
+#
+# STRATEGY:
+# 1. Create an encryption dataset with a passphrase key format
+# 2. Unmount the dataset
+# 3. Verify the key format is passphrase
+# 4. Change the key format to hex
+# 5. Verify the key format is hex
+# 6. Attempt to reload the dataset's key
+# 7. Change the key format to raw
+# 8. Verify the key format is raw
+# 9. Attempt to reload the dataset's key
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS1
+}
+log_onexit cleanup
+
+log_assert "'zfs change-key -o' should change the key format"
+
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS1"
+log_must zfs unmount $TESTPOOL/$TESTFS1
+
+log_must verify_keyformat $TESTPOOL/$TESTFS1 "passphrase"
+
+log_must eval "echo $HEXKEY | zfs change-key -o keyformat=hex" \
+ "$TESTPOOL/$TESTFS1"
+log_must verify_keyformat $TESTPOOL/$TESTFS1 "hex"
+
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+log_must eval "echo $HEXKEY | zfs load-key $TESTPOOL/$TESTFS1"
+
+log_must eval "printf '%s' $RAWKEY | zfs change-key -o keyformat=raw" \
+ "$TESTPOOL/$TESTFS1"
+log_must verify_keyformat $TESTPOOL/$TESTFS1 "raw"
+
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+log_must eval "printf '%s' $RAWKEY | zfs load-key $TESTPOOL/$TESTFS1"
+
+log_pass "'zfs change-key -o' changes the key format"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_inherit.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_inherit.ksh
new file mode 100755
index 000000000000..94820c37ecc0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_inherit.ksh
@@ -0,0 +1,78 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs change-key -i' should cause a dataset to inherit its parent key
+#
+# STRATEGY:
+# 1. Create a parent encrypted dataset
+# 2. Create a child dataset as an encryption root
+# 3. Attempt to inherit the parent key
+# 4. Verify the key is inherited
+# 5. Unmount the parent and unload its key
+# 6. Verify the key is unavailable for parent and child
+# 7. Load the parent key
+# 8. Verify the key is available for parent and child
+# 9. Attempt to mount the datasets
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+}
+log_onexit cleanup
+
+log_assert "'zfs change-key -i' should cause a dataset to inherit its" \
+ "parent key"
+
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS1"
+log_must eval "echo $PASSPHRASE1 | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt" \
+ "$TESTPOOL/$TESTFS1/child"
+
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/child \
+ "$TESTPOOL/$TESTFS1/child"
+
+log_must zfs change-key -i $TESTPOOL/$TESTFS1/child
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/child "$TESTPOOL/$TESTFS1"
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+
+log_must key_unavailable $TESTPOOL/$TESTFS1
+log_must key_unavailable $TESTPOOL/$TESTFS1/child
+
+log_must eval "echo $PASSPHRASE | zfs load-key $TESTPOOL/$TESTFS1"
+
+log_must key_available $TESTPOOL/$TESTFS1
+log_must key_available $TESTPOOL/$TESTFS1/child
+
+log_must zfs mount $TESTPOOL/$TESTFS1
+log_must zfs mount $TESTPOOL/$TESTFS1/child
+
+log_pass "'zfs change-key -i' causes a dataset to inherit its parent key"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_load.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_load.ksh
new file mode 100755
index 000000000000..4ed4aadfe0fa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_load.ksh
@@ -0,0 +1,58 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs change-key -l' should load a dataset's key to change it.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Unload dataset and unload its key
+# 3. Attempt to change the key
+# 4. Verify the dataset key is loaded
+# 3. Attempt to change the key
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS1
+}
+log_onexit cleanup
+
+log_assert "'zfs change-key -l' should load a dataset's key to change it"
+
+log_must eval "echo $PASSPHRASE > /$TESTPOOL/pkey"
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+
+log_must zfs change-key -l $TESTPOOL/$TESTFS1
+log_must key_available $TESTPOOL/$TESTFS1
+
+log_must zfs change-key -l $TESTPOOL/$TESTFS1
+
+log_pass "'zfs change-key -l' loads a dataset's key to change it"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_location.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_location.ksh
new file mode 100755
index 000000000000..5cbe34b269ba
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_location.ksh
@@ -0,0 +1,65 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs change-key -o' should change the keylocation.
+#
+# STRATEGY:
+# 1. Create an encryption dataset with a file key location
+# 2. Change the key location to 'prompt'
+# 3. Verify the key location
+# 4. Unmount the dataset and unload its key
+# 5. Attempt to load the dataset's key
+# 6. Attempt to change the key location to 'none'
+# 7. Attempt to change the key location to an invalid value
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS1
+}
+log_onexit cleanup
+
+log_assert "'zfs change-key -o' should change the keylocation"
+
+log_must eval "echo $PASSPHRASE > /$TESTPOOL/pkey"
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1
+log_must verify_keylocation $TESTPOOL/$TESTFS1 "file:///$TESTPOOL/pkey"
+
+log_must eval "echo $PASSPHRASE1 | zfs change-key -o keylocation=prompt" \
+ "$TESTPOOL/$TESTFS1"
+log_must verify_keylocation $TESTPOOL/$TESTFS1 "prompt"
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+log_must eval "echo $PASSPHRASE1 | zfs load-key $TESTPOOL/$TESTFS1"
+
+log_mustnot zfs change-key -o keylocation=none $TESTPOOL/$TESTFS1
+log_mustnot zfs change-key -o keylocation=foobar $TESTPOOL/$TESTFS1
+
+log_pass "'zfs change-key -o' changes the keylocation"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_pbkdf2iters.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_pbkdf2iters.ksh
new file mode 100755
index 000000000000..b1672248be12
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_change-key/zfs_change-key_pbkdf2iters.ksh
@@ -0,0 +1,75 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs change-key -o' should change the pbkdf2 iterations.
+#
+# STRATEGY:
+# 1. Create an encryption dataset with 200k PBKDF2 iterations
+# 2. Unmount the dataset
+# 3. Change the PBKDF2 iterations to 150k
+# 4. Verify the PBKDF2 iterations
+# 5. Unload the dataset's key
+# 6. Attempt to load the dataset's key
+#
+
+verify_runnable "both"
+
+function verify_pbkdf2iters
+{
+ typeset ds=$1
+ typeset iterations=$2
+ typeset iters=$(get_prop pbkdf2iters $ds)
+
+ if [[ "$iters" != "$iterations" ]]; then
+ log_fail "Expected $iterations iterations, got $iters"
+ fi
+
+ return 0
+}
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS1
+}
+log_onexit cleanup
+
+log_assert "'zfs change-key -o' should change the pbkdf2 iterations"
+
+log_must eval "echo $PASSPHRASE > /$TESTPOOL/pkey"
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL/pkey -o pbkdf2iters=200000 \
+ $TESTPOOL/$TESTFS1
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must verify_pbkdf2iters $TESTPOOL/$TESTFS1 "200000"
+
+log_must zfs change-key -o pbkdf2iters=150000 $TESTPOOL/$TESTFS1
+log_must verify_pbkdf2iters $TESTPOOL/$TESTFS1 "150000"
+
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+log_must zfs load-key $TESTPOOL/$TESTFS1
+
+log_pass "'zfs change-key -o' changes the pbkdf2 iterations"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/Makefile.am
new file mode 100644
index 000000000000..06099c0c2b79
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/Makefile.am
@@ -0,0 +1,17 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_clone
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_clone_001_neg.ksh \
+ zfs_clone_002_pos.ksh \
+ zfs_clone_003_pos.ksh \
+ zfs_clone_004_pos.ksh \
+ zfs_clone_005_pos.ksh \
+ zfs_clone_006_pos.ksh \
+ zfs_clone_007_pos.ksh \
+ zfs_clone_008_neg.ksh \
+ zfs_clone_009_neg.ksh \
+ zfs_clone_010_pos.ksh \
+ zfs_clone_encrypted.ksh \
+ zfs_clone_deeply_nested.ksh \
+ zfs_clone_rm_nested.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/cleanup.ksh
new file mode 100755
index 000000000000..d247991fbbdb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_container_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/setup.ksh
new file mode 100755
index 000000000000..985554f8cd2e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/setup.ksh
@@ -0,0 +1,36 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_container_volume_setup ${DISK}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_001_neg.ksh
new file mode 100755
index 000000000000..b83ccdf48c79
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_001_neg.ksh
@@ -0,0 +1,126 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs clone' should fail with inapplicable scenarios, including:
+# * Null arguments
+# * non-existent snapshots.
+# * invalid characters in ZFS namesapec
+# * Leading slash in the target clone name
+# * The argument contains an empty component.
+# * The pool specified in the target doesn't exist.
+# * The parent dataset of the target doesn't exist.
+# * The argument refer to a pool, not dataset.
+# * The target clone already exists.
+# * Null target clone argument.
+# * Too many arguments.
+# * Invalid record sizes.
+#
+# STRATEGY:
+# 1. Create an array of parameters
+# 2. For each parameter in the array, execute the sub-command
+# 3. Verify an error is returned.
+#
+
+verify_runnable "both"
+
+typeset target1=$TESTPOOL/$TESTFS1
+typeset target2=$TESTPOOL/$TESTCTR1/$TESTFS1
+typeset targets="$target1 $target2 $NONEXISTPOOLNAME/$TESTFS"
+
+set -A args "" \
+ "$TESTPOOL/$TESTFS@blah $target1" "$TESTPOOL/$TESTVOL@blah $target1" \
+ "$TESTPOOL/$TESTFS@blah* $target1" "$TESTPOOL/$TESTVOL@blah* $target1" \
+ "$SNAPFS $target1*" "$SNAPFS1 $target1*" \
+ "$SNAPFS /$target1" "$SNAPFS1 /$target1" \
+ "$SNAPFS $TESTPOOL//$TESTFS1" "$SNAPFS1 $TESTPOOL//$TESTFS1" \
+ "$SNAPFS $NONEXISTPOOLNAME/$TESTFS" "$SNAPFS1 $NONEXISTPOOLNAME/$TESTFS" \
+ "$SNAPFS" "$SNAPFS1" \
+ "$SNAPFS $target1 $target2" "$SNAPFS1 $target1 $target2" \
+ "-o recordsize=2M $SNAPFS1 $target1" \
+ "-o recordsize=128B $SNAPFS1 $target1"
+typeset -i argsnum=${#args[*]}
+typeset -i j=0
+while (( j < argsnum )); do
+ args[((argsnum+j))]="-p ${args[j]}"
+ ((j = j + 1))
+done
+
+set -A moreargs "$SNAPFS $target2" "$SNAPFS1 $target2" \
+ "$SNAPFS $TESTPOOL" "$SNAPFS1 $TESTPOOL" \
+ "$SNAPFS $TESTPOOL/$TESTCTR" "$SNAPFS $TESTPOOL/$TESTFS" \
+ "$SNAPFS1 $TESTPOOL/$TESTCTR" "$SNAPFS1 $TESTPOOL/$TESTFS"
+
+set -A args ${args[*]} ${moreargs[*]}
+
+function setup_all
+{
+ log_note "Create snapshots and mount them..."
+
+ for snap in $SNAPFS $SNAPFS1 ; do
+ if ! snapexists $snap ; then
+ log_must zfs snapshot $snap
+ fi
+ done
+
+ return 0
+}
+
+function cleanup_all
+{
+ for fs in $targets; do
+ datasetexists $fs && log_must zfs destroy -f $fs
+ done
+
+ for snap in $SNAPFS $SNAPFS1 ; do
+ snapexists $snap && log_must zfs destroy -Rf $snap
+ done
+
+ return 0
+}
+
+log_assert "Badly-formed 'zfs clone' with inapplicable scenarios" \
+ "should return an error."
+log_onexit cleanup_all
+
+setup_all
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_mustnot zfs clone ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "Badly formed 'zfs clone' with inapplicable scenarios" \
+ "fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_002_pos.ksh
new file mode 100755
index 000000000000..8e69a7adcc3d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_002_pos.ksh
@@ -0,0 +1,89 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs clone -p' should work as expected
+#
+# STRATEGY:
+# 1. prepare snapshots
+# 2. make sure without -p option, 'zfs clone' will fail
+# 3. with -p option, the clone can be created
+# 4. run 'zfs clone -p' again, the exit code should be zero
+#
+
+verify_runnable "both"
+
+function setup_all
+{
+ log_note "Create snapshots and mount them..."
+
+ for snap in $SNAPFS $SNAPFS1 ; do
+ if ! snapexists $snap ; then
+ log_must zfs snapshot $snap
+ fi
+ done
+
+ return 0
+}
+
+function cleanup_all
+{
+
+ if datasetexists $TESTPOOL/notexist ; then
+ log_must zfs destroy -rRf $TESTPOOL/notexist
+ fi
+
+ for snap in $SNAPFS $SNAPFS1 ; do
+ if snapexists $snap ; then
+ log_must zfs destroy -Rf $snap
+ fi
+ done
+
+ return 0
+}
+
+log_assert "clone -p should work as expected."
+log_onexit cleanup_all
+
+setup_all
+
+log_must verify_opt_p_ops "clone" "fs" $SNAPFS \
+ $TESTPOOL/notexist/new/clonefs$$
+
+if is_global_zone ; then
+ log_must verify_opt_p_ops "clone" "vol" $SNAPFS1 \
+ $TESTPOOL/notexist/new/clonevol$$
+fi
+
+log_pass "clone -p should work as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_003_pos.ksh
new file mode 100755
index 000000000000..522275759880
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_003_pos.ksh
@@ -0,0 +1,76 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs clone -o property=value filesystem' can successfully create a ZFS
+# clone filesystem with correct property set.
+#
+# STRATEGY:
+# 1. Create a ZFS clone filesystem in the storage pool with -o option
+# 2. Verify the filesystem created successfully
+# 3. Verify the property is correctly set
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if snapexists $SNAPFS ; then
+ log_must zfs destroy -Rf $SNAPFS
+ fi
+}
+
+log_onexit cleanup
+
+
+log_assert "'zfs clone -o property=value filesystem' can successfully create" \
+ "a ZFS clone filesystem with correct property set."
+
+log_must zfs snapshot $SNAPFS
+
+typeset -i i=0
+while (( $i < ${#RW_FS_PROP[*]} )); do
+ log_must zfs clone -o ${RW_FS_PROP[$i]} $SNAPFS $TESTPOOL/$TESTCLONE
+ datasetexists $TESTPOOL/$TESTCLONE || \
+ log_fail "zfs clone $TESTPOOL/$TESTCLONE fail."
+ propertycheck $TESTPOOL/$TESTCLONE ${RW_FS_PROP[i]} || \
+ log_fail "${RW_FS_PROP[i]} is failed to set."
+ log_must zfs destroy -f $TESTPOOL/$TESTCLONE
+ (( i = i + 1 ))
+done
+
+log_pass "'zfs clone -o property=value filesystem' can successfully create" \
+ "a ZFS clone filesystem with correct property set."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_004_pos.ksh
new file mode 100755
index 000000000000..8d86f5501863
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_004_pos.ksh
@@ -0,0 +1,87 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs clone -o property=value filesystem' can successfully create a ZFS
+# clone filesystem with multiple properties set.
+#
+# STRATEGY:
+# 1. Create a ZFS clone filesystem in the storage pool with multiple -o options
+# 2. Verify the filesystem created successfully
+# 3. Verify the properties are correctly set
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if snapexists $SNAPFS ; then
+ log_must zfs destroy -Rf $SNAPFS
+ fi
+}
+
+log_onexit cleanup
+
+log_assert "'zfs clone -o property=value filesystem' can successfully create" \
+ "a ZFS clone filesystem with multiple properties set."
+
+typeset -i i=0
+typeset opts=""
+
+log_must zfs snapshot $SNAPFS
+
+while (( $i < ${#RW_FS_PROP[*]} )); do
+ if [[ ${RW_FS_PROP[$i]} != *"checksum"* ]]; then
+ opts="$opts -o ${RW_FS_PROP[$i]}"
+ fi
+ (( i = i + 1 ))
+done
+
+log_must zfs clone $opts $SNAPFS $TESTPOOL/$TESTCLONE
+datasetexists $TESTPOOL/$TESTCLONE || \
+ log_fail "zfs create $TESTPOOL/$TESTCLONE fail."
+
+i=0
+while (( $i < ${#RW_FS_PROP[*]} )); do
+ if [[ ${RW_FS_PROP[$i]} != *"checksum"* ]]; then
+ propertycheck $TESTPOOL/$TESTCLONE ${RW_FS_PROP[i]} || \
+ log_fail "${RW_FS_PROP[i]} is failed to set."
+ fi
+ (( i = i + 1 ))
+done
+
+log_pass "'zfs clone -o property=value filesystem' can successfully create" \
+ "a ZFS clone filesystem with multiple properties set."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_005_pos.ksh
new file mode 100755
index 000000000000..afa8b46a6f7c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_005_pos.ksh
@@ -0,0 +1,78 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs clone -o property=value -V size volume' can successfully create a ZFS
+# clone volume with correct property set.
+#
+# STRATEGY:
+# 1. Create a ZFS clone volume in the storage pool with -o option
+# 2. Verify the volume created successfully
+# 3. Verify the property is correctly set
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if snapexists $SNAPFS1 ; then
+ log_must zfs destroy -Rf $SNAPFS1
+ fi
+}
+
+log_onexit cleanup
+
+log_assert "'zfs clone -o property=value -V size volume' can successfully" \
+ "create a ZFS clone volume with correct property set."
+
+log_must zfs snapshot $SNAPFS1
+typeset -i i=0
+while (( $i < ${#RW_VOL_CLONE_PROP[*]} )); do
+ log_must zfs clone -o ${RW_VOL_CLONE_PROP[$i]} $SNAPFS1 \
+ $TESTPOOL/$TESTCLONE
+ block_device_wait
+
+ datasetexists $TESTPOOL/$TESTCLONE || \
+ log_fail "zfs clone $TESTPOOL/$TESTCLONE fail."
+ propertycheck $TESTPOOL/$TESTCLONE ${RW_VOL_CLONE_PROP[i]} || \
+ log_fail "${RW_VOL_CLONE_PROP[i]} is failed to set."
+ log_must zfs destroy -f $TESTPOOL/$TESTCLONE
+
+ (( i = i + 1 ))
+done
+
+log_pass "'zfs clone -o property=value volume' can successfully" \
+ "create a ZFS clone volume with correct property set."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_006_pos.ksh
new file mode 100755
index 000000000000..2127eb117bf5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_006_pos.ksh
@@ -0,0 +1,86 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs clone -o property=value volume' can successfully create a ZFS
+# clone volume with multiple properties set.
+#
+# STRATEGY:
+# 1. Create a ZFS clone volume in the storage pool with -o option
+# 2. Verify the volume created successfully
+# 3. Verify the properties are correctly set
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if snapexists $SNAPFS1 ; then
+ log_must_busy zfs destroy -Rf $SNAPFS1
+ fi
+}
+
+log_onexit cleanup
+
+log_assert "'zfs clone -o property=value volume' can successfully" \
+ "create a ZFS clone volume with multiple correct properties set."
+
+typeset -i i=0
+typeset opts=""
+
+log_must zfs snapshot $SNAPFS1
+
+while (( $i < ${#RW_VOL_CLONE_PROP[*]} )); do
+ if [[ ${RW_VOL_CLONE_PROP[$i]} != *"checksum"* ]]; then
+ opts="$opts -o ${RW_VOL_CLONE_PROP[$i]}"
+ fi
+ (( i = i + 1 ))
+done
+
+log_must zfs clone $opts $SNAPFS1 $TESTPOOL/$TESTCLONE
+
+i=0
+while (( $i < ${#RW_VOL_CLONE_PROP[*]} )); do
+ if [[ ${RW_VOL_CLONE_PROP[$i]} != *"checksum"* ]]; then
+ propertycheck $TESTPOOL/$TESTCLONE ${RW_VOL_CLONE_PROP[i]} || \
+ log_fail "${RW_VOL_CLONE_PROP[i]} is failed to set."
+ fi
+ (( i = i + 1 ))
+done
+
+log_pass "'zfs clone -o property=value volume' can successfully" \
+ "create a ZFS clone volume with multiple correct properties set."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_007_pos.ksh
new file mode 100755
index 000000000000..6fba72b58067
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_007_pos.ksh
@@ -0,0 +1,85 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs clone -o version=' could upgrade version, but downgrade is denied.
+#
+# STRATEGY:
+# 1. Create clone with "-o version=" specified
+# 2. Verify it succeed while upgrade, but fails while the version downgraded.
+#
+
+ZFS_VERSION=$(zfs upgrade | head -1 | awk '{print $NF}' \
+ | sed -e 's/\.//g')
+
+verify_runnable "both"
+
+function cleanup
+{
+ if snapexists $SNAPFS ; then
+ log_must zfs destroy -Rf $SNAPFS
+ fi
+}
+
+log_onexit cleanup
+
+log_assert "'zfs clone -o version=' could upgrade version," \
+ "but downgrade is denied."
+
+log_must zfs snapshot $SNAPFS
+
+typeset -i ver
+
+if (( ZFS_TEST_VERSION == 0 )) ; then
+ (( ZFS_TEST_VERSION = ZFS_VERSION ))
+fi
+
+(( ver = ZFS_TEST_VERSION ))
+while (( ver <= ZFS_VERSION )); do
+ log_must zfs clone -o version=$ver $SNAPFS $TESTPOOL/$TESTCLONE
+ cleanup
+ (( ver = ver + 1 ))
+done
+
+(( ver = 0 ))
+while (( ver < ZFS_TEST_VERSION )); do
+ log_mustnot zfs clone -o version=$ver \
+ $SNAPFS $TESTPOOL/$TESTCLONE
+ log_mustnot datasetexists $TESTPOOL/$TESTCLONE
+ cleanup
+ (( ver = ver + 1 ))
+done
+
+log_pass "'zfs clone -o version=' could upgrade version," \
+ "but downgrade is denied."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_008_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_008_neg.ksh
new file mode 100755
index 000000000000..8e306fd445ea
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_008_neg.ksh
@@ -0,0 +1,80 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs clone -o <filesystem>' fails with bad <filesystem> arguments, including:
+# *Same property set multiple times via '-o property=value'
+# *Volume's property set on filesystem
+#
+# STRATEGY:
+# 1. Create an array of <filesystem> arguments
+# 2. Execute 'zfs clone -o <filesystem>' with each argument
+# 3. Verify an error is returned.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if snapexists $SNAPFS ; then
+ log_must zfs destroy -Rf $SNAPFS
+ fi
+}
+
+log_onexit cleanup
+
+log_assert "Verify 'zfs clone -o <filesystem>' fails with bad <filesystem> argument."
+
+log_must zfs snapshot $SNAPFS
+
+typeset -i i=0
+while (( $i < ${#RW_FS_PROP[*]} )); do
+ log_mustnot zfs clone -o ${RW_FS_PROP[i]} -o ${RW_FS_PROP[i]} \
+ $SNAPFS $TESTPOOL/$TESTCLONE
+ log_mustnot zfs clone -p -o ${RW_FS_PROP[i]} -o ${RW_FS_PROP[i]} \
+ $SNAPFS $TESTPOOL/$TESTCLONE
+ ((i = i + 1))
+done
+
+i=0
+while (( $i < ${#VOL_ONLY_PROP[*]} )); do
+ log_mustnot zfs clone -o ${VOL_ONLY_PROP[i]} \
+ $SNAPFS $TESTPOOL/$TESTCLONE
+ log_mustnot zfs clone -p -o ${VOL_ONLY_PROP[i]} \
+ $SNAPFS $TESTPOOL/$TESTCLONE
+ ((i = i + 1))
+done
+
+log_pass "'zfs clone -o <filesystem>' fails with bad <filesystem> argument."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_009_neg.ksh
new file mode 100755
index 000000000000..030c6af7ae68
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_009_neg.ksh
@@ -0,0 +1,80 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs clone -o <volume>' fails with badly formed arguments,including:
+# *Same property set multiple times via '-o property=value'
+# *Filesystems's property set on volume
+#
+# STRATEGY:
+# 1. Create an array of badly formed arguments
+# 2. For each argument, execute 'zfs clone -o <volume>'
+# 3. Verify an error is returned.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if snapexists $SNAPFS1 ; then
+ log_must zfs destroy -Rf $SNAPFS1
+ fi
+}
+
+log_onexit cleanup
+
+log_assert "Verify 'zfs clone -o <volume>' fails with bad <volume> argument."
+
+log_must zfs snapshot $SNAPFS1
+
+typeset -i i=0
+while (( $i < ${#RW_VOL_PROP[*]} )); do
+ log_mustnot zfs clone -o ${RW_VOL_PROP[i]} -o ${RW_VOL_PROP[i]} \
+ $SNAPFS1 $TESTPOOL/$TESTCLONE
+ log_mustnot zfs clone -p -o ${RW_VOL_PROP[i]} -o ${RW_VOL_PROP[i]} \
+ $SNAPFS1 $TESTPOOL/$TESTCLONE
+ ((i = i + 1))
+done
+
+i=0
+while (( $i < ${#FS_ONLY_PROP[*]} )); do
+ log_mustnot zfs clone -o ${FS_ONLY_PROP[i]} \
+ $SNAPFS1 $TESTPOOL/$TESTCLONE
+ log_mustnot zfs clone -p -o ${FS_ONLY_PROP[i]} \
+ $SNAPFS1 $TESTPOOL/$TESTCLONE
+ ((i = i + 1))
+done
+
+log_pass "Verify 'zfs clone -o <volume>' fails with bad <volume> argument."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_010_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_010_pos.ksh
new file mode 100755
index 000000000000..dcf80095db28
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_010_pos.ksh
@@ -0,0 +1,229 @@
+#!/bin/ksh
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify 'zfs list -t all -o name,origin,clones' prints the correct
+# clone information
+#
+# STRATEGY:
+# 1. Create datasets
+# 2. Create recursive snapshots and their clones
+# 3. Verify zfs clones property displays right information for different
+# cases
+#
+
+verify_runnable "both"
+
+function local_cleanup
+{
+ typeset -i i=1
+ for ds in $datasets; do
+ datasetexists $ds/$TESTCLONE.$i && \
+ log_must zfs destroy -rf $ds/$TESTCLONE.$i
+ datasetexists $ds && log_must zfs destroy -Rf $ds
+ ((i=i+1))
+ done
+}
+
+# Set up filesystem with clones
+function setup_ds
+{
+ typeset -i i=1
+ # create nested datasets
+ log_must zfs create -p $TESTPOOL/$TESTFS1/$TESTFS2/$TESTFS3
+
+ # verify dataset creation
+ for ds in $datasets; do
+ datasetexists $ds || log_fail "Create $ds dataset fail."
+ done
+
+ # create recursive nested snapshot
+ log_must zfs snapshot -r $TESTPOOL/$TESTFS1@snap
+ for ds in $datasets; do
+ datasetexists $ds@snap || \
+ log_fail "Create $ds@snap snapshot fail."
+ done
+ for ds in $datasets; do
+ for fs in $datasets; do
+ log_must zfs clone $ds@snap $fs/$TESTCLONE.$i
+ done
+ ((i=i+1))
+ done
+}
+
+# Verify clone list
+function verify_clones
+{
+ typeset -i no_clones=$1
+ typeset unexpected=$2
+ typeset clone_snap=$3
+ typeset -i i=1
+ for ds in $datasets; do
+ if [[ -n $clone_snap ]]; then
+ clone_snap=/$TESTCLONE.$i
+ fi
+ snapshot=$(echo "$names" | grep $ds$clone_snap@snap)
+ actual_clone=$(zfs list -t all -o clones $snapshot | tail -1)
+ save=$IFS
+ IFS=','
+ typeset -a clones=()
+ for token in $actual_clone; do
+ clones=( "${clones[@]}" "$token" )
+ done
+ IFS=$save
+ [[ ${#clones[*]} -ne $no_clones ]] && \
+ log_fail "$snapshot has unexpected number of clones" \
+ " ${#clones[*]}"
+ expected_clone=""
+ unexpected_clone=""
+ if [[ $unexpected -eq 1 ]]; then
+ for fs in $datasets; do
+ if [[ $fs == $ds ]]; then
+ if [[ -z $clone_snap ]]; then
+ unexpected_clone=$fs/$TESTCLONE.$i
+ (for match in ${clones[@]};do
+ [[ $match != $unexpected_clone ]] && \
+ exit 0; done) || log_fail \
+ "Unexpected clones of the snapshot"
+ else
+ expected_clone=$fs
+ unexpected_clone=$fs/$TESTCLONE.$i
+ (for match in ${clones[@]};do
+ [[ $match == $expected_clone ]] && \
+ [[ $match != $unexpected_clone ]] \
+ && exit 0; done) || log_fail \
+ "Unexpected clones of the snapshot"
+ fi
+ else
+ expected_clone=$fs/$TESTCLONE.$i
+ (for match in ${clones[@]};do
+ [[ $match == $expected_clone ]] && \
+ exit 0; done) || log_fail \
+ "Unexpected clones of the snapshot"
+ fi
+ done
+ else
+ for fs in $datasets; do
+ expected_clone=$fs/$TESTCLONE.$i
+ (for match in ${clones[@]};do
+ [[ $match == $expected_clone ]] && exit 0; \
+ done) || log_fail "Unexpected clones" \
+ " of the snapshot"
+ done
+ fi
+ ((i=i+1))
+ done
+}
+
+
+log_onexit local_cleanup
+datasets="$TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS1/$TESTFS2
+ $TESTPOOL/$TESTFS1/$TESTFS2/$TESTFS3"
+
+typeset -a d_clones
+typeset -a deferred_snaps
+typeset -i i
+log_must setup_ds
+
+log_note "Verify zfs clone property for multiple clones"
+names=$(zfs list -rt all -o name $TESTPOOL)
+log_must verify_clones 3 0
+
+log_note "verify clone property for clone deletion"
+i=1
+for ds in $datasets; do
+ log_must zfs destroy $ds/$TESTCLONE.$i
+ ((i=i+1))
+done
+names=$(zfs list -rt all -o name $TESTPOOL)
+log_must verify_clones 2 1
+
+log_must local_cleanup
+log_must setup_ds
+
+log_note "verify zfs deferred destroy on clones property"
+names=$(zfs list -rt all -o name $TESTPOOL)
+for ds in $datasets; do
+ log_must zfs destroy -d $ds@snap
+ deferred_snaps=( "${deferred_snaps[@]}" "$ds@snap" )
+done
+log_must verify_clones 3 0
+
+log_note "verify zfs deferred destroy by destroying clones on clones property"
+d_clones=()
+i=1
+for ds in $datasets; do
+ for fs in $datasets; do
+ log_must zfs destroy $fs/$TESTCLONE.$i
+ d_clones=( "${d_clones[@]}" "$fs/$TESTCLONE.$i" )
+ done
+ ((i=i+1))
+done
+names=$(zfs list -rtall -o name $TESTPOOL)
+for snap in ${deferred_snaps[@]}; do
+ status=$(echo "$names" | grep $snap)
+ [[ -z $status ]] || \
+ log_fail "$snap exist after deferred destroy"
+done
+for dclone in ${d_clones[@]}; do
+ log_note "D CLONE = $dclone"
+ status=$(echo "$names" | grep $dclone)
+ [[ -z $status ]] || \
+ log_fail "$dclone exist after deferred destroy"
+done
+
+log_must local_cleanup
+log_must setup_ds
+log_note "verify clone property for zfs promote"
+i=1
+for ds in $datasets; do
+ log_must zfs promote $ds/$TESTCLONE.$i
+ ((i=i+1))
+done
+names=$(zfs list -rt all -o name,clones $TESTPOOL)
+log_must verify_clones 3 1 $TESTCLONE
+for ds in $datasets; do
+ log_must zfs promote $ds
+done
+log_must local_cleanup
+
+log_note "verify clone list truncated correctly"
+fs=$TESTPOOL/$TESTFS1
+xs=""; for i in {1..200}; do xs+="x"; done
+if is_linux; then
+ ZFS_MAXPROPLEN=4096
+else
+ ZFS_MAXPROPLEN=1024
+fi
+log_must zfs create $fs
+log_must zfs snapshot $fs@snap
+for (( i = 1; i <= (ZFS_MAXPROPLEN / 200 + 1); i++ )); do
+ log_must zfs clone ${fs}@snap ${fs}/${TESTCLONE}${xs}.${i}
+done
+clone_list=$(zfs list -o clones $fs@snap)
+char_count=$(echo "$clone_list" | tail -1 | wc | awk '{print $3}')
+[[ $char_count -eq $ZFS_MAXPROPLEN ]] || \
+ log_fail "Clone list not truncated correctly. Unexpected character count" \
+ "$char_count"
+
+log_pass "'zfs list -o name,origin,clones prints the correct clone information."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_deeply_nested.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_deeply_nested.ksh
new file mode 100755
index 000000000000..b83807765791
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_deeply_nested.ksh
@@ -0,0 +1,69 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Deeply nested clones can be created and destroyed successfully
+#
+# STRATEGY:
+# 1. Create a deeply nested chain of clones
+# 2. Verify we can promote and destroy datasets in the chain without issues
+# NOTE:
+# Ported from scripts used to reproduce issue #3959 and #7279
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_dataset "$clonesfs" "-rRf"
+}
+log_onexit cleanup
+
+log_assert "Deeply nested clones should be created and destroyed without issues"
+
+snapname='snap'
+snaprename='temporary-snap'
+clonesfs="$TESTPOOL/$TESTFS1"
+
+# NOTE: set mountpoint=none to avoid mount/umount calls and speed up the process
+log_must zfs create -o mountpoint=none $clonesfs
+log_must zfs create $clonesfs/0
+dsname="$clonesfs/0@$snapname"
+log_must zfs snapshot $dsname
+
+# 1. Create a deeply nested chain of clones
+for c in {1..250}; do
+ log_must zfs clone $dsname $clonesfs/$c
+ dsname="$clonesfs/$c@$snapname"
+ log_must zfs snapshot $dsname
+done
+
+# 2. Verify we can promote and destroy datasets in the chain without issues
+for c in {0..249}; do
+ log_must zfs rename $clonesfs/$c@$snapname $clonesfs/$c@$snaprename
+ log_must zfs promote $clonesfs/$((c+1))
+ log_must zfs destroy -r $clonesfs/$c
+ log_must zfs destroy $clonesfs/$((c+1))@$snaprename
+done
+
+log_pass "Deeply nested clones can be created and destroyed successfully"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_encrypted.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_encrypted.ksh
new file mode 100755
index 000000000000..86f335bde2a0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_encrypted.ksh
@@ -0,0 +1,83 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs clone' should create encrypted clones of encrypted datasets
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Create a snapshot of the dataset
+# 3. Attempt to clone the snapshot as an unencrypted dataset
+# 4. Attempt to clone the snapshot with a new key
+# 5. Attempt to clone the snapshot as a child of an unencrypted dataset
+# 6. Attempt to clone the snapshot as a child of an encrypted dataset
+# 7. Verify the encryption root of the datasets
+# 8. Unmount all datasets and unload their keys
+# 9. Attempt to load the encryption root's key
+# 10. Verify each dataset's key is loaded
+# 11. Attempt to mount each dataset
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS2 && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS2
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+}
+log_onexit cleanup
+
+log_assert "'zfs clone' should create encrypted clones of encrypted datasets"
+
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS1"
+log_must zfs snapshot $TESTPOOL/$TESTFS1@now
+
+log_mustnot zfs clone -o encryption=off $TESTPOOL/$TESTFS1@now \
+ $TESTPOOL/$TESTFS2
+log_mustnot eval "echo $PASSPHRASE1 | zfs clone -o keyformat=passphrase" \
+ "$TESTPOOL/$TESTFS1@now $TESTPOOL/$TESTFS2"
+log_must zfs clone $TESTPOOL/$TESTFS1@now $TESTPOOL/$TESTFS2
+log_must zfs clone $TESTPOOL/$TESTFS1@now $TESTPOOL/$TESTFS1/child
+
+log_must verify_encryption_root $TESTPOOL/$TESTFS2 $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/child $TESTPOOL/$TESTFS1
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unmount $TESTPOOL/$TESTFS2
+log_must zfs unload-key -a
+
+log_must eval "echo $PASSPHRASE | zfs load-key $TESTPOOL/$TESTFS1"
+
+log_must key_available $TESTPOOL/$TESTFS1
+log_must key_available $TESTPOOL/$TESTFS1/child
+log_must key_available $TESTPOOL/$TESTFS2
+
+log_must zfs mount $TESTPOOL/$TESTFS1
+log_must zfs mount $TESTPOOL/$TESTFS1/child
+log_must zfs mount $TESTPOOL/$TESTFS2
+
+log_pass "'zfs clone' creates encrypted clones of encrypted datasets"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_rm_nested.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_rm_nested.ksh
new file mode 100755
index 000000000000..447fbb36b412
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_rm_nested.ksh
@@ -0,0 +1,77 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# When a snapshot is destroyed, we used to recurse all clones
+# that are downstream of the destroyed snapshot (e.g. to remove
+# its key and merge its deadlist entries to the previous one).
+# This recursion would break the stack on deeply nested clone
+# hierarchies. To avoid this problem today, we keep heap-allocated
+# records of all the clones as we traverse their hierarchy.
+#
+# This test ensures and showcases that our new method works with
+# deeply nested clone hierarchies.
+#
+# STRATEGY:
+# 1. Create an fs and take a snapshot of it (snapshot foo)
+# 2. Take a second snapshot of the same fs (snapshot bar) on
+# top of snapshot foo
+# 3. Create a clone of snapshot bar and then take a snapshot
+# of it.
+# 4. Create a clone of the newly-created snapshot and then
+# take a snapshot of it.
+# 5. Repeat step [4] many times to create a deeply nested hierarchy.
+# 6. Destroy snapshot foo.
+#
+
+verify_runnable "both"
+
+typeset FS0=$TESTPOOL/0
+typeset FOO=foo
+typeset BAR=BAR
+
+typeset FS0SNAPFOO=$FS0@$FOO
+typeset FS0SNAPBAR=$FS0@$BAR
+
+typeset -i numds=300
+
+log_must zfs create $FS0
+
+function test_cleanup
+{
+ log_must zfs destroy -Rf $FS0
+
+ return 0
+}
+
+log_must zfs snapshot $FS0SNAPFOO
+log_must zfs snapshot $FS0SNAPBAR
+
+log_onexit test_cleanup
+
+for (( i=1; i<numds; i++ )); do
+ log_must zfs clone $TESTPOOL/$((i-1))@$BAR $TESTPOOL/$i
+ log_must zfs snapshot $TESTPOOL/$i@$BAR
+done
+
+log_must zfs destroy $FS0SNAPFOO
+
+log_pass "Snapshot deletion doesn't break the stack in deeply nested " \
+ "clone hierarchies."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/Makefile.am
new file mode 100644
index 000000000000..4ac103a8ec6a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/Makefile.am
@@ -0,0 +1,14 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_copies
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_copies_001_pos.ksh \
+ zfs_copies_002_pos.ksh \
+ zfs_copies_003_pos.ksh \
+ zfs_copies_004_neg.ksh \
+ zfs_copies_005_neg.ksh \
+ zfs_copies_006_pos.ksh
+
+dist_pkgdata_DATA = \
+ zfs_copies.cfg \
+ zfs_copies.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/cleanup.ksh
new file mode 100755
index 000000000000..f5e862593e1e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/cleanup.ksh
@@ -0,0 +1,44 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_copies/zfs_copies.cfg
+
+#
+# umount the ufs|ext fs if there is timedout in the ufs|ext test
+#
+
+if ismounted $FS_MNTPOINT $NEWFS_DEFAULT_FS ; then
+ log_must umount -f $FS_MNTPOINT
+ rm -fr $FS_MNTPOINT
+fi
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/setup.ksh
new file mode 100755
index 000000000000..d4cf2095012b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/setup.ksh
@@ -0,0 +1,31 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_volume_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.cfg
new file mode 100644
index 000000000000..eb85e65c790e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.cfg
@@ -0,0 +1,37 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+export ZPOOL_VERSION_1_FILES="zfs-pool-v1.dat.bz2"
+export ZPOOL_VERSION_1_NAME="v1-pool"
+
+export FILESIZE=10m
+export FILE=file.copies
+export SLEEPTIME=30
+export FS_MNTPOINT=/testdir_nfs_mntpoint
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib
new file mode 100644
index 000000000000..e886de432af4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib
@@ -0,0 +1,158 @@
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_copies/zfs_copies.cfg
+
+#
+# Compare the value of copies property with specified value
+# $1, the dataset name
+# $2, the expected copies value
+#
+function cmp_prop
+{
+ typeset ds=$1
+ typeset val_expect=$2
+ typeset val_actual
+
+ val_actual=$(get_prop copies $ds)
+ if [[ $val_actual != $val_expect ]]; then
+ log_fail "Expected value ($val_expect) != actual value " \
+ "($val_actual)"
+ fi
+}
+
+#
+# Check the used space is charged correctly
+# $1, the number of used space
+# $2, the expected common factor between the used space and the file space
+#
+function check_used
+{
+ typeset charged_spc=$1
+ typeset -i used
+ typeset -i expected_cfactor=$2
+ typeset -i cfactor
+ typeset -i fsize=${FILESIZE%[m|M]}
+
+ ((used = $charged_spc / 1024 / 1024))
+ ((cfactor = used / fsize))
+ if ((cfactor != expected_cfactor)); then
+ log_fail "The space is not charged correctly while setting" \
+ "copies as $expected_cfactor."
+ fi
+}
+
+#
+# test ncopies on volume
+# $1 test type zfs|ufs|ext2
+# $2 copies
+# $3 mntp for ufs|ext2 test
+function do_vol_test
+{
+ typeset type=$1
+ typeset copies=$2
+ typeset mntp=$3
+
+ vol=$TESTPOOL/$TESTVOL1
+ vol_b_path=$ZVOL_DEVDIR/$TESTPOOL/$TESTVOL1
+ vol_r_path=$ZVOL_RDEVDIR/$TESTPOOL/$TESTVOL1
+
+ log_must zfs create -V $VOLSIZE -o copies=$copies $vol
+ log_must zfs set refreservation=none $vol
+ block_device_wait
+
+ case "$type" in
+ "ext2")
+ if is_freebsd; then
+ log_unsupported "ext2 test not implemented for freebsd"
+ fi
+ log_must eval "new_fs $vol_r_path >/dev/null 2>&1"
+ log_must mount -o rw $vol_b_path $mntp
+ ;;
+ "ufs")
+ if is_linux; then
+ log_unsupported "ufs test not implemented for linux"
+ fi
+ log_must eval "new_fs $vol_r_path >/dev/null 2>&1"
+ log_must mount $vol_b_path $mntp
+ ;;
+ "zfs")
+ if is_freebsd; then
+ # Pool creation on zvols is forbidden by default.
+ # Save and restore the current setting.
+ typeset _saved=$(get_tunable VOL_RECURSIVE)
+ log_must set_tunable64 VOL_RECURSIVE 1 # Allow
+ zpool create $TESTPOOL1 $vol_b_path
+ typeset _zpool_create_result=$?
+ log_must set_tunable64 VOL_RECURSIVE $_saved # Restore
+ log_must test $_zpool_create_result = 0
+ else
+ log_must zpool create $TESTPOOL1 $vol_b_path
+ fi
+ log_must zfs create $TESTPOOL1/$TESTFS1
+ ;;
+ *)
+ log_unsupported "$type test not implemented"
+ ;;
+ esac
+
+ ((nfilesize = copies * ${FILESIZE%m}))
+ pre_used=$(get_prop used $vol)
+ ((target_size = pre_used + nfilesize))
+
+ if [[ $type == "zfs" ]]; then
+ log_must mkfile $FILESIZE /$TESTPOOL1/$TESTFS1/$FILE
+ else
+ log_must mkfile $FILESIZE $mntp/$FILE
+ fi
+
+ post_used=$(get_prop used $vol)
+ ((retries = 0))
+ while ((post_used < target_size && retries++ < 42)); do
+ sleep 1
+ post_used=$(get_prop used $vol)
+ done
+
+ ((used = post_used - pre_used))
+ if ((used < nfilesize)); then
+ log_fail "The space is not charged correctly while setting" \
+ "copies as $copies ($used < $nfilesize)" \
+ "pre=${pre_used} post=${post_used}"
+ fi
+
+ if [[ $type == "zfs" ]]; then
+ log_must zpool destroy $TESTPOOL1
+ else
+ log_must umount $mntp
+ fi
+
+ log_must zfs destroy $vol
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_001_pos.ksh
new file mode 100755
index 000000000000..2ed881a36706
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_001_pos.ksh
@@ -0,0 +1,116 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib
+
+#
+# DESCRIPTION:
+# Verify "copies" property can be correctly set as 1,2 and 3 and different
+# filesystem can have different value of "copies" property within the same pool.
+#
+# STRATEGY:
+# 1. Create different filesystems with copies set as 1,2,3;
+# 2. Verify that the "copies" property has been set correctly
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset ds
+
+ for ds in $fs1 $fs2 $vol1 $vol2; do
+ if datasetexists $ds; then
+ log_must zfs destroy $ds
+ fi
+ done
+}
+
+log_assert "Verify 'copies' property with correct arguments works or not."
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+fs1=$TESTPOOL/$TESTFS1
+fs2=$TESTPOOL/$TESTFS2
+vol=$TESTPOOL/$TESTVOL
+vol1=$TESTPOOL/$TESTVOL1
+vol2=$TESTPOOL/$TESTVOL2
+
+#
+# Check the default value for copies property
+#
+for ds in $fs $vol; do
+ cmp_prop $ds 1
+done
+
+for val in 1 2 3; do
+ log_must zfs create -o copies=$val $fs1
+ if is_global_zone; then
+ log_must zfs create -V $VOLSIZE -o copies=$val $vol1
+ block_device_wait
+ else
+ log_must zfs create -o copies=$val $vol1
+ fi
+ for ds in $fs1 $vol1; do
+ cmp_prop $ds $val
+ done
+
+ for val2 in 3 2 1; do
+ log_must zfs create -o copies=$val2 $fs2
+ if is_global_zone; then
+ log_must zfs create -V $VOLSIZE -o copies=$val2 $vol2
+ block_device_wait
+ else
+ log_must zfs create -o copies=$val2 $vol2
+ fi
+ for ds in $fs2 $vol2; do
+ cmp_prop $ds $val2
+ log_must zfs destroy $ds
+ block_device_wait
+ done
+ done
+
+ for ds in $fs1 $vol1; do
+ log_must zfs destroy $ds
+ block_device_wait
+ done
+
+done
+
+for val in 3 2 1; do
+ for ds in $fs $vol; do
+ log_must zfs set copies=$val $ds
+ cmp_prop $ds $val
+ done
+done
+
+log_pass "'copies' property with correct arguments works as expected. "
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_002_pos.ksh
new file mode 100755
index 000000000000..c88e300412f1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_002_pos.ksh
@@ -0,0 +1,119 @@
+#!/bin/ksh
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib
+
+#
+# DESCRIPTION:
+# Verify that the space used by multiple copies is charged correctly
+#
+# STRATEGY:
+# 1. Create filesystems with copies set as 2,3 respectively;
+# 2. Copy specified size data into each filesystem;
+# 3. Verify that the space is charged as expected with zfs list, ls -s, df(1m),
+# du(1) commands;
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset val
+
+ for val in 1 2 3; do
+ if datasetexists $TESTPOOL/fs_$val; then
+ log_must zfs destroy $TESTPOOL/fs_$val
+ fi
+ done
+}
+
+log_assert "Verify that the space used by multiple copies is charged correctly."
+log_onexit cleanup
+
+for val in 1 2 3; do
+ log_must zfs create -o copies=$val $TESTPOOL/fs_$val
+
+ log_must mkfile $FILESIZE /$TESTPOOL/fs_$val/$FILE
+done
+
+#
+# Sync up the filesystem
+#
+sync
+
+#
+# Verify 'zfs list' can correctly list the space charged
+#
+log_note "Verify 'zfs list' can correctly list the space charged."
+fsize=${FILESIZE%[m|M]}
+for val in 1 2 3; do
+ used=$(get_prop used $TESTPOOL/fs_$val)
+ check_used $used $val
+done
+
+log_note "Verify 'ls -s' can correctly list the space charged."
+if is_linux || is_freebsd; then
+ blksize=1024
+else
+ blksize=512
+fi
+for val in 1 2 3; do
+ blks=`ls -ls /$TESTPOOL/fs_$val/$FILE | awk '{print $1}'`
+ (( used = blks * $blksize )) # bytes
+ check_used $used $val
+done
+
+log_note "Verify df(1M) can correctly display the space charged."
+for val in 1 2 3; do
+ if is_freebsd; then
+ used=`df -m /$TESTPOOL/fs_$val | grep $TESTPOOL/fs_$val \
+ | awk -v fs=fs_$val '$4 ~ fs {print $3}'`
+ else
+ used=`df -F zfs -k /$TESTPOOL/fs_$val/$FILE | grep $TESTPOOL/fs_$val \
+ | awk '{print $3}'`
+ (( used = used * 1024 )) # kb -> bytes
+ fi
+ check_used $used $val
+done
+
+log_note "Verify du(1) can correctly display the space charged."
+for val in 1 2 3; do
+ if is_freebsd; then
+ used=`du -h /$TESTPOOL/fs_$val/$FILE | awk '{print $1}'`
+ else
+ used=`du -k /$TESTPOOL/fs_$val/$FILE | awk '{print $1}'`
+ (( used = used * 1024 )) # kb -> bytes
+ fi
+ check_used $used $val
+done
+
+log_pass "The space used by multiple copies is charged correctly as expected. "
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_003_pos.ksh
new file mode 100755
index 000000000000..98420cb7f2ab
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_003_pos.ksh
@@ -0,0 +1,68 @@
+#!/bin/ksh
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib
+
+#
+# DESCRIPTION:
+# Verify that the volume space used by multiple copies is charged correctly
+#
+# STRATEGY:
+# 1. Create volume;
+# 2. Create ZFS filesystem based on the volume;
+# 3. Set the copies property of volume to 1,2 or 3;
+# 4. Copy specified size data into each filesystem;
+# 5. Verify that the volume space is charged as expected.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if poolexists $TESTPOOL1; then
+ destroy_pool $TESTPOOL1
+ fi
+
+ if datasetexists $vol; then
+ log_must zfs destroy $vol
+ fi
+}
+
+log_assert "Verify that ZFS volume space used by multiple copies is charged correctly."
+log_onexit cleanup
+vol=$TESTPOOL/$TESTVOL1
+
+
+for val in 1 2 3; do
+ do_vol_test zfs $val
+done
+
+log_pass "The volume space used by multiple copies is charged correctly as expected. "
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_004_neg.ksh
new file mode 100755
index 000000000000..dc007b11160d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_004_neg.ksh
@@ -0,0 +1,58 @@
+#!/bin/ksh
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib
+
+#
+# DESCRIPTION:
+# Verify that copies cannot be set to other value except for 1, 2 or 3
+#
+# STRATEGY:
+# 1. Create filesystems with copies set as any value other than 1, 2 or 3
+# 2. Verify that the create operations fail
+#
+
+verify_runnable "both"
+
+log_assert "Verify that copies property cannot be set to any value other than 1,2 or 3"
+
+set -A badval 0 01 02 03 0 -1 -2 -3 10 20 30 4 5 6 blah
+
+for val in ${badval[@]}; do
+ log_mustnot zfs create -o copies=$val $TESTPOOL/$TESTFS1
+ log_mustnot zfs create -V $VOLSIZE -o copies=$val $TESTPOOL/$TESTVOL1
+ log_mustnot zfs set copies=$val $TESTPOOL/$TESTFS
+ log_mustnot zfs set copies=$val $TESTPOOL/$TESTVOL
+ block_device_wait
+done
+
+log_pass "The copies property cannot be set to any value other than 1,2 or 3 as expected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_005_neg.ksh
new file mode 100755
index 000000000000..6a8b81ac5b87
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_005_neg.ksh
@@ -0,0 +1,80 @@
+#!/bin/ksh
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib
+
+#
+# DESCRIPTION:
+# Verify that copies cannot be set with pool version 1
+#
+# STRATEGY:
+# 1. Create filesystems with copies set in a pool with version 1
+# 2. Verify that the create operations fail
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if poolexists $ZPOOL_VERSION_1_NAME; then
+ destroy_pool $ZPOOL_VERSION_1_NAME
+ fi
+
+ if [[ -f $TEST_BASE_DIR/$ZPOOL_VERSION_1_FILES ]]; then
+ rm -f $TEST_BASE_DIR/$ZPOOL_VERSION_1_FILES
+ fi
+
+ if [[ -f $TEST_BASE_DIR/${ZPOOL_VERSION_1_FILES%.*} ]]; then
+ rm -f $TEST_BASE_DIR/${ZPOOL_VERSION_1_FILES%.*}
+ fi
+}
+
+log_assert "Verify that copies cannot be set with pool version 1"
+log_onexit cleanup
+
+log_must cp $STF_SUITE/tests/functional/cli_root/zpool_upgrade/blockfiles/$ZPOOL_VERSION_1_FILES $TEST_BASE_DIR
+log_must bunzip2 $TEST_BASE_DIR/$ZPOOL_VERSION_1_FILES
+log_must zpool import -d $TEST_BASE_DIR $ZPOOL_VERSION_1_NAME
+log_must zfs create $ZPOOL_VERSION_1_NAME/$TESTFS
+log_must zfs create -V 1m $ZPOOL_VERSION_1_NAME/$TESTVOL
+block_device_wait
+
+for val in 3 2 1; do
+ for ds in $ZPOOL_VERSION_1_NAME/$TESTFS $ZPOOL_VERSION_1_NAME/$TESTVOL; do
+ log_mustnot zfs set copies=$val $ds
+ done
+ for ds in $ZPOOL_VERSION_1_NAME/$TESTFS1 $ZPOOL_VERSION_1_NAME/$TESTVOL1; do
+ log_mustnot zfs create -o copies=$val $ds
+ done
+done
+
+log_pass "Verification pass: copies cannot be set with pool version 1. "
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_006_pos.ksh
new file mode 100755
index 000000000000..4a3ef76de763
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_copies/zfs_copies_006_pos.ksh
@@ -0,0 +1,77 @@
+#!/bin/ksh
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_copies/zfs_copies.kshlib
+
+#
+# DESCRIPTION:
+# Verify that the volume space used by multiple copies is charged correctly
+#
+# STRATEGY:
+# 1. Create volume
+# 2. Create UFS filesystem based on the volume
+# 3. Set the copies property of volume to 1,2 or 3
+# 4. Copy specified size data into each filesystem
+# 5. Verify that the volume space is charged as expected
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if ismounted $mntp $NEWFS_DEFAULT_FS ; then
+ log_must umount $mntp
+ fi
+
+ if datasetexists $vol; then
+ log_must zfs destroy $vol
+ fi
+
+ if [[ -d $mntp ]]; then
+ rm -rf $mntp
+ fi
+}
+
+
+log_assert "Verify that ZFS volume space used by multiple copies is charged correctly."
+log_onexit cleanup
+mntp=$FS_MNTPOINT
+vol=$TESTPOOL/$TESTVOL1
+
+if [[ ! -d $mntp ]]; then
+ mkdir -p $mntp
+fi
+
+for copies in 1 2 3; do
+ do_vol_test $NEWFS_DEFAULT_FS $copies $mntp
+done
+
+log_pass "The volume space used by multiple copies is charged correctly as expected. "
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_create/Makefile.am
new file mode 100644
index 000000000000..cb65507ae711
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/Makefile.am
@@ -0,0 +1,27 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_create
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_create_001_pos.ksh \
+ zfs_create_002_pos.ksh \
+ zfs_create_003_pos.ksh \
+ zfs_create_004_pos.ksh \
+ zfs_create_005_pos.ksh \
+ zfs_create_006_pos.ksh \
+ zfs_create_007_pos.ksh \
+ zfs_create_008_neg.ksh \
+ zfs_create_009_neg.ksh \
+ zfs_create_010_neg.ksh \
+ zfs_create_011_pos.ksh \
+ zfs_create_012_pos.ksh \
+ zfs_create_013_pos.ksh \
+ zfs_create_014_pos.ksh \
+ zfs_create_encrypted.ksh \
+ zfs_create_crypt_combos.ksh \
+ zfs_create_dryrun.ksh \
+ zfs_create_verbose.ksh
+
+dist_pkgdata_DATA = \
+ properties.kshlib \
+ zfs_create_common.kshlib \
+ zfs_create.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/properties.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_create/properties.kshlib
new file mode 100644
index 000000000000..4130ba446334
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/properties.kshlib
@@ -0,0 +1,73 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2015 by Delphix. All rights reserved.
+#
+
+set -A RW_FS_PROP "quota=536870912" \
+ "reservation=536870912" \
+ "recordsize=262144" \
+ "mountpoint=/tmp/mnt$$" \
+ "checksum=fletcher2" \
+ "compression=lzjb" \
+ "atime=off" \
+ "devices=off" \
+ "exec=off" \
+ "setuid=off" \
+ "readonly=on" \
+ "snapdir=visible" \
+ "canmount=off" \
+ "local:department=123"
+
+set -A RW_VOL_PROP "volblocksize=16384" \
+ "checksum=fletcher2" \
+ "compression=lzjb" \
+ "readonly=on" \
+ "local:department=123"
+
+set -A RW_VOL_CLONE_PROP "checksum=fletcher2" \
+ "compression=lzjb" \
+ "readonly=on" \
+ "local:department=123"
+
+set -A FS_ONLY_PROP "quota=536870912" \
+ "recordsize=65536" \
+ "mountpoint=/tmp/mnt$$" \
+ "atime=off" \
+ "devices=off" \
+ "exec=off" \
+ "setuid=off" \
+ "snapdir=visible" \
+ "canmount=off" \
+ "version=1"
+if is_freebsd; then
+ FS_ONLY_PROP+=("jailed=on")
+else
+ FS_ONLY_PROP+=("zoned=on")
+fi
+
+set -A VOL_ONLY_PROP "volblocksize=16384" "volsize=536870912"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create.cfg
new file mode 100644
index 000000000000..9bf25327ef8d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create.cfg
@@ -0,0 +1,65 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+export BYND_MAX_NAME="byondmaxnamelength\
+012345678901234567890123456789\
+012345678901234567890123456789\
+012345678901234567890123456789\
+012345678901234567890123456789\
+012345678901234567890123456789\
+012345678901234567890123456789\
+012345678901234567890123456789\
+012345678901234567890123456789"
+
+export BYND_NEST_LIMIT="a/a/a/\
+a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/\
+a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/\
+a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/\
+a/a"
+
+# There're 3 different prompt messages while create
+# a volume that great than 1TB on 32-bit
+# - volume size exceeds limit for this system. (happy gate)
+# - max volume size is 1TB on 32-bit systems (s10u2)
+# - value is too large (old)
+
+export VOL_LIMIT_KEYWORD1="1TB on 32-bit"
+export VOL_LIMIT_KEYWORD2="value is too large"
+export VOL_LIMIT_KEYWORD3="volume size exceeds limit"
+
+set -A size "8k" "8K" "35K" "1m" "1M" "1mb" "1mB" "1Mb" "1MB" "1g" "1G" \
+ "1p" "1P" "1z" "1Z" "1gb" "1gB" "1Gb" "1GB" "1pb" "1pB" "1Pb" \
+ "1PB" "1zb" "1zB" "1Zb" "1ZB"
+
+# If a datasize has a volume size that is not a multiple of the blocksize,
+# explicitly check that its size has been rounded up to the nearest multiple
+# The volume with the exact size must exist in the "size" array above
+set -A explicit_size_check "35K"
+set -A expected_rounded_size "40960"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_001_pos.ksh
new file mode 100755
index 000000000000..0e580a8474ca
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_001_pos.ksh
@@ -0,0 +1,71 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs create <filesystem>' can create a ZFS filesystem in the namespace.
+#
+# STRATEGY:
+# 1. Create a ZFS filesystem in the storage pool
+# 2. Verify the filesystem created successfully
+#
+
+verify_runnable "both"
+
+
+function cleanup
+{
+ typeset -i i=0
+ while (( $i < ${#datasets[*]} )); do
+ datasetexists ${datasets[$i]} && \
+ log_must zfs destroy -f ${datasets[$i]}
+ ((i = i + 1))
+ done
+}
+
+log_onexit cleanup
+
+set -A datasets "$TESTPOOL/$TESTFS1" "$TESTPOOL/$LONGFSNAME" "$TESTPOOL/..." \
+ "$TESTPOOL/_1234_"
+
+log_assert "'zfs create <filesystem>' can create a ZFS filesystem in the namespace."
+
+typeset -i i=0
+while (( $i < ${#datasets[*]} )); do
+ log_must zfs create ${datasets[$i]}
+ datasetexists ${datasets[$i]} || \
+ log_fail "zfs create ${datasets[$i]} fail."
+ ((i = i + 1))
+done
+
+log_pass "'zfs create <filesystem>' works as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_002_pos.ksh
new file mode 100755
index 000000000000..0218e2e16b68
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_002_pos.ksh
@@ -0,0 +1,93 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs create -s -V <size> <volume>' can create various-size sparse volume.
+#
+# STRATEGY:
+# 1. Create a volume in the storage pool.
+# 2. Verify the volume is created correctly.
+# 3. Verify that the volume created has its volsize rounded to the nearest
+# multiple of the blocksize (in this case, the default blocksize)
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset -i j=0
+ while [[ $j -lt ${#size[*]} ]]; do
+ destroy_dataset $TESTPOOL/${TESTVOL}${size[j]}
+ ((j = j + 1))
+ done
+}
+
+log_onexit cleanup
+
+
+log_assert "'zfs create -s -V <size> <volume>' succeeds"
+
+typeset -i j=0
+while (( $j < ${#size[*]} )); do
+ typeset cmdline="zfs create -s -V ${size[j]} \
+ $TESTPOOL/${TESTVOL}${size[j]}"
+
+ str=$(eval $cmdline 2>&1)
+ if (( $? == 0 )); then
+ log_note "SUCCESS: $cmdline"
+ log_must datasetexists $TESTPOOL/${TESTVOL}${size[j]}
+ elif [[ $str == *${VOL_LIMIT_KEYWORD1}* || \
+ $str == *${VOL_LIMIT_KEYWORD2}* || \
+ $str == *${VOL_LIMIT_KEYWORD3}* ]]
+ then
+ log_note "UNSUPPORTED: $cmdline"
+ else
+ log_fail "$cmdline"
+ fi
+
+ ((j = j + 1))
+done
+
+typeset -i j=0
+while (( $j < ${#explicit_size_check[*]} )); do
+ propertycheck ${TESTPOOL}/${TESTVOL}${explicit_size_check[j]} \
+ volsize=${expected_rounded_size[j]} || \
+ log_fail "volsize ${size[j]} was not rounded up"
+
+ ((j = j + 1))
+done
+
+log_pass "'zfs create -s -V <size> <volume>' works as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_003_pos.ksh
new file mode 100755
index 000000000000..2906e32dab8c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_003_pos.ksh
@@ -0,0 +1,69 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create.cfg
+
+#
+# DESCRIPTION:
+# 'zfs create [-b <blocksize>] -V <size> <volume>' can create a volume
+# with specified blocksize, which is power of 2 between 512 - 128k.
+#
+# STRATEGY:
+# 1. Create a volume with blocksize in the storage pool
+# 2. Verify the volume created successfully
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ datasetexists $vol && \
+ log_must zfs destroy -f $vol
+}
+
+log_assert "Verify creating volume with specified blocksize works."
+log_onexit cleanup
+
+set -A options "" "-b 1k" "-b 1K" "-b 1024" "-b 1024b"
+vol=$TESTPOOL/$TESTVOL
+
+typeset -i i=0
+while (( i < ${#options[*]} )); do
+ log_must zfs create ${options[i]} -V $VOLSIZE $vol
+ datasetexists $vol || \
+ log_fail "zfs create ${options[i]} -V $VOLSIZE $vol fail."
+
+ log_must_busy zfs destroy -f $vol
+ ((i = i + 1))
+done
+
+log_pass "'zfs create [-b <blocksize>] -V <size> <volume>' works as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_004_pos.ksh
new file mode 100755
index 000000000000..200b4a091567
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_004_pos.ksh
@@ -0,0 +1,73 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs create -o property=value filesystem' can successfully create a ZFS
+# filesystem with correct property set.
+#
+# STRATEGY:
+# 1. Create a ZFS filesystem in the storage pool with -o option
+# 2. Verify the filesystem created successfully
+# 3. Verify the property is correctly set
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS1
+}
+
+log_onexit cleanup
+
+
+log_assert "'zfs create -o property=value filesystem' can successfully create \
+ a ZFS filesystem with correct property set."
+
+typeset -i i=0
+while (( $i < ${#RW_FS_PROP[*]} )); do
+ log_must zfs create -o ${RW_FS_PROP[$i]} $TESTPOOL/$TESTFS1
+ datasetexists $TESTPOOL/$TESTFS1 || \
+ log_fail "zfs create $TESTPOOL/$TESTFS1 fail."
+ propertycheck $TESTPOOL/$TESTFS1 ${RW_FS_PROP[i]} || \
+ log_fail "${RW_FS_PROP[i]} is failed to set."
+ log_must zfs destroy -f $TESTPOOL/$TESTFS1
+ (( i = i + 1 ))
+done
+
+log_pass "'zfs create -o property=value filesystem' can successfully create \
+ a ZFS filesystem with correct property set."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_005_pos.ksh
new file mode 100755
index 000000000000..e953c65ded95
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_005_pos.ksh
@@ -0,0 +1,85 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs create -o property=value filesystem' can successfully create a ZFS
+# filesystem with multiple properties set.
+#
+# STRATEGY:
+# 1. Create a ZFS filesystem in the storage pool with multiple -o options
+# 2. Verify the filesystem created successfully
+# 3. Verify the properties are correctly set
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS1
+}
+
+log_onexit cleanup
+
+
+log_assert "'zfs create -o property=value filesystem' can successfully create \
+ a ZFS filesystem with multiple properties set."
+
+typeset -i i=0
+typeset opts=""
+
+while (( $i < ${#RW_FS_PROP[*]} )); do
+ if [[ ${RW_FS_PROP[$i]} != *"checksum"* ]]; then
+ opts="$opts -o ${RW_FS_PROP[$i]}"
+ fi
+ (( i = i + 1 ))
+done
+
+log_must zfs create $opts $TESTPOOL/$TESTFS1
+datasetexists $TESTPOOL/$TESTFS1 || \
+ log_fail "zfs create $TESTPOOL/$TESTFS1 fail."
+
+i=0
+while (( $i < ${#RW_FS_PROP[*]} )); do
+ if [[ ${RW_FS_PROP[$i]} != *"checksum"* ]]; then
+ propertycheck $TESTPOOL/$TESTFS1 ${RW_FS_PROP[i]} || \
+ log_fail "${RW_FS_PROP[i]} is failed to set."
+ fi
+ (( i = i + 1 ))
+done
+
+log_pass "'zfs create -o property=value filesystem' can successfully create \
+ a ZFS filesystem with multiple properties set."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_006_pos.ksh
new file mode 100755
index 000000000000..2a664a424619
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_006_pos.ksh
@@ -0,0 +1,84 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs create -o property=value -V size volume' can successfully create a ZFS
+# volume with correct property set.
+#
+# STRATEGY:
+# 1. Create a ZFS volume in the storage pool with -o option
+# 2. Verify the volume created successfully
+# 3. Verify the property is correctly set
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTVOL1 && \
+ log_must zfs destroy -f $TESTPOOL/$TESTVOL1
+}
+
+log_onexit cleanup
+
+
+log_assert "'zfs create -o property=value -V size volume' can successfully \
+ create a ZFS volume with correct property set."
+
+typeset -i i=0
+while (( $i < ${#RW_VOL_PROP[*]} )); do
+ log_must zfs create -o ${RW_VOL_PROP[$i]} -V $VOLSIZE \
+ $TESTPOOL/$TESTVOL1
+ datasetexists $TESTPOOL/$TESTVOL1 || \
+ log_fail "zfs create -V size $TESTPOOL/$TESTVOL1 fail."
+ propertycheck $TESTPOOL/$TESTVOL1 ${RW_VOL_PROP[i]} || \
+ log_fail "${RW_VOL_PROP[i]} is failed to set."
+ log_must_busy zfs destroy -f $TESTPOOL/$TESTVOL1
+
+ log_must zfs create -s -o ${RW_VOL_PROP[$i]} -V $VOLSIZE \
+ $TESTPOOL/$TESTVOL1
+ datasetexists $TESTPOOL/$TESTVOL1 || \
+ log_fail "zfs create -s -V $TESTPOOL/$TESTVOL1 fail."
+ propertycheck $TESTPOOL/$TESTVOL1 ${RW_VOL_PROP[i]} || \
+ log_fail "${RW_VOL_PROP[i]} is failed to set."
+ log_must_busy zfs destroy -f $TESTPOOL/$TESTVOL1
+
+ (( i = i + 1 ))
+done
+
+log_pass "'zfs create -o property=value -V size volume' can successfully \
+ create a ZFS volume with correct property set."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_007_pos.ksh
new file mode 100755
index 000000000000..c49c77703409
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_007_pos.ksh
@@ -0,0 +1,91 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs create -o property=value -V size volume' can successfully create a ZFS
+# volume with multiple properties set.
+#
+# STRATEGY:
+# 1. Create a ZFS volume in the storage pool with -o option
+# 2. Verify the volume created successfully
+# 3. Verify the properties are correctly set
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_dataset $TESTPOOL/$TESTVOL
+ destroy_dataset $TESTPOOL/$TESTVOL1
+}
+
+log_onexit cleanup
+
+
+log_assert "'zfs create -o property=value -V size volume' can successfully \
+ create a ZFS volume with correct property set."
+
+typeset -i i=0
+typeset opts=""
+
+while (( $i < ${#RW_VOL_PROP[*]} )); do
+ if [[ ${RW_VOL_PROP[$i]} != *"checksum"* ]]; then
+ opts="$opts -o ${RW_VOL_PROP[$i]}"
+ fi
+ (( i = i + 1 ))
+done
+
+log_must zfs create $opts -V $VOLSIZE $TESTPOOL/$TESTVOL
+datasetexists $TESTPOOL/$TESTVOL || \
+ log_fail "zfs create $TESTPOOL/$TESTVOL fail."
+log_must zfs create -s $opts -V $VOLSIZE $TESTPOOL/$TESTVOL1
+datasetexists $TESTPOOL/$TESTVOL1 || \
+ log_fail "zfs create $TESTPOOL/$TESTVOL1 fail."
+
+i=0
+while (( $i < ${#RW_VOL_PROP[*]} )); do
+ if [[ ${RW_VOL_PROP[$i]} != *"checksum"* ]]; then
+ propertycheck $TESTPOOL/$TESTVOL ${RW_VOL_PROP[i]} || \
+ log_fail "${RW_VOL_PROP[i]} is failed to set."
+ propertycheck $TESTPOOL/$TESTVOL1 ${RW_VOL_PROP[i]} || \
+ log_fail "${RW_VOL_PROP[i]} is failed to set."
+ fi
+ (( i = i + 1 ))
+done
+
+log_pass "'zfs create -o property=value -V size volume' can successfully \
+ create a ZFS volume with correct property set."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_008_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_008_neg.ksh
new file mode 100755
index 000000000000..43c3ab0de338
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_008_neg.ksh
@@ -0,0 +1,113 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create.cfg
+
+#
+# DESCRIPTION:
+# 'zfs create' should return an error with badly formed parameters.
+#
+# STRATEGY:
+# 1. Create an array of parameters
+# 2. For each parameter in the array, execute 'zfs create'
+# 3. Verify an error is returned.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $TESTPOOL/$TESTFS1 ; then
+ log_must zfs destroy -f $TESTPOOL/$TESTFS1
+ fi
+}
+
+log_onexit cleanup
+
+set -A args "ab" "-?" "-cV" "-Vc" "-c -V" "c" "V" "--c" "-e" "-s" \
+ "-blah" "-cV 12k" "-s -cV 1P" "-sc" "-Vs 5g" "-o" "--o" "-O" "--O" \
+ "-o QuOta=none" "-o quota=non" "-o quota=abcd" "-o quota=0" "-o quota=" \
+ "-o ResErVaTi0n=none" "-o reserV=none" "-o reservation=abcd" "-o reserv=" \
+ "-o recorDSize=64k" "-o recordsize=2048K" "-o recordsize=2M" \
+ "-o recordsize=256" "-o recsize=" "-o recsize=zero" "-o recordsize=0" \
+ "-o mountPoint=/tmp/tmpfile$$" "-o mountpoint=non0" "-o mountpoint=" \
+ "-o mountpoint=LEGACY" "-o mounpoint=none" \
+ "-o sharenfs=ON" "-o ShareNFS=off" "-o sharenfs=sss" \
+ "-o checkSUM=on" "-o checksum=SHA256" "-o chsum=off" "-o checksum=aaa" \
+ "-o checkSUM=on -V $VOLSIZE" "-o checksum=SHA256 -V $VOLSIZE" \
+ "-o chsum=off -V $VOLSIZE" "-o checksum=aaa -V $VOLSIZE" \
+ "-o compression=of" "-o ComPression=lzjb" "-o compress=ON" "-o compress=a" \
+ "-o compression=of -V $VOLSIZE" "-o ComPression=lzjb -V $VOLSIZE" \
+ "-o compress=ON -V $VOLSIZE" "-o compress=a -V $VOLSIZE" \
+ "-o atime=ON" "-o ATime=off" "-o atime=bbb" \
+ "-o deviCes=on" "-o devices=OFF" "-o devices=aaa" \
+ "-o exec=ON" "-o EXec=off" "-o exec=aaa" \
+ "-o readonly=ON" "-o reADOnly=off" "-o rdonly=OFF" "-o rdonly=aaa" \
+ "-o readonly=ON -V $VOLSIZE" "-o reADOnly=off -V $VOLSIZE" \
+ "-o rdonly=OFF -V $VOLSIZE" "-o rdonly=aaa -V $VOLSIZE" \
+ "-o snapdIR=hidden" "-o snapdir=VISible" "-o snapdir=aaa" \
+ "-o aclmode=DIScard" "-o aclmODE=groupmask" "-o aclmode=aaa" \
+ "-o aclinherit=deny" "-o aclinHerit=secure" "-o aclinherit=aaa" \
+ "-o type=volume" "-o type=snapshot" "-o type=filesystem" \
+ "-o type=volume -V $VOLSIZE" "-o type=snapshot -V $VOLSIZE" \
+ "-o type=filesystem -V $VOLSIZE" \
+ "-o creation=aaa" "-o creation=aaa -V $VOLSIZE" \
+ "-o used=10K" "-o used=10K -V $VOLSIZE" \
+ "-o available=10K" "-o available=10K -V $VOLSIZE" \
+ "-o referenced=10K" "-o referenced=10K -V $VOLSIZE" \
+ "-o compressratio=1.00x" "-o compressratio=1.00x -V $VOLSIZE" \
+ "-o version=0" "-o version=1.234" "-o version=10K" "-o version=-1" \
+ "-o version=aaa" "-o version=999"
+if is_freebsd; then
+ args+=("-o jailed=ON" "-o JaiLed=off" "-o jailed=aaa")
+else
+ args+=("-o zoned=ON" "-o ZoNed=off" "-o zoned=aaa")
+fi
+
+log_assert "'zfs create' should return an error with badly-formed parameters."
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ typeset arg=${args[i]}
+ if is_freebsd; then
+ # FreeBSD does not strictly validate share options (yet).
+ if [[ "$arg" == "-o sharenfs="* ]]; then
+ ((i = i + 1))
+ continue
+ fi
+ fi
+ log_mustnot zfs create $arg $TESTPOOL/$TESTFS1
+ log_mustnot zfs create -p $arg $TESTPOOL/$TESTFS1
+ ((i = i + 1))
+done
+
+log_pass "'zfs create' with badly formed parameters failed as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_009_neg.ksh
new file mode 100755
index 000000000000..63f5e595ea38
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_009_neg.ksh
@@ -0,0 +1,130 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs create <filesystem>' fails with bad <filesystem> arguments, including:
+# *Invalid character against the ZFS namespace
+# *Incomplete component
+# *Too many arguments
+# *Filesystem already exists
+# *Beyond maximal name length.
+# *Same property set multiple times via '-o property=value'
+# *Volume's property set on filesystem
+# *Exceeding maximum name nesting
+#
+# STRATEGY:
+# 1. Create an array of <filesystem> arguments
+# 2. Execute 'zfs create <filesystem>' with each argument
+# 3. Verify an error is returned.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset -i i
+ typeset found
+
+ #
+ # check to see if there is any new fs created during the test
+ # if so destroy it.
+ #
+ for dset in $(zfs list -H | \
+ awk '{print $1}' | grep / ); do
+ found=false
+ i=0
+ while (( $i < ${#existed_fs[*]} )); do
+ if [[ $dset == ${existed_fs[i]} ]]; then
+ found=true
+ break
+ fi
+ (( i = i + 1 ))
+ done
+
+ #
+ # new fs created during the test, cleanup it
+ #
+ if [[ $found == "false" ]]; then
+ log_must zfs destroy -f $dset
+ fi
+ done
+}
+
+log_onexit cleanup
+
+set -A args "$TESTPOOL/" "$TESTPOOL//blah" "$TESTPOOL/@blah" \
+ "$TESTPOOL/blah@blah" "$TESTPOOL/blah^blah" "$TESTPOOL/blah%blah" \
+ "$TESTPOOL/blah*blah" "$TESTPOOL/blah blah" \
+ "-s $TESTPOOL/$TESTFS1" "-b 1092 $TESTPOOL/$TESTFS1" \
+ "-b 64k $TESTPOOL/$TESTFS1" "-s -b 32k $TESTPOOL/$TESTFS1" \
+ "$TESTPOOL/$BYND_MAX_NAME" "$TESTPOOL/$BYND_NEST_LIMIT" \
+ "$TESTPOOL/." "$TESTPOOL/.." "$TESTPOOL/../blah" "$TESTPOOL/./blah" \
+ "$TESTPOOL/blah/./blah" "$TESTPOOL/blah/../blah"
+
+log_assert "Verify 'zfs create <filesystem>' fails with bad <filesystem> argument."
+
+datasetexists $TESTPOOL/$TESTFS || \
+ log_must zfs create $TESTPOOL/$TESTFS
+
+set -A existed_fs $(zfs list -H | awk '{print $1}' | grep / )
+
+log_mustnot zfs create $TESTPOOL
+log_mustnot zfs create $TESTPOOL/$TESTFS
+
+typeset -i i=0
+while (( $i < ${#args[*]} )); do
+ log_mustnot zfs create ${args[$i]}
+ log_mustnot zfs create -p ${args[$i]}
+ ((i = i + 1))
+done
+
+i=0
+while (( $i < ${#RW_FS_PROP[*]} )); do
+ log_mustnot zfs create -o ${RW_FS_PROP[i]} -o ${RW_FS_PROP[i]} \
+ $TESTPOOL/$TESTFS1
+ log_mustnot zfs create -p -o ${RW_FS_PROP[i]} -o ${RW_FS_PROP[i]} \
+ $TESTPOOL/$TESTFS1
+ ((i = i + 1))
+done
+
+i=0
+while (( $i < ${#VOL_ONLY_PROP[*]} )); do
+ log_mustnot zfs create -o ${VOL_ONLY_PROP[i]} $TESTPOOL/$TESTFS1
+ log_mustnot zfs create -p -o ${VOL_ONLY_PROP[i]} $TESTPOOL/$TESTFS1
+ ((i = i + 1))
+done
+
+log_pass "'zfs create <filesystem>' fails as expected with bad <filesystem> argument."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_010_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_010_neg.ksh
new file mode 100755
index 000000000000..4b1401d8649b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_010_neg.ksh
@@ -0,0 +1,149 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs create [-b <blocksize> ] -V <size> <volume>' fails with badly formed
+# <size> or <volume> arguments,including:
+# *Invalid volume size and volume name
+# *Invalid blocksize
+# *Incomplete component in the dataset tree
+# *The volume already exists
+# *The volume name beyond the maximal name length - 256.
+# *Same property set multiple times via '-o property=value'
+# *Filesystems's property set on volume
+#
+# STRATEGY:
+# 1. Create an array of badly formed arguments
+# 2. For each argument, execute 'zfs create -V <size> <volume>'
+# 3. Verify an error is returned.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset -i i
+ typeset found
+
+ #
+ # check to see if there is any new fs created during the test
+ # if so destroy it.
+ #
+ for dset in $(zfs list -H | \
+ awk '{print $1}' | grep / ); do
+ found=false
+ i=0
+ while (( $i < ${#existed_fs[*]} )); do
+ if [[ $dset == ${existed_fs[i]} ]]; then
+ found=true
+ break
+ fi
+ (( i = i + 1 ))
+ done
+
+ #
+ # new fs created during the test, cleanup it
+ #
+ if [[ $found == "false" ]]; then
+ log_must zfs destroy -f $dset
+ fi
+ done
+}
+
+log_onexit cleanup
+
+log_assert "Verify 'zfs create [-s] [-b <blocksize> ] -V <size> <volume>' fails with" \
+ "badly-formed <size> or <volume> arguments."
+
+set -A args "$VOLSIZE" "$TESTVOL1" \
+ "$VOLSIZE $TESTVOL1" "0 $TESTPOOL/$TESTVOL1" \
+ "-1gb $TESTPOOL/$TESTVOL1" "1g? $TESTPOOL/$TESTVOL1" \
+ "1.01BB $TESTPOOL/$TESTVOL1" "1%g $TESTPOOL/$TESTVOL1" \
+ "1g% $TESTPOOL/$TESTVOL1" "1g$ $TESTPOOL/$TESTVOL1" \
+ "$m $TESTPOOL/$TESTVOL1" "1m$ $TESTPOOL/$TESTVOL1" \
+ "1m! $TESTPOOL/$TESTVOL1" \
+ "1gbb $TESTPOOL/blah" "1blah $TESTPOOL/blah" "blah $TESTPOOL/blah" \
+ "$VOLSIZE $TESTPOOL" "$VOLSIZE $TESTPOOL/" "$VOLSIZE $TESTPOOL//blah"\
+ "$VOLSIZE $TESTPOOL/blah@blah" "$VOLSIZE $TESTPOOL/blah^blah" \
+ "$VOLSIZE $TESTPOOL/blah*blah" "$VOLSIZE $TESTPOOL/blah%blah" \
+ "$VOLSIZE blah" "$VOLSIZE $TESTPOOL/$BYND_MAX_NAME" \
+ "1m -b $TESTPOOL/$TESTVOL1" "1m -b 11k $TESTPOOL/$TESTVOL1" \
+ "1m -b 511 $TESTPOOL/$TESTVOL1"
+
+set -A options "" "-s"
+
+datasetexists $TESTPOOL/$TESTVOL || \
+ log_must zfs create -V $VOLSIZE $TESTPOOL/$TESTVOL
+
+set -A existed_fs $(zfs list -H | awk '{print $1}' | grep / )
+
+log_mustnot zfs create -V $VOLSIZE $TESTPOOL/$TESTVOL
+log_mustnot zfs create -s -V $VOLSIZE $TESTPOOL/$TESTVOL
+
+typeset -i i=0
+typeset -i j=0
+while (( i < ${#options[*]} )); do
+
+ j=0
+ while (( j < ${#args[*]} )); do
+ log_mustnot zfs create ${options[$i]} -V ${args[$j]}
+ log_mustnot zfs create -p ${options[$i]} -V ${args[$j]}
+
+ ((j = j + 1))
+ done
+
+ j=0
+ while (( $j < ${#RW_VOL_PROP[*]} )); do
+ log_mustnot zfs create ${options[$i]} -o ${RW_VOL_PROP[j]} \
+ -o ${RW_VOL_PROP[j]} -V $VOLSIZE $TESTPOOL/$TESTVOL1
+ log_mustnot zfs create -p ${options[$i]} -o ${RW_VOL_PROP[j]} \
+ -o ${RW_VOL_PROP[j]} -V $VOLSIZE $TESTPOOL/$TESTVOL1
+ ((j = j + 1))
+ done
+
+ j=0
+ while (( $j < ${#FS_ONLY_PROP[*]} )); do
+ log_mustnot zfs create ${options[$i]} -o ${FS_ONLY_PROP[j]} \
+ -V $VOLSIZE $TESTPOOL/$TESTVOL1
+ log_mustnot zfs create -p ${options[$i]} -o ${FS_ONLY_PROP[j]} \
+ -V $VOLSIZE $TESTPOOL/$TESTVOL1
+ ((j = j + 1))
+ done
+
+ ((i = i + 1))
+done
+
+log_pass "'zfs create [-s][-b <blocksize>] -V <size> <volume>' fails as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_011_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_011_pos.ksh
new file mode 100755
index 000000000000..982a4ea16b5e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_011_pos.ksh
@@ -0,0 +1,70 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs create -p' should work as expected
+#
+# STRATEGY:
+# 1. To create $newdataset with -p option, first make sure the upper level
+# of $newdataset does not exist
+# 2. Make sure without -p option, 'zfs create' will fail
+# 3. Create $newdataset with -p option, verify it is created
+# 4. Run 'zfs create -p $newdataset' again, the exit code should be zero
+# even $newdataset exists
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $TESTPOOL/$TESTFS1 ; then
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS1
+ fi
+}
+
+log_onexit cleanup
+
+typeset newdataset1="$TESTPOOL/$TESTFS1/$TESTFS/$TESTFS1"
+typeset newdataset2="$TESTPOOL/$TESTFS1/$TESTFS/$TESTVOL1"
+
+log_assert "'zfs create -p' works as expected."
+
+log_must verify_opt_p_ops "create" "fs" $newdataset1
+
+# verify volume creation
+if is_global_zone; then
+ log_must verify_opt_p_ops "create" "vol" $newdataset2
+fi
+
+log_pass "'zfs create -p' works as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_012_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_012_pos.ksh
new file mode 100755
index 000000000000..d8aa06407755
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_012_pos.ksh
@@ -0,0 +1,71 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs create -p -o version=1' should only cause the leaf filesystem to be version=1
+#
+# STRATEGY:
+# 1. Create $newdataset with -p option, verify it is created
+# 2. Verify only the leaf filesystem to be version=1, others use the current version
+#
+
+ZFS_VERSION=$(zfs upgrade | head -1 | awk '{print $NF}' \
+ | sed -e 's/\.//g')
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $TESTPOOL/$TESTFS1 ; then
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS1
+ fi
+}
+
+log_onexit cleanup
+
+
+typeset newdataset1="$TESTPOOL/$TESTFS1/$TESTFS/$TESTFS1"
+
+log_assert "'zfs create -p -o version=1' only cause the leaf filesystem to be version=1."
+
+log_must zfs create -p -o version=1 $newdataset1
+log_must datasetexists $newdataset1
+
+log_must check_fs_version $TESTPOOL/$TESTFS1/$TESTFS/$TESTFS1 1
+for fs in $TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS1/$TESTFS ; do
+ log_must check_fs_version $fs $ZFS_VERSION
+done
+
+log_pass "'zfs create -p -o version=1' only cause the leaf filesystem to be version=1."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_013_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_013_pos.ksh
new file mode 100755
index 000000000000..993c6436a7b1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_013_pos.ksh
@@ -0,0 +1,82 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create.cfg
+
+#
+# DESCRIPTION:
+# 'zfs create -s -V <size> <volume>' can create various-size sparse volume
+# with long fs name
+#
+# STRATEGY:
+# 1. Create a volume in the storage pool.
+# 2. Verify the volume is created correctly.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset -i j=0
+ while [[ $j -lt ${#size[*]} ]]; do
+ destroy_dataset $TESTPOOL/${LONGFSNAME}${size[j]}
+ ((j = j + 1))
+ done
+}
+
+log_onexit cleanup
+
+
+log_assert "'zfs create -s -V <size> <volume>' succeeds"
+
+typeset -i j=0
+while (( $j < ${#size[*]} )); do
+ typeset cmdline="zfs create -s -V ${size[j]} \
+ $TESTPOOL/${LONGFSNAME}${size[j]}"
+
+ str=$(eval $cmdline 2>&1)
+ if (( $? == 0 )); then
+ log_note "SUCCESS: $cmdline"
+ log_must datasetexists $TESTPOOL/${LONGFSNAME}${size[j]}
+ elif [[ $str == *${VOL_LIMIT_KEYWORD1}* || \
+ $str == *${VOL_LIMIT_KEYWORD2}* || \
+ $str == *${VOL_LIMIT_KEYWORD3}* ]]
+ then
+ log_note "UNSUPPORTED: $cmdline"
+ else
+ log_fail "$cmdline"
+ fi
+
+ ((j = j + 1))
+done
+
+log_pass "'zfs create -s -V <size> <volume>' works as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_014_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_014_pos.ksh
new file mode 100755
index 000000000000..d1a8153d60e5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_014_pos.ksh
@@ -0,0 +1,59 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# check 'zfs create <filesystem>' works at the name length boundary
+#
+# STRATEGY:
+# 1. Verify creating filesystem with name length 255 would succeed
+# 2. Verify creating filesystem with name length 256 would fail
+# 3. Verify the pool can be re-imported
+
+verify_runnable "both"
+
+# namelen 255 and 256
+TESTFS1=$(for i in $(seq $((254 - ${#TESTPOOL}))); do echo z ; done | tr -d '\n')
+TESTFS2=$(for i in $(seq $((255 - ${#TESTPOOL}))); do echo z ; done | tr -d '\n')
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 &&
+ log_must zfs destroy $TESTPOOL/$TESTFS1
+}
+
+log_onexit cleanup
+
+log_assert "'zfs create <filesystem>' can create a ZFS filesystem with name length 255."
+
+log_must zfs create $TESTPOOL/$TESTFS1
+log_mustnot zfs create $TESTPOOL/$TESTFS2
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+
+log_pass "'zfs create <filesystem>' works as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
new file mode 100644
index 000000000000..4c3f8b908c10
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
@@ -0,0 +1,54 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Check if the user property is identical to the expected value.
+#
+# $1 dataset
+# $2 property string
+#
+function propertycheck
+{
+ typeset dtst=$1
+ typeset propstr=$2
+
+ typeset prop=$(echo $propstr | awk -F= '{print $1}')
+ typeset expect_value=$(echo $propstr | awk -F= '{print $2}')
+ typeset value=$(zfs get -H -p -o value $prop $dtst)
+
+
+ if [[ "$expect_value" == "$value" ]]; then
+ return 0
+ else
+ return 1
+ fi
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_crypt_combos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_crypt_combos.ksh
new file mode 100755
index 000000000000..141b2557d622
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_crypt_combos.ksh
@@ -0,0 +1,99 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017, Datto, Inc. All rights reserved.
+# Copyright (c) 2019, DilOS
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs create' should create an encrypted dataset with a valid encryption
+# algorithm, key format, key location, and key.
+#
+# STRATEGY:
+# 1. Create a filesystem for each combination of encryption type and key format
+# 2. Verify that each filesystem has the correct properties set
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS1
+}
+
+log_onexit cleanup
+
+set -A ENCRYPTION_ALGS \
+ "encryption=on" \
+ "encryption=aes-128-ccm" \
+ "encryption=aes-192-ccm" \
+ "encryption=aes-256-ccm" \
+ "encryption=aes-128-gcm" \
+ "encryption=aes-192-gcm" \
+ "encryption=aes-256-gcm"
+
+set -A ENCRYPTION_PROPS \
+ "encryption=aes-256-gcm" \
+ "encryption=aes-128-ccm" \
+ "encryption=aes-192-ccm" \
+ "encryption=aes-256-ccm" \
+ "encryption=aes-128-gcm" \
+ "encryption=aes-192-gcm" \
+ "encryption=aes-256-gcm"
+
+set -A KEYFORMATS "keyformat=raw" \
+ "keyformat=hex" \
+ "keyformat=passphrase"
+
+set -A USER_KEYS "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" \
+ "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" \
+ "abcdefgh"
+
+log_assert "'zfs create' should create encrypted datasets using all" \
+ "combinations of supported properties"
+
+typeset -i i=0
+while (( i < ${#ENCRYPTION_ALGS[*]} )); do
+ typeset -i j=0
+ while (( j < ${#KEYFORMATS[*]} )); do
+ log_must eval "printf '%s' ${USER_KEYS[j]} | zfs create" \
+ "-o ${ENCRYPTION_ALGS[i]} -o ${KEYFORMATS[j]}" \
+ "$TESTPOOL/$TESTFS1"
+
+ datasetexists $TESTPOOL/$TESTFS1 || \
+ log_fail "Failed to create dataset using" \
+ "${ENCRYPTION_ALGS[i]} and ${KEYFORMATS[j]}"
+
+ propertycheck $TESTPOOL/$TESTFS1 ${ENCRYPTION_PROPS[i]} || \
+ log_fail "failed to set ${ENCRYPTION_ALGS[i]}"
+ propertycheck $TESTPOOL/$TESTFS1 ${KEYFORMATS[j]} || \
+ log_fail "failed to set ${KEYFORMATS[j]}"
+
+ log_must zfs destroy -f $TESTPOOL/$TESTFS1
+ (( j = j + 1 ))
+ done
+ (( i = i + 1 ))
+done
+
+log_pass "'zfs create' creates encrypted datasets using all combinations of" \
+ "supported properties"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_dryrun.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_dryrun.ksh
new file mode 100755
index 000000000000..64b8296f46bf
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_dryrun.ksh
@@ -0,0 +1,169 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2019 Joyent, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+
+#
+# DESCRIPTION:
+# zfs create -n should perform basic sanity checking but should never create a
+# dataset. If -v and/or -P are used, it should verbose about what would be
+# created if sanity checks pass.
+#
+# STRATEGY:
+# 1. Attempt to create a file system and a volume using various combinations of
+# -n with -v and -P.
+#
+
+verify_runnable "both"
+
+#
+# Verifies that valid commands with -n and without -[vP]:
+# - succeed
+# - do not create a dataset
+# - do not generate output
+#
+function dry_create_no_output
+{
+ typeset -a cmd=(zfs create -n "$@")
+
+ log_note "$0: ${cmd[@]}"
+ log_must "${cmd[@]}"
+ datasetexists "$TESTPOOL/$TESTFS1" &&
+ log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'"
+ typeset out=$("${cmd[@]}" 2>&1)
+ [[ -z "$out" ]] ||
+ log_fail "unexpected output '$out' from '${cmd[@]}'"
+}
+
+#
+# Verifies that commands with invalid properties or invalid property values
+# - fail
+# - do not create a dataset
+# - generate a message on stderr
+#
+function dry_create_error
+{
+ typeset -a cmd=(zfs create -n "$@")
+
+ log_note "$0: ${cmd[@]}"
+ log_mustnot "${cmd[@]}"
+ datasetexists "$TESTPOOL/$TESTFS1" &&
+ log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'"
+ typeset out=$("${cmd[@]}" 2>&1 >/dev/null)
+ [[ -z "$out" ]] &&
+ log_fail "expected an error message but got none from '${cmd[@]}'"
+}
+
+#
+# Verifies that dry-run commands with parseable output
+# - succeed
+# - do not create datasets
+# - generate parseable output on stdout
+# - output matches expectations
+#
+function dry_create_parseable
+{
+ typeset -n exp=$1
+ shift
+ typeset -a cmd=(zfs create -Pn "$@")
+ typeset ds=${cmd[${#cmd[@]} - 1]}
+ typeset out
+ typeset -a toks
+ typeset -a props
+ typeset found_create=false
+
+ log_note "$0: ${cmd[@]}"
+ out=$("${cmd[@]}")
+ (( $? == 0 )) ||
+ log_fail "unexpected failure getting stdout from '${cmd[@]}'"
+ datasetexists "$TESTPOOL/$TESTFS1" &&
+ log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'"
+ echo "$out" | while IFS=$'\t' read -A toks; do
+ log_note "verifying ${toks[@]}"
+ case ${toks[0]} in
+ create)
+ log_must test "${#toks[@]}" -eq 2
+ log_must test "${toks[1]}" == "$ds"
+ found_create="yes, I found create"
+ ;;
+ property)
+ log_must test "${#toks[@]}" -eq 3
+ typeset prop=${toks[1]}
+ typeset val=${toks[2]}
+ if [[ -z "${exp[$prop]}" ]]; then
+ log_fail "unexpectedly got property '$prop'"
+ fi
+ # We may not know the exact value a property will take
+ # on. This is the case for at least refreservation.
+ if [[ ${exp[$prop]} != "*" ]]; then
+ log_must test "${exp[$prop]}" == "$val"
+ fi
+ unset exp[$prop]
+ ;;
+ *)
+ log_fail "Unexpected line ${toks[@]}"
+ ;;
+ esac
+ done
+
+ log_must test "$found_create" == "yes, I found create"
+ log_must test "extra props: ${!exp[@]}" == "extra props: "
+}
+
+function cleanup
+{
+ if datasetexists "$TESTPOOL/$TESTFS1"; then
+ log_must zfs destroy -r "$TESTPOOL/$TESTFS1"
+ fi
+}
+log_onexit cleanup
+
+log_assert "zfs create -n creates nothing but can describe what would be" \
+ "created"
+
+# Typical creations should succeed
+dry_create_no_output "$TESTPOOL/$TESTFS1"
+dry_create_no_output -V 10m "$TESTPOOL/$TESTFS1"
+# It shouldn't do a space check right now
+dry_create_no_output -V 100t "$TESTPOOL/$TESTFS1"
+# It shouldn't create parent datasets either
+dry_create_no_output -p "$TESTPOOL/$TESTFS1/$TESTFS2"
+dry_create_no_output -pV 10m "$TESTPOOL/$TESTFS1/$TESTFS2"
+
+# Various invalid properties should be recognized and result in an error
+dry_create_error -o nosuchprop=42 "$TESTPOOL/$TESTFS1"
+dry_create_error -b 1234 -V 10m "$TESTPOOL/$TESTFS1"
+
+# Parseable output should be parseable.
+typeset -A expect
+expect=([compression]=on)
+dry_create_parseable expect -o compression=on "$TESTPOOL/$TESTFS1"
+
+# Sparse volumes should not get a gratuitous refreservation
+expect=([volblocksize]=4096 [volsize]=$((1024 * 1024 * 10)))
+dry_create_parseable expect -b 4k -V 10m -s "$TESTPOOL/$TESTFS1"
+
+# Non-sparse volumes should have refreservation
+expect=(
+ [volblocksize]=4096
+ [volsize]=$((1024 * 1024 * 10))
+ [refreservation]="*"
+)
+dry_create_parseable expect -b 4k -V 10m "$TESTPOOL/$TESTFS1"
+
+log_pass "zfs create -n creates nothing but can describe what would be" \
+ "created"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_encrypted.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_encrypted.ksh
new file mode 100755
index 000000000000..7e5072f0d5fd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_encrypted.ksh
@@ -0,0 +1,136 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017, Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# ZFS should create datasets only if they have a valid combination of
+# encryption properties set.
+#
+# penc = parent encrypted
+# enc = encryption
+# loc = keylocation provided
+# fmt = keyformat provided
+#
+# penc enc fmt loc valid notes
+# -------------------------------------------
+# no unspec 0 0 yes inherit no encryption (not tested here)
+# no unspec 0 1 no no crypt specified
+# no unspec 1 0 no no crypt specified
+# no unspec 1 1 no no crypt specified
+# no off 0 0 yes explicit no encryption
+# no off 0 1 no keylocation given, but crypt off
+# no off 1 0 no keyformat given, but crypt off
+# no off 1 1 no keyformat given, but crypt off
+# no on 0 0 no no keyformat specified for new key
+# no on 0 1 no no keyformat specified for new key
+# no on 1 0 yes new encryption root
+# no on 1 1 yes new encryption root
+# yes unspec 0 0 yes inherit encryption
+# yes unspec 0 1 no no keyformat specified
+# yes unspec 1 0 yes new encryption root, crypt inherited
+# yes unspec 1 1 yes new encryption root, crypt inherited
+# yes off 0 0 yes unencrypted child of encrypted parent
+# yes off 0 1 no keylocation given, but crypt off
+# yes off 1 0 no keyformat given, but crypt off
+# yes off 1 1 no keyformat given, but crypt off
+# yes on 0 0 yes inherited encryption, local crypt
+# yes on 0 1 no no keyformat specified for new key
+# yes on 1 0 yes new encryption root
+# yes on 1 1 yes new encryption root
+#
+# STRATEGY:
+# 1. Attempt to create a dataset using all combinations of encryption
+# properties
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+ datasetexists $TESTPOOL/$TESTFS2 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS2
+}
+log_onexit cleanup
+
+log_assert "ZFS should create datasets only if they have a valid" \
+ "combination of encryption properties set."
+
+# Unencrypted parent
+log_must zfs create $TESTPOOL/$TESTFS1
+log_mustnot zfs create -o keyformat=passphrase $TESTPOOL/$TESTFS1/c1
+log_mustnot zfs create -o keylocation=prompt $TESTPOOL/$TESTFS1/c1
+log_mustnot zfs create -o keyformat=passphrase -o keylocation=prompt \
+ $TESTPOOL/$TESTFS1/c1
+
+log_must zfs create -o encryption=off $TESTPOOL/$TESTFS1/c1
+log_mustnot zfs create -o encryption=off -o keylocation=prompt \
+ $TESTPOOL/$TESTFS1/c2
+log_mustnot zfs create -o encryption=off -o keyformat=passphrase \
+ $TESTPOOL/$TESTFS1/c2
+log_mustnot zfs create -o encryption=off -o keyformat=passphrase \
+ -o keylocation=prompt $TESTPOOL/$TESTFS1/c2
+
+log_mustnot zfs create -o encryption=on $TESTPOOL/$TESTFS1/c2
+log_mustnot zfs create -o encryption=on -o keylocation=prompt \
+ $TESTPOOL/$TESTFS1/c2
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS1/c3"
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS1/c4"
+
+# Encrypted parent
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS2"
+
+log_must zfs create $TESTPOOL/$TESTFS2/c1
+log_mustnot zfs create -o keylocation=prompt $TESTPOOL/$TESTFS2/c2
+log_must eval "echo $PASSPHRASE | zfs create -o keyformat=passphrase" \
+ "$TESTPOOL/$TESTFS2/c3"
+log_must eval "echo $PASSPHRASE | zfs create -o keyformat=passphrase" \
+ "-o keylocation=prompt $TESTPOOL/$TESTFS2/c4"
+
+log_must zfs create -o encryption=off $TESTPOOL/$TESTFS2/c5
+log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS2/c5)" == "off"
+
+log_mustnot zfs create -o encryption=off -o keylocation=prompt \
+ $TESTPOOL/$TESTFS2/c5
+log_mustnot zfs create -o encryption=off -o keyformat=passphrase \
+ $TESTPOOL/$TESTFS2/c5
+log_mustnot zfs create -o encryption=off -o keyformat=passphrase \
+ -o keylocation=prompt $TESTPOOL/$TESTFS2/c5
+
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "$TESTPOOL/$TESTFS2/c6"
+log_mustnot zfs create -o encryption=on -o keylocation=prompt \
+ $TESTPOOL/$TESTFS2/c7
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS2/c7"
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS2/c8"
+
+log_pass "ZFS creates datasets only if they have a valid combination of" \
+ "encryption properties set."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_verbose.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_verbose.ksh
new file mode 100755
index 000000000000..a07ccc7e9ace
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_verbose.ksh
@@ -0,0 +1,165 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2019 Joyent, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+
+#
+# DESCRIPTION:
+# zfs create -P without -n should be verbose about dataset creation.
+#
+# STRATEGY:
+# 1. Attempt to create a file system and a volume using various properties
+# and -P
+# 2. Exercise the combination of -p and -P.
+#
+
+verify_runnable "both"
+
+#
+# Verifies that non dry-run commands with parseable output
+# - succeed
+# - create datasets
+# - generate parseable output on stdout
+# - output matches expectations
+#
+function dry_create_parseable
+{
+ typeset -n exp=$1
+ shift
+ typeset -a cmd=(zfs create -P "$@")
+ typeset ds=${cmd[${#cmd[@]} - 1]}
+ typeset out
+ typeset -a toks
+ typeset -a props
+ typeset found_create=false
+ typeset create_ancestors=
+ typeset opt
+
+ # Parse the arguments to see if -p was used.
+ while getopts :PV:b:ospv opt; do
+ case $opt in
+ p) create_ancestors=needed ;;
+ *) continue ;;
+ esac
+ done
+
+ log_note "$0: ${cmd[@]}"
+ out=$("${cmd[@]}")
+ (( $? == 0 )) ||
+ log_fail "unexpected failure getting stdout from '${cmd[@]}'"
+ datasetexists "$TESTPOOL/$TESTFS1" ||
+ log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'"
+ echo "$out" | while IFS=$'\t' read -A toks; do
+ log_note "verifying ${toks[@]}"
+ case ${toks[0]} in
+ create_ancestors)
+ case "$create_ancestors" in
+ needed)
+ log_must test "${toks[1]}" == "$ds"
+ create_ancestors="found ${toks[1]}"
+ ;;
+ found*)
+ log_fail "multiple ancestor creation" \
+ "$create_ancestors and ${toks[1]}"
+ ;;
+ "")
+ log_fail "unexpected create_ancestors"
+ ;;
+ *)
+ log_fail "impossible error: fix the test"
+ ;;
+ esac
+ ;;
+ create)
+ log_must test "${#toks[@]}" -eq 2
+ log_must test "${toks[1]}" == "$ds"
+ found_create="yes, I found create"
+ ;;
+ property)
+ log_must test "${#toks[@]}" -eq 3
+ typeset prop=${toks[1]}
+ typeset val=${toks[2]}
+ if [[ -z "${exp[$prop]}" ]]; then
+ log_fail "unexpectedly got property '$prop'"
+ fi
+ # We may not know the exact value a property will take
+ # on. This is the case for at least refreservation.
+ if [[ ${exp[$prop]} != "*" ]]; then
+ log_must test "${exp[$prop]}" == "$val"
+ fi
+ unset exp[$prop]
+ ;;
+ *)
+ log_fail "Unexpected line ${toks[@]}"
+ ;;
+ esac
+ done
+
+ log_must test "$found_create" == "yes, I found create"
+ log_must test "extra props: ${!exp[@]}" == "extra props: "
+
+ case "$create_ancestors" in
+ "")
+ log_must_busy zfs destroy "$ds"
+ ;;
+ "found $ds")
+ log_must_busy zfs destroy -r "$(echo "$ds" | cut -d/ -f1-2)"
+ ;;
+ needed)
+ log_fail "Expected but did not find create_ancestors"
+ ;;
+ *)
+ log_fail "Unexpected value for create_ancestors:" \
+ "$create_ancestors"
+ ;;
+ esac
+}
+
+function cleanup
+{
+ if datasetexists "$TESTPOOL/$TESTFS1"; then
+ log_must_busy zfs destroy -r "$TESTPOOL/$TESTFS1"
+ fi
+}
+log_onexit cleanup
+
+log_assert "zfs create -v creates datasets verbosely"
+
+# Parseable output should be parseable.
+typeset -A expect
+expect=([compression]=on)
+dry_create_parseable expect -o compression=on "$TESTPOOL/$TESTFS1"
+
+# Ancestor creation with -p should emit relevant line
+expect=([compression]=on)
+dry_create_parseable expect -p -o compression=on "$TESTPOOL/$TESTFS1"
+expect=([compression]=on)
+dry_create_parseable expect -p -o compression=on "$TESTPOOL/$TESTFS1/$TESTVOL"
+
+# Sparse volumes should not get a gratuitous refreservation
+expect=([volblocksize]=4096 [volsize]=$((1024 * 1024 * 10)))
+dry_create_parseable expect -b 4k -V 10m -s "$TESTPOOL/$TESTFS1"
+
+# Non-sparse volumes should have refreservation
+expect=(
+ [volblocksize]=4096
+ [volsize]=$((1024 * 1024 * 10))
+ [refreservation]="*"
+)
+dry_create_parseable expect -b 4k -V 10m "$TESTPOOL/$TESTFS1"
+
+log_pass "zfs create -v creates datasets verbosely"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/Makefile.am
new file mode 100644
index 000000000000..c012b35d05b4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/Makefile.am
@@ -0,0 +1,29 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_destroy
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_clone_livelist_condense_and_disable.ksh \
+ zfs_clone_livelist_condense_races.ksh \
+ zfs_destroy_001_pos.ksh \
+ zfs_destroy_002_pos.ksh \
+ zfs_destroy_003_pos.ksh \
+ zfs_destroy_004_pos.ksh \
+ zfs_destroy_005_neg.ksh \
+ zfs_destroy_006_neg.ksh \
+ zfs_destroy_007_neg.ksh \
+ zfs_destroy_008_pos.ksh \
+ zfs_destroy_009_pos.ksh \
+ zfs_destroy_010_pos.ksh \
+ zfs_destroy_011_pos.ksh \
+ zfs_destroy_012_pos.ksh \
+ zfs_destroy_013_neg.ksh \
+ zfs_destroy_014_pos.ksh \
+ zfs_destroy_015_pos.ksh \
+ zfs_destroy_016_pos.ksh \
+ zfs_destroy_clone_livelist.ksh \
+ zfs_destroy_dev_removal.ksh \
+ zfs_destroy_dev_removal_condense.ksh
+
+dist_pkgdata_DATA = \
+ zfs_destroy_common.kshlib \
+ zfs_destroy.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/cleanup.ksh
new file mode 100755
index 000000000000..e838ba8a5947
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_clone_livelist_condense_and_disable.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_clone_livelist_condense_and_disable.ksh
new file mode 100755
index 000000000000..ab506debe9eb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_clone_livelist_condense_and_disable.ksh
@@ -0,0 +1,125 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+# DESCRIPTION
+# Verify zfs destroy test for clones with the livelist feature
+# enabled.
+
+# STRATEGY
+# 1. Clone where livelist is condensed
+# - create clone, write several files, delete those files
+# - check that the number of livelist entries decreases
+# after the delete
+# 2. Clone where livelist is deactivated
+# - create clone, write files. Delete those files and the
+# file in the filesystem when the snapshot was created
+# so the clone and snapshot no longer share data
+# - check that the livelist is destroyed
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
+
+function cleanup
+{
+ log_must zfs destroy -Rf $TESTPOOL/$TESTFS1
+ # reset the livelist sublist size to the original value
+ set_tunable64 LIVELIST_MAX_ENTRIES $ORIGINAL_MAX
+ # reset the minimum percent shared to 75
+ set_tunable32 LIVELIST_MIN_PERCENT_SHARED $ORIGINAL_MIN
+}
+
+function check_ll_len
+{
+ string="$(zdb -vvvvv $TESTPOOL | grep "Livelist")"
+ substring="$1"
+ msg=$2
+ if test "${string#*$substring}" != "$string"; then
+ return 0 # $substring is in $string
+ else
+ log_note $string
+ log_fail "$msg" # $substring is not in $string
+ fi
+}
+
+function test_condense
+{
+ # set the max livelist entries to a small value to more easily
+ # trigger a condense
+ set_tunable64 LIVELIST_MAX_ENTRIES 20
+ # set a small percent shared threshold so the livelist is not disabled
+ set_tunable32 LIVELIST_MIN_PERCENT_SHARED 10
+ clone_dataset $TESTFS1 snap $TESTCLONE
+
+ # sync between each write to make sure a new entry is created
+ for i in {0..4}; do
+ log_must mkfile 5m /$TESTPOOL/$TESTCLONE/testfile$i
+ log_must zpool sync $TESTPOOL
+ done
+
+ check_ll_len "5 entries" "Unexpected livelist size"
+
+ # sync between each write to allow for a condense of the previous entry
+ for i in {0..4}; do
+ log_must mkfile 5m /$TESTPOOL/$TESTCLONE/testfile$i
+ log_must zpool sync $TESTPOOL
+ done
+
+ check_ll_len "6 entries" "Condense did not occur"
+
+ log_must zfs destroy $TESTPOOL/$TESTCLONE
+ check_livelist_gone
+}
+
+function test_deactivated
+{
+ # Threshold set to 50 percent
+ set_tunable32 LIVELIST_MIN_PERCENT_SHARED 50
+ clone_dataset $TESTFS1 snap $TESTCLONE
+
+ log_must mkfile 5m /$TESTPOOL/$TESTCLONE/$TESTFILE0
+ log_must mkfile 5m /$TESTPOOL/$TESTCLONE/$TESTFILE1
+ log_must zpool sync $TESTPOOL
+ # snapshot and clone share 'atestfile', 33 percent
+ check_livelist_gone
+ log_must zfs destroy -R $TESTPOOL/$TESTCLONE
+
+ # Threshold set to 20 percent
+ set_tunable32 LIVELIST_MIN_PERCENT_SHARED 20
+ clone_dataset $TESTFS1 snap $TESTCLONE
+
+ log_must mkfile 5m /$TESTPOOL/$TESTCLONE/$TESTFILE0
+ log_must mkfile 5m /$TESTPOOL/$TESTCLONE/$TESTFILE1
+ log_must mkfile 5m /$TESTPOOL/$TESTCLONE/$TESTFILE2
+ log_must zpool sync $TESTPOOL
+ # snapshot and clone share 'atestfile', 25 percent
+ check_livelist_exists $TESTCLONE
+ log_must rm /$TESTPOOL/$TESTCLONE/atestfile
+ # snapshot and clone share no files
+ check_livelist_gone
+ log_must zfs destroy -R $TESTPOOL/$TESTCLONE
+}
+
+ORIGINAL_MAX=$(get_tunable LIVELIST_MAX_ENTRIES)
+ORIGINAL_MIN=$(get_tunable LIVELIST_MIN_PERCENT_SHARED)
+
+log_onexit cleanup
+log_must zfs create $TESTPOOL/$TESTFS1
+log_must mkfile 5m /$TESTPOOL/$TESTFS1/atestfile
+log_must zfs snapshot $TESTPOOL/$TESTFS1@snap
+test_condense
+test_deactivated
+
+log_pass "Clone's livelist condenses and disables as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_clone_livelist_condense_races.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_clone_livelist_condense_races.ksh
new file mode 100755
index 000000000000..453b502416ed
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_clone_livelist_condense_races.ksh
@@ -0,0 +1,117 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+# DESCRIPTION
+# Test race conditions for livelist condensing
+
+# STRATEGY
+# These tests exercise code paths that deal with a livelist being
+# simultaneously condensed and deactivated (deleted, exported or disabled).
+# If a variable is set, the zthr will pause until it is cancelled or waited
+# and then a counter variable keeps track of whether or not the code path is
+# reached.
+
+# 1. Deletion race: repeatedly overwrite the same file to trigger condense
+# and then delete the clone.
+# 2. Disable race: Overwrite enough files to trigger condenses and disabling of
+# the livelist.
+# 3. Export race: repeatedly overwrite the same file to trigger condense and
+# then export the pool.
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
+
+function cleanup
+{
+ log_must zfs destroy -Rf $TESTPOOL/$TESTFS1
+ # reset the livelist sublist size to the original value
+ set_tunable64 LIVELIST_MAX_ENTRIES $ORIGINAL_MAX
+ # reset the condense tests to 0
+ set_tunable32 LIVELIST_CONDENSE_ZTHR_PAUSE 0
+ set_tunable32 LIVELIST_CONDENSE_SYNC_PAUSE 0
+}
+
+function delete_race
+{
+ set_tunable32 "$1" 0
+ log_must zfs clone $TESTPOOL/$TESTFS1@snap $TESTPOOL/$TESTCLONE
+ for i in {1..5}; do
+ log_must zpool sync $TESTPOOL
+ log_must mkfile 5m /$TESTPOOL/$TESTCLONE/out
+ done
+ log_must zfs destroy $TESTPOOL/$TESTCLONE
+ log_must zpool sync $TESTPOOL
+ [[ "1" == "$(get_tunable "$1")" ]] || \
+ log_fail "delete/condense race test failed"
+}
+
+function export_race
+{
+ set_tunable32 "$1" 0
+ log_must zfs clone $TESTPOOL/$TESTFS1@snap $TESTPOOL/$TESTCLONE
+ for i in {1..5}; do
+ log_must zpool sync $TESTPOOL
+ log_must mkfile 5m /$TESTPOOL/$TESTCLONE/out
+ done
+ log_must zpool export $TESTPOOL
+ log_must zpool import $TESTPOOL
+ [[ "1" == "$(get_tunable "$1")" ]] || \
+ log_fail "export/condense race test failed"
+ log_must zfs destroy $TESTPOOL/$TESTCLONE
+}
+
+function disable_race
+{
+ set_tunable32 "$1" 0
+ log_must zfs clone $TESTPOOL/$TESTFS1@snap $TESTPOOL/$TESTCLONE
+ for i in {1..5}; do
+ log_must zpool sync $TESTPOOL
+ log_must mkfile 5m /$TESTPOOL/$TESTCLONE/out
+ done
+ # overwrite the file shared with the origin to trigger disable
+ log_must mkfile 100m /$TESTPOOL/$TESTCLONE/atestfile
+ log_must zpool sync $TESTPOOL
+ [[ "1" == "$(get_tunable "$1")" ]] || \
+ log_fail "disable/condense race test failed"
+ log_must zfs destroy $TESTPOOL/$TESTCLONE
+}
+
+ORIGINAL_MAX=$(get_tunable LIVELIST_MAX_ENTRIES)
+
+log_onexit cleanup
+
+log_must zfs create $TESTPOOL/$TESTFS1
+log_must mkfile 100m /$TESTPOOL/$TESTFS1/atestfile
+log_must zpool sync $TESTPOOL
+log_must zfs snapshot $TESTPOOL/$TESTFS1@snap
+
+# Reduce livelist size to trigger condense more easily
+set_tunable64 LIVELIST_MAX_ENTRIES 20
+
+# Test cancellation path in the zthr
+set_tunable32 LIVELIST_CONDENSE_ZTHR_PAUSE 1
+set_tunable32 LIVELIST_CONDENSE_SYNC_PAUSE 0
+disable_race LIVELIST_CONDENSE_ZTHR_CANCEL
+delete_race LIVELIST_CONDENSE_ZTHR_CANCEL
+export_race LIVELIST_CONDENSE_ZTHR_CANCEL
+
+# Test cancellation path in the synctask
+set_tunable32 LIVELIST_CONDENSE_ZTHR_PAUSE 0
+set_tunable32 LIVELIST_CONDENSE_SYNC_PAUSE 1
+disable_race LIVELIST_CONDENSE_SYNC_CANCEL
+delete_race LIVELIST_CONDENSE_SYNC_CANCEL
+
+log_pass "Clone livelist condense race conditions passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
new file mode 100644
index 000000000000..a62739b07ec8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
@@ -0,0 +1,39 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+export TESTFSCLONE=${TESTFS}clone
+export TESTVOLCLONE=${TESTVOL}clone
+export CTR=$TESTPOOL/$TESTCTR
+export FS=$CTR/$TESTFS
+export VOL=$CTR/$TESTVOL
+export FSSNAP=$FS@$TESTSNAP
+export VOLSNAP=$VOL@$TESTSNAP
+export FSCLONE=$TESTPOOL/$TESTFSCLONE
+export VOLCLONE=$TESTPOOL/$TESTVOLCLONE
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_001_pos.ksh
new file mode 100755
index 000000000000..26857d48d48b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_001_pos.ksh
@@ -0,0 +1,235 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs destroy -r|-rf|-R|-Rf <fs|ctr|vol|snap>' should recursively destroy
+# all children and clones based on options.
+#
+# STRATEGY:
+# 1. Create test environment according to options. There are three test
+# models can be created. Only ctr, fs & vol; with snap; with clone.
+# 2. According to option, make the dataset busy or not.
+# 3. Run 'zfs destroy [-rRf] <dataset>'
+# 4. According to dataset and option, check if get the expected results.
+#
+
+verify_runnable "both"
+
+#
+# According to parameters, 1st, create suitable testing environment. 2nd,
+# run 'zfs destroy $opt <dataset>'. 3rd, check the system status.
+#
+# $1 option of 'zfs destroy'
+# $2 dataset will be destroyed.
+#
+function test_n_check
+{
+ typeset opt=$1
+ typeset dtst=$2
+
+ if ! is_global_zone ; then
+ if [[ $dtst == $VOL || $dtst == $VOLSNAP ]]; then
+ log_note "UNSUPPORTED: Volume are unavailable in LZ."
+ return
+ fi
+ fi
+
+ # '-f' has no effect on non-filesystems
+ if [[ $opt == -f ]]; then
+ if [[ $dtst != $FS ]]; then
+ log_note "UNSUPPORTED: '-f ' is only available for " \
+ "leaf FS."
+ return
+ fi
+ fi
+
+ # Clean the test environment and make it clear.
+ if datasetexists $CTR; then
+ log_must zfs destroy -Rf $CTR
+ fi
+
+ # According to option create test compatible environment.
+ case $opt in
+ -r|-rf) setup_testenv snap ;;
+ -R|-Rf) setup_testenv clone ;;
+ -f) setup_testenv ;;
+ *) log_fail "Incorrect option: '$opt'." ;;
+ esac
+
+ #
+ # According to different dataset type, create busy condition when try to
+ # destroy this dataset.
+ #
+ typeset mpt_dir
+ case $dtst in
+ $CTR|$FS)
+ if [[ $opt == *f* ]]; then
+ mpt_dir=$(get_prop mountpoint $FS)
+ pidlist="$pidlist $(mkbusy \
+ $mpt_dir/$TESTFILE0)"
+ log_note "mkbusy $mpt_dir/$TESTFILE0 " \
+ "(pidlist: $pidlist)"
+ [[ -z $pidlist ]] && \
+ log_fail "Failure from mkbusy"
+ log_mustnot zfs destroy -rR $dtst
+ fi
+ ;;
+ $VOL)
+ if [[ $opt == *f* ]]; then
+ pidlist="$pidlist $(mkbusy \
+ $TESTDIR1/$TESTFILE0)"
+ log_note "mkbusy $TESTDIR1/$TESTFILE0 " \
+ "(pidlist: $pidlist)"
+ [[ -z $pidlist ]] && \
+ log_fail "Failure from mkbusy"
+ log_mustnot zfs destroy -rR $dtst
+ fi
+ ;;
+ $VOLSNAP)
+ if [[ $opt == *f* ]]; then
+ pidlist="$pidlist $(mkbusy \
+ $TESTDIR1/$TESTFILE0)"
+ log_note "mkbusy $TESTDIR1/$TESTFILE0 " \
+ "(pidlist: $pidlist)"
+ [[ -z $pidlist ]] && \
+ log_fail "Failure from mkbusy"
+ log_must_busy zfs destroy -rR $dtst
+ log_must zfs snapshot $dtst
+ fi
+ ;;
+ $FSSNAP)
+ if [[ $opt == *f* ]]; then
+ mpt_dir=$(snapshot_mountpoint $dtst)
+ pidlist="$pidlist $(mkbusy $mpt_dir)"
+ log_note "mkbusy $mpt_dir (pidlist: $pidlist)"
+ [[ -z $pidlist ]] && \
+ log_fail "Failure from mkbusy"
+ if is_linux ; then
+ log_mustnot zfs destroy -rR $dtst
+ else
+ log_must zfs destroy -rR $dtst
+ log_must zfs snapshot $dtst
+ fi
+ fi
+ ;;
+ *) log_fail "Unsupported dataset: '$dtst'."
+ esac
+
+ # Kill any lingering instances of mkbusy, and clear the list.
+ if is_linux ; then
+ [[ -z $pidlist ]] || log_must kill -TERM $pidlist
+ pidlist=""
+ log_mustnot pgrep -fl mkbusy
+ fi
+
+ # Firstly, umount ufs filesystem which was created by zfs volume.
+ if is_global_zone; then
+ log_must umount -f $TESTDIR1
+ fi
+
+ # Invoke 'zfs destroy [-rRf] <dataset>'
+ log_must_busy zfs destroy $opt $dtst
+ block_device_wait
+
+ # Kill any lingering instances of mkbusy, and clear the list.
+ if ! is_linux ; then
+ [[ -z $pidlist ]] || log_must kill -TERM $pidlist
+ pidlist=""
+ log_mustnot pgrep -fl mkbusy
+ fi
+
+ case $dtst in
+ $CTR) check_dataset datasetnonexists \
+ $CTR $FS $VOL $FSSNAP $VOLSNAP
+ if [[ $opt == *R* ]]; then
+ check_dataset datasetnonexists \
+ $FSCLONE $VOLCLONE
+ fi
+ ;;
+ $FS) check_dataset datasetexists $CTR $VOL
+ check_dataset datasetnonexists $FS
+ if [[ $opt != -f ]]; then
+ check_dataset datasetexists $VOLSNAP
+ check_dataset datasetnonexists $FSSNAP
+ fi
+ if [[ $opt == *R* ]]; then
+ check_dataset datasetexists $VOLCLONE
+ check_dataset datasetnonexists $FSCLONE
+ fi
+ ;;
+ $VOL) check_dataset datasetexists $CTR $FS $FSSNAP
+ check_dataset datasetnonexists $VOL $VOLSNAP
+ if [[ $opt == *R* ]]; then
+ check_dataset datasetexists $FSCLONE
+ check_dataset datasetnonexists $VOLCLONE
+ fi
+ ;;
+ $FSSNAP)
+ check_dataset datasetexists $CTR $FS $VOL $VOLSNAP
+ check_dataset datasetnonexists $FSSNAP
+ if [[ $opt == *R* ]]; then
+ check_dataset datasetexists $VOLCLONE
+ check_dataset datasetnonexists $FSCLONE
+ fi
+ ;;
+ $VOLSNAP)
+ check_dataset datasetexists $CTR $FS $VOL $FSSNAP
+ check_dataset datasetnonexists $VOLSNAP
+ if [[ $opt == *R* ]]; then
+ check_dataset datasetexists $FSCLONE
+ check_dataset datasetnonexists $VOLCLONE
+ fi
+ ;;
+ esac
+
+ log_note "'zfs destroy $opt $dtst' passed."
+}
+
+log_assert "'zfs destroy -r|-R|-f|-rf|-Rf <fs|ctr|vol|snap>' should " \
+ "recursively destroy all children."
+log_onexit cleanup_testenv
+
+typeset dtst=""
+typeset opt=""
+typeset pidlist=""
+for dtst in $CTR $FS $VOL $FSSNAP $VOLSNAP; do
+ for opt in "-r" "-R" "-f" "-rf" "-Rf"; do
+ log_note "Starting test: zfs destroy $opt $dtst"
+ test_n_check $opt $dtst
+ done
+done
+
+log_pass "'zfs destroy -r|-R|-f|-rf|-Rf <fs|ctr|vol|snap>' passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_002_pos.ksh
new file mode 100755
index 000000000000..128921226a73
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_002_pos.ksh
@@ -0,0 +1,95 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+
+#
+# DESCRIPTION:
+# 'zfs destroy <filesystem|volume|snapshot>' can successfully destroy
+# the specified dataset which has no active dependents.
+#
+# STRATEGY:
+# 1. Create a filesystem,volume and snapshot in the storage pool
+# 2. Destroy the filesystem,volume and snapshot
+# 3. Verify the datasets are destroyed successfully
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset -i i=0
+ while (( $i < ${#data_objs[*]} )); do
+ destroy_dataset "${data_objs[i]}" "-rf"
+ ((i = i + 1))
+ done
+}
+
+log_assert "Verify 'zfs destroy' can destroy the specified datasets without active" \
+ "dependents."
+log_onexit cleanup
+
+if is_global_zone ; then
+ set -A data_objs "$TESTPOOL/$TESTFS@$TESTSNAP" "$TESTPOOL/$TESTFS1" \
+ "$TESTPOOL/$TESTVOL" "$TESTPOOL/$TESTVOL1"
+else
+ set -A data_objs "$TESTPOOL/$TESTFS@$TESTSNAP" "$TESTPOOL/$TESTFS1"
+fi
+
+log_must zfs create $TESTPOOL/$TESTFS1
+log_must zfs snapshot $TESTPOOL/$TESTFS@$TESTSNAP
+
+if is_global_zone ; then
+ log_must zfs create -V $VOLSIZE $TESTPOOL/$TESTVOL
+
+ # Max volume size is 1TB on 32-bit systems
+ [[ is_32bit ]] && \
+ BIGVOLSIZE=1Tb
+ log_must zfs create -sV $BIGVOLSIZE $TESTPOOL/$TESTVOL1
+fi
+
+typeset -i i=0
+while (( $i < ${#data_objs[*]} )); do
+ datasetexists ${data_objs[i]} || \
+ log_fail "Create <filesystem>|<volume>|<snapshot> fail."
+ ((i = i + 1))
+done
+
+i=0
+while (( $i < ${#data_objs[*]} )); do
+ destroy_dataset "${data_objs[i]}"
+ datasetexists ${data_objs[i]} && \
+ log_fail "'zfs destroy <filesystem>|<volume>|<snapshot>' fail."
+ ((i = i + 1))
+done
+
+log_pass "'zfs destroy <filesystem>|<volume>|<snapshot>' works as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_003_pos.ksh
new file mode 100755
index 000000000000..04e9713124b1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_003_pos.ksh
@@ -0,0 +1,156 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+
+#
+# DESCRIPTION:
+# Verify 'zfs destroy [-rR]' succeeds as root.
+#
+# STRATEGY:
+# 1. Create two datasets in the storage pool
+# 2. Create fs,vol,ctr,snapshot and clones of snapshot in the two datasets
+# 3. Create clone in the second dataset for the snapshot in the first dataset
+# 4. Verify 'zfs destroy -r' fails to destroy dataset with clone outside it
+# 5. Verify 'zfs destroy -R' succeeds to destroy dataset with clone outside it
+# 6. Verify 'zfs destroy -r' succeeds to destroy dataset without clone outside it.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for obj in $ctr2 $ctr1 $ctr; do
+ datasetexists $obj && \
+ log_must zfs destroy -Rf $obj
+ done
+
+ for mntp in $TESTDIR1 $TESTDIR2; do
+ [[ -d $mntp ]] && \
+ log_must rm -rf $mntp
+ done
+}
+
+log_assert "Verify that 'zfs destroy [-rR]' succeeds as root. "
+
+log_onexit cleanup
+
+#
+# Preparations for testing
+#
+for dir in $TESTDIR1 $TESTDIR2; do
+ [[ ! -d $dir ]] && \
+ log_must mkdir -p $dir
+done
+
+ctr=$TESTPOOL/$TESTCTR
+ctr1=$TESTPOOL/$TESTCTR1
+ctr2=$ctr/$TESTCTR2
+ctr3=$ctr1/$TESTCTR2
+child_fs=$ctr/$TESTFS1
+child_fs1=$ctr1/$TESTFS2
+child_fs_mntp=$TESTDIR1
+child_fs1_mntp=$TESTDIR2
+child_vol=$ctr/$TESTVOL
+child_vol1=$ctr1/$TESTVOL
+child_fs_snap=$child_fs@snap
+child_fs1_snap=$child_fs1@snap
+child_fs_snap_clone=$ctr/$TESTCLONE
+child_fs_snap_clone1=$ctr1/${TESTCLONE}_across_ctr
+child_fs_snap_clone2=$ctr2/$TESTCLONE2
+child_fs1_snap_clone=$ctr1/$TESTCLONE1
+child_fs1_snap_clone1=$ctr/${TESTCLONE1}_across_ctr
+
+#
+# Create two datasets in the storage pool
+#
+log_must zfs create $ctr
+log_must zfs create $ctr1
+
+#
+# Create children datasets fs,vol,snapshot in the datasets, and
+# clones across two datasets
+#
+log_must zfs create $ctr2
+
+for fs in $child_fs $child_fs1; do
+ log_must zfs create $fs
+done
+
+log_must zfs set mountpoint=$child_fs_mntp $child_fs
+log_must zfs set mountpoint=$child_fs1_mntp $child_fs1
+
+for snap in $child_fs_snap $child_fs1_snap; do
+ log_must zfs snapshot $snap
+done
+
+if is_global_zone ; then
+ for vol in $child_vol $child_vol1; do
+ log_must zfs create -V $VOLSIZE $vol
+ done
+fi
+
+for clone in $child_fs_snap_clone $child_fs_snap_clone1; do
+ log_must zfs clone $child_fs_snap $clone
+done
+
+
+for clone in $child_fs1_snap_clone $child_fs1_snap_clone1; do
+ log_must zfs clone $child_fs1_snap $clone
+done
+
+log_note "Verify that 'zfs destroy -r' fails to destroy dataset " \
+ "with dependent clone outside it."
+
+for obj in $child_fs $child_fs1 $ctr $ctr1; do
+ log_mustnot zfs destroy -r $obj
+ datasetexists $obj || \
+ log_fail "'zfs destroy -r' fails to keep dependent " \
+ "clone outside the hierarchy."
+done
+
+
+log_note "Verify that 'zfs destroy -R' succeeds to destroy dataset " \
+ "with dependent clone outside it."
+
+log_must zfs destroy -R $ctr1
+datasetexists $ctr1 && \
+ log_fail "'zfs destroy -R' fails to destroy dataset with clone outside it."
+
+log_note "Verify that 'zfs destroy -r' succeeds to destroy dataset " \
+ "without dependent clone outside it."
+
+log_must zfs destroy -r $ctr
+datasetexists $ctr && \
+ log_fail "'zfs destroy -r' fails to destroy dataset with clone outside it."
+
+log_pass "'zfs destroy [-rR] succeeds as root."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_004_pos.ksh
new file mode 100755
index 000000000000..3db1331ff57e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_004_pos.ksh
@@ -0,0 +1,126 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+
+#
+# DESCRIPTION:
+# Verify 'zfs destroy -f' succeeds as root.
+#
+# STRATEGY:
+# 1. Create filesystem in the storage pool
+# 2. Set mountpoint for the filesystem and make it busy
+# 3. Verify that 'zfs destroy' fails to destroy the filesystem
+# 4. Verify 'zfs destroy -f' succeeds to destroy the filesystem.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ cd $olddir
+
+ datasetexists $clone && \
+ log_must zfs destroy -f $clone
+
+ snapexists $snap && \
+ log_must zfs destroy -f $snap
+
+ for fs in $fs1 $fs2; do
+ datasetexists $fs && \
+ log_must zfs destroy -f $fs
+ done
+
+ for dir in $TESTDIR1 $TESTDIR2; do
+ [[ -d $dir ]] && \
+ log_must rm -rf $dir
+ done
+}
+
+log_assert "Verify that 'zfs destroy -f' succeeds as root. "
+
+log_onexit cleanup
+
+#
+# Preparations for testing
+#
+olddir=$PWD
+
+for dir in $TESTDIR1 $TESTDIR2; do
+ [[ ! -d $dir ]] && \
+ log_must mkdir -p $dir
+done
+
+fs1=$TESTPOOL/$TESTFS1
+mntp1=$TESTDIR1
+fs2=$TESTPOOL/$TESTFS2
+snap=$TESTPOOL/$TESTFS2@snap
+clone=$TESTPOOL/$TESTCLONE
+mntp2=$TESTDIR2
+
+#
+# Create filesystem and clone in the storage pool, mount them and
+# make the mountpoint busy
+#
+for fs in $fs1 $fs2; do
+ log_must zfs create $fs
+done
+
+log_must zfs snapshot $snap
+log_must zfs clone $snap $clone
+
+log_must zfs set mountpoint=$mntp1 $fs1
+log_must zfs set mountpoint=$mntp2 $clone
+
+for arg in "$fs1 $mntp1" "$clone $mntp2"; do
+ fs=`echo $arg | awk '{print $1}'`
+ mntp=`echo $arg | awk '{print $2}'`
+
+ log_note "Verify that 'zfs destroy' fails to" \
+ "destroy filesystem when it is busy."
+ cd $mntp
+ log_mustnot zfs destroy $fs
+
+ if is_linux; then
+ log_mustnot zfs destroy -f $fs
+ datasetnonexists $fs && \
+ log_fail "'zfs destroy -f' destroyed busy filesystem."
+ else
+ log_must zfs destroy -f $fs
+ datasetexists $fs && \
+ log_fail "'zfs destroy -f' fail to destroy busy filesystem."
+ fi
+
+ cd $olddir
+done
+
+log_pass "'zfs destroy -f' succeeds as root."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_005_neg.ksh
new file mode 100755
index 000000000000..1c5b2cf1c741
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_005_neg.ksh
@@ -0,0 +1,204 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+# Copyright (c) 2018 Datto Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
+
+#
+# DESCRIPTION:
+# Separately verify 'zfs destroy -f|-r|-rf|-R|-rR <dataset>' will fail in
+# different conditions.
+#
+# STRATEGY:
+# 1. Create pool, fs & vol.
+# 2. Create snapshot for fs & vol.
+# 3. Invoke 'zfs destroy ''|-f <dataset>', it should fail.
+# 4. Create clone for fs & vol.
+# 5. Invoke 'zfs destroy -r|-rf <dataset>', it should fail.
+# 6. Write file to filesystem or enter snapshot mountpoint.
+# 7. Invoke 'zfs destroy -R|-rR <dataset>', it should fail.
+#
+
+verify_runnable "both"
+
+log_assert "Separately verify 'zfs destroy -f|-r|-rf|-R|-rR <dataset>' will " \
+ "fail in different conditions."
+log_onexit cleanup_testenv
+
+#
+# Run 'zfs destroy [-rRf] <dataset>', make sure it fail.
+#
+# $1 the collection of options
+# $2 the collection of datasets
+#
+function negative_test
+{
+ typeset options=$1
+ typeset datasets=$2
+
+ for dtst in $datasets; do
+ if ! is_global_zone; then
+ if [[ $dtst == $VOL || $dtst == $VOLSNAP || \
+ $dtst == $VOLCLONE ]]
+ then
+ log_note "UNSUPPORTED: " \
+ "Volume is unavailable in LZ."
+ continue
+ fi
+ fi
+ for opt in $options; do
+ log_mustnot zfs destroy $opt $dtst
+ done
+ done
+}
+
+#
+# Create snapshots for filesystem and volume,
+# and verify 'zfs destroy' fails without '-r' or '-R'.
+#
+setup_testenv snap
+negative_test "-f" "$CTR $FS $VOL"
+
+#
+# Create clones for filesystem and volume,
+# and verify 'zfs destroy' fails without '-R'.
+#
+setup_testenv clone
+negative_test "-r -rf" "$CTR $FS $VOL"
+
+#
+# Get $FS mountpoint and make it busy, and verify 'zfs destroy $CTR' fails
+# without '-f'. Then verify the remaining datasets are correct. See below for
+# an explanation of what 'correct' means for this test.
+#
+mntpt=$(get_prop mountpoint $FS)
+pidlist=$(mkbusy $mntpt/$TESTFILE0)
+log_note "mkbusy $mntpt/$TESTFILE0 (pidlist: $pidlist)"
+[[ -z $pidlist ]] && log_fail "Failure from mkbusy"
+negative_test "-R -rR" $CTR
+
+# The following busy datasets will still exist
+check_dataset datasetexists $CTR $FS $VOL
+
+# The following datasets will not exist because of best-effort recursive destroy
+if datasetexists $VOLSNAP || datasetexists $FSSNAP; then
+ log_must zfs list -rtall
+ log_fail "Unexpected datasets remaining"
+fi
+
+#
+# Create the clones for test environment, and verify 'zfs destroy $FS' fails
+# without '-f'. Then verify the FS snap and clone are the only datasets
+# that were removed.
+#
+setup_testenv clone
+negative_test "-R -rR" $FS
+check_dataset datasetexists $CTR $FS $VOL $VOLSNAP $VOLCLONE
+check_dataset datasetnonexists $FSSNAP $FSCLONE
+
+log_must kill $pidlist
+log_mustnot pgrep -fl mkbusy
+pidlist=""
+
+#
+# Create the clones for test environment and make the volume busy.
+# Then verify 'zfs destroy $CTR' fails without '-f'.
+#
+# Then verify the expected datasets exist (see below).
+#
+if is_global_zone; then
+ setup_testenv clone
+ pidlist=$(mkbusy $TESTDIR1/$TESTFILE0)
+ log_note "mkbusy $TESTDIR1/$TESTFILE0 (pidlist: $pidlist)"
+ [[ -z $pidlist ]] && log_fail "Failure from mkbusy"
+ negative_test "-R -rR" $CTR
+ check_dataset datasetexists $CTR $VOL
+ check_dataset datasetnonexists $VOLSNAP $VOLCLONE
+
+ # Due to recursive destroy being a best-effort operation,
+ # all of the non-busy datasets below should be gone now.
+ check_dataset datasetnonexists $FS $FSSNAP $FSCLONE
+fi
+
+#
+# Create the clones for test environment and make the volume busy.
+# Then verify 'zfs destroy $VOL' fails without '-f'.
+#
+# Then verify the snapshot and clone are destroyed, but nothing else is.
+#
+if is_global_zone; then
+ setup_testenv clone
+ negative_test "-R -rR" $VOL
+ check_dataset datasetexists $CTR $VOL $FS $FSSNAP $FSCLONE
+ check_dataset datasetnonexists $VOLSNAP $VOLCLONE
+fi
+
+log_must kill $pidlist
+log_mustnot pgrep -fl mkbusy
+pidlist=""
+
+#
+# Create the clones for test environment and make the snapshot busy.
+#
+# For Linux verify 'zfs destroy $snap' fails due to the busy mount point. Then
+# verify the snapshot remains and the clone was destroyed, but nothing else is.
+#
+# Under illumos verify 'zfs destroy $snap' succeeds without '-f'. Then verify
+# the snapshot and clone are destroyed, but nothing else is.
+#
+
+mntpt=$(snapshot_mountpoint $FSSNAP)
+pidlist=$(mkbusy $mntpt)
+log_note "mkbusy $mntpt (pidlist: $pidlist)"
+[[ -z $pidlist ]] && log_fail "Failure from mkbusy"
+
+for option in -R -rR ; do
+ setup_testenv clone
+
+ if is_linux; then
+ log_mustnot zfs destroy $option $FSSNAP
+ check_dataset datasetexists $CTR $FS $VOL $FSSNAP
+ check_dataset datasetnonexists $FSCLONE
+ else
+ log_must zfs destroy $option $FSSNAP
+ check_dataset datasetexists $CTR $FS $VOL
+ check_dataset datasetnonexists $FSSNAP $FSCLONE
+ fi
+done
+
+log_must kill $pidlist
+log_mustnot pgrep -fl mkbusy
+pidlist=""
+
+log_pass "zfs destroy -f|-r|-rf|-R|-rR <dataset>' failed in different " \
+ "condition passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_006_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_006_neg.ksh
new file mode 100755
index 000000000000..7dbcb242041d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_006_neg.ksh
@@ -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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+
+#
+# DESCRIPTION:
+# 'zfs destroy' should return an error with badly formed parameters,
+# including null destroyed object parameter, invalid options excluding
+# '-r' and '-f', non-existent datasets.
+#
+# STRATEGY:
+# 1. Create an array of parameters
+# 2. For each parameter in the array, execute 'zfs destroy'
+# 3. Verify an error is returned.
+#
+
+verify_runnable "both"
+
+
+set -A args "" "-r" "-f" "-rf" "-fr" "$TESTPOOL" "-f $TESTPOOL" \
+ "-? $TESTPOOL/$TESTFS" "$TESTPOOL/blah"\
+ "-r $TESTPOOL/blah" "-f $TESTPOOL/blah" "-rf $TESTPOOL/blah" \
+ "-fr $TESTPOOL/blah" "-$ $TESTPOOL/$TESTFS" "-5 $TESTPOOL/$TESTFS" \
+ "-rfgh $TESTPOOL/$TESTFS" "-rghf $TESTPOOL/$TESTFS" \
+ "$TESTPOOL/$TESTFS@blah" "/$TESTPOOL/$TESTFS" "-f /$TESTPOOL/$TESTFS" \
+ "-rf /$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTFS $TESTPOOL/$TESTFS" \
+ "-rRf $TESTPOOL/$TESTFS $TESTPOOL/$TESTFS"
+
+log_assert "'zfs destroy' should return an error with badly-formed parameters."
+
+typeset -i i=0
+while (( $i < ${#args[*]} )); do
+ log_mustnot zfs destroy ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "'zfs destroy' badly formed parameters fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_007_neg.ksh
new file mode 100755
index 000000000000..70ad45af0488
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_007_neg.ksh
@@ -0,0 +1,76 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+
+#
+# DESCRIPTION:
+# 'zpool destroy' failed if this filesystem is namespace-parent
+# of origin.
+#
+# STRATEGY:
+# 1. Create pool, fs and snapshot.
+# 2. Create a namespace-parent of origin clone.
+# 3. Promote this clone
+# 4. Verify the original fs can not be destroyed.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $clonesnap; then
+ log_must zfs promote $fs
+ fi
+ datasetexists $clone && log_must zfs destroy $clone
+ datasetexists $fssnap && log_must zfs destroy $fssnap
+}
+
+log_assert "Destroy dataset which is namespace-parent of origin should failed."
+log_onexit cleanup
+
+# Define variable $fssnap & and namespace-parent of origin clone.
+fs=$TESTPOOL/$TESTFS
+fssnap=$fs@snap
+clone=$fs/clone
+clonesnap=$fs/clone@snap
+
+# Define key word for expected failure.
+KEY_WORDS="filesystem has children"
+
+log_must zfs snapshot $fssnap
+log_must zfs clone $fssnap $clone
+log_must zfs promote $clone
+log_mustnot_expect "$KEY_WORDS" zfs destroy $fs
+log_mustnot_expect "$KEY_WORDS" zfs destroy $clone
+
+log_pass "Destroy dataset which is namespace-parent of origin passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_008_pos.ksh
new file mode 100755
index 000000000000..f8b8f9005514
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_008_pos.ksh
@@ -0,0 +1,64 @@
+#!/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) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
+
+################################################################################
+#
+# 'zfs destroy -d <snap>' should destroy the snapshot when no clone exists.
+#
+# 1. Create test environment without clones.
+# 2. 'zfs destroy -d <snap>'
+# 3. Verify that the snapshot was destroyed.
+#
+################################################################################
+
+function test_s_run
+{
+ typeset snap=$1
+
+ log_must zfs destroy -d $snap
+ log_mustnot datasetexists $snap
+}
+
+log_assert "'zfs destroy -d <snap>' destroys snapshot if there is no clone"
+log_onexit cleanup_testenv
+
+setup_testenv snap
+
+for snap in $FSSNAP $VOLSNAP; do
+ if [[ $snap == $VOLSNAP ]]; then
+ if is_global_zone; then
+ test_s_run $snap
+ fi
+ else
+ test_s_run $snap
+ fi
+done
+
+log_pass "'zfs destroy -d <snap>' destroys snapshot if there is no clone"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_009_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_009_pos.ksh
new file mode 100755
index 000000000000..57e5761bc064
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_009_pos.ksh
@@ -0,0 +1,73 @@
+#!/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) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
+
+################################################################################
+#
+# 'zfs destroy -d <snap>' should mark snapshot for deferred destroy when
+# clone exists and destroy when clone is destroyed.
+#
+# 1. Create test environment with clones.
+# 2. 'zfs destroy -d <snap>'
+# 3. Verify snapshot is marked for deferred destroy.
+# 4. 'zfs destroy <clone>'
+# 3. Verify that the snapshot and clone are destroyed.
+#
+################################################################################
+
+function test_c_run
+{
+ typeset dstype=$1
+
+ snap=$(eval echo \$${dstype}SNAP)
+ clone=$(eval echo \$${dstype}CLONE)
+ log_must zfs destroy -d $snap
+ log_must datasetexists $snap
+ log_must eval "[[ $(get_prop defer_destroy $snap) == 'on' ]]"
+ log_must zfs destroy $clone
+ log_mustnot datasetexists $snap
+ log_mustnot datasetexists $clone
+}
+
+log_assert "'zfs destroy -d <snap>' marks cloned snapshot for deferred destroy"
+log_onexit cleanup_testenv
+
+setup_testenv clone
+
+for dstype in FS VOL; do
+ if [[ $dstype == VOL ]]; then
+ if is_global_zone; then
+ test_c_run $dstype
+ fi
+ else
+ test_c_run $dstype
+ fi
+done
+
+log_pass "'zfs destroy -d <snap>' marks cloned snapshot for deferred destroy"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_010_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_010_pos.ksh
new file mode 100755
index 000000000000..369029775f4b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_010_pos.ksh
@@ -0,0 +1,77 @@
+#!/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) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
+
+################################################################################
+#
+# When using 'zfs destroy -R' on a file system hierarchy that includes a
+# snapshot and a clone of that snapshot, and the snapshot has been
+# defer-destroyed, make sure that the 'zfs destroy -R' works as expected.
+# In particular make sure that libzfs is not confused by the fact that the
+# kernel will automatically remove the defer-destroyed snapshot when the
+# clone is destroyed.
+#
+# 1. Create test environment.
+# 2. Create a clone of the snapshot.
+# 3. 'zfs destroy -d <snap>'
+# 4. 'zfs destroy -R'
+# 5. Verify that the snapshot and clone are destroyed.
+#
+################################################################################
+
+function test_clone_run
+{
+ typeset dstype=$1
+
+ ds=$(eval echo \$${dstype})
+ snap=$(eval echo \$${dstype}SNAP)
+ clone=$(eval echo \$${dstype}CLONE)
+ log_must zfs destroy -d $snap
+ log_must datasetexists $snap
+ log_must_busy zfs destroy -R $clone
+ log_mustnot datasetexists $snap
+ log_mustnot datasetexists $clone
+}
+
+log_assert "'zfs destroy -R' works on deferred destroyed snapshots"
+log_onexit cleanup_testenv
+
+setup_testenv clone
+
+for dstype in FS VOL; do
+ if [[ $dstype == VOL ]]; then
+ if is_global_zone; then
+ test_clone_run $dstype
+ fi
+ else
+ test_clone_run $dstype
+ fi
+done
+
+log_pass "'zfs destroy -R' works on deferred destroyed snapshots"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_011_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_011_pos.ksh
new file mode 100755
index 000000000000..634bfc20c167
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_011_pos.ksh
@@ -0,0 +1,63 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
+
+################################################################################
+#
+# 'zfs destroy -d <snap>' should mark snapshot for deferred destroy when
+# there is a user hold.
+#
+# 1. Create test environment without clones.
+# 2. 'zfs hold <tag> <snap>'
+# 3. 'zfs destroy -d <snap>'
+# 4. Verify snapshot is marked for deferred destroy.
+# 5. 'zfs release <tag> <snap>'
+# 6. Verify that the snapshot is destroyed.
+#
+################################################################################
+
+function test_snap_run
+{
+ typeset dstype=$1
+
+ snap=$(eval echo \$${dstype}SNAP)
+ log_must zfs hold zfstest $snap
+ log_must zfs destroy -d $snap
+ log_must datasetexists $snap
+ log_must eval "[[ $(get_prop defer_destroy $snap) == 'on' ]]"
+ log_must zfs release zfstest $snap
+ log_mustnot datasetexists $snap
+}
+
+log_assert "'zfs destroy -d <snap>' marks held snapshot for deferred destroy"
+log_onexit cleanup_testenv
+
+setup_testenv snap
+
+for dstype in FS VOL; do
+ if [[ $dstype == VOL ]]; then
+ if is_global_zone; then
+ test_snap_run $dstype
+ fi
+ else
+ test_snap_run $dstype
+ fi
+done
+
+log_pass "'zfs destroy -d <snap>' marks held snapshot for deferred destroy"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_012_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_012_pos.ksh
new file mode 100755
index 000000000000..d4b64cf4cf14
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_012_pos.ksh
@@ -0,0 +1,75 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
+
+################################################################################
+#
+# Deferred destroyed snapshots remain until the last hold is released.
+#
+# 1. Create test environment without clones.
+# 2. 'zfs hold <tag1> <snap>'
+# 3. 'zfs destroy -d <snap>'
+# 4. Sequence of holds/releases including invalid ones that should fail.
+# 4. Verify snapshot still exists.
+# 5. Release all holds.
+# 6. Verify that the snapshot is destroyed.
+#
+################################################################################
+
+function test_snap_run
+{
+ typeset dstype=$1
+
+ snap=$(eval echo \$${dstype}SNAP)
+ log_must zfs hold zfstest1 $snap
+ log_must zfs destroy -d $snap
+ log_must datasetexists $snap
+ log_must eval "[[ $(get_prop defer_destroy $snap) == 'on' ]]"
+
+ log_must zfs hold zfstest2 $snap
+ log_mustnot zfs hold zfstest1 $snap
+ log_mustnot zfs hold zfstest2 $snap
+
+ log_must zfs release zfstest1 $snap
+ log_must datasetexists $snap
+ log_mustnot zfs release zfstest1 $snap
+ log_must datasetexists $snap
+ log_mustnot zfs release zfstest3 $snap
+ log_must datasetexists $snap
+
+ log_must zfs release zfstest2 $snap
+ log_mustnot datasetexists $snap
+}
+
+log_assert "deferred destroyed snapshots remain until last hold is released"
+log_onexit cleanup_testenv
+
+setup_testenv snap
+
+for dstype in FS VOL; do
+ if [[ $dstype == VOL ]]; then
+ if is_global_zone; then
+ test_snap_run $dstype
+ fi
+ else
+ test_snap_run $dstype
+ fi
+done
+
+log_pass "deferred destroyed snapshots remain until last hold is released"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_013_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_013_neg.ksh
new file mode 100755
index 000000000000..406c9d43fff9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_013_neg.ksh
@@ -0,0 +1,62 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
+
+################################################################################
+#
+# Destroy of held snapshot should fail.
+#
+# 1. Create test environment without clones.
+# 2. 'zfs hold <tag> <snap>'
+# 3. 'zfs destroy <snap>' should fail.
+# 4. Verify snapshot still exists.
+# 5. 'zfs release <tag> <snap>'
+# 6. Verify that we can destroy the snapshot.
+#
+################################################################################
+
+function test_snap_run
+{
+ typeset dstype=$1
+
+ snap=$(eval echo \$${dstype}SNAP)
+ log_must zfs hold zfstest $snap
+ log_mustnot zfs destroy $snap
+ log_must datasetexists $snap
+ log_must zfs release zfstest $snap
+ log_must zfs destroy $snap
+ log_mustnot datasetexists $snap
+}
+
+log_assert "zfs destroy of held snapshots fails"
+log_onexit cleanup_testenv
+
+setup_testenv snap
+
+for dstype in FS VOL; do
+ if [[ $dstype == VOL ]]; then
+ if is_global_zone; then
+ test_snap_run $dstype
+ fi
+ else
+ test_snap_run $dstype
+ fi
+done
+
+log_pass "zfs destroy of held snapshots fails"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_014_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_014_pos.ksh
new file mode 100755
index 000000000000..58c4cfb5646d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_014_pos.ksh
@@ -0,0 +1,79 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+
+#
+# DESCRIPTION:
+# 'zfs destroy -R <snapshot>' can destroy all the child
+# snapshots and preserves all the nested datasets.
+#
+# STRATEGY:
+# 1. Create nested datasets in the storage pool.
+# 2. Create recursive snapshots for all the nested datasets.
+# 3. Verify when snapshots are destroyed recursively, all
+# the nested datasets still exist.
+#
+
+verify_runnable "both"
+
+log_assert "Verify 'zfs destroy -R <snapshot>' does not destroy" \
+ "nested datasets."
+log_onexit cleanup
+
+datasets="$TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS1/$TESTFS2
+ $TESTPOOL/$TESTFS1/$TESTFS2/$TESTFS3"
+
+function cleanup
+{
+ for ds in $datasets; do
+ datasetexists $ds && zfs destroy -rf $ds
+ done
+}
+
+# create nested datasets
+log_must zfs create -p $TESTPOOL/$TESTFS1/$TESTFS2/$TESTFS3
+
+# verify dataset creation
+for ds in $datasets; do
+ datasetexists $ds || log_fail "Create $ds dataset fail."
+done
+
+# create recursive nested snapshot
+log_must zfs snapshot -r $TESTPOOL/$TESTFS1@snap
+for ds in $datasets; do
+ datasetexists $ds@snap || log_fail "Create $ds@snap snapshot fail."
+done
+
+# destroy nested snapshot recursively
+log_must zfs destroy -R $TESTPOOL/$TESTFS1@snap
+
+# verify snapshot destroy
+for ds in $datasets; do
+ datasetexists $ds@snap && log_fail "$ds@snap exists. Destroy failed!"
+done
+
+# verify nested datasets still exist
+for ds in $datasets; do
+ datasetexists $ds || log_fail "Recursive snapshot destroy deleted $ds"
+done
+
+log_pass "'zfs destroy -R <snapshot>' works as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_015_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_015_pos.ksh
new file mode 100755
index 000000000000..f399ad270634
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_015_pos.ksh
@@ -0,0 +1,161 @@
+#!/bin/ksh
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+# DESCRIPTION
+# zfs destroy <dataset@snap1,snap2..> can destroy a list of multiple
+# snapshots from the same datasets
+#
+# STRATEGY
+# 1. Create multiple snapshots for the same datset
+# 2. Run zfs destroy for these snapshots for a mix of valid and
+# invalid snapshot names
+# 3. Run zfs destroy for snapshots from different datasets and
+# pools
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && zfs destroy -R $TESTPOOL/$TESTFS1
+ datasetexists $TESTPOOL/$TESTFS2 && zfs destroy -R $TESTPOOL/$TESTFS2
+ poolexists $TESTPOOL2 && zpool destroy $TESTPOOL2
+ rm -rf $VIRTUAL_DISK
+}
+
+log_assert "zfs destroy for multiple snapshot is handled correctly"
+log_onexit cleanup
+
+zfs create $TESTPOOL/$TESTFS1
+typeset -i i=1
+snaplist=""
+log_note "zfs destroy on valid snapshot names"
+for i in 1 2 3 4 5; do
+ log_must zfs snapshot $TESTPOOL/$TESTFS1@snap$i
+ snaplist=$snaplist,snap$i
+done
+snaplist=${snaplist#,}
+log_must zfs destroy $TESTPOOL/$TESTFS1@$snaplist
+for i in 1 2 3 4 5; do
+ log_mustnot snapexists $TESTPOOL/$TESFS1@snap$i
+done
+
+log_note "zfs destroy with all bogus snapshot names"
+log_mustnot zfs destroy $TESTPOOL/$TESTFS1@snap12,snap21,sna@pple1@,s""nappy2
+
+log_note "zfs destroy with some bogus snapshot names"
+for i in 1 2 3; do
+ log_must zfs snapshot $TESTPOOL/$TESTFS1@snap$i
+done
+log_must zfs destroy $TESTPOOL/$TESTFS1@snap1,snap2,snapple1,snappy2,snap3
+for i in 1 2 3; do
+ log_mustnot snapexists $TESTPOOL/$TESTFS1@snap$i
+done
+
+log_note "zfs destroy with some snapshot names having special characters"
+for i in 1 2 3; do
+ log_must zfs snapshot $TESTPOOL/$TESTFS1@snap$i
+done
+log_must zfs destroy $TESTPOOL/$TESTFS1@snap1,@,snap2,,,,snap3,
+for i in 1 2 3; do
+ log_mustnot snapexists $TESTPOOL/$TESTFS1@snap$i
+done
+log_note "zfs destroy for too many snapshots"
+snaplist=""
+for i in {1..100}; do
+ log_must zfs snapshot $TESTPOOL/$TESTFS1@snap$i
+ snaplist=$snaplist,snap$i
+done
+snaplist=${snaplist#,}
+log_must zfs destroy $TESTPOOL/$TESTFS1@$snaplist
+for i in {1..100}; do
+ log_mustnot snapexists $TESTPOOL/$TESTFS1@snap$i
+done
+log_note "zfs destroy multiple snapshots with hold"
+snaplist=""
+for i in 1 2 3 4 5; do
+ log_must zfs snapshot $TESTPOOL/$TESTFS1@snap$i
+ log_must zfs hold keep $TESTPOOL/$TESTFS1@snap$i
+ snaplist=$snaplist,snap$i
+done
+snaplist=${snaplist#,}
+log_mustnot zfs destroy $TESTPOOL/$TESTFS1@$snaplist
+for i in 1 2 3 4 5; do
+ log_must zfs release keep $TESTPOOL/$TESTFS1@snap$i
+done
+log_must zfs destroy $TESTPOOL/$TESTFS1@$snaplist
+
+log_note "zfs destroy for multiple snapshots having clones"
+for i in 1 2 3 4 5; do
+ log_must zfs snapshot $TESTPOOL/$TESTFS1@snap$i
+done
+snaplist=""
+for i in 1 2 3 4 5; do
+ log_must zfs clone $TESTPOOL/$TESTFS1@snap$i $TESTPOOL/$TESTFS1/clone$i
+ snaplist=$snaplist,snap$i
+done
+snaplist=${snaplist#,}
+log_mustnot zfs destroy $TESTPOOL/$TESTFS1@$snaplist
+for i in 1 2 3 4 5; do
+ log_must snapexists $TESTPOOL/$TESTFS1@snap$i
+ log_must zfs destroy $TESTPOOL/$TESTFS1/clone$i
+done
+
+log_note "zfs destroy for snapshots for different datasets"
+log_must zfs create $TESTPOOL/$TESTFS2
+log_must zfs snapshot $TESTPOOL/$TESTFS2@fs2snap
+log_must zfs create $TESTPOOL/$TESTFS1/$TESTFS2
+log_must zfs snapshot $TESTPOOL/$TESTFS1/$TESTFS2@fs12snap
+
+long_arg=$TESTPOOL/$TESTFS1@snap1,$TESTPOOL/$TESTFS2@fs2snap,
+long_arg=$long_arg$TESTPOOL/$TESTFS1/$TESTFS2@fs12snap
+log_must zfs destroy $long_arg
+log_mustnot snapexists $TESTPOOL/$TESTFS1@snap1
+log_must snapexists $TESTPOOL/$TESTFS2@fs2snap
+log_must snapexists $TESTPOOL/$TESTFS1/$TESTFS2@fs12snap
+
+log_must zfs destroy $TESTPOOL/$TESTFS1@fs2snap,fs12snap,snap2
+log_must snapexists $TESTPOOL/$TESTFS2@fs2snap
+log_must snapexists $TESTPOOL/$TESTFS1/$TESTFS2@fs12snap
+log_mustnot snapexists $TESTPOOL/$TESTFS1@snap2
+
+log_must zfs destroy $TESTPOOL/$TESTFS2@fs2snap,fs12snap,snap3
+log_mustnot snapexists $TESTPOOL/$TESTFS2@fs2snap
+log_must snapexists $TESTPOOL/$TESTFS1/$TESTFS2@fs12snap
+log_must snapexists $TESTPOOL/$TESTFS1@snap3
+
+log_note "zfs destroy for snapshots from different pools"
+VIRTUAL_DISK=$TEST_BASE_DIR/disk
+log_must mkfile $MINVDEVSIZE $VIRTUAL_DISK
+log_must zpool create $TESTPOOL2 $VIRTUAL_DISK
+log_must poolexists $TESTPOOL2
+
+log_must zfs create $TESTPOOL2/$TESTFS1
+log_must zfs snapshot $TESTPOOL2/$TESTFS1@snap
+long_arg=$TESTPOOL2/$TESTFS1@snap,$TESTPOOL/$TESTFS1@snap3,
+long_arg=$long_arg$TESTPOOL/$TESTFS1@snap5
+log_must zfs destroy $long_arg
+log_mustnot snapexists $TESTPOOL2/$TESTFS1@snap
+log_must snapexists $TESTPOOL/$TESTFS1@snap3
+log_must snapexists $TESTPOOL/$TESTFS1@snap5
+
+log_must zfs snapshot $TESTPOOL2/$TESTFS1@snap
+log_must zfs destroy $TESTPOOL2/$TESTFS1@snap5,snap3,snap
+log_mustnot snapexists $TESTPOOL2/$TESTFS1@snap
+log_must snapexists $TESTPOOL/$TESTFS1@snap3
+log_must snapexists $TESTPOOL/$TESTFS1@snap5
+
+log_pass "zfs destroy for multiple snapshots passes"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_016_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_016_pos.ksh
new file mode 100755
index 000000000000..1e129ddd3bc9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_016_pos.ksh
@@ -0,0 +1,186 @@
+#!/bin/ksh
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+# DESCRIPTION
+# Verify zfs destroy test for range of snapshots by giving a list
+# of valid and invalid arguments.
+
+# STRATEGY
+# 1. Create a list of valid and invalid arguments for range snapshot
+# destroy.
+# 2. Set up a filesystem and a volume with multiple snapshots
+# 3. Run zfs destroy for all the arguments and verify existence of snapshots
+# 4. Verify the destroy for snapshots with clones and hold
+
+. $STF_SUITE/include/libtest.shlib
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -R $TESTPOOL/$TESTFS1
+ datasetexists $TESTPOOL/$TESTVOL && \
+ log_must zfs destroy -Rf $TESTPOOL/$TESTVOL
+}
+
+function setup_snapshots
+{
+ for i in $snaps; do
+ datasetexists $TESTPOOL/$TESTFS1@snap$i && \
+ log_must zfs destroy $TESTPOOL/$TESTFS1@snap$i
+ datasetexists $TESTPOOL/$TESTVOL@snap$i && \
+ log_must zfs destroy $TESTPOOL/$TESTVOL@snap$i
+ log_must zfs snapshot $TESTPOOL/$TESTFS1@snap$i
+ log_must zfs snapshot $TESTPOOL/$TESTVOL@snap$i
+ done
+}
+
+function verify_snapshots
+{
+ typeset snap_exists=${1:-0}
+ if [[ $snap_exists == 1 ]]; then
+ for i in $range; do
+ snapexists $TESTPOOL/$TESTFS1@snap$i || \
+ log_fail "zfs destroy should not have destroyed" \
+ "$TESTPOOL/$TESTFS1@snap$i"
+ snapexists $TESTPOOL/$TESTVOL@snap$i || \
+ log_fail "zfs destroy should not have destroyed" \
+ "$TESTPOOL/$TESTVOL@snap$i"
+ done
+ else
+ for i in $range; do
+ snapexists $TESTPOOL/$TESTFS1@snap$i && \
+ log_fail "zfs destroy should have destroyed" \
+ "$TESTPOOL/$TESTFS1@snap$i"
+ snapexists $TESTPOOL/$TESTVOL@snap$i && \
+ log_fail "zfs destroy should have destroyed" \
+ "$TESTPOOL/$TESTVOL@snap$i"
+ done
+ fi
+}
+
+invalid_args="@snap0%snap5 @snap1%snap6 @snap0%snap6 @snap5%snap1 \
+ @snap1%$TESTPOOL/$TESTFS1@snap5 @snap1%%snap5 @snap1%@snap5 \
+ @@snap1%snap5 snap1%snap5 snap1%snap3%snap5"
+valid_args="@snap1%snap5 @%"
+log_assert "zfs destroy deletes ranges of snapshots"
+log_onexit cleanup
+
+log_must zfs create $TESTPOOL/$TESTFS1
+log_must zfs create -V $VOLSIZE $TESTPOOL/$TESTVOL
+snaps="1 2 3 4 5"
+log_note "Verify the valid arguments"
+range="1 2 3 4 5"
+for args in $valid_args; do
+ setup_snapshots
+ log_must zfs destroy $TESTPOOL/$TESTFS1$args
+ log_must zfs destroy $TESTPOOL/$TESTVOL$args
+ verify_snapshots
+done
+
+log_note "Verify invalid arguments"
+setup_snapshots
+for args in $invalid_args; do
+ log_mustnot zfs destroy $TESTPOOL/$TESTFS1$args
+ log_mustnot zfs destroy $TESTPOOL/$TESTVOL$args
+ log_must verify_snapshots 1
+done
+
+log_note "Destroy the beginning range"
+
+log_must zfs destroy $TESTPOOL/$TESTFS1@%snap3
+log_must zfs destroy $TESTPOOL/$TESTVOL@%snap3
+range="1 2 3"
+verify_snapshots
+range="4 5"
+verify_snapshots 1
+
+setup_snapshots
+log_note "Destroy the mid range"
+log_must zfs destroy $TESTPOOL/$TESTFS1@snap2%snap4
+log_must zfs destroy $TESTPOOL/$TESTVOL@snap2%snap4
+range="2 3 4"
+verify_snapshots
+log_must zfs destroy $TESTPOOL/$TESTFS1@snap1%snap5
+log_must zfs destroy $TESTPOOL/$TESTVOL@snap1%snap5
+range="1 5"
+verify_snapshots
+
+setup_snapshots
+log_note "Destroy the end range"
+log_must zfs destroy $TESTPOOL/$TESTFS1@snap3%
+log_must zfs destroy $TESTPOOL/$TESTVOL@snap3%
+range="1 2"
+verify_snapshots 1
+range="3 4 5"
+verify_snapshots
+
+setup_snapshots
+log_note "Destroy a simple list"
+log_must zfs destroy $TESTPOOL/$TESTFS1@snap2,snap4
+log_must zfs destroy $TESTPOOL/$TESTVOL@snap2,snap4
+range="2 4"
+verify_snapshots
+range="1 3 5"
+verify_snapshots 1
+
+setup_snapshots
+log_note "Destroy a list and range together"
+log_must zfs destroy $TESTPOOL/$TESTFS1@snap1%snap3,snap5
+log_must zfs destroy $TESTPOOL/$TESTVOL@snap1%snap3,snap5
+range="1 2 3 5"
+verify_snapshots
+range=4
+verify_snapshots 1
+
+snaps="1 2 3 5 6 7 8 9 10"
+setup_snapshots
+log_note "Destroy a list of ranges"
+log_must zfs destroy $TESTPOOL/$TESTFS1@snap1%snap3,snap5
+log_must zfs destroy $TESTPOOL/$TESTVOL@snap1%snap3,snap5
+range="1 2 3 5"
+verify_snapshots
+range=4
+verify_snapshots 1
+
+snaps="1 2 3 4 5"
+setup_snapshots
+log_note "Snapshot destroy with hold"
+range="1 2 3 4 5"
+for i in 1 2 3 4 5; do
+ log_must zfs hold keep $TESTPOOL/$TESTFS1@snap$i
+ log_must zfs hold keep $TESTPOOL/$TESTVOL@snap$i
+done
+log_mustnot zfs destroy $TESTPOOL/$TESTFS1@snap1%snap5
+log_mustnot zfs destroy $TESTPOOL/$TESTVOL@snap1%snap5
+verify_snapshots 1
+for i in 1 2 3 4 5; do
+ log_must zfs release keep $TESTPOOL/$TESTFS1@snap$i
+ log_must zfs release keep $TESTPOOL/$TESTVOL@snap$i
+done
+log_must zfs destroy $TESTPOOL/$TESTFS1@snap1%snap5
+log_must zfs destroy $TESTPOOL/$TESTVOL@snap1%snap5
+verify_snapshots
+
+log_note "Range destroy for snapshots having clones"
+setup_snapshots
+for i in 1 2 3 4 5; do
+ log_must zfs clone $TESTPOOL/$TESTFS1@snap$i $TESTPOOL/$TESTFS1/clone$i
+done
+log_must zfs destroy -R $TESTPOOL/$TESTFS1@snap1%snap5
+log_must zfs destroy $TESTPOOL/$TESTVOL@snap1%snap5
+verify_snapshots
+
+log_pass "'zfs destroy' successfully destroys ranges of snapshots"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_clone_livelist.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_clone_livelist.ksh
new file mode 100755
index 000000000000..2da58ec96cac
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_clone_livelist.ksh
@@ -0,0 +1,164 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018, 2020 by Delphix. All rights reserved.
+#
+
+# DESCRIPTION
+# Verify zfs destroy test for clones with the livelist feature
+# enabled.
+
+# STRATEGY
+# 1. One clone with an empty livelist
+# - create the clone, check that livelist exists
+# - delete the clone, check that livelist is eventually
+# destroyed
+# 2. One clone with populated livelist
+# - create the clone, check that livelist exists
+# - write multiple files to the clone
+# - delete the clone, check that livelist is eventually
+# destroyed
+# 3. Multiple clones with empty livelists
+# - same as 1. but with multiple clones
+# 4. Multiple clones with populated livelists
+# - same as 2. but with multiple clones
+# 5. Clone of clone with populated livelists with promote
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && zfs destroy -R $TESTPOOL/$TESTFS1
+ # reset the livelist sublist size to its original value
+ set_tunable64 LIVELIST_MAX_ENTRIES $ORIGINAL_MAX
+}
+
+function clone_write_file
+{
+ log_must mkfile 1m /$TESTPOOL/$1/$2
+ log_must zpool sync $TESTPOOL
+}
+
+function test_one_empty
+{
+ clone_dataset $TESTFS1 snap $TESTCLONE
+
+ log_must zfs destroy $TESTPOOL/$TESTCLONE
+ check_livelist_gone
+}
+
+function test_one
+{
+ clone_dataset $TESTFS1 snap $TESTCLONE
+
+ clone_write_file $TESTCLONE $TESTFILE0
+ clone_write_file $TESTCLONE $TESTFILE1
+ clone_write_file $TESTCLONE $TESTFILE2
+ log_must rm /$TESTPOOL/$TESTCLONE/$TESTFILE0
+ log_must rm /$TESTPOOL/$TESTCLONE/$TESTFILE2
+ check_livelist_exists $TESTCLONE
+
+ log_must zfs destroy $TESTPOOL/$TESTCLONE
+ check_livelist_gone
+}
+
+function test_multiple_empty
+{
+ clone_dataset $TESTFS1 snap $TESTCLONE
+ clone_dataset $TESTFS1 snap $TESTCLONE1
+ clone_dataset $TESTFS1 snap $TESTCLONE2
+
+ log_must zfs destroy $TESTPOOL/$TESTCLONE
+ log_must zfs destroy $TESTPOOL/$TESTCLONE1
+ log_must zfs destroy $TESTPOOL/$TESTCLONE2
+ check_livelist_gone
+}
+
+function test_multiple
+{
+ clone_dataset $TESTFS1 snap $TESTCLONE
+ clone_dataset $TESTFS1 snap $TESTCLONE1
+ clone_dataset $TESTFS1 snap $TESTCLONE2
+
+ clone_write_file $TESTCLONE $TESTFILE0
+
+ clone_write_file $TESTCLONE1 $TESTFILE0
+ clone_write_file $TESTCLONE1 $TESTFILE1
+ clone_write_file $TESTCLONE1 $TESTFILE2
+
+ clone_write_file $TESTCLONE2 $TESTFILE0
+ log_must rm /$TESTPOOL/$TESTCLONE2/$TESTFILE0
+ clone_write_file $TESTCLONE2 $TESTFILE1
+ log_must rm /$TESTPOOL/$TESTCLONE2/$TESTFILE1
+
+ check_livelist_exists $TESTCLONE
+ check_livelist_exists $TESTCLONE1
+ check_livelist_exists $TESTCLONE2
+
+ log_must zfs destroy $TESTPOOL/$TESTCLONE
+ log_must zfs destroy $TESTPOOL/$TESTCLONE1
+ log_must zfs destroy $TESTPOOL/$TESTCLONE2
+ check_livelist_gone
+}
+
+function test_promote
+{
+ clone_dataset $TESTFS1 snap $TESTCLONE
+
+ log_must zfs promote $TESTPOOL/$TESTCLONE
+ check_livelist_gone
+ log_must zfs destroy -R $TESTPOOL/$TESTCLONE
+}
+
+function test_clone_clone_promote
+{
+ log_must zfs create $TESTPOOL/fs
+ log_must dd if=/dev/zero of=/$TESTPOOL/fs/file bs=128k count=100
+ log_must zfs snapshot $TESTPOOL/fs@snap
+ log_must zfs clone $TESTPOOL/fs@snap $TESTPOOL/clone
+ log_must dd if=/dev/zero of=/$TESTPOOL/clone/clonefile bs=128k count=10
+ log_must zfs snapshot $TESTPOOL/clone@csnap
+ log_must zfs clone $TESTPOOL/clone@csnap $TESTPOOL/cloneclone
+
+ check_livelist_exists clone
+ check_livelist_exists cloneclone
+
+ # Promote should remove both clones' livelists
+ log_must zfs promote $TESTPOOL/cloneclone
+ check_livelist_gone
+
+ # This destroy should not use a livelist
+ log_must zfs destroy $TESTPOOL/clone
+ log_must zdb -bcc $TESTPOOL
+}
+
+ORIGINAL_MAX=$(get_tunable LIVELIST_MAX_ENTRIES)
+
+log_onexit cleanup
+log_must zfs create $TESTPOOL/$TESTFS1
+log_must mkfile 20m /$TESTPOOL/$TESTFS1/atestfile
+log_must zfs snapshot $TESTPOOL/$TESTFS1@snap
+
+# set a small livelist entry size to more easily test multiple entry livelists
+set_tunable64 LIVELIST_MAX_ENTRIES 20
+
+test_one_empty
+test_one
+test_multiple_empty
+test_multiple
+test_promote
+test_clone_clone_promote
+
+log_pass "Clone with the livelist feature enabled could be destroyed," \
+ "also could be promoted and destroyed as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
new file mode 100644
index 000000000000..096c18f069ff
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
@@ -0,0 +1,174 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+
+#
+# Create or recover a set of test environment which include ctr, vol, fs,
+# snap & clone. It looks like the following.
+#
+# pool
+# |ctr
+# | |fs
+# | | |fssnap
+# | |vol
+# | |volsnap
+# |fsclone
+# |volclone
+#
+# $1 indicate which dependent dataset need be created. Such as 'snap', 'clone'.
+#
+function setup_testenv #[dtst]
+{
+ typeset dtst=$1
+
+ if ! datasetexists $CTR; then
+ log_must zfs create $CTR
+ fi
+ if ! datasetexists $FS; then
+ log_must zfs create $FS
+ fi
+ # Volume test is only available on global zone
+ if ! datasetexists $VOL && is_global_zone; then
+ log_must zfs create -V $VOLSIZE $VOL
+ block_device_wait
+
+ log_must new_fs $ZVOL_DEVDIR/$VOL
+
+ if [[ ! -d $TESTDIR1 ]]; then
+ log_must mkdir $TESTDIR1
+ fi
+ log_must mount $ZVOL_DEVDIR/$VOL $TESTDIR1
+ fi
+
+ if [[ $dtst == snap || $dtst == clone ]]; then
+ if ! datasetexists $FSSNAP; then
+ log_must zfs snapshot $FSSNAP
+ fi
+ if ! datasetexists $VOLSNAP && is_global_zone; then
+ log_must zfs snapshot $VOLSNAP
+ fi
+ fi
+
+ if [[ $dtst == clone ]]; then
+ if ! datasetexists $FSCLONE; then
+ log_must zfs clone $FSSNAP $FSCLONE
+ fi
+ if ! datasetexists $VOLCLONE && is_global_zone; then
+ log_must zfs clone $VOLSNAP $VOLCLONE
+ block_device_wait
+ fi
+ fi
+}
+
+# Clean up the testing environment
+#
+function cleanup_testenv
+{
+ if is_global_zone && ismounted "$TESTDIR1" "$NEWFS_DEFAULT_FS" ; then
+ log_must umount -f $TESTDIR1
+ fi
+ if [[ -d $TESTDIR1 ]]; then
+ log_must rm -rf $TESTDIR1
+ fi
+
+ pkill mkbusy
+
+ if datasetexists $CTR; then
+ log_must zfs destroy -Rf $CTR
+ fi
+}
+
+#
+# Delete volume and related datasets from list, if the test cases was
+# running in local zone. Then check them are existed or non-exists.
+#
+# $1 function name
+# $2-n datasets name
+#
+function check_dataset
+{
+ typeset funname=$1
+ typeset newlist=""
+ typeset dtst
+ shift
+
+ for dtst in "$@"; do
+ # Volume and related stuff are unavailable in local zone
+ if ! is_global_zone; then
+ if [[ $dtst == $VOL || $dtst == $VOLSNAP || \
+ $dtst == $VOLCLONE ]]
+ then
+ continue
+ fi
+ fi
+ newlist="$newlist $dtst"
+ done
+
+ if (( ${#newlist} != 0 )); then
+ # Run each item in $newlist individually so on failure, the
+ # problematic dataset is listed in the logs.
+ for i in $newlist; do
+ log_must $funname $i
+ done
+ fi
+}
+
+# Use zdb to see if a livelist exists for a given clone
+# $1 clone name
+function check_livelist_exists
+{
+ zdb -vvvvv $TESTPOOL/$1 | grep "Livelist" || \
+ log_fail "zdb could not find Livelist"
+}
+
+# Check that a livelist has been removed, waiting for deferred destroy entries
+# to be cleared from zdb.
+function check_livelist_gone
+{
+ log_must zpool wait -t free $TESTPOOL
+ zpool sync
+ zdb -vvvvv $TESTPOOL | grep "Livelist" && \
+ log_fail "zdb found Livelist after the clone is deleted."
+}
+
+# Create a clone in the testpool based on $TESTFS@snap. Verify that the clone
+# was created and that it includes a livelist
+# $1 fs name
+# $2 snap name
+# $3 clone name
+function clone_dataset
+{
+ log_must zfs clone $TESTPOOL/$1@$2 $TESTPOOL/$3
+ datasetexists $TESTPOOL/$3 || \
+ log_fail "zfs clone $TESTPOOL/$3 fail."
+ check_livelist_exists $3
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_dev_removal.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_dev_removal.ksh
new file mode 100755
index 000000000000..107c13319666
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_dev_removal.ksh
@@ -0,0 +1,68 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+# DESCRIPTION
+# Verify that livelists tracking remapped blocks can be
+# properly destroyed.
+
+# STRATEGY
+# 1. Create a pool with disk1 and create a filesystem, snapshot
+# and clone. Write several files to the clone.
+# 2. Add disk2 to the pool and then remove disk1, triggering a
+# remap of the blkptrs tracked in the livelist.
+# 3. Delete the clone
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+function cleanup
+{
+ poolexists $TESTPOOL2 && zpool destroy $TESTPOOL2
+ [[ -f $VIRTUAL_DISK1 ]] && log_must rm $VIRTUAL_DISK1
+ [[ -f $VIRTUAL_DISK2 ]] && log_must rm $VIRTUAL_DISK2
+}
+
+log_onexit cleanup
+
+VIRTUAL_DISK1=$TEST_BASE_DIR/disk1
+VIRTUAL_DISK2=$TEST_BASE_DIR/disk2
+log_must truncate -s $(($MINVDEVSIZE * 8)) $VIRTUAL_DISK1
+log_must truncate -s $(($MINVDEVSIZE * 16)) $VIRTUAL_DISK2
+
+log_must zpool create $TESTPOOL2 $VIRTUAL_DISK1
+log_must poolexists $TESTPOOL2
+
+log_must zfs create $TESTPOOL2/$TESTFS
+log_must mkfile 25m /$TESTPOOL2/$TESTFS/atestfile
+log_must zfs snapshot $TESTPOOL2/$TESTFS@snap
+
+log_must zfs clone $TESTPOOL2/$TESTFS@snap $TESTPOOL2/$TESTCLONE
+
+log_must mkfile 1m /$TESTPOOL2/$TESTCLONE/$TESTFILE0
+log_must mkfile 1m /$TESTPOOL2/$TESTCLONE/$TESTFILE1
+log_must mkfile 1m /$TESTPOOL2/$TESTCLONE/$TESTFILE2
+
+log_must zpool add $TESTPOOL2 $VIRTUAL_DISK2
+log_must zpool remove $TESTPOOL2 $VIRTUAL_DISK1
+wait_for_removal $TESTPOOL2
+
+log_must rm /$TESTPOOL2/$TESTCLONE/$TESTFILE0
+log_must rm /$TESTPOOL2/$TESTCLONE/$TESTFILE1
+
+log_must zfs destroy $TESTPOOL2/$TESTCLONE
+
+log_pass "Clone with the livelist feature and remapped blocks," \
+ "can be destroyed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_dev_removal_condense.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_dev_removal_condense.ksh
new file mode 100755
index 000000000000..ab646daecedc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_dev_removal_condense.ksh
@@ -0,0 +1,94 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+# DESCRIPTION
+# Verify that livelists tracking remapped blocks can be
+# properly condensed.
+
+# STRATEGY
+# 1. Create a pool with disk1 and create a filesystem, snapshot
+# and clone. Create two files for the first livelist entry and
+# pause condensing.
+# 2. Add disk2 to the pool and then remove disk1, triggering a
+# remap of the blkptrs tracked in the livelist.
+# 3. Overwrite the first file several times to trigger a condense,
+# overwrite the second file once and resume condensing, now with
+# extra blkptrs added during the remap
+# 4. Check that the test added new ALLOC blkptrs mid-condense using
+# a variable set in that code path
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy.cfg
+
+function cleanup
+{
+ poolexists $TESTPOOL2 && zpool destroy $TESTPOOL2
+ # reset livelist max size
+ set_tunable64 LIVELIST_MAX_ENTRIES $ORIGINAL_MAX
+ [[ -f $VIRTUAL_DISK1 ]] && log_must rm $VIRTUAL_DISK1
+ [[ -f $VIRTUAL_DISK2 ]] && log_must rm $VIRTUAL_DISK2
+}
+
+log_onexit cleanup
+
+ORIGINAL_MAX=$(get_tunable LIVELIST_MAX_ENTRIES)
+set_tunable64 LIVELIST_MAX_ENTRIES 20
+
+VIRTUAL_DISK1=$TEST_BASE_DIR/disk1
+VIRTUAL_DISK2=$TEST_BASE_DIR/disk2
+log_must truncate -s $(($MINVDEVSIZE * 8)) $VIRTUAL_DISK1
+log_must truncate -s $(($MINVDEVSIZE * 16)) $VIRTUAL_DISK2
+
+log_must zpool create $TESTPOOL2 $VIRTUAL_DISK1
+log_must poolexists $TESTPOOL2
+
+log_must zfs create $TESTPOOL2/$TESTFS
+log_must mkfile 100m /$TESTPOOL2/$TESTFS/atestfile
+log_must zfs snapshot $TESTPOOL2/$TESTFS@snap
+
+log_must zfs clone $TESTPOOL2/$TESTFS@snap $TESTPOOL2/$TESTCLONE
+
+# Create initial files and pause condense zthr on next execution
+log_must mkfile 10m /$TESTPOOL2/$TESTCLONE/A
+log_must mkfile 1m /$TESTPOOL2/$TESTCLONE/B
+log_must zpool sync $TESTPOOL2
+set_tunable32 LIVELIST_CONDENSE_SYNC_PAUSE 1
+
+# Add a new dev and remove the old one
+log_must zpool add $TESTPOOL2 $VIRTUAL_DISK2
+log_must zpool remove $TESTPOOL2 $VIRTUAL_DISK1
+wait_for_removal $TESTPOOL2
+
+set_tunable32 LIVELIST_CONDENSE_NEW_ALLOC 0
+# Trigger a condense
+log_must mkfile 10m /$TESTPOOL2/$TESTCLONE/A
+log_must zpool sync $TESTPOOL2
+log_must mkfile 10m /$TESTPOOL2/$TESTCLONE/A
+log_must zpool sync $TESTPOOL2
+# Write remapped blkptrs which will modify the livelist mid-condense
+log_must mkfile 1m /$TESTPOOL2/$TESTCLONE/B
+
+# Resume condense thr
+set_tunable32 LIVELIST_CONDENSE_SYNC_PAUSE 0
+log_must zpool sync $TESTPOOL2
+# Check that we've added new ALLOC blkptrs during the condense
+[[ "0" < "$(get_tunable LIVELIST_CONDENSE_NEW_ALLOC)" ]] || \
+ log_fail "removal/condense test failed"
+
+log_must zfs destroy $TESTPOOL2/$TESTCLONE
+log_pass "Clone with the livelist feature and remapped blocks," \
+ "can be condensed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_diff/.gitignore b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/.gitignore
new file mode 100644
index 000000000000..7fa74c3575bd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/.gitignore
@@ -0,0 +1 @@
+/socket
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_diff/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/Makefile.am
new file mode 100644
index 000000000000..db90e058559d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/Makefile.am
@@ -0,0 +1,17 @@
+include $(top_srcdir)/config/Rules.am
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_diff
+
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ zfs_diff_changes.ksh \
+ zfs_diff_cliargs.ksh \
+ zfs_diff_encrypted.ksh \
+ zfs_diff_timestamp.ksh \
+ zfs_diff_types.ksh
+
+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_diff
+
+pkgexec_PROGRAMS = socket
+socket_SOURCES = socket.c
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_diff/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/cleanup.ksh
new file mode 100755
index 000000000000..1adac153d740
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/cleanup.ksh
@@ -0,0 +1,19 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_diff/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/setup.ksh
new file mode 100755
index 000000000000..e37841addf88
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/setup.ksh
@@ -0,0 +1,21 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_volume_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_diff/socket.c b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/socket.c
new file mode 100644
index 000000000000..a8c814e7b5b6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/socket.c
@@ -0,0 +1,58 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+ */
+
+#include <fcntl.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* ARGSUSED */
+int
+main(int argc, char *argv[])
+{
+ struct sockaddr_un sock;
+ int fd;
+ char *path;
+ size_t size;
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s /path/to/socket\n", argv[0]);
+ exit(1);
+ }
+ path = argv[1];
+ size = sizeof (sock.sun_path);
+ strncpy(sock.sun_path, (char *)path, size - 1);
+ sock.sun_path[size - 1] = '\0';
+
+ sock.sun_family = AF_UNIX;
+ if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) {
+ perror("socket");
+ return (1);
+ }
+ if (bind(fd, (struct sockaddr *)&sock, sizeof (struct sockaddr_un))) {
+ perror("bind");
+ return (1);
+ }
+ if (close(fd)) {
+ perror("close");
+ return (1);
+ }
+ return (0);
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_changes.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_changes.ksh
new file mode 100755
index 000000000000..51a1b4aa1199
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_changes.ksh
@@ -0,0 +1,96 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs diff' should display changes correctly.
+#
+# STRATEGY:
+# 1. Create a filesystem with both files and directories, then snapshot it
+# 2. Generate different types of changes and verify 'zfs diff' displays them
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy -r "$DATASET"
+ rm -f "$FILEDIFF"
+}
+
+#
+# Verify object $path has $change type
+# Valid types are:
+# * - (The path has been removed)
+# * + (The path has been created)
+# * M (The path has been modified)
+# * R (The path has been renamed)
+#
+function verify_object_change # <path> <change>
+{
+ path="$1"
+ change="$2"
+
+ log_must eval "zfs diff -F $TESTSNAP1 $TESTSNAP2 > $FILEDIFF"
+ diffchg="$(awk -v path="$path" '$NF == path { print $1 }' < $FILEDIFF)"
+ if [[ "$diffchg" != "$change" ]]; then
+ log_fail "Unexpected change for $path ('$diffchg' != '$change')"
+ else
+ log_note "Object $path change is displayed correctly: '$change'"
+ fi
+}
+
+log_assert "'zfs diff' should display changes correctly."
+log_onexit cleanup
+
+DATASET="$TESTPOOL/$TESTFS/fs"
+TESTSNAP1="$DATASET@snap1"
+TESTSNAP2="$DATASET@snap2"
+FILEDIFF="$TESTDIR/zfs-diff.txt"
+
+# 1. Create a filesystem with both files and directories, then snapshot it
+log_must zfs create $DATASET
+MNTPOINT="$(get_prop mountpoint $DATASET)"
+log_must touch "$MNTPOINT/fremoved"
+log_must touch "$MNTPOINT/frenamed"
+log_must touch "$MNTPOINT/fmodified"
+log_must mkdir "$MNTPOINT/dremoved"
+log_must mkdir "$MNTPOINT/drenamed"
+log_must mkdir "$MNTPOINT/dmodified"
+log_must zfs snapshot "$TESTSNAP1"
+
+# 2. Generate different types of changes and verify 'zfs diff' displays them
+log_must rm -f "$MNTPOINT/fremoved"
+log_must mv "$MNTPOINT/frenamed" "$MNTPOINT/frenamed.new"
+log_must touch "$MNTPOINT/fmodified"
+log_must rmdir "$MNTPOINT/dremoved"
+log_must mv "$MNTPOINT/drenamed" "$MNTPOINT/drenamed.new"
+log_must touch "$MNTPOINT/dmodified/file"
+log_must touch "$MNTPOINT/fcreated"
+log_must mkdir "$MNTPOINT/dcreated"
+log_must zfs snapshot "$TESTSNAP2"
+verify_object_change "$MNTPOINT/fremoved" "-"
+verify_object_change "$MNTPOINT/frenamed.new" "R"
+verify_object_change "$MNTPOINT/fmodified" "M"
+verify_object_change "$MNTPOINT/fcreated" "+"
+verify_object_change "$MNTPOINT/dremoved" "-"
+verify_object_change "$MNTPOINT/drenamed.new" "R"
+verify_object_change "$MNTPOINT/dmodified" "M"
+verify_object_change "$MNTPOINT/dcreated" "+"
+
+log_pass "'zfs diff' displays changes correctly."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_cliargs.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_cliargs.ksh
new file mode 100755
index 000000000000..c4b42afee472
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_cliargs.ksh
@@ -0,0 +1,80 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs diff' should only work with supported options.
+#
+# STRATEGY:
+# 1. Create two snapshots
+# 2. Verify every supported option is accepted
+# 3. Verify supported options raise an error with unsupported arguments
+# 4. Verify other unsupported options raise an error
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for snap in $TESTSNAP1 $TESTSNAP2; do
+ if snapexists "$snap"; then
+ log_must zfs destroy "$snap"
+ fi
+ done
+}
+
+log_assert "'zfs diff' should only work with supported options."
+log_onexit cleanup
+
+typeset goodopts=("" "-F" "-H" "-t" "-FH" "-Ft" "-Ht" "-FHt")
+typeset badopts=("-f" "-h" "-h" "-T" "-Fx" "-Ho" "-tT" "-")
+
+DATASET="$TESTPOOL/$TESTFS"
+TESTSNAP1="$DATASET@snap1"
+TESTSNAP2="$DATASET@snap2"
+
+# 1. Create two snapshots
+log_must zfs snapshot "$TESTSNAP1"
+log_must zfs snapshot "$TESTSNAP2"
+
+# 2. Verify every supported option is accepted
+for opt in ${goodopts[@]}
+do
+ log_must zfs diff $opt "$TESTSNAP1"
+ log_must zfs diff $opt "$TESTSNAP1" "$DATASET"
+ log_must zfs diff $opt "$TESTSNAP1" "$TESTSNAP2"
+done
+
+# 3. Verify supported options raise an error with unsupported arguments
+for opt in ${goodopts[@]}
+do
+ log_mustnot zfs diff $opt
+ log_mustnot zfs diff $opt "$DATASET"
+ log_mustnot zfs diff $opt "$DATASET@noexists"
+ log_mustnot zfs diff $opt "$DATASET" "$TESTSNAP1"
+ log_mustnot zfs diff $opt "$TESTSNAP2" "$TESTSNAP1"
+done
+
+# 4. Verify other unsupported options raise an error
+for opt in ${badopts[@]}
+do
+ log_mustnot zfs diff $opt "$TESTSNAP1" "$DATASET"
+ log_mustnot zfs diff $opt "$TESTSNAP1" "$TESTSNAP2"
+done
+
+log_pass "'zfs diff' only works with supported options."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_encrypted.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_encrypted.ksh
new file mode 100755
index 000000000000..96e6d9b5ae89
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_encrypted.ksh
@@ -0,0 +1,63 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2018, Datto Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs diff' should work with encrypted datasets
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Create two snapshots of the dataset
+# 3. Perform 'zfs diff -Ft' and verify no errors occur
+# 4. Perform the same test on a dataset with large dnodes
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_dataset "$TESTPOOL/$TESTFS1" "-r"
+ destroy_dataset "$TESTPOOL/$TESTFS2" "-r"
+}
+
+log_assert "'zfs diff' should work with encrypted datasets"
+log_onexit cleanup
+
+# 1. Create an encrypted dataset
+log_must eval "echo 'password' | zfs create -o encryption=on \
+ -o keyformat=passphrase $TESTPOOL/$TESTFS1"
+MNTPOINT="$(get_prop mountpoint $TESTPOOL/$TESTFS1)"
+
+# 2. Create two snapshots of the dataset
+log_must zfs snapshot $TESTPOOL/$TESTFS1@snap1
+log_must touch "$MNTPOINT/file"
+log_must zfs snapshot $TESTPOOL/$TESTFS1@snap2
+
+# 3. Perform 'zfs diff' and verify no errors occur
+log_must zfs diff -Ft $TESTPOOL/$TESTFS1@snap1 $TESTPOOL/$TESTFS1@snap2
+
+# 4. Perform the same test on a dataset with large dnodes
+log_must eval "echo 'password' | zfs create -o dnodesize=4k \
+ -o encryption=on -o keyformat=passphrase $TESTPOOL/$TESTFS2"
+MNTPOINT="$(get_prop mountpoint $TESTPOOL/$TESTFS2)"
+log_must zfs snapshot $TESTPOOL/$TESTFS2@snap1
+log_must touch "$MNTPOINT/file"
+log_must zfs snapshot $TESTPOOL/$TESTFS2@snap2
+log_must zfs diff -Ft $TESTPOOL/$TESTFS2@snap1 $TESTPOOL/$TESTFS2@snap2
+
+log_pass "'zfs diff' works with encrypted datasets"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_timestamp.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_timestamp.ksh
new file mode 100755
index 000000000000..a4cedca49ce8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_timestamp.ksh
@@ -0,0 +1,104 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs diff -t' should display inode change time correctly.
+#
+# STRATEGY:
+# 1. Create a snapshot
+# 2. Create some files with a random delay and snapshot the filesystem again
+# 3. Verify 'zfs diff -t' correctly display timestamps
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for snap in $TESTSNAP1 $TESTSNAP2; do
+ if snapexists "$snap"; then
+ log_must zfs destroy "$snap"
+ fi
+ done
+ find "$MNTPOINT" -type f -delete
+ rm -f "$FILEDIFF"
+}
+
+#
+# Creates $count files in $fspath. Waits a random delay between each file.
+#
+function create_random # <fspath> <count>
+{
+ fspath="$1"
+ typeset -i count="$2"
+ typeset -i i=0
+
+ while (( i < count )); do
+ log_must touch "$fspath/file$i"
+ sleep $(random_int_between 1 3)
+ (( i = i + 1 ))
+ done
+}
+
+log_assert "'zfs diff -t' should display inode change time correctly."
+log_onexit cleanup
+
+DATASET="$TESTPOOL/$TESTFS"
+TESTSNAP1="$DATASET@snap1"
+TESTSNAP2="$DATASET@snap2"
+MNTPOINT="$(get_prop mountpoint $DATASET)"
+FILEDIFF="$TESTDIR/zfs-diff.txt"
+FILENUM=5
+
+# 1. Create a snapshot
+log_must zfs snapshot "$TESTSNAP1"
+
+# 2. Create some files with a random delay and snapshot the filesystem again
+create_random "$MNTPOINT" $FILENUM
+log_must zfs snapshot "$TESTSNAP2"
+
+# 3. Verify 'zfs diff -t' correctly display timestamps
+typeset -i count=0
+log_must eval "zfs diff -t $TESTSNAP1 $TESTSNAP2 > $FILEDIFF"
+awk '{print substr($1,1,index($1,".")-1)" "$NF}' < "$FILEDIFF" | while read line
+do
+ read ctime file <<< "$line"
+
+ # If path from 'zfs diff' is not a file (could be xattr object) skip it
+ if [[ ! -f "$file" ]]; then
+ continue;
+ fi
+
+ if is_freebsd; then
+ filetime="$(stat -f "%c" $file)"
+ else
+ filetime="$(stat -c '%Z' $file)"
+ fi
+ if [[ "$filetime" != "$ctime" ]]; then
+ log_fail "Unexpected ctime for file $file ($filetime != $ctime)"
+ else
+ log_note "Correct ctime read on $file: $ctime"
+ fi
+
+ (( i = i + 1 ))
+done
+if [[ $i != $FILENUM ]]; then
+ log_fail "Wrong number of files verified ($i != $FILENUM)"
+fi
+
+log_pass "'zfs diff -t' displays inode change time correctly."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_types.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_types.ksh
new file mode 100755
index 000000000000..8e521b9f5a1e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_types.ksh
@@ -0,0 +1,134 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs diff -F' shows different object types correctly.
+#
+# STRATEGY:
+# 1. Prepare a dataset
+# 2. Create different objects and verify 'zfs diff -F' shows the correct type
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy -r "$DATASET"
+ rm -f "$FILEDIFF"
+}
+
+#
+# Verify object at $path is of type $symbol using 'zfs diff -F'
+# Valid types are:
+# * B (Block device)
+# * C (Character device)
+# * / (Directory)
+# * > (Door)
+# * | (Named pipe)
+# * @ (Symbolic link)
+# * P (Event port)
+# * = (Socket)
+# * F (Regular file)
+#
+function verify_object_class # <path> <symbol>
+{
+ path="$1"
+ symbol="$2"
+
+ log_must eval "zfs diff -F $TESTSNAP1 $TESTSNAP2 > $FILEDIFF"
+ diffsym="$(awk -v path="$path" '$NF == path { print $2 }' < $FILEDIFF)"
+ if [[ "$diffsym" != "$symbol" ]]; then
+ log_fail "Unexpected type for $path ('$diffsym' != '$symbol')"
+ else
+ log_note "Object $path type is correctly displayed as '$symbol'"
+ fi
+
+ log_must zfs destroy "$TESTSNAP1"
+ log_must zfs destroy "$TESTSNAP2"
+}
+
+log_assert "'zfs diff -F' should show different object types correctly."
+log_onexit cleanup
+
+DATASET="$TESTPOOL/$TESTFS/fs"
+TESTSNAP1="$DATASET@snap1"
+TESTSNAP2="$DATASET@snap2"
+FILEDIFF="$TESTDIR/zfs-diff.txt"
+if is_freebsd; then
+ MAJOR=$(stat -f %Hr /dev/null)
+ MINOR=$(stat -f %Lr /dev/null)
+else
+ MAJOR=$(stat -c %t /dev/null)
+ MINOR=$(stat -c %T /dev/null)
+fi
+
+# 1. Prepare a dataset
+log_must zfs create $DATASET
+MNTPOINT="$(get_prop mountpoint $DATASET)"
+log_must zfs set devices=on $DATASET
+log_must zfs set xattr=sa $DATASET
+
+# 2. Create different objects and verify 'zfs diff -F' shows the correct type
+# 2. F (Regular file)
+log_must zfs snapshot "$TESTSNAP1"
+log_must touch "$MNTPOINT/file"
+log_must zfs snapshot "$TESTSNAP2"
+verify_object_class "$MNTPOINT/file" "F"
+
+# 2. @ (Symbolic link)
+log_must zfs snapshot "$TESTSNAP1"
+log_must ln -s "$MNTPOINT/file" "$MNTPOINT/link"
+log_must zfs snapshot "$TESTSNAP2"
+verify_object_class "$MNTPOINT/link" "@"
+
+# 2. B (Block device)
+log_must zfs snapshot "$TESTSNAP1"
+log_must mknod "$MNTPOINT/bdev" b $MAJOR $MINOR
+log_must zfs snapshot "$TESTSNAP2"
+verify_object_class "$MNTPOINT/bdev" "B"
+
+# 2. C (Character device)
+log_must zfs snapshot "$TESTSNAP1"
+log_must mknod "$MNTPOINT/cdev" c $MAJOR $MINOR
+log_must zfs snapshot "$TESTSNAP2"
+verify_object_class "$MNTPOINT/cdev" "C"
+
+# 2. | (Named pipe)
+log_must zfs snapshot "$TESTSNAP1"
+if is_freebsd; then
+ log_must mkfifo "$MNTPOINT/fifo"
+else
+ log_must mknod "$MNTPOINT/fifo" p
+fi
+log_must zfs snapshot "$TESTSNAP2"
+verify_object_class "$MNTPOINT/fifo" "|"
+
+# 2. / (Directory)
+log_must zfs snapshot "$TESTSNAP1"
+log_must mkdir "$MNTPOINT/dir"
+log_must zfs snapshot "$TESTSNAP2"
+verify_object_class "$MNTPOINT/dir" "/"
+
+# 2. = (Socket)
+log_must zfs snapshot "$TESTSNAP1"
+log_must $STF_SUITE/tests/functional/cli_root/zfs_diff/socket "$MNTPOINT/sock"
+log_must zfs snapshot "$TESTSNAP2"
+verify_object_class "$MNTPOINT/sock" "="
+
+log_pass "'zfs diff -F' shows different object types correctly."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_get/Makefile.am
new file mode 100644
index 000000000000..22e95907675d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/Makefile.am
@@ -0,0 +1,18 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_get
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_get_001_pos.ksh \
+ zfs_get_002_pos.ksh \
+ zfs_get_003_pos.ksh \
+ zfs_get_004_pos.ksh \
+ zfs_get_005_neg.ksh \
+ zfs_get_006_neg.ksh \
+ zfs_get_007_neg.ksh \
+ zfs_get_008_pos.ksh \
+ zfs_get_009_pos.ksh \
+ zfs_get_010_neg.ksh
+
+dist_pkgdata_DATA = \
+ zfs_get_common.kshlib \
+ zfs_get_list_d.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/setup.ksh
new file mode 100755
index 000000000000..9692385996d1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_container_volume_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_001_pos.ksh
new file mode 100755
index 000000000000..eeae5390f088
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_001_pos.ksh
@@ -0,0 +1,163 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib
+
+#
+# DESCRIPTION:
+# Setting the valid option and properties, 'zfs get' should return the
+# correct property value.
+#
+# STRATEGY:
+# 1. Create pool, filesystem, volume, snapshot, and bookmark.
+# 2. Setting valid parameter, 'zfs get' should succeed.
+# 3. Compare the output property name with the original input property.
+#
+
+verify_runnable "both"
+
+typeset options=("" "-p" "-r" "-H")
+
+typeset -i i=${#options[*]}
+typeset -i j=0
+while ((j<${#depth_options[*]}));
+do
+ options[$i]=-"${depth_options[$j]}"
+ ((j+=1))
+ ((i+=1))
+done
+
+typeset zfs_props=("type" used available creation volsize referenced \
+ compressratio mounted origin recordsize quota reservation mountpoint \
+ sharenfs checksum compression atime devices exec readonly setuid \
+ snapdir aclinherit canmount primarycache secondarycache version \
+ usedbychildren usedbydataset usedbyrefreservation usedbysnapshots)
+if is_freebsd; then
+ typeset zfs_props_os=(jailed aclmode)
+else
+ typeset zfs_props_os=(zoned acltype)
+fi
+typeset userquota_props=(userquota@root groupquota@root userused@root \
+ groupused@root)
+typeset all_props=("${zfs_props[@]}" \
+ "${zfs_props_os[@]}" \
+ "${userquota_props[@]}")
+typeset dataset=($TESTPOOL/$TESTCTR $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL \
+ $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTVOL@$TESTSNAP)
+
+typeset bookmark_props=(creation)
+typeset bookmark=($TESTPOOL/$TESTFS#$TESTBKMARK $TESTPOOL/$TESTVOL#$TESTBKMARK)
+
+#
+# According to dataset and option, checking if 'zfs get' return correct
+# property information.
+#
+# $1 dataset
+# $2 properties which are expected to output into $TESTDIR/$TESTFILE0
+# $3 option
+#
+function check_return_value
+{
+ typeset dst=$1
+ typeset props=$2
+ typeset opt=$3
+ typeset -i found=0
+ typeset p
+
+ for p in $props; do
+ found=0
+
+ while read line; do
+ typeset item
+ item=$(echo $line | awk '{print $2}' 2>&1)
+
+ if [[ $item == $p ]]; then
+ ((found += 1))
+ break
+ fi
+ done < $TESTDIR/$TESTFILE0
+
+ if ((found == 0)); then
+ log_fail "'zfs get $opt $props $dst' return " \
+ "error message.'$p' haven't been found."
+ fi
+ done
+
+ log_note "SUCCESS: 'zfs get $opt $prop $dst'."
+}
+
+log_assert "Setting the valid options and properties 'zfs get' should return " \
+ "the correct property value."
+log_onexit cleanup
+
+# Create filesystem and volume's snapshot
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+create_snapshot $TESTPOOL/$TESTVOL $TESTSNAP
+
+# Create filesystem and volume's bookmark
+create_bookmark $TESTPOOL/$TESTFS $TESTSNAP $TESTBKMARK
+create_bookmark $TESTPOOL/$TESTVOL $TESTSNAP $TESTBKMARK
+
+typeset -i i=0
+while ((i < ${#dataset[@]})); do
+ for opt in "${options[@]}"; do
+ for prop in ${all_props[@]}; do
+ eval "zfs get $opt $prop ${dataset[i]} > \
+ $TESTDIR/$TESTFILE0"
+ ret=$?
+ if [[ $ret != 0 ]]; then
+ log_fail "zfs get returned: $ret"
+ fi
+ check_return_value ${dataset[i]} "$prop" "$opt"
+ done
+ done
+ ((i += 1))
+done
+
+i=0
+while ((i < ${#bookmark[@]})); do
+ for opt in "${options[@]}"; do
+ for prop in ${bookmark_props[@]}; do
+ eval "zfs get $opt $prop ${bookmark[i]} > \
+ $TESTDIR/$TESTFILE0"
+ ret=$?
+ if [[ $ret != 0 ]]; then
+ log_fail "zfs get returned: $ret"
+ fi
+ check_return_value ${bookmark[i]} "$prop" "$opt"
+ done
+ done
+ ((i += 1))
+done
+
+log_pass "Setting the valid options to dataset, it should succeed and return " \
+ "valid value. 'zfs get' pass."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_002_pos.ksh
new file mode 100755
index 000000000000..c3746514eae0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_002_pos.ksh
@@ -0,0 +1,97 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib
+
+#
+# DESCRIPTION:
+# Setting the valid option and properties 'zfs get' return correct value.
+# It should be successful.
+#
+# STRATEGY:
+# 1. Create pool, filesystem, dataset, volume and snapshot.
+# 2. Getting the options and properties random combination.
+# 3. Using the combination as the parameters of 'zfs get' to check the
+# command line return value.
+#
+
+verify_runnable "both"
+
+typeset options=(" " p r H)
+
+typeset zfs_props=("type" used available creation volsize referenced \
+ compressratio mounted origin recordsize quota reservation mountpoint \
+ sharenfs checksum compression atime devices exec readonly setuid \
+ snapdir aclinherit canmount primarycache secondarycache version \
+ usedbychildren usedbydataset usedbyrefreservation usedbysnapshots)
+if is_freebsd; then
+ typeset zfs_props_os=(jailed aclmode)
+else
+ typeset zfs_props_os=(zoned acltype)
+fi
+typeset userquota_props=(userquota@root groupquota@root userused@root \
+ groupused@root)
+typeset props=("${zfs_props[@]}" \
+ "${zfs_props_os[@]}" \
+ "${userquota_props[@]}")
+typeset dataset=($TESTPOOL/$TESTCTR $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL \
+ $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTVOL@$TESTSNAP)
+
+log_assert "Setting the valid options and properties 'zfs get' return " \
+ "correct value. It should be successful."
+log_onexit cleanup
+
+# Create volume and filesystem's snapshot
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+create_snapshot $TESTPOOL/$TESTVOL $TESTSNAP
+
+#
+# Begin to test 'get [-prH] <property[,property]...>
+# <filesystem|dataset|volume|snapshot>'
+# 'get [-prH] <-a|-d> <filesystem|dataset|volume|snapshot>"
+#
+typeset -i opt_numb=8
+typeset -i prop_numb=20
+for dst in ${dataset[@]}; do
+ # option can be empty, so "" is necessary.
+ for opt in "" $(gen_option_str "${options[*]}" "-" "" $opt_numb); do
+ for prop in $(gen_option_str "${props[*]}" "" "," $prop_numb)
+ do
+ zfs get $opt $prop $dst > /dev/null 2>&1
+ ret=$?
+ if [[ $ret != 0 ]]; then
+ log_fail "zfs get $opt $prop $dst (Code: $ret)"
+ fi
+ done
+ done
+done
+
+log_pass "Setting the valid options to dataset, 'zfs get' pass."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_003_pos.ksh
new file mode 100755
index 000000000000..2ea5aa0cb4cf
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_003_pos.ksh
@@ -0,0 +1,65 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs get' should get consistent report with different options.
+#
+# STRATEGY:
+# 1. Create pool and filesystem.
+# 2. 'zfs mount -o remount,noatime <fs>.'
+# 3. Verify the value of 'zfs get atime' and 'zfs get all | grep atime'
+# are identical.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs mount -o remount,atime $TESTPOOL/$TESTFS
+}
+
+log_assert "'zfs get' should get consistent report with different option."
+log_onexit cleanup
+
+log_must zfs set atime=on $TESTPOOL/$TESTFS
+log_must zfs mount -o remount,noatime $TESTPOOL/$TESTFS
+
+value1=$(zfs get -H atime $TESTPOOL/$TESTFS | awk '{print $3}')
+value2=$(zfs get -H all $TESTPOOL/$TESTFS | awk '{print $2 " " $3}' | \
+ grep ^atime | awk '{print $2}')
+if [[ $value1 != $value2 ]]; then
+ log_fail "value1($value1) != value2($value2)"
+fi
+
+log_pass "'zfs get' get consistent report with different option passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_004_pos.ksh
new file mode 100755
index 000000000000..4bd61137c7be
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_004_pos.ksh
@@ -0,0 +1,227 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify 'zfs get all' can get all properties for all datasets in the system
+#
+# STRATEGY:
+# 1. Create datasets for testing
+# 2. Issue 'zfs get all' command
+# 3. Verify the command gets all available properties of all datasets
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ [[ -e $propfile ]] && rm -f $propfile
+
+ datasetexists $clone && \
+ log_must zfs destroy $clone
+ for snap in $fssnap $volsnap ; do
+ snapexists $snap && \
+ log_must zfs destroy $snap
+ done
+
+ if [[ -n $globalzone ]] ; then
+ for pool in $TESTPOOL1 $TESTPOOL2 $TESTPOOL3; do
+ poolexists $pool && \
+ log_must zpool destroy -f $pool
+ done
+ for file in `ls $TESTDIR1/poolfile*`; do
+ rm -f $file
+ done
+ else
+ for fs in $TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS2 $TESTPOOL/$TESTFS3; do
+ datasetexists $fs && \
+ log_must zfs destroy -rf $fs
+ done
+ fi
+}
+
+log_assert "Verify the functions of 'zfs get all' work."
+log_onexit cleanup
+
+typeset globalzone=""
+
+if is_global_zone ; then
+ globalzone="true"
+fi
+
+set -A opts "" "-r" "-H" "-p" "-rHp" "-o name" \
+ "-s local,default,temporary,inherited,none" \
+ "-o name -s local,default,temporary,inherited,none" \
+ "-rHp -o name -s local,default,temporary,inherited,none"
+set -A usrprops "a:b=c" "d_1:1_e=0f" "123:456=789"
+
+fs=$TESTPOOL/$TESTFS
+fssnap=$fs@$TESTSNAP
+clone=$TESTPOOL/$TESTCLONE
+volsnap=$TESTPOOL/$TESTVOL@$TESTSNAP
+
+#set user defined properties for $TESTPOOL
+for usrprop in ${usrprops[@]}; do
+ log_must zfs set $usrprop $TESTPOOL
+done
+# create snapshot and clone in $TESTPOOL
+log_must zfs snapshot $fssnap
+log_must zfs clone $fssnap $clone
+log_must zfs snapshot $volsnap
+
+# collect datasets which can be set user defined properties
+usrpropds="$clone $fs"
+
+# collect all datasets which we are creating
+allds="$fs $clone $fssnap $volsnap"
+
+#create pool and datasets to guarantee testing under multiple pools and datasets.
+file=$TESTDIR1/poolfile
+typeset FILESIZE=$MINVDEVSIZE
+(( DFILESIZE = $FILESIZE * 2 ))
+typeset -i VOLSIZE=10485760
+availspace=$(get_prop available $TESTPOOL)
+typeset -i i=0
+
+# make sure 'availspace' is larger then twice of FILESIZE to create a new pool.
+# If any, we only totally create 3 pools for multiple datasets testing to limit
+# testing time
+while (( availspace > DFILESIZE )) && (( i < 3 )) ; do
+ (( i += 1 ))
+
+ if [[ -n $globalzone ]] ; then
+ log_must mkfile $FILESIZE ${file}$i
+ eval pool=\$TESTPOOL$i
+ log_must zpool create $pool ${file}$i
+ else
+ eval pool=$TESTPOOL/\$TESTFS$i
+ log_must zfs create $pool
+ fi
+
+ #set user defined properties for testing
+ for usrprop in ${usrprops[@]}; do
+ log_must zfs set $usrprop $pool
+ done
+
+ #create datasets in pool
+ log_must zfs create $pool/$TESTFS
+ log_must zfs snapshot $pool/$TESTFS@$TESTSNAP
+ log_must zfs clone $pool/$TESTFS@$TESTSNAP $pool/$TESTCLONE
+
+ if [[ -n $globalzone ]] ; then
+ log_must zfs create -V $VOLSIZE $pool/$TESTVOL
+ else
+ log_must zfs create $pool/$TESTVOL
+ fi
+
+ ds=`zfs list -H -r -o name -t filesystem,volume $pool`
+ usrpropds="$usrpropds $pool/$TESTFS $pool/$TESTCLONE $pool/$TESTVOL"
+ allds="$allds $pool/$TESTFS $pool/$TESTCLONE $pool/$TESTVOL \
+ $pool/$TESTFS@$TESTSNAP"
+
+ availspace=$(get_prop available $TESTPOOL)
+done
+
+#the expected number of property for each type of dataset in this testing
+typeset -i fspropnum=27
+typeset -i snappropnum=8
+typeset -i volpropnum=15
+propfile=$TEST_BASE_DIR/allpropfile.$$
+
+typeset -i i=0
+typeset -i propnum=0
+typeset -i failflag=0
+while (( i < ${#opts[*]} )); do
+ [[ -e $propfile ]] && rm -f $propfile
+ log_must eval "zfs get ${opts[i]} all >$propfile"
+
+ for ds in $allds; do
+ grep $ds $propfile >/dev/null 2>&1
+ (( $? != 0 )) && \
+ log_fail "There is no property for" \
+ "dataset $ds in 'get all' output."
+
+ propnum=`cat $propfile | awk '{print $1}' | \
+ grep "${ds}$" | wc -l`
+ ds_type=`zfs get -H -o value type $ds`
+ case $ds_type in
+ filesystem )
+ (( propnum < fspropnum )) && \
+ (( failflag += 1 ))
+ ;;
+ snapshot )
+ (( propnum < snappropnum )) && \
+ (( failflag += 1 ))
+ ;;
+ volume )
+ (( propnum < volpropnum )) && \
+ (( failflag += 1 ))
+ ;;
+ esac
+
+ (( failflag != 0 )) && \
+ log_fail " 'zfs get all' fails to get out " \
+ "all properties for dataset $ds."
+
+ (( propnum = 0 ))
+ (( failflag = 0 ))
+ done
+
+ (( i += 1 ))
+done
+
+log_note "'zfs get' can get particular property for all datasets with that property."
+
+function do_particular_prop_test #<property> <suitable datasets>
+{
+ typeset props="$1"
+ typeset ds="$2"
+
+ for prop in ${commprops[*]}; do
+ ds=`zfs get -H -o name $prop`
+
+ [[ "$ds" != "$allds" ]] && \
+ log_fail "The result datasets are $ds, but all suitable" \
+ "datasets are $allds for the property $prop"
+ done
+}
+
+# Here, we do a testing for user defined properties and the most common properties
+# for all datasets.
+commprop="type creation used referenced compressratio"
+usrprop="a:b d_1:1_e 123:456"
+
+do_particular_prop_test "$commprop" "$allds"
+do_particular_prop_test "$usrprop" "$usrpropds"
+
+log_pass "'zfs get all' works as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_005_neg.ksh
new file mode 100755
index 000000000000..510c54506d0f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_005_neg.ksh
@@ -0,0 +1,156 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib
+
+#
+# DESCRIPTION:
+# Setting the invalid option and properties, 'zfs get' should failed.
+#
+# STRATEGY:
+# 1. Create pool, filesystem, volume and snapshot.
+# 2. Getting incorrect combination by invalid parameters
+# 3. Using the combination as the parameters of 'zfs get' to check the
+# command line return value.
+#
+
+verify_runnable "both"
+
+typeset val_opts=(p r H)
+typeset v_props=(type used available creation volsize referenced compressratio \
+ mounted origin recordsize quota reservation mountpoint sharenfs checksum \
+ compression atime devices exec readonly setuid snapdir version \
+ aclinherit canmount primarycache secondarycache \
+ usedbychildren usedbydataset usedbyrefreservation usedbysnapshots)
+if is_freebsd; then
+ typeset v_props_os=(jailed aclmode)
+else
+ typeset v_props_os=(zoned acltype)
+fi
+typeset userquota_props=(userquota@root groupquota@root userused@root \
+ groupused@root)
+typeset val_props=("${v_props[@]}" \
+ "${v_props_os[@]}" \
+ "${userquota_props[@]}")
+set -f # Force shell does not parse '?' and '*' as the wildcard
+typeset inval_opts=(P R h ? *)
+typeset inval_props=(Type 0 ? * -on --on readonl time USED RATIO MOUNTED)
+
+typeset dataset=($TESTPOOL/$TESTFS $TESTPOOL/$TESTCTR $TESTPOOL/$TESTVOL \
+ $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTVOL@$TESTSNAP)
+
+typeset -i opt_numb=6
+typeset -i prop_numb=12
+
+val_opts_str=$(gen_option_str "${val_opts[*]}" "-" "" $opt_numb)
+val_props_str=$(gen_option_str "${val_props[*]}" "" "," $prop_numb)
+
+inval_opts_str=$(gen_option_str "${inval_opts[*]}" "-" "" $opt_numb)
+inval_props_str=$(gen_option_str "${inval_props[*]}" "" "," $prop_numb)
+
+typeset val_bookmark_props=(creation)
+typeset bookmark=($TESTPOOL/$TESTFS#$TESTBKMARK $TESTPOOL/$TESTVOL#$TESTBKMARK)
+
+#
+# Test different options and properties combination.
+#
+# $1 options
+# $2 properties
+#
+function test_options
+{
+ typeset opts=$1
+ typeset props=$2
+
+ for dst in ${dataset[@]}; do
+ for opt in $opts; do
+ for prop in $props; do
+ zfs get $opt -- $prop $dst > /dev/null 2>&1
+ ret=$?
+ if [[ $ret == 0 ]]; then
+ log_fail "zfs get $opt -- $prop " \
+ "$dst unexpectedly succeeded."
+ fi
+ done
+ done
+ done
+}
+
+#
+# Test different options and properties combination for bookmarks.
+#
+# $1 options
+# $2 properties
+#
+function test_options_bookmarks
+{
+ typeset opts=$1
+ typeset props=$2
+
+ for dst in ${bookmark[@]}; do
+ for opt in $opts; do
+ for prop in $props; do
+ zfs get $opt -- $prop $dst > /dev/null 2>&1
+ ret=$?
+ if [[ $ret == 0 ]]; then
+ log_fail "zfs get $opt -- $prop " \
+ "$dst unexpectedly succeeded."
+ fi
+ done
+ done
+ done
+}
+
+log_assert "Setting the invalid option and properties, 'zfs get' should be \
+ failed."
+log_onexit cleanup
+
+# Create filesystem and volume's snapshot
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+create_snapshot $TESTPOOL/$TESTVOL $TESTSNAP
+
+# Create filesystem and volume's bookmark
+create_bookmark $TESTPOOL/$TESTFS $TESTSNAP $TESTBKMARK
+create_bookmark $TESTPOOL/$TESTVOL $TESTSNAP $TESTBKMARK
+
+log_note "Valid options + invalid properties, 'zfs get' should fail."
+test_options "$val_opts_str" "$inval_props_str"
+test_options_bookmarks "$val_opts_str" "$inval_props_str"
+
+log_note "Invalid options + valid properties, 'zfs get' should fail."
+test_options "$inval_opts_str" "$val_props_str"
+test_options_bookmarks "$inval_opts_str" "$val_bookmark_props"
+
+log_note "Invalid options + invalid properties, 'zfs get' should fail."
+test_options "$inval_opts_str" "$inval_props_str"
+test_options_bookmarks "$inval_opts_str" "$inval_props_str"
+
+log_pass "Setting the invalid options to dataset, 'zfs get' pass."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_006_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_006_neg.ksh
new file mode 100755
index 000000000000..a91685849069
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_006_neg.ksh
@@ -0,0 +1,68 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify 'zfs get all' can deal with invalid scenarios
+#
+# STRATEGY:
+# 1. Define invalid scenarios for 'zfs get all'
+# 2. Run zfs get with those invalid scenarios
+# 3. Verify that zfs get fails with invalid scenarios
+#
+
+verify_runnable "both"
+
+log_assert "Verify 'zfs get all' fails with invalid combination scenarios."
+
+set -f # Force ksh ignore '?' and '*'
+set -A bad_combine "ALL" "\-R all" "-P all" "-h all" "-rph all" "-RpH all" "-PrH all" \
+ "-o all" "-s all" "-? all" "-* all" "-?* all" "all -r" "all -p" \
+ "all -H" "all -rp" "all -rH" "all -ph" "all -rpH" "all -r $TESTPOOL" \
+ "all -H $TESTPOOL" "all -p $TESTPOOL" "all -r -p -H $TESTPOOL" \
+ "all -rph $TESTPOOL" "all,available,reservation $TESTPOOL" \
+ "all $TESTPOOL?" "all $TESTPOOL*" "all nonexistpool"
+
+export POSIXLY_CORRECT=1
+
+typeset -i i=0
+while (( i < ${#bad_combine[*]} ))
+do
+ log_mustnot eval "zfs get ${bad_combine[i]} >/dev/null"
+
+ (( i = i + 1 ))
+done
+
+unset POSIXLY_CORRECT
+
+log_pass "'zfs get all' fails with invalid combinations scenarios as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_007_neg.ksh
new file mode 100755
index 000000000000..9bb00807f1b0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_007_neg.ksh
@@ -0,0 +1,64 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs get -o' should fail with invalid column names
+#
+# STRATEGY:
+# 1. Run zfs get -o with invalid column name combinations
+# 2. Verify that zfs get returns error
+#
+
+verify_runnable "both"
+
+log_assert "'zfs get -o' fails with invalid options or column names"
+
+set -A badargs "o name,property,value,resource" "o name" \
+ "-O name,property,value,source" "-oo name" "-o blah" \
+ "-o name,property,blah,source" "-o name,name,name,name,name" \
+ "-o name,property,value,," "-o *,*,*,*" "-o ?,?,?,?" \
+ "-o" "-o ,,,,," "-o -o -o -o" "-o NAME,PROPERTY,VALUE,SOURCE" \
+ "-o name,properTy,value,source" "-o name, property, value,source" \
+ "-o name:property:value:source" "-o name,property:value,source" \
+ "-o name;property;value;source"
+
+typeset -i i=0
+while (( i < ${#badargs[*]} ))
+do
+ log_mustnot eval "zfs get \"${badargs[i]}\" >/dev/null 2>&1"
+
+ (( i = i + 1 ))
+done
+
+log_pass "'zfs get -o' fails with invalid options or column name as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_008_pos.ksh
new file mode 100755
index 000000000000..296fe99968c8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_008_pos.ksh
@@ -0,0 +1,117 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib
+
+#
+# DESCRIPTION:
+# Verify "-d <n>" can work with other options
+#
+# STRATEGY:
+# 1. Create pool, filesystem, dataset, volume, snapshot, and bookmark.
+# 2. Getting an -d option, other options and properties random combination.
+# 3. Using the combination as the parameters of 'zfs get' to check the
+# command line return value.
+#
+
+verify_runnable "both"
+
+set -A options " " "-r" "-H" "-p" "-rHp" "-o name" \
+ "-s local,default,temporary,inherited,none" \
+ "-o name -s local,default,temporary,inherited,none" \
+ "-rHp -o name -s local,default,temporary,inherited,none"
+
+set -A props type used available creation volsize referenced compressratio \
+ mounted origin recordsize quota reservation mountpoint sharenfs \
+ checksum compression atime devices exec readonly setuid snapdir \
+ aclinherit canmount primarycache secondarycache \
+ usedbychildren usedbydataset usedbyrefreservation usedbysnapshots \
+ userquota@root groupquota@root userused@root groupused@root
+if is_freebsd; then
+ set -A props ${props[*]} jailed aclmode
+else
+ set -A props ${props[*]} zoned acltype
+fi
+
+zfs upgrade -v > /dev/null 2>&1
+if [[ $? -eq 0 ]]; then
+ set -A props ${props[*]} version
+fi
+
+set -A dataset $TESTPOOL/$TESTCTR $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL \
+ $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTVOL@$TESTSNAP
+
+set -A bookmark_props creation
+set -A bookmark $TESTPOOL/$TESTFS#$TESTBKMARK $TESTPOOL/$TESTVOL#$TESTBKMARK
+
+log_assert "Verify '-d <n>' can work with other options"
+log_onexit cleanup
+
+# Create volume and filesystem's snapshot
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+create_snapshot $TESTPOOL/$TESTVOL $TESTSNAP
+
+# Create filesystem and volume's bookmark
+create_bookmark $TESTPOOL/$TESTFS $TESTSNAP $TESTBKMARK
+create_bookmark $TESTPOOL/$TESTVOL $TESTSNAP $TESTBKMARK
+
+typeset -i opt_numb=16
+typeset -i prop_numb=16
+typeset -i i=0
+typeset -i item=0
+typeset -i depth_item=0
+
+for dst in ${dataset[@]}; do
+ (( i=0 ))
+ while (( i < opt_numb )); do
+ (( item = $RANDOM % ${#options[@]} ))
+ (( depth_item = $RANDOM % ${#depth_options[@]} ))
+ for prop in $(gen_option_str "${props[*]}" "" "," $prop_numb)
+ do
+ log_must eval "zfs get -${depth_options[depth_item]} ${options[item]} $prop $dst > /dev/null 2>&1"
+ done
+ (( i += 1 ))
+ done
+done
+
+for dst in ${bookmark[@]}; do
+ (( i=0 ))
+ while (( i < opt_numb )); do
+ (( item = $RANDOM % ${#options[@]} ))
+ (( depth_item = $RANDOM % ${#depth_options[@]} ))
+ log_must eval "zfs get -${depth_options[depth_item]} ${options[item]} $bookmark_props $dst > /dev/null 2>&1"
+ (( i += 1 ))
+ done
+done
+
+log_pass "Verify '-d <n>' can work with other options"
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_009_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_009_pos.ksh
new file mode 100755
index 000000000000..7fd6918b43db
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_009_pos.ksh
@@ -0,0 +1,112 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs get -d <n>' should get expected output.
+#
+# STRATEGY:
+# 1. Create a multiple depth filesystem.
+# 2. 'zfs get -d <n>' to get the output.
+# 3. 'zfs get -r|egrep' to get the expected output.
+# 4. Compare the two outputs, they should be same.
+#
+
+verify_runnable "both"
+
+if is_kmemleak; then
+ log_unsupported "Test case runs slowly when kmemleak is enabled"
+fi
+
+log_assert "'zfs get -d <n>' should get expected output."
+log_onexit depth_fs_cleanup
+
+set -A all_props type used available creation volsize referenced \
+ compressratio mounted origin recordsize quota reservation mountpoint \
+ sharenfs checksum compression atime devices exec readonly setuid \
+ snapdir aclinherit canmount primarycache secondarycache \
+ usedbychildren usedbydataset usedbyrefreservation usedbysnapshots \
+ userquota@root groupquota@root userused@root groupused@root
+if is_freebsd; then
+ set -A all_props ${all_props[*]} jailed aclmode
+else
+ set -A all_props ${all_props[*]} zoned acltype
+fi
+
+zfs upgrade -v > /dev/null 2>&1
+if [[ $? -eq 0 ]]; then
+ set -A all_props ${all_props[*]} version
+fi
+
+depth_fs_setup
+
+mntpnt=$(get_prop mountpoint $DEPTH_FS)
+DEPTH_OUTPUT="$mntpnt/depth_output"
+EXPECT_OUTPUT="$mntpnt/expect_output"
+typeset -i prop_numb=16
+typeset -i old_val=0
+typeset -i j=0
+typeset eg_opt="$DEPTH_FS"$
+for dp in ${depth_array[@]}; do
+ (( j=old_val+1 ))
+ while (( j<=dp && j<=MAX_DEPTH )); do
+ eg_opt="$eg_opt""|depth""$j"$
+ (( j+=1 ))
+ done
+ for prop in $(gen_option_str "${all_props[*]}" "" "," $prop_numb); do
+ log_must eval "zfs get -H -d $dp -o name $prop $DEPTH_FS > $DEPTH_OUTPUT"
+ log_must eval "zfs get -rH -o name $prop $DEPTH_FS | egrep -e '$eg_opt' > $EXPECT_OUTPUT"
+ log_must diff $DEPTH_OUTPUT $EXPECT_OUTPUT
+ done
+ (( old_val=dp ))
+done
+
+# Ensure 'zfs get -t snapshot <dataset>' works as though -d 1 was specified
+log_must eval "zfs get -H -t snapshot -o name creation $DEPTH_FS > $DEPTH_OUTPUT"
+log_must eval "zfs get -H -t snapshot -d 1 -o name creation $DEPTH_FS > $EXPECT_OUTPUT"
+log_must diff $DEPTH_OUTPUT $EXPECT_OUTPUT
+
+# Ensure 'zfs get -t snap' works as a shorthand for 'zfs get -t snapshot'
+log_must eval "zfs get -H -t snap -d 1 -o name creation $DEPTH_FS > $DEPTH_OUTPUT"
+log_must eval "zfs get -H -t snapshot -d 1 -o name creation $DEPTH_FS > $EXPECT_OUTPUT"
+log_must diff $DEPTH_OUTPUT $EXPECT_OUTPUT
+
+# Ensure 'zfs get -t bookmark <dataset>' works as though -d 1 was specified
+log_must eval "zfs get -H -t bookmark -o name creation $DEPTH_FS > $DEPTH_OUTPUT"
+log_must eval "zfs get -H -t bookmark -d 1 -o name creation $DEPTH_FS > $EXPECT_OUTPUT"
+log_must diff $DEPTH_OUTPUT $EXPECT_OUTPUT
+
+
+log_pass "'zfs get -d <n>' should get expected output."
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_010_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_010_neg.ksh
new file mode 100755
index 000000000000..e1f53845fd9c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_010_neg.ksh
@@ -0,0 +1,59 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib
+
+#
+# DESCRIPTION:
+# A negative depth or a non numeric depth should fail in 'zfs get -d <n>'
+#
+# STRATEGY:
+# 1. Run zfs get -d with negative depth or non numeric depth
+# 2. Verify that zfs get returns error
+#
+
+verify_runnable "both"
+
+log_assert "A negative depth or a non numeric depth should fail in 'zfs get -d <n>'"
+
+set -A badargs "a" "AB" "aBc" "2A" "a2b" "aB2" "-1" "-32" "-999"
+
+typeset -i i=0
+while (( i < ${#badargs[*]} ))
+do
+ log_mustnot eval "zfs get -d ${badargs[i]} $TESTPOOL/$TESTFS >/dev/null 2>&1"
+ (( i = i + 1 ))
+done
+
+log_pass "A negative depth or a non numeric depth should fail in 'zfs get -d <n>'"
+
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib
new file mode 100644
index 000000000000..d8cb9af028e5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_common.kshlib
@@ -0,0 +1,106 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# According to $elements, $prefix and $separator, the function random produce
+# the number of $counter combination.
+#
+# $1 elements which is used to get the combination.
+# $2 prefix is appended to the combination
+# $3 separator between the combination, such as ' ' or ','
+# $4 counter is the number of combination which you want to get.
+#
+function gen_option_str # $elements $prefix $separator $counter
+{
+ typeset elements=""
+ typeset prefix=${2}
+ typeset separator=${3}
+ typeset -i counter=${4:-0}
+ typeset -i i=0
+ typeset comb_str=""
+
+ for e in $1; do
+ elements[i]="$e"
+ (( i += 1 ))
+ done
+ (( ${#elements[@]} == 0 )) && log_fail "The elements can't be empty."
+
+ typeset -i item=0
+ typeset -i j=0
+ typeset -i numb_item=0
+
+ # Loop and get the specified number combination strings.
+ i=0
+ while (( i < counter )); do
+ j=0
+ numb_item=0
+ comb_str=""
+
+ # Get random number items for each combinations.
+ (( numb_item = ($RANDOM % ${#elements[@]}) + 1 ))
+
+ while (( j < numb_item )); do
+ # Random select elements from the array
+ (( item = $RANDOM % ${#elements[@]} ))
+
+ if (( ${#comb_str} == 0 )); then
+ comb_str=${elements[item]}
+ else
+ comb_str=$comb_str$separator${elements[item]}
+ fi
+ (( j += 1 ))
+ done
+
+ echo "$prefix$comb_str"
+
+ (( i += 1 ))
+ done
+}
+
+#
+# Cleanup the volume snapshot, filesystem snapshot, volume bookmark, and
+# filesystem bookmark that were created for this test case.
+#
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTVOL@$TESTSNAP && \
+ destroy_snapshot $TESTPOOL/$TESTVOL@$TESTSNAP
+ datasetexists $TESTPOOL/$TESTFS@$TESTSNAP && \
+ destroy_snapshot $TESTPOOL/$TESTFS@$TESTSNAP
+
+ bkmarkexists $TESTPOOL/$TESTVOL#$TESTBKMARK && \
+ destroy_bookmark $TESTPOOL/$TESTVOL#$TESTBKMARK
+ bkmarkexists $TESTPOOL/$TESTFS#$TESTBKMARK && \
+ destroy_bookmark $TESTPOOL/$TESTFS#$TESTBKMARK
+
+ [[ -e $TESTFILE0 ]] && log_must rm $TESTFILE0
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib
new file mode 100644
index 000000000000..48b3268f7813
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib
@@ -0,0 +1,84 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DEPTH_FS=$TESTPOOL/depth_fs
+MAX_DEPTH=3
+DS_COUNT=3
+set -A depth_options "d 0" "d 1" "d 2" "d 4" "d 32"
+set -A depth_array 0 1 2 4 32
+
+#
+# Setup multiple depths datasets, including fs, volumes, snapshots and bookmarks.
+#
+function depth_fs_setup
+{
+ typeset -i i j k
+ typeset fslist
+
+ log_must zfs create $DEPTH_FS
+
+ (( i=1 ))
+ while (( i<=MAX_DEPTH )); do
+ if (( i==1 )); then
+ fslist=$DEPTH_FS
+ else
+ (( k=i-1 ))
+ fslist=$(zfs list -rH -t filesystem -o name $DEPTH_FS|grep depth"$k"$)
+ if (( $? != 0 )); then
+ log_fail "No depth$k filesystem"
+ fi
+ fi
+ for fs in $fslist; do
+ (( j=1 ))
+ while (( j<=DS_COUNT )); do
+ log_must zfs create $fs/fs_"$j"_depth"$i"
+ if is_global_zone ; then
+ log_must zfs create -V 8M $fs/vol_"$j"_depth"$i"
+ fi
+ log_must zfs snapshot $fs@snap_"$j"_depth"$i"
+ log_must zfs bookmark $fs@snap_"$j"_depth"$i" '#bookmark'_"$j"_depth"$i"
+ (( j=j+1 ))
+ done
+ done
+ (( i=i+1 ))
+ done
+}
+
+#
+# Cleanup multiple depths filesystem.
+#
+function depth_fs_cleanup
+{
+ log_must zfs destroy -rR $DEPTH_FS
+}
+
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/Makefile.am
new file mode 100644
index 000000000000..5f5e3858787e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/Makefile.am
@@ -0,0 +1,5 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_ids_to_path
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_ids_to_path_001_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/cleanup.ksh
new file mode 100755
index 000000000000..b5ff02217237
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/cleanup.ksh
@@ -0,0 +1,29 @@
+#!/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) 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/setup.ksh
new file mode 100755
index 000000000000..fd6f8f8bb078
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/setup.ksh
@@ -0,0 +1,31 @@
+#!/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) 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_setup $DISKS
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/zfs_ids_to_path_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/zfs_ids_to_path_001_pos.ksh
new file mode 100755
index 000000000000..563b3e00dd89
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/zfs_ids_to_path_001_pos.ksh
@@ -0,0 +1,96 @@
+#!/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) 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION: Identify the objset id and the object id of a file in a
+# filesystem, and verify that zfs_ids_to_path behaves correctly with them.
+#
+# STRATEGY:
+# 1. Create a dataset
+# 2. Makes files in the dataset
+# 3. Verify that zfs_ids_to_path outputs the correct format for each one
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_dataset $TESTPOOL/$TESTFS
+ zfs create -o mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+function test_one
+{
+ typeset ds_id="$1"
+ typeset ds_path="$2"
+ typeset file_path="$3"
+
+ typeset mntpnt=$(get_prop mountpoint $ds_path)
+ typeset file_id=$(ls -i /$mntpnt/$file_path | sed 's/ .*//')
+ typeset output=$(zfs_ids_to_path $TESTPOOL $ds_id $file_id)
+ [[ "$output" == "$mntpnt/$file_path" ]] || \
+ log_fail "Incorrect output for non-verbose while mounted: $output"
+ output=$(zfs_ids_to_path -v $TESTPOOL $ds_id $file_id)
+ [[ "$output" == "$ds_path:/$file_path" ]] || \
+ log_fail "Incorrect output for verbose while mounted: $output"
+ log_must zfs unmount $ds_path
+ output=$(zfs_ids_to_path $TESTPOOL $ds_id $file_id)
+ [[ "$output" == "$ds_path:/$file_path" ]] || \
+ log_fail "Incorrect output for non-verbose while unmounted: $output"
+ output=$(zfs_ids_to_path -v $TESTPOOL $ds_id $file_id)
+ [[ "$output" == "$ds_path:/$file_path" ]] || \
+ log_fail "Incorrect output for verbose while unmounted: $output"
+ log_must zfs mount $ds_path
+}
+
+log_onexit cleanup
+
+typeset BASE=$TESTPOOL/$TESTFS
+typeset TESTFILE1=f1
+typeset TESTDIR1=d1
+typeset TESTFILE2=d1/f2
+typeset TESTDIR2=d1/d2
+typeset TESTFILE3=d1/d2/f3
+typeset TESTFILE4=d1/d2/f4
+
+typeset mntpnt=$(get_prop mountpoint $BASE)
+
+log_must touch /$mntpnt/$TESTFILE1
+log_must mkdir /$mntpnt/$TESTDIR1
+log_must touch /$mntpnt/$TESTFILE2
+log_must mkdir /$mntpnt/$TESTDIR2
+log_must touch /$mntpnt/$TESTFILE3
+log_must touch /$mntpnt/$TESTFILE4
+
+typeset ds_id=$(zdb $BASE | grep "^Dataset" | sed 's/.* ID \([0-9]*\).*/\1/')
+test_one $ds_id $BASE $TESTFILE1
+test_one $ds_id $BASE $TESTFILE2
+test_one $ds_id $BASE $TESTFILE3
+test_one $ds_id $BASE $TESTFILE4
+
+log_pass "zfs_ids_to_path displayed correctly"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/Makefile.am
new file mode 100644
index 000000000000..95a51ec757ea
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/Makefile.am
@@ -0,0 +1,8 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_inherit
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ zfs_inherit_001_neg.ksh \
+ zfs_inherit_002_neg.ksh \
+ zfs_inherit_003_pos.ksh \
+ zfs_inherit_mountpoint.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/setup.ksh
new file mode 100755
index 000000000000..9692385996d1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_container_volume_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_001_neg.ksh
new file mode 100755
index 000000000000..62f255ca38b7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_001_neg.ksh
@@ -0,0 +1,82 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs inherit' should return an error when attempting to inherit
+# properties which are not inheritable.
+#
+# STRATEGY:
+# 1. Create an array of properties which cannot be inherited
+# 2. For each property in the array, execute 'zfs inherit'
+# 3. Verify an error is returned.
+#
+
+verify_runnable "both"
+
+# Define uninherited properties and their short name.
+typeset props_str="type used available avail creation referenced refer \
+ compressratio ratio mounted origin quota reservation \
+ reserv volsize volblocksize volblock"
+
+zfs upgrade -v > /dev/null 2>&1
+if [[ $? -eq 0 ]]; then
+ props_str="$props_str version"
+fi
+
+set -A prop $props_str canmount
+
+
+log_assert "'zfs inherit' should return an error when attempting to inherit" \
+ " un-inheritable properties."
+
+typeset -i i=0
+for obj in $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL; do
+ i=0
+ while [[ $i -lt ${#prop[*]} ]]; do
+ orig_val=$(get_prop ${prop[i]} $obj)
+
+ log_mustnot zfs inherit ${prop[i]} $obj
+
+ new_val=$(get_prop ${prop[i]} $obj)
+
+ if [[ $new_val != $orig_val ]]; then
+ log_fail "${prop[i]} property changed from $orig_val "
+ " to $new_val"
+ fi
+ ((i = i + 1))
+ done
+done
+
+log_pass "'zfs inherit' failed as expected when attempting to inherit" \
+ " un-inheritable properties."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_002_neg.ksh
new file mode 100755
index 000000000000..61f22ea091d1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_002_neg.ksh
@@ -0,0 +1,107 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2011, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs inherit' should return an error with bad parameters in one command.
+#
+# STRATEGY:
+# 1. Set an array of bad options and invalid properties to 'zfs inherit'
+# 2. Execute 'zfs inherit' with bad options and passing invalid properties
+# 3. Verify an error is returned.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if snapexists $TESTPOOL/$TESTFS@$TESTSNAP; then
+ log_must zfs destroy $TESTPOOL/$TESTFS@$TESTSNAP
+ fi
+}
+
+log_assert "'zfs inherit' should return an error with bad parameters in" \
+ "one command."
+log_onexit cleanup
+
+set -A badopts "r" "R" "-R" "-rR" "-a" "-" "-?" "-1" "-2" "-v" "-n"
+set -A props "recordsize" "mountpoint" "sharenfs" "checksum" "compression" \
+ "atime" "devices" "exec" "setuid" "readonly" "snapdir" "aclmode" \
+ "aclinherit" "xattr" "copies"
+if is_freebsd; then
+ props+=("jailed")
+else
+ props+=("zoned")
+fi
+set -A illprops "recordsiz" "mountpont" "sharen" "compres" "atme" "blah"
+
+log_must zfs snapshot $TESTPOOL/$TESTFS@$TESTSNAP
+
+typeset -i i=0
+for ds in $TESTPOOL $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL \
+ $TESTPOOL/$TESTFS@$TESTSNAP; do
+
+ # zfs inherit should fail with bad options
+ for opt in ${badopts[@]}; do
+ for prop in ${props[@]}; do
+ log_mustnot eval "zfs inherit $opt $prop $ds \
+ >/dev/null 2>&1"
+ done
+ done
+
+ # zfs inherit should fail with invalid properties
+ for prop in "${illprops[@]}"; do
+ log_mustnot eval "zfs inherit $prop $ds >/dev/null 2>&1"
+ log_mustnot eval "zfs inherit -r $prop $ds >/dev/null 2>&1"
+ done
+
+ # zfs inherit should fail with too many arguments
+ (( i = 0 ))
+ while (( i < ${#props[*]} -1 )); do
+ log_mustnot eval "zfs inherit ${props[(( i ))]} \
+ ${props[(( i + 1 ))]} $ds >/dev/null 2>&1"
+ log_mustnot eval "zfs inherit -r ${props[(( i ))]} \
+ ${props[(( i + 1 ))]} $ds >/dev/null 2>&1"
+
+ (( i = i + 2 ))
+ done
+
+done
+
+# zfs inherit should fail with missing datasets
+for prop in ${props[@]}; do
+ log_mustnot eval "zfs inherit $prop >/dev/null 2>&1"
+ log_mustnot eval "zfs inherit -r $prop >/dev/null 2>&1"
+done
+
+log_pass "'zfs inherit' failed as expected when passing illegal arguments."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_003_pos.ksh
new file mode 100755
index 000000000000..3317b09e2b5b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_003_pos.ksh
@@ -0,0 +1,90 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs inherit' should return an error with bad parameters in one command.
+#
+# STRATEGY:
+# 1. Set an array of bad options and invalid properties to 'zfs inherit'
+# 2. Execute 'zfs inherit' with bad options and passing invalid properties
+# 3. Verify an error is returned.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for ds in $TESTPOOL $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL ; do
+ if snapexists $ds@$TESTSNAP; then
+ log_must zfs destroy $ds@$TESTSNAP
+ fi
+ done
+ cleanup_user_prop $TESTPOOL
+}
+
+log_assert "'zfs inherit' should inherit user property."
+log_onexit cleanup
+
+for ds in $TESTPOOL $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL ; do
+ typeset prop_name=$(valid_user_property 10)
+ typeset value=$(user_property_value 16)
+
+ log_must eval "zfs set $prop_name='$value' $ds"
+
+ log_must zfs snapshot $ds@$TESTSNAP
+
+ typeset snapvalue=$(get_prop $prop_name $ds@$TESTSNAP)
+
+ if [[ "$snapvalue" != "$value" ]] ; then
+ log_fail "The '$ds@$TESTSNAP '$prop_name' value '$snapvalue' " \
+ "not equal to the expected value '$value'."
+ fi
+
+ snapvalue=$(user_property_value 16)
+ log_must eval "zfs set $prop_name='$snapvalue' $ds@$TESTSNAP"
+
+ log_must zfs inherit $prop_name $ds@$TESTSNAP
+
+ snapvalue=$(get_prop $prop_name $ds@$TESTSNAP)
+
+ if [[ "$snapvalue" != "$value" ]] ; then
+ log_fail "The '$ds@$TESTSNAP '$prop_name' value '$snapvalue' " \
+ "not equal to the expected value '$value'."
+ fi
+
+
+done
+
+log_pass "'zfs inherit' inherit user property."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_mountpoint.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_mountpoint.ksh
new file mode 100755
index 000000000000..9c1251533c1e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_inherit/zfs_inherit_mountpoint.ksh
@@ -0,0 +1,62 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy is of the CDDL is also available via the Internet
+# at http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2018 Datto Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# zfs inherit should inherit mountpoint on mountpoint=none children
+#
+# STRATEGY:
+# 1. Create a set of nested datasets with mountpoint=none
+# 2. Verify datasets aren't mounted
+# 3. Inherit mountpoint and verify all datasets are now mounted
+#
+
+verify_runnable "both"
+
+function inherit_cleanup
+{
+ log_must zfs destroy -fR $TESTPOOL/inherit_test
+}
+
+log_onexit inherit_cleanup
+
+
+log_must zfs create -o mountpoint=none $TESTPOOL/inherit_test
+log_must zfs create $TESTPOOL/inherit_test/child
+
+if ismounted $TESTPOOL/inherit_test; then
+ log_fail "$TESTPOOL/inherit_test is mounted"
+fi
+if ismounted $TESTPOOL/inherit_test/child; then
+ log_fail "$TESTPOOL/inherit_test/child is mounted"
+fi
+
+log_must zfs inherit mountpoint $TESTPOOL/inherit_test
+
+if ! ismounted $TESTPOOL/inherit_test; then
+ log_fail "$TESTPOOL/inherit_test is not mounted"
+fi
+if ! ismounted $TESTPOOL/inherit_test/child; then
+ log_fail "$TESTPOOL/inherit_test/child is not mounted"
+fi
+
+log_pass "Verified mountpoint for mountpoint=none children inherited."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_jail/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/Makefile.am
new file mode 100644
index 000000000000..b6dd7721e63e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_jail
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ jail.conf \
+ zfs_jail_001_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_jail/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_jail/jail.conf b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/jail.conf
new file mode 100644
index 000000000000..23a9dabeb4bf
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/jail.conf
@@ -0,0 +1,9 @@
+testjail {
+ allow.mount.zfs;
+ allow.mount;
+ devfs_ruleset = 4;
+ enforce_statfs = 0;
+ mount.devfs;
+ path = "/";
+ persist;
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_jail/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_jail/zfs_jail_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/zfs_jail_001_pos.ksh
new file mode 100755
index 000000000000..2c0808110276
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_jail/zfs_jail_001_pos.ksh
@@ -0,0 +1,84 @@
+#!/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 2020 iXsystems, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Test basic functionality of `zfs jail` and `zfs unjail`.
+#
+# STRATEGY:
+# 1. Create a jail.
+# 2. Perform some basic ZFS operations on a dataset both in the host and
+# in the jail to confirm the dataset is functional in the host
+# and hidden in in the jail.
+# 3. Run `zfs jail` to expose the dataset in the jail.
+# 4. Perform some basic ZFS operations on the dataset both in the host and
+# in the jail to confirm the dataset is functional in the jail and host.
+# 5. Run `zfs unjail` to return the dataset to the host.
+# 6. Perform some basic ZFS operations on the dataset both in the host and
+# in the jail to confirm the dataset is functional in the host
+# and hidden in in the jail.
+#
+
+verify_runnable "global"
+
+JAIL="testjail"
+JAIL_CONF="$STF_SUITE/tests/functional/cli_root/zfs_jail/jail.conf"
+
+function cleanup
+{
+ if jls -j $JAIL name >/dev/null 2>&1; then
+ jail -r -f $JAIL_CONF $JAIL
+ fi
+}
+
+log_onexit cleanup
+
+log_assert "Verify that a dataset can be jailed and unjailed."
+
+# 1. Create a jail.
+log_must jail -c -f $JAIL_CONF $JAIL
+
+# 2. Try some basic ZFS operations.
+log_must zfs list $TESTPOOL
+log_mustnot jexec $JAIL zfs list $TESTPOOL
+
+# 3. Jail the dataset.
+log_must zfs jail $JAIL $TESTPOOL
+
+# 4. Try some basic ZFS operations.
+log_must zfs list $TESTPOOL
+log_must jexec $JAIL zfs list $TESTPOOL
+
+# 5. Unjail the dataset.
+log_must zfs unjail $JAIL $TESTPOOL
+
+# 6. Try some basic ZFS operations.
+log_must zfs list $TESTPOOL
+log_mustnot jexec $JAIL zfs list $TESTPOOL
+
+log_pass "Datasets can be jailed and unjailed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/Makefile.am
new file mode 100644
index 000000000000..06b4239a6d96
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/Makefile.am
@@ -0,0 +1,14 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_load-key
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_load-key.ksh \
+ zfs_load-key_all.ksh \
+ zfs_load-key_file.ksh \
+ zfs_load-key_location.ksh \
+ zfs_load-key_noop.ksh \
+ zfs_load-key_recursive.ksh
+
+dist_pkgdata_DATA = \
+ zfs_load-key.cfg \
+ zfs_load-key_common.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key.cfg
new file mode 100644
index 000000000000..90d9f63f1dba
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key.cfg
@@ -0,0 +1,26 @@
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+export PASSPHRASE="password"
+export PASSPHRASE1="password1"
+export PASSPHRASE2="password2"
+export HEXKEY="000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"
+export HEXKEY1="201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A090807060504030201"
+export RAWKEY="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+export RAWKEY1="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key.ksh
new file mode 100755
index 000000000000..847a6aabd3c8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key.ksh
@@ -0,0 +1,85 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs load-key' should only load a key for an unloaded encrypted dataset.
+#
+# STRATEGY:
+# 1. Attempt to load the default dataset's key
+# 2. Unmount the dataset
+# 3. Attempt to load the default dataset's key
+# 4. Create an encrypted dataset
+# 5. Unmount the dataset and unload its key
+# 6. Attempt to load the dataset's key
+# 7. Verify the dataset's key is loaded
+# 8. Attempt to load the dataset's key again
+# 9. Create an encrypted pool
+# 10. Unmount the pool and unload its key
+# 11. Attempt to load the pool's key
+# 12. Verify the pool's key is loaded
+# 13. Attempt to load the pool's key again
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy $TESTPOOL/$TESTFS1
+ poolexists $TESTPOOL1 && log_must destroy_pool $TESTPOOL1
+}
+log_onexit cleanup
+
+log_assert "'zfs load-key' should only load the key for an" \
+ "unloaded encrypted dataset"
+
+log_mustnot eval "echo $PASSPHRASE | zfs load-key $TESTPOOL/$TESTFS"
+
+log_must zfs unmount $TESTPOOL/$TESTFS
+log_mustnot eval "echo $PASSPHRASE | zfs load-key $TESTPOOL/$TESTFS"
+
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS1"
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+
+log_must eval "echo $PASSPHRASE | zfs load-key $TESTPOOL/$TESTFS1"
+log_must key_available $TESTPOOL/$TESTFS1
+
+log_mustnot eval "echo $PASSPHRASE | zfs load-key $TESTPOOL/$TESTFS1"
+
+typeset DISK2="$(echo $DISKS | awk '{ print $2 }')"
+log_must eval "echo $PASSPHRASE | zpool create -O encryption=on" \
+ "-O keyformat=passphrase -O keylocation=prompt $TESTPOOL1 $DISK2"
+
+log_must zfs unmount $TESTPOOL1
+log_must zfs unload-key $TESTPOOL1
+
+log_must eval "echo $PASSPHRASE | zfs load-key $TESTPOOL1"
+log_must key_available $TESTPOOL1
+
+log_mustnot eval "echo $PASSPHRASE | zfs load-key $TESTPOOL1"
+
+log_pass "'zfs load-key' only loads the key for an unloaded encrypted dataset"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_all.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_all.ksh
new file mode 100755
index 000000000000..5e331fd1200d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_all.ksh
@@ -0,0 +1,77 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs load-key -a' should load keys for all datasets.
+#
+# STRATEGY:
+# 1. Create an encrypted filesystem, encrypted zvol, and an encrypted pool
+# 2. Unmount all datasets and unload their keys
+# 3. Attempt to load all dataset keys
+# 4. Verify each dataset has its key loaded
+# 5. Attempt to mount the pool and filesystem
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy $TESTPOOL/$TESTFS1
+ datasetexists $TESTPOOL/zvol && log_must zfs destroy $TESTPOOL/zvol
+ poolexists $TESTPOOL1 && log_must destroy_pool $TESTPOOL1
+}
+log_onexit cleanup
+
+log_assert "'zfs load-key -a' should load keys for all datasets"
+
+log_must eval "echo $PASSPHRASE1 > /$TESTPOOL/pkey"
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1
+
+log_must zfs create -V 64M -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/zvol
+
+typeset DISK2="$(echo $DISKS | awk '{ print $2}')"
+log_must zpool create -O encryption=on -O keyformat=passphrase \
+ -O keylocation=file:///$TESTPOOL/pkey $TESTPOOL1 $DISK2
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+
+log_must zfs unload-key $TESTPOOL/zvol
+
+log_must zfs unmount $TESTPOOL1
+log_must zfs unload-key $TESTPOOL1
+
+log_must zfs load-key -a
+
+log_must key_available $TESTPOOL1
+log_must key_available $TESTPOOL/zvol
+log_must key_available $TESTPOOL/$TESTFS1
+
+log_must zfs mount $TESTPOOL1
+log_must zfs mount $TESTPOOL/$TESTFS1
+
+log_pass "'zfs load-key -a' loads keys for all datasets"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
new file mode 100644
index 000000000000..d9066f9cbf57
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
@@ -0,0 +1,101 @@
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key.cfg
+
+# Return 0 is a dataset key is available, 1 otherwise
+#
+# $1 - dataset
+#
+function key_available
+{
+ typeset ds=$1
+
+ datasetexists $ds || return 1
+
+ typeset val=$(get_prop keystatus $ds)
+ if [[ "$val" == "none" ]]; then
+ log_note "Dataset $ds is not encrypted"
+ elif [[ "$val" == "available" ]]; then
+ return 0
+ fi
+
+ return 1
+}
+
+function key_unavailable
+{
+ key_available $1 && return 1
+ return 0
+}
+
+function verify_keyformat
+{
+ typeset ds=$1
+ typeset format=$2
+ typeset fmt=$(get_prop keyformat $ds)
+
+ if [[ "$fmt" != "$format" ]]; then
+ log_fail "Expected keyformat $format, got $fmt"
+ fi
+
+ return 0
+}
+
+function verify_keylocation
+{
+ typeset ds=$1
+ typeset location=$2
+ typeset keyloc=$(get_prop keylocation $ds)
+
+ if [[ "$keyloc" != "$location" ]]; then
+ log_fail "Expected keylocation $location, got $keyloc"
+ fi
+
+ return 0
+}
+
+function verify_encryption_root
+{
+ typeset ds=$1
+ typeset val=$2
+ typeset eroot=$(get_prop encryptionroot $ds)
+
+ if [[ "$eroot" != "$val" ]]; then
+ log_note "Expected encryption root '$val', got '$eroot'"
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_origin
+{
+ typeset ds=$1
+ typeset val=$2
+ typeset orig=$(get_prop origin $ds)
+
+ if [[ "$orig" != "$val" ]]; then
+ log_note "Expected origin '$val', got '$orig'"
+ return 1
+ fi
+
+ return 0
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_file.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_file.ksh
new file mode 100755
index 000000000000..7cbda43ff241
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_file.ksh
@@ -0,0 +1,58 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs load-key' should load a dataset's key from a file.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset with a key file
+# 2. Unmount the dataset and unload the key
+# 3. Attempt to load the dataset's key
+# 4. Verify the key is loaded
+# 5. Attempt to mount the dataset
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy $TESTPOOL/$TESTFS1
+}
+log_onexit cleanup
+
+log_assert "'zfs load-key' should load a key from a file"
+
+log_must eval "echo $PASSPHRASE > /$TESTPOOL/pkey"
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+
+log_must zfs load-key $TESTPOOL/$TESTFS1
+log_must key_available $TESTPOOL/$TESTFS1
+log_must zfs mount $TESTPOOL/$TESTFS1
+
+log_pass "'zfs load-key' loads a key from a file"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_location.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_location.ksh
new file mode 100755
index 000000000000..d0b1cdb20ec7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_location.ksh
@@ -0,0 +1,73 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs load-key -L' should override keylocation with provided value.
+#
+# STRATEGY:
+# 1. Create a key file
+# 2. Copy the key file to another location
+# 3. Create an encrypted dataset using the keyfile
+# 4. Unmount the dataset and unload its key
+# 5. Attempt to load the dataset specifying a keylocation of file
+# 6. Verify the key is loaded
+# 7. Verify the keylocation is the original key file
+# 8. Unload the dataset's key
+# 9. Attempt to load the dataset specifying a keylocation of prompt
+# 10. Verify the key is loaded
+# 11. Verify the keylocation is the original key file
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy $TESTPOOL/$TESTFS1
+}
+log_onexit cleanup
+
+log_assert "'zfs load-key -L' should override keylocation with provided value"
+
+typeset key_location="/$TESTPOOL/pkey1"
+
+log_must eval "echo $PASSPHRASE > $key_location"
+log_must cp $key_location /$TESTPOOL/pkey2
+
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file://$key_location $TESTPOOL/$TESTFS1
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+
+log_must zfs load-key -L file:///$TESTPOOL/pkey2 $TESTPOOL/$TESTFS1
+log_must key_available $TESTPOOL/$TESTFS1
+log_must verify_keylocation $TESTPOOL/$TESTFS1 "file://$key_location"
+
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+log_must eval "echo $PASSPHRASE | zfs load-key -L prompt $TESTPOOL/$TESTFS1"
+log_must key_available $TESTPOOL/$TESTFS1
+log_must verify_keylocation $TESTPOOL/$TESTFS1 "file://$key_location"
+
+log_pass "'zfs load-key -L' overrides keylocation with provided value"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_noop.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_noop.ksh
new file mode 100755
index 000000000000..bfce786448d9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_noop.ksh
@@ -0,0 +1,54 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs load-key -n' should load the key for an already loaded dataset.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Attempt to load the dataset's key
+# 3. Verify the key is loaded
+# 4. Attempt to load the dataset's key with an invalid key
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy $TESTPOOL/$TESTFS1
+}
+log_onexit cleanup
+
+log_assert "'zfs load-key -n' should load the key for a loaded dataset"
+
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS1"
+
+log_must eval "echo $PASSPHRASE | zfs load-key -n $TESTPOOL/$TESTFS1"
+log_must key_available $TESTPOOL/$TESTFS1
+
+log_mustnot eval "echo $PASSPHRASE1 | zfs load-key -n $TESTPOOL/$TESTFS1"
+
+log_pass "'zfs load-key -n' loads the key for a loaded dataset"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_recursive.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_recursive.ksh
new file mode 100755
index 000000000000..7385b69cf5fe
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_load-key/zfs_load-key_recursive.ksh
@@ -0,0 +1,66 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs load-key -r' should recursively load keys.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Create a child dataset as an encryption root
+# 3. Unmount all datasets and unload their keys
+# 4. Attempt to load all dataset keys
+# 5. Verify each dataset has its key loaded
+# 6. Attempt to mount each dataset
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+}
+log_onexit cleanup
+
+log_assert "'zfs load-key -r' should recursively load keys"
+
+log_must eval "echo $PASSPHRASE1 > /$TESTPOOL/pkey"
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1
+
+log_must zfs create -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1/child
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1/child
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+
+log_must zfs load-key -r $TESTPOOL
+log_must key_available $TESTPOOL/$TESTFS1
+log_must key_available $TESTPOOL/$TESTFS1/child
+
+log_must zfs mount $TESTPOOL/$TESTFS1
+log_must zfs mount $TESTPOOL/$TESTFS1/child
+
+log_pass "'zfs load-key -r' recursively loads keys"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/Makefile.am
new file mode 100644
index 000000000000..37c0942381cc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/Makefile.am
@@ -0,0 +1,27 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_mount
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_mount_001_pos.ksh \
+ zfs_mount_002_pos.ksh \
+ zfs_mount_003_pos.ksh \
+ zfs_mount_004_pos.ksh \
+ zfs_mount_005_pos.ksh \
+ zfs_mount_006_pos.ksh \
+ zfs_mount_007_pos.ksh \
+ zfs_mount_008_pos.ksh \
+ zfs_mount_009_neg.ksh \
+ zfs_mount_010_neg.ksh \
+ zfs_mount_011_neg.ksh \
+ zfs_mount_012_pos.ksh \
+ zfs_mount_all_001_pos.ksh \
+ zfs_mount_all_fail.ksh \
+ zfs_mount_all_mountpoints.ksh \
+ zfs_mount_encrypted.ksh \
+ zfs_mount_remount.ksh \
+ zfs_mount_test_race.ksh \
+ zfs_multi_mount.ksh
+
+dist_pkgdata_DATA = \
+ zfs_mount.cfg \
+ zfs_mount.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.cfg
new file mode 100644
index 000000000000..c8e46895d2a6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.cfg
@@ -0,0 +1,39 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+export mountcmd=mount
+export mountforce="$mountcmd -f"
+export mountall="$mountcmd -a"
+
+export unmountcmd=unmount
+export unmountforce="$unmountcmd -f"
+export unmountall="$unmountcmd -a"
+
+export NONEXISTFSNAME="nonexistfs50charslong_0123456789012345678901234567"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
new file mode 100644
index 000000000000..bd45fabbcde9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
@@ -0,0 +1,134 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.cfg
+
+function force_unmount #dev
+{
+ typeset dev=$1
+
+ ismounted $dev
+ if (( $? == 0 )); then
+ log_must zfs $unmountforce $dev
+ fi
+ return 0
+}
+
+# Create pool and ( fs | container | vol ) with the given parameters,
+# it'll destroy prior exist one that has the same name.
+
+function setup_filesystem #disklist #pool #fs #mntpoint #type #vdev
+{
+ typeset disklist=$1
+ typeset pool=$2
+ typeset fs=${3##/}
+ typeset mntpoint=$4
+ typeset type=$5
+ typeset vdev=$6
+
+ if [[ -z $pool || -z $fs || -z $mntpoint ]]; then
+ log_note "Missing parameter: (\"$pool\", \"$fs\", \"$mntpoint\")"
+ return 1
+ fi
+
+ if is_global_zone && [[ -z $disklist ]] ; then
+ log_note "Missing disklist."
+ return 1
+ fi
+
+ if [[ $vdev != "" && \
+ $vdev != "mirror" && \
+ $vdev != "raidz" ]] ; then
+
+ log_note "Wrong vdev: (\"$vdev\")"
+ return 1
+ fi
+
+ poolexists $pool || \
+ create_pool $pool $vdev $disklist
+
+ datasetexists $pool/$fs && \
+ log_must cleanup_filesystem $pool $fs
+
+ rmdir $mntpoint > /dev/null 2>&1
+ if [[ ! -d $mntpoint ]]; then
+ log_must mkdir -p $mntpoint
+ fi
+
+ case "$type" in
+ 'ctr') log_must zfs create -o mountpoint=$mntpoint $pool/$fs
+ ;;
+ 'vol') log_must zfs create -V $VOLSIZE $pool/$fs
+ block_device_wait
+ ;;
+ *) log_must zfs create -o mountpoint=$mntpoint $pool/$fs
+ ;;
+ esac
+
+ return 0
+}
+
+# Destroy ( fs | container | vol ) with the given parameters.
+function cleanup_filesystem #pool #fs
+{
+ typeset pool=$1
+ typeset fs=${2##/}
+ typeset mtpt=""
+
+ if [[ -z $pool || -z $fs ]]; then
+ log_note "Missing parameter: (\"$pool\", \"$fs\")"
+ return 1
+ fi
+
+ if datasetexists "$pool/$fs" ; then
+ mtpt=$(get_prop mountpoint "$pool/$fs")
+ destroy_dataset "$pool/$fs" "-r"
+
+ [[ -d $mtpt ]] && \
+ log_must rm -rf $mtpt
+ else
+ return 1
+ fi
+
+ return 0
+}
+
+# Make sure 'zfs mount' should display all ZFS filesystems currently mounted.
+# The results of 'zfs mount' and 'df -F zfs' should be identical.
+function verify_mount_display
+{
+ typeset fs
+
+ for fs in $(zfs $mountcmd | awk '{print $1}') ; do
+ log_must mounted $fs
+ done
+ return 0
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_001_pos.ksh
new file mode 100755
index 000000000000..c46a35695492
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_001_pos.ksh
@@ -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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+
+#
+# DESCRIPTION:
+# Invoke "zfs mount <filesystem>" with a regular name of filesystem,
+# will mount that filesystem successfully.
+#
+# STRATEGY:
+# 1. Make sure that the ZFS filesystem is unmounted.
+# 2. Invoke 'zfs mount <filesystem>'.
+# 3. Verify that the filesystem is mounted.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must force_unmount $TESTPOOL/$TESTFS
+ return 0
+}
+
+log_assert "Verify that 'zfs $mountcmd <filesystem>' succeeds as root."
+
+log_onexit cleanup
+
+unmounted $TESTPOOL/$TESTFS || \
+ log_must cleanup
+
+log_must zfs $mountcmd $TESTPOOL/$TESTFS
+
+log_note "Make sure the filesystem $TESTPOOL/$TESTFS is mounted"
+mounted $TESTPOOL/$TESTFS || \
+ log_fail Filesystem $TESTPOOL/$TESTFS is unmounted
+
+log_pass "'zfs $mountcmd <filesystem>' succeeds as root."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_002_pos.ksh
new file mode 100755
index 000000000000..8ee3e029fb4a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_002_pos.ksh
@@ -0,0 +1,78 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+
+#
+# DESCRIPTION:
+# Invoking "zfs mount <filesystem>" with a filesystem whose name is not in
+# "zfs list", will fail with a return code of 1.
+#
+# STRATEGY:
+# 1. Make sure the NONEXISTFSNAME ZFS filesystem is not in 'zfs list'.
+# 2. Invoke 'zfs mount <filesystem>'.
+# 3. Verify that mount failed with return code of 1.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset fs
+ for fs in $NONEXISTFSNAME $TESTFS ; do
+ log_must force_unmount $TESTPOOL/$fs
+ done
+}
+
+
+log_assert "Verify that 'zfs $mountcmd' with a filesystem " \
+ "whose name is not in 'zfs list' will fail with return code 1."
+
+log_onexit cleanup
+
+log_note "Make sure the filesystem $TESTPOOL/$NONEXISTFSNAME " \
+ "is not in 'zfs list'"
+log_mustnot zfs list $TESTPOOL/$NONEXISTFSNAME
+
+typeset -i ret=0
+zfs $mountcmd $TESTPOOL/$NONEXISTFSNAME
+ret=$?
+(( ret == 1 )) || \
+ log_fail "'zfs $mountcmd $TESTPOOL/$NONEXISTFSNAME' " \
+ "unexpected return code of $ret."
+
+log_note "Make sure the filesystem $TESTPOOL/$NONEXISTFSNAME is unmounted"
+unmounted $TESTPOOL/$NONEXISTFSNAME || \
+ log_fail Filesystem $TESTPOOL/$NONEXISTFSNAME is mounted
+
+log_pass "'zfs $mountcmd' with a filesystem " \
+ "whose name is not in 'zfs list' failed with return code 1."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_003_pos.ksh
new file mode 100755
index 000000000000..59d8c235f8fe
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_003_pos.ksh
@@ -0,0 +1,90 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+
+#
+# DESCRIPTION:
+# Invoke "zfs mount <filesystem>" with a filesystem whose mountpoint property
+# is 'legacy' or 'none',
+# it will fail with a return code of 1 and issue an error message.
+#
+# STRATEGY:
+# 1. Make sure that the ZFS filesystem is unmounted.
+# 2. Mount the filesystem using the various combinations
+# - zfs set mountpoint=legacy <filesystem>
+# - zfs set mountpoint=none <filesystem>
+# 3. Verify that mount failed with return code of 1.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+ log_must force_unmount $TESTPOOL/$TESTFS
+ return 0
+}
+
+log_assert "Verify that 'zfs $mountcmd' with a filesystem " \
+ "whose mountpoint property is 'legacy' or 'none' " \
+ "will fail with return code 1."
+
+log_onexit cleanup
+
+set -A mopt "legacy" "none"
+
+typeset -i ret=0
+typeset -i i=0
+
+while (( i < ${#mopt[*]} )); do
+ unmounted $TESTPOOL/$TESTFS || \
+ log_must cleanup
+
+ log_must zfs set mountpoint=${mopt[i]} $TESTPOOL/$TESTFS
+
+ zfs $mountcmd $TESTPOOL/$TESTFS
+ ret=$?
+ (( ret == 1)) || \
+ log_fail "'zfs $mountcmd $TESTPOOL/$TESTFS' " \
+ "unexpected return code of $ret."
+
+ log_note "Make sure the filesystem $TESTPOOL/$TESTFS is unmounted"
+ unmounted $TESTPOOL/$TESTFS || \
+ log_fail Filesystem $TESTPOOL/$TESTFS is mounted
+
+ ((i = i + 1))
+done
+
+log_pass "Verify that 'zfs $mountcmd' with a filesystem " \
+ "whose mountpoint property is 'legacy' or 'none' " \
+ "will fail with return code 1."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_004_pos.ksh
new file mode 100755
index 000000000000..4874c6d6530a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_004_pos.ksh
@@ -0,0 +1,83 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+
+#
+# DESCRIPTION:
+# Invoke "zfs mount <filesystem>" with a filesystem
+# which has been already mounted,
+# it will fail with a return code of 1
+#
+# STRATEGY:
+# 1. Make sure that the ZFS filesystem is unmounted.
+# 2. Invoke 'zfs mount <filesystem>'.
+# 3. Verify that the filesystem is mounted.
+# 4. Invoke 'zfs mount <filesystem>' the second times.
+# 5. Verify the last mount operation failed with return code of 1.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must force_unmount $TESTPOOL/$TESTFS
+ return 0
+}
+
+typeset -i ret=0
+
+log_assert "Verify that 'zfs $mountcmd <filesystem>' " \
+ "with a mounted filesystem will fail with return code 1."
+
+log_onexit cleanup
+
+unmounted $TESTPOOL/$TESTFS || \
+ log_must cleanup
+
+log_must zfs $mountcmd $TESTPOOL/$TESTFS
+
+mounted $TESTPOOL/$TESTFS || \
+ log_unresolved "Filesystem $TESTPOOL/$TESTFS is unmounted"
+
+zfs $mountcmd $TESTPOOL/$TESTFS
+ret=$?
+(( ret == 1 )) || \
+ log_fail "'zfs $mountcmd $TESTPOOL/$TESTFS' " \
+ "unexpected return code of $ret."
+
+log_note "Make sure the filesystem $TESTPOOL/$TESTFS is mounted"
+mounted $TESTPOOL/$TESTFS || \
+ log_fail Filesystem $TESTPOOL/$TESTFS is unmounted
+
+log_pass "'zfs $mountcmd <filesystem>' with a mounted filesystem " \
+ "will fail with return code 1."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_005_pos.ksh
new file mode 100755
index 000000000000..c0cb693f6ce6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_005_pos.ksh
@@ -0,0 +1,99 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+
+#
+# DESCRIPTION:
+# Invoke "zfs mount <filesystem>" with a filesystem but its mountpoint
+# is currently in use. Under Linux this should succeed and is the
+# expected behavior, it will fail with a return code of 1 and issue
+# an error message on other platforms.
+#
+# STRATEGY:
+# 1. Make sure that the ZFS filesystem is unmounted.
+# 2. Apply 'zfs set mountpoint=path <filesystem>'.
+# 3. Change directory to that given mountpoint.
+# 3. Invoke 'zfs mount <filesystem>'.
+# 4. Verify that mount succeeds on Linux and FreeBSD and fails for other
+# platforms.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ [[ "$PWD" = "$TESTDIR" ]] && cd -
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+ log_must force_unmount $TESTPOOL/$TESTFS
+ return 0
+}
+
+typeset -i ret=0
+
+log_assert "Verify that 'zfs $mountcmd' with a filesystem " \
+ "whose mountpoint is currently in use will fail with return code 1."
+
+log_onexit cleanup
+
+unmounted $TESTPOOL/$TESTFS || \
+ log_must cleanup
+
+[[ -d $TESTDIR ]] || \
+ log_must mkdir -p $TESTDIR
+
+cd $TESTDIR || \
+ log_unresolved "Unable change directory to $TESTDIR"
+
+zfs $mountcmd $TESTPOOL/$TESTFS
+ret=$?
+if is_linux || is_freebsd; then
+ (( ret == 0 )) || \
+ log_fail "'zfs $mountcmd $TESTPOOL/$TESTFS' " \
+ "unexpected return code of $ret."
+else
+ (( ret == 1 )) || \
+ log_fail "'zfs $mountcmd $TESTPOOL/$TESTFS' " \
+ "unexpected return code of $ret."
+fi
+
+log_note "Make sure the filesystem $TESTPOOL/$TESTFS is unmounted"
+if is_linux || is_freebsd; then
+ mounted $TESTPOOL/$TESTFS || \
+ log_fail Filesystem $TESTPOOL/$TESTFS is unmounted
+else
+ unmounted $TESTPOOL/$TESTFS || \
+ log_fail Filesystem $TESTPOOL/$TESTFS is mounted
+fi
+
+log_pass "'zfs $mountcmd' with a filesystem " \
+ "whose mountpoint is currently in use failed with return code 1."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_006_pos.ksh
new file mode 100755
index 000000000000..5edce35c721e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_006_pos.ksh
@@ -0,0 +1,147 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+# Copyright (c) 2018, Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+
+#
+# DESCRIPTION:
+# Invoke "zfs mount <filesystem>" with a filesystem mountpoint that is
+# identical to an existing one. It will fail with a return code of 1
+# when overlay=off. Place a file in the directory to ensure the failure.
+# Also test overlay=on (default) in which case the mount will not fail.
+#
+# STRATEGY:
+# 1. Prepare an existing mounted filesystem.
+# 2. Setup a new filesystem with overlay=off and make sure that it is
+# unmounted.
+# 3. Place a file in the mount point folder.
+# 4. Mount the new filesystem using the various combinations
+# - zfs set mountpoint=<identical path> <filesystem>
+# - zfs set mountpoint=<top path> <filesystem>
+# 5. Verify that mount failed with return code of 1.
+# 6. For Linux, also set overlay=on and verify the mount is
+# allowed.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must force_unmount $TESTPOOL/$TESTFS
+
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ cleanup_filesystem $TESTPOOL $TESTFS1
+
+ [[ -d $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+ log_must force_unmount $TESTPOOL/$TESTFS
+
+ return 0
+}
+
+typeset -i ret=0
+
+log_assert "Verify that 'zfs $mountcmd <filesystem>'" \
+ "where the mountpoint is identical or on top of an existing one" \
+ "will fail with return code 1 when overlay=off."
+
+log_onexit cleanup
+
+unmounted $TESTPOOL/$TESTFS || \
+ log_must force_unmount $TESTPOOL/$TESTFS
+
+[[ -d $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR
+
+typeset -i MAXDEPTH=3
+typeset -i depth=0
+typeset mtpt=$TESTDIR
+
+while (( depth < MAXDEPTH )); do
+ mtpt=$mtpt/$depth
+ (( depth = depth + 1))
+done
+
+log_must zfs set mountpoint=$mtpt $TESTPOOL/$TESTFS
+log_must zfs $mountcmd $TESTPOOL/$TESTFS
+
+log_must zfs set overlay=off $TESTPOOL/$TESTFS
+if ! is_illumos; then
+ touch $mtpt/file.1
+ log_must ls -l $mtpt | grep file
+fi
+
+mounted $TESTPOOL/$TESTFS || \
+ log_unresolved "Filesystem $TESTPOOL/$TESTFS is unmounted"
+
+log_must zfs create -o overlay=off $TESTPOOL/$TESTFS1
+
+unmounted $TESTPOOL/$TESTFS1 || \
+ log_must force_unmount $TESTPOOL/$TESTFS1
+
+while [[ $depth -gt 0 ]] ; do
+ (( depth == MAXDEPTH )) && \
+ log_note "Verify that 'zfs $mountcmd <filesystem>'" \
+ "with a mountpoint that is identical to an existing one" \
+ "will fail with return code 1."
+
+ log_must zfs set mountpoint=$mtpt $TESTPOOL/$TESTFS1
+ log_note "zfs $mountcmd $TESTPOOL/$TESTFS1"
+
+ log_mustnot zfs $mountcmd $TESTPOOL/$TESTFS1
+
+ if ! is_illumos; then
+ # Test the overlay=on feature which allows
+ # mounting of non-empty directory.
+ log_must zfs set overlay=on $TESTPOOL/$TESTFS1
+ log_must zfs $mountcmd $TESTPOOL/$TESTFS1
+ log_must force_unmount $TESTPOOL/$TESTFS1
+ log_must zfs set overlay=off $TESTPOOL/$TESTFS1
+ fi
+
+ unmounted $TESTPOOL/$TESTFS1 || \
+ log_fail "Filesystem $TESTPOOL/$TESTFS1 is mounted."
+
+ mtpt=${mtpt%/*}
+
+ (( depth == MAXDEPTH )) && \
+ log_note "Verify that 'zfs $mountcmd <filesystem>'" \
+ "with a mountpoint on top of an existing one" \
+ "will fail with return code 1."
+ (( depth = depth - 1 ))
+done
+
+log_pass "'zfs $mountcmd <filesystem>'" \
+ "with a mountpoint that is identical or on top of an existing one" \
+ "will fail with return code 1."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_007_pos.ksh
new file mode 100755
index 000000000000..409dd06d7f88
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_007_pos.ksh
@@ -0,0 +1,163 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+
+#
+# DESCRIPTION:
+# The following options can be set on a temporary basis using the -o option
+# without affecting the on-disk property. The original on-disk value will be
+# restored when the file system is unmounted and mounted.
+#
+# PROPERTY MOUNT OPTION
+# atime atime/noatime
+# devices devices/nodevices
+# exec exec/noexec
+# readonly ro/rw
+# setuid setuid/nosetuid
+#
+# STRATEGY:
+# 1. Create filesystem and get original property value.
+# 2. Using 'zfs mount -o' to set filesystem property.
+# 3. Verify the property was set temporarily.
+# 4. Verify it will not affect the property that is stored on disk.
+#
+
+function cleanup
+{
+ if ! ismounted $TESTPOOL/$TESTFS; then
+ log_must zfs mount $TESTPOOL/$TESTFS
+ fi
+}
+
+log_assert "Verify '-o' will set filesystem property temporarily, " \
+ "without affecting the property that is stored on disk."
+log_onexit cleanup
+
+set -A properties "atime" "exec" "readonly" "setuid"
+if ! is_freebsd; then
+ properties+=("devices")
+fi
+
+#
+# Get the specified filesystem property reverse mount option.
+#
+# $1 filesystem
+# $2 property
+#
+function get_reverse_option
+{
+ typeset fs=$1
+ typeset prop=$2
+
+ # Define property value: "reverse if value=on" "reverse if value=off"
+ if is_linux; then
+ set -A values "noatime" "atime" \
+ "noexec" "exec" \
+ "rw" "ro" \
+ "nosuid" "suid" \
+ "nodev" "dev"
+ elif is_freebsd; then
+ set -A values "noatime" "atime" \
+ "noexec" "exec" \
+ "rw" "ro" \
+ "nosetuid" "setuid"
+ else
+ set -A values "noatime" "atime" \
+ "noexec" "exec" \
+ "rw" "ro" \
+ "nosetuid" "setuid" \
+ "nodevices" "devices"
+ fi
+
+ typeset -i i=0
+ while (( i < ${#properties[@]} )); do
+ if [[ $prop == ${properties[$i]} ]]; then
+ break
+ fi
+
+ (( i += 1 ))
+ done
+ if (( i >= ${#properties[@]} )); then
+ log_fail "Incorrect option: $prop"
+ fi
+
+ typeset val
+ typeset -i ind=0
+ val=$(get_prop $prop $fs) || log_fail "get_prop $prop $fs"
+ if [[ $val == "on" ]]; then
+ (( ind = i * 2 ))
+ else
+ (( ind = i * 2 + 1 ))
+ fi
+
+ echo ${values[$ind]}
+}
+
+fs=$TESTPOOL/$TESTFS
+cleanup
+
+for property in ${properties[@]}; do
+ orig_val=$(get_prop $property $fs)
+ (($? != 0)) && log_fail "get_prop $property $fs"
+
+ # Set filesystem property temporarily
+ reverse_opt=$(get_reverse_option $fs $property)
+ log_must zfs unmount $fs
+ log_must zfs mount -o $reverse_opt $fs
+
+ cur_val=$(get_prop $property $fs)
+ (($? != 0)) && log_fail "get_prop $property $fs"
+
+ # In LZ, a user with all zone privileges can never with "devices"
+ if ! is_global_zone && [[ $property == devices ]] ; then
+ if [[ $cur_val != off || $orig_val != off ]]; then
+ log_fail "'devices' property shouldn't " \
+ "be enabled in LZ"
+ fi
+ elif [[ $orig_val == $cur_val ]]; then
+ log_fail "zfs mount -o $reverse_opt " \
+ "doesn't change property."
+ fi
+
+ # unmount & mount will revert property to the original value
+ log_must zfs unmount $fs
+ log_must zfs mount $fs
+
+ cur_val=$(get_prop $property $fs)
+ (($? != 0)) && log_fail "get_prop $property $fs"
+ if [[ $orig_val != $cur_val ]]; then
+ log_fail "zfs mount -o $reverse_opt " \
+ "change the property that is stored on disks"
+ fi
+done
+
+log_pass "Verify '-o' set filesystem property temporarily passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_008_pos.ksh
new file mode 100755
index 000000000000..4b3bf40bc3be
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_008_pos.ksh
@@ -0,0 +1,97 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs mount -O' allow the file system to be mounted over an existing
+# mount point, making the underlying file system inaccessible.
+#
+# STRATEGY:
+# 1. Create two filesystem fs & fs1, and create two test files for them.
+# 2. Unmount fs1 and set mountpoint property is identical to fs.
+# 3. Verify 'zfs mount -O' will make the underlying filesystem fs
+# inaccessible.
+#
+
+function cleanup
+{
+ ! ismounted $fs && log_must zfs mount $fs
+
+ if datasetexists $fs1; then
+ log_must zfs destroy $fs1
+ fi
+
+ if [[ -f $testfile ]]; then
+ log_must rm -f $testfile
+ fi
+}
+
+log_assert "Verify 'zfs mount -O' will override existing mount point."
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS; fs1=$TESTPOOL/$TESTFS1
+
+cleanup
+
+# Get the original mountpoint of $fs and $fs1
+mntpnt=$(get_prop mountpoint $fs)
+log_must zfs create $fs1
+mntpnt1=$(get_prop mountpoint $fs1)
+
+testfile=$mntpnt/$TESTFILE0; testfile1=$mntpnt1/$TESTFILE1
+log_must mkfile 1M $testfile $testfile1
+
+log_must zfs unmount $fs1
+log_must zfs set mountpoint=$mntpnt $fs1
+log_must zfs mount $fs1
+log_must zfs unmount $fs1
+log_must zfs mount -O $fs1
+
+# Create new file in override mountpoint
+log_must mkfile 1M $mntpnt/$TESTFILE2
+
+# Verify the underlying file system inaccessible
+log_mustnot ls $testfile
+log_must ls $mntpnt/$TESTFILE1 $mntpnt/$TESTFILE2
+
+# Verify $TESTFILE2 was created in $fs1, rather than $fs
+log_must zfs unmount $fs1
+log_must zfs set mountpoint=$mntpnt1 $fs1
+log_must zfs mount $fs1
+log_must ls $testfile1 $mntpnt1/$TESTFILE2
+
+# Verify $TESTFILE2 was not created in $fs, and $fs is accessible again.
+log_mustnot ls $mntpnt/$TESTFILE2
+log_must ls $testfile
+
+log_pass "Verify 'zfs mount -O' override mount point passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_009_neg.ksh
new file mode 100755
index 000000000000..978a5a4f2eea
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_009_neg.ksh
@@ -0,0 +1,111 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+
+#
+# DESCRIPTION:
+# Try each 'zfs mount' with inapplicable scenarios to make sure
+# it returns an error. include:
+# * '-a', but also with a specific filesystem.
+#
+# STRATEGY:
+# 1. Create an array of parameters
+# 2. For each parameter in the array, execute the sub-command
+# 3. Verify an error is returned.
+#
+
+verify_runnable "both"
+
+multifs="$TESTFS $TESTFS1"
+datasets=""
+
+for fs in $multifs ; do
+ datasets="$datasets $TESTPOOL/$fs"
+done
+
+set -A args "$mountall $TESTPOOL/$TESTFS"
+
+function setup_all
+{
+ typeset fs
+
+ for fs in $multifs ; do
+ setup_filesystem "$DISKS" "$TESTPOOL" \
+ "$fs" \
+ "${TEST_BASE_DIR%%/}/testroot$$/$TESTPOOL/$fs"
+ done
+ return 0
+}
+
+function cleanup_all
+{
+ typeset fs
+
+ cleanup_filesystem "$TESTPOOL" "$TESTFS1"
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+
+ [[ -d ${TEST_BASE_DIR%%/}/testroot$$ ]] && \
+ rm -rf ${TEST_BASE_DIR%%/}/testroot$$
+
+
+ return 0
+}
+
+function verify_all
+{
+ typeset fs
+
+ for fs in $multifs ; do
+ log_must unmounted $TESTPOOL/$fs
+ done
+ return 0
+}
+
+log_assert "Badly-formed 'zfs $mountcmd' with inapplicable scenarios " \
+ "should return an error."
+log_onexit cleanup_all
+
+log_must setup_all
+
+log_must zfs $unmountall
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_mustnot zfs ${args[i]}
+ ((i = i + 1))
+done
+
+log_must verify_all
+
+log_pass "Badly formed 'zfs $mountcmd' with inapplicable scenarios " \
+ "fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_010_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_010_neg.ksh
new file mode 100755
index 000000000000..53ebf1f26248
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_010_neg.ksh
@@ -0,0 +1,75 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that zfs mount should fail when mounting a mounted zfs filesystem or
+# the mountpoint is busy. On Linux the mount should succeed.
+#
+# STRATEGY:
+# 1. Make a zfs filesystem mounted or mountpoint busy
+# 2. Use zfs mount to mount the filesystem
+# 3. Verify that zfs mount succeeds on Linux and fails for other platforms
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if ! ismounted $fs; then
+ log_must zfs mount $fs
+ fi
+}
+
+log_assert "zfs mount fails with mounted filesystem or busy mountpoint"
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+if ! ismounted $fs; then
+ log_must zfs mount $fs
+fi
+
+log_mustnot zfs mount $fs
+
+mpt=$(get_prop mountpoint $fs)
+log_must zfs umount $fs
+curpath=`dirname $0`
+cd $mpt
+if is_linux || is_freebsd; then
+ log_must zfs mount $fs
+else
+ log_mustnot zfs mount $fs
+fi
+cd $curpath
+
+log_pass "zfs mount fails with mounted filesystem or busy mountpoint as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_011_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_011_neg.ksh
new file mode 100755
index 000000000000..a116b4647c09
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_011_neg.ksh
@@ -0,0 +1,81 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that zfs mount should fail with bad parameters
+#
+# STRATEGY:
+# 1. Make an array of bad parameters
+# 2. Use zfs mount to mount the filesystem
+# 3. Verify that zfs mount returns error
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if snapexists $TESTPOOL/$TESTFS@$TESTSNAP; then
+ log_must_busy zfs destroy $TESTPOOL/$TESTFS@$TESTSNAP
+ fi
+
+ if is_global_zone && datasetexists $TESTPOOL/$TESTVOL; then
+ log_must_busy zfs destroy $TESTPOOL/$TESTVOL
+ fi
+}
+
+log_assert "zfs mount fails with bad parameters"
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+set -A badargs "A" "-A" "-" "-x" "-?" "=" "-o *" "-a"
+
+for arg in "${badargs[@]}"; do
+ log_mustnot eval "zfs mount $arg $fs >/dev/null 2>&1"
+done
+
+#verify that zfs mount fails with invalid dataset
+for opt in "-o abc" "-O"; do
+ log_mustnot eval "zfs mount $opt /$fs >/dev/null 2>&1"
+done
+
+#verify that zfs mount fails with volume and snapshot
+log_must zfs snapshot $TESTPOOL/$TESTFS@$TESTSNAP
+log_mustnot eval "zfs mount $TESTPOOL/$TESTFS@$TESTSNAP >/dev/null 2>&1"
+
+if is_global_zone; then
+ log_must zfs create -V 10m $TESTPOOL/$TESTVOL
+ log_mustnot eval "zfs mount $TESTPOOL/$TESTVOL >/dev/null 2>&1"
+fi
+
+log_pass "zfs mount fails with bad parameters as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_012_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_012_pos.ksh
new file mode 100755
index 000000000000..5ff094d2c479
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_012_pos.ksh
@@ -0,0 +1,53 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2015 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that zfs mount succeeds with a non-empty directory
+#
+
+#
+# STRATEGY:
+# 1. Unmount the dataset
+# 2. Create a new empty directory
+# 3. Set the dataset's mountpoint
+# 4. Attempt to mount the dataset
+# 5. Verify the mount succeeds
+# 6. Unmount the dataset
+# 7. Create a file in the directory created in step 2
+# 8. Attempt to mount the dataset
+# 9. Verify the mount succeeds
+#
+
+verify_runnable "both"
+
+log_assert "zfs mount succeeds with non-empty directory"
+
+fs=$TESTPOOL/$TESTFS
+
+log_must zfs umount $fs
+log_must mkdir -p $TESTDIR
+log_must zfs set mountpoint=$TESTDIR $fs
+log_must zfs mount $fs
+log_must zfs umount $fs
+log_must touch $TESTDIR/testfile.$$
+log_must zfs mount $fs
+log_must zfs umount $fs
+log_must rm -rf $TESTDIR
+
+log_pass "zfs mount succeeds with non-empty directory as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_001_pos.ksh
new file mode 100755
index 000000000000..765e242796b8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_001_pos.ksh
@@ -0,0 +1,202 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+
+# DESCRIPTION:
+# Verify that 'zfs mount -a' succeeds as root.
+#
+# STRATEGY:
+# 1. Create a group of pools with specified vdev.
+# 2. Create zfs filesystems within the given pools.
+# 3. Unmount all the filesystems.
+# 4. Verify that 'zfs mount -a' command succeed,
+# and all available ZFS filesystems are mounted.
+# 5. Verify that 'zfs mount' is identical with 'df -F zfs'
+#
+
+verify_runnable "both"
+
+set -A fs "$TESTFS" "$TESTFS1"
+set -A ctr "" "$TESTCTR" "$TESTCTR/$TESTCTR1" "$TESTCTR1"
+set -A vol "$TESTVOL" "$TESTVOL1"
+
+function setup_all
+{
+ typeset -i i=0
+ typeset -i j=0
+ typeset path
+
+ while (( i < ${#ctr[*]} )); do
+
+ path=${TEST_BASE_DIR%%/}/testroot$$/$TESTPOOL
+ if [[ -n ${ctr[i]} ]]; then
+ path=$path/${ctr[i]}
+
+ setup_filesystem "$DISKS" "$TESTPOOL" \
+ "${ctr[i]}" "$path" \
+ "ctr"
+ fi
+
+ if is_global_zone ; then
+ j=0
+ while (( j < ${#vol[*]} )); do
+ setup_filesystem "$DISKS" "$TESTPOOL" \
+ "${ctr[i]}/${vol[j]}" \
+ "$path/${vol[j]}" \
+ "vol"
+ ((j = j + 1))
+ done
+ fi
+
+ j=0
+ while (( j < ${#fs[*]} )); do
+ setup_filesystem "$DISKS" "$TESTPOOL" \
+ "${ctr[i]}/${fs[j]}" \
+ "$path/${fs[j]}"
+ ((j = j + 1))
+ done
+
+ ((i = i + 1))
+ done
+
+ return 0
+}
+
+function cleanup_all
+{
+ typeset -i i=0
+ typeset -i j=0
+ typeset path
+
+ ((i = ${#ctr[*]} - 1))
+
+ while (( i >= 0 )); do
+ if is_global_zone ; then
+ j=0
+ while (( j < ${#vol[*]} )); do
+ cleanup_filesystem "$TESTPOOL" \
+ "${ctr[i]}/${vol[j]}"
+ ((j = j + 1))
+ done
+ fi
+
+ j=0
+ while (( j < ${#fs[*]} )); do
+ cleanup_filesystem "$TESTPOOL" \
+ "${ctr[i]}/${fs[j]}"
+ ((j = j + 1))
+ done
+
+ [[ -n ${ctr[i]} ]] && \
+ cleanup_filesystem "$TESTPOOL" "${ctr[i]}"
+
+ ((i = i - 1))
+ done
+
+ [[ -d ${TEST_BASE_DIR%%/}/testroot$$ ]] && \
+ rm -rf ${TEST_BASE_DIR%%/}/testroot$$
+}
+
+#
+# This function takes a single true/false argument. If true it will verify that
+# all file systems are mounted. If false it will verify that they are not
+# mounted.
+#
+function verify_all
+{
+ typeset -i i=0
+ typeset -i j=0
+ typeset path
+ typeset logfunc
+
+ if $1; then
+ logfunc=log_must
+ else
+ logfunc=log_mustnot
+ fi
+
+ while (( i < ${#ctr[*]} )); do
+
+ path=$TESTPOOL
+ [[ -n ${ctr[i]} ]] && \
+ path=$path/${ctr[i]}
+
+ if is_global_zone ; then
+ j=0
+ while (( j < ${#vol[*]} )); do
+ log_mustnot mounted "$path/${vol[j]}"
+ ((j = j + 1))
+ done
+ fi
+
+ j=0
+ while (( j < ${#fs[*]} )); do
+ $logfunc mounted "$path/${fs[j]}"
+ ((j = j + 1))
+ done
+
+ $logfunc mounted "$path"
+
+ ((i = i + 1))
+ done
+
+ return 0
+}
+
+
+log_assert "Verify that 'zfs $mountall' succeeds as root, " \
+ "and all available ZFS filesystems are mounted."
+
+log_onexit cleanup_all
+
+log_must setup_all
+
+export __ZFS_POOL_RESTRICT="$TESTPOOL"
+log_must zfs $unmountall
+unset __ZFS_POOL_RESTRICT
+
+verify_all false
+
+export __ZFS_POOL_RESTRICT="$TESTPOOL"
+log_must zfs $mountall
+unset __ZFS_POOL_RESTRICT
+
+verify_all true
+
+log_note "Verify that 'zfs $mountcmd' will display " \
+ "all ZFS filesystems currently mounted."
+
+verify_mount_display
+
+log_pass "'zfs $mountall' succeeds as root, " \
+ "and all available ZFS filesystems are mounted."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_fail.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_fail.ksh
new file mode 100755
index 000000000000..d1103bddccbd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_fail.ksh
@@ -0,0 +1,105 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+
+# DESCRIPTION:
+# Verify that if 'zfs mount -a' fails to mount one filesystem,
+# the command fails with a non-zero error code, but all other
+# filesystems are mounted.
+#
+# STRATEGY:
+# 1. Create zfs filesystems
+# 2. Unmount a leaf filesystem
+# 3. Create a file in the above filesystem's mountpoint
+# 4. Verify that 'zfs mount -a' succeeds if overlay=on and
+# fails to mount the above if overlay=off
+# 5. Verify that all other filesystems were mounted
+#
+
+verify_runnable "both"
+
+typeset -a filesystems
+typeset path=${TEST_BASE_DIR%%/}/testroot$$/$TESTPOOL
+typeset fscount=10
+
+function setup_all
+{
+ # Create $fscount filesystems at the top level of $path
+ for ((i=0; i<$fscount; i++)); do
+ setup_filesystem "$DISKS" "$TESTPOOL" $i "$path/$i" ctr
+ done
+
+ zfs list -r $TESTPOOL
+
+ return 0
+}
+
+function cleanup_all
+{
+ export __ZFS_POOL_RESTRICT="$TESTPOOL"
+ log_must zfs $unmountall
+ unset __ZFS_POOL_RESTRICT
+
+ [[ -d ${TEST_BASE_DIR%%/}/testroot$$ ]] && \
+ rm -rf ${TEST_BASE_DIR%%/}/testroot$$
+}
+
+log_onexit cleanup_all
+
+log_must setup_all
+
+#
+# Unmount all of the above so that we can create the stray file
+# in one of the mountpoint directories.
+#
+export __ZFS_POOL_RESTRICT="$TESTPOOL"
+log_must zfs $unmountall
+unset __ZFS_POOL_RESTRICT
+
+# All of our filesystems should be unmounted at this point
+for ((i=0; i<$fscount; i++)); do
+ log_mustnot mounted "$TESTPOOL/$i"
+done
+
+# Create a stray file in one filesystem's mountpoint
+touch $path/0/strayfile
+
+export __ZFS_POOL_RESTRICT="$TESTPOOL"
+
+# Verify that zfs mount -a succeeds with overlay=on (default)
+log_must zfs $mountall
+log_must mounted "$TESTPOOL/0"
+log_must zfs $unmountall
+
+# Verify that zfs mount -a succeeds with overlay=off
+log_must zfs set overlay=off "$TESTPOOL/0"
+log_mustnot zfs $mountall
+log_mustnot mounted "$TESTPOOL/0"
+
+unset __ZFS_POOL_RESTRICT
+
+# All other filesystems should be mounted
+for ((i=1; i<$fscount; i++)); do
+ log_must mounted "$TESTPOOL/$i"
+done
+
+log_pass "'zfs $mountall' behaves as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_mountpoints.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_mountpoints.ksh
new file mode 100755
index 000000000000..3e6a24bbcda3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_all_mountpoints.ksh
@@ -0,0 +1,162 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+
+# DESCRIPTION:
+# Verify that 'zfs mount -a' succeeds given a set of filesystems
+# whose mountpoints have a parent/child relationship which is
+# counter to the filesystem parent/child relationship.
+#
+# STRATEGY:
+# 1. Create zfs filesystems within the given pool.
+# 2. Unmount all the filesystems.
+# 3. Verify that 'zfs mount -a' command succeed,
+# and all available ZFS filesystems are mounted.
+# 4. Verify that 'zfs mount' is identical with 'df -F zfs'
+#
+
+verify_runnable "both"
+
+typeset -a filesystems
+
+function setup_all
+{
+ typeset path=${TEST_BASE_DIR%%/}/testroot$$/$TESTPOOL
+ typeset fscount=10
+
+ #
+ # Generate an array of filesystem names that represent a deep
+ # hierarchy as such:
+ #
+ # 0
+ # 0/1
+ # 0/1/2
+ # 0/1/2/3
+ # 0/1/2/3/4
+ # ...
+ #
+ fs=0
+ for ((i=0; i<$fscount; i++)); do
+ if [[ $i -gt 0 ]]; then
+ fs=$fs/$i
+ fi
+ filesystems+=($fs)
+ done
+
+ # Create all of the above filesystems
+ for ((i=0; i<$fscount; i++)); do
+ fs=${filesystems[$i]}
+ setup_filesystem "$DISKS" "$TESTPOOL" "$fs" "$path/$i" ctr
+ done
+
+ zfs list -r $TESTPOOL
+
+ #
+ # Unmount all of the above so that we can setup our convoluted
+ # mount paths.
+ #
+ export __ZFS_POOL_RESTRICT="$TESTPOOL"
+ log_must zfs $unmountall
+ unset __ZFS_POOL_RESTRICT
+
+ #
+ # Configure the mount paths so that each mountpoint is contained
+ # in a child filesystem. We should end up with something like the
+ # following structure (modulo the number of filesystems):
+ #
+ # NAME MOUNTPOINT
+ # testpool /testpool
+ # testpool/0 /testroot25416/testpool/0/1/2/3/4/5/6
+ # testpool/0/1 /testroot25416/testpool/0/1/2/3/4/5
+ # testpool/0/1/2 /testroot25416/testpool/0/1/2/3/4
+ # testpool/0/1/2/3 /testroot25416/testpool/0/1/2/3
+ # testpool/0/1/2/3/4 /testroot25416/testpool/0/1/2
+ # testpool/0/1/2/3/4/5 /testroot25416/testpool/0/1
+ # testpool/0/1/2/3/4/5/6 /testroot25416/testpool/0
+ #
+ for ((i=0; i<$fscount; i++)); do
+ fs=$TESTPOOL/${filesystems[$(($fscount - $i - 1))]}
+ mnt=$path/${filesystems[$i]}
+ zfs set mountpoint=$mnt $fs
+ done
+
+ zfs list -r $TESTPOOL
+
+ return 0
+}
+
+function cleanup_all
+{
+ export __ZFS_POOL_RESTRICT="$TESTPOOL"
+ log_must zfs $unmountall
+ unset __ZFS_POOL_RESTRICT
+
+ for fs in ${filesystems[@]}; do
+ cleanup_filesystem "$TESTPOOL" "$fs"
+ done
+ [[ -d ${TEST_BASE_DIR%%/}/testroot$$ ]] && \
+ rm -rf ${TEST_BASE_DIR%%/}/testroot$$
+}
+
+#
+# This function takes a single true/false argument. If true it will verify that
+# all file systems are mounted. If false it will verify that they are not
+# mounted.
+#
+function verify_all
+{
+ if $1; then
+ logfunc=log_must
+ else
+ logfunc=log_mustnot
+ fi
+
+ for fs in ${filesystems[@]}; do
+ $logfunc mounted "$TESTPOOL/$fs"
+ done
+
+ return 0
+}
+
+log_onexit cleanup_all
+
+log_must setup_all
+
+export __ZFS_POOL_RESTRICT="$TESTPOOL"
+log_must zfs $unmountall
+unset __ZFS_POOL_RESTRICT
+
+verify_all false
+
+export __ZFS_POOL_RESTRICT="$TESTPOOL"
+log_must zfs $mountall
+unset __ZFS_POOL_RESTRICT
+
+verify_all true
+
+log_note "Verify that 'zfs $mountcmd' will display " \
+ "all ZFS filesystems currently mounted."
+
+verify_mount_display
+
+log_pass "'zfs $mountall' succeeds as root, " \
+ "and all available ZFS filesystems are mounted."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_encrypted.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_encrypted.ksh
new file mode 100755
index 000000000000..9749a9b3aa8a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_encrypted.ksh
@@ -0,0 +1,69 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017, Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs mount -l' should accept a valid key as it mounts the filesystem.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Unmount and unload the dataset's key
+# 3. Verify the key is unloaded
+# 4. Attempt to mount all datasets in the pool
+# 5. Verify that no error code is produced
+# 6. Verify that the encrypted dataset is not mounted
+# 7. Attempt to load the key while mounting the dataset
+# 8. Verify the key is loaded
+# 9. Verify the dataset is mounted
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS1
+}
+
+log_onexit cleanup
+
+log_assert "'zfs mount -l' should properly load a valid wrapping key"
+
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS1"
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+log_must key_unavailable $TESTPOOL/$TESTFS1
+
+log_must zfs mount -a
+unmounted $TESTPOOL/$TESTFS1 || \
+ log_fail "Filesystem $TESTPOOL/$TESTFS1 is mounted"
+
+log_must eval "echo $PASSPHRASE | zfs mount -l $TESTPOOL/$TESTFS1"
+log_must key_available $TESTPOOL/$TESTFS1
+
+mounted $TESTPOOL/$TESTFS1 || \
+ log_fail "Filesystem $TESTPOOL/$TESTFS1 is unmounted"
+
+log_pass "'zfs mount -l' properly loads a valid wrapping key"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_remount.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_remount.ksh
new file mode 100755
index 000000000000..9712c793a919
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_remount.ksh
@@ -0,0 +1,171 @@
+#!/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 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+
+#
+# DESCRIPTION:
+# Verify remount functionality, especially on readonly objects.
+#
+# STRATEGY:
+# 1. Prepare a filesystem and a snapshot
+# 2. Verify we can (re)mount the dataset readonly/read-write
+# 3. Verify we can mount the snapshot and it's mounted readonly
+# 4. Verify we can't remount it read-write
+# 5. Verify we can remount a dataset readonly and unmount it with
+# encryption=on and sync=disabled (issue #7753)
+# 6. Re-import the pool readonly
+# 7. Verify we can't remount its filesystem read-write
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must_busy zpool export $TESTPOOL
+ log_must zpool import $TESTPOOL
+ snapexists $TESTSNAP && log_must zfs destroy $TESTSNAP
+ [[ -d $MNTPSNAP ]] && log_must rmdir $MNTPSNAP
+ return 0
+}
+
+if is_freebsd; then
+ typeset RO="-t zfs -ur"
+ typeset RW="-t zfs -uw"
+else
+ typeset RO="-o remount,ro"
+ typeset RW="-o remount,rw"
+fi
+
+#
+# Verify the $filesystem is mounted readonly
+# This is preferred over "log_mustnot touch $fs" because we actually want to
+# verify the error returned is EROFS
+#
+function readonlyfs # filesystem
+{
+ typeset filesystem="$1"
+
+ file_write -o create -f $filesystem/file.dat
+ ret=$?
+ if [[ $ret != 30 ]]; then
+ log_fail "Writing to $filesystem did not return EROFS ($ret)."
+ fi
+}
+
+#
+# Verify $dataset is mounted with $option
+#
+function checkmount # dataset option
+{
+ typeset dataset="$1"
+ typeset option="$2"
+ typeset options=""
+
+ if is_freebsd; then
+ options=$(mount -p | awk -v ds="$dataset" '$1 == ds { print $4 }')
+ else
+ options=$(awk -v ds="$dataset" '$1 == ds { print $4 }' /proc/mounts)
+ fi
+ if [[ "$options" == '' ]]; then
+ log_fail "Dataset $dataset is not mounted"
+ elif [[ ! -z "${options##*$option*}" ]]; then
+ log_fail "Dataset $dataset is not mounted with expected "\
+ "option $option ($options)"
+ else
+ log_note "Dataset $dataset is mounted with option $option"
+ fi
+}
+
+log_assert "Verify remount functionality on both filesystem and snapshots"
+
+log_onexit cleanup
+
+# 1. Prepare a filesystem and a snapshot
+TESTFS=$TESTPOOL/$TESTFS
+TESTSNAP="$TESTFS@snap"
+datasetexists $TESTFS || log_must zfs create $TESTFS
+snapexists $TESTSNAP || log_must zfs snapshot $TESTSNAP
+log_must zfs set readonly=off $TESTFS
+MNTPFS="$(get_prop mountpoint $TESTFS)"
+MNTPSNAP="$TESTDIR/zfs_snap_mount"
+log_must mkdir -p $MNTPSNAP
+
+# 2. Verify we can (re)mount the dataset readonly/read-write
+log_must touch $MNTPFS/file.dat
+checkmount $TESTFS 'rw'
+log_must mount $RO $TESTFS $MNTPFS
+readonlyfs $MNTPFS
+checkmount $TESTFS 'ro'
+log_must mount $RW $TESTFS $MNTPFS
+log_must touch $MNTPFS/file.dat
+checkmount $TESTFS 'rw'
+
+if is_linux; then
+ # 3. Verify we can (re)mount the snapshot readonly
+ log_must mount -t zfs $TESTSNAP $MNTPSNAP
+ readonlyfs $MNTPSNAP
+ checkmount $TESTSNAP 'ro'
+ log_must mount $RO $TESTSNAP $MNTPSNAP
+ readonlyfs $MNTPSNAP
+ checkmount $TESTSNAP 'ro'
+ log_must umount $MNTPSNAP
+fi
+
+# 4. Verify we can't remount a snapshot read-write
+# The "mount -o rw" command will succeed but the snapshot is mounted readonly.
+# The "mount -o remount,rw" command must fail with an explicit error.
+log_must mount -t zfs -o rw $TESTSNAP $MNTPSNAP
+readonlyfs $MNTPSNAP
+checkmount $TESTSNAP 'ro'
+log_mustnot mount $RW $TESTSNAP $MNTPSNAP
+readonlyfs $MNTPSNAP
+checkmount $TESTSNAP 'ro'
+log_must umount $MNTPSNAP
+
+# 5. Verify we can remount a dataset readonly and unmount it with
+# encryption=on and sync=disabled (issue #7753)
+log_must eval "echo 'password' | zfs create -o sync=disabled \
+ -o encryption=on -o keyformat=passphrase $TESTFS/crypt"
+CRYPT_MNTPFS="$(get_prop mountpoint $TESTFS/crypt)"
+log_must touch $CRYPT_MNTPFS/file.dat
+log_must mount $RO $TESTFS/crypt $CRYPT_MNTPFS
+log_must umount -f $CRYPT_MNTPFS
+zpool sync $TESTPOOL
+
+# 6. Re-import the pool readonly
+log_must zpool export $TESTPOOL
+log_must zpool import -o readonly=on $TESTPOOL
+
+# 7. Verify we can't remount its filesystem read-write
+readonlyfs $MNTPFS
+checkmount $TESTFS 'ro'
+log_mustnot mount $RW $MNTPFS
+readonlyfs $MNTPFS
+checkmount $TESTFS 'ro'
+
+log_pass "Both filesystem and snapshots can be remounted correctly."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_test_race.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_test_race.ksh
new file mode 100755
index 000000000000..404770b2727f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_test_race.ksh
@@ -0,0 +1,116 @@
+#!/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2019 by Tomohiro Kusumi. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.cfg
+
+#
+# DESCRIPTION:
+# Verify parallel mount ordering is consistent.
+#
+# There was a bug in initial thread dispatching algorithm which put threads
+# under race condition which resulted in undefined mount order. The purpose
+# of this test is to verify `zfs unmount -a` succeeds (not `zfs mount -a`
+# succeeds, it always does) after `zfs mount -a`, which could fail if threads
+# race. See github.com/zfsonlinux/zfs/issues/{8450,8833,8878} for details.
+#
+# STRATEGY:
+# 1. Create pools and filesystems.
+# 2. Set same mount point for >1 datasets.
+# 3. Unmount all datasets.
+# 4. Mount all datasets.
+# 5. Unmount all datasets (verify this succeeds).
+#
+
+verify_runnable "both"
+
+TMPDIR=${TMPDIR:-$TEST_BASE_DIR}
+MNTPT=$TMPDIR/zfs_mount_test_race_mntpt
+DISK1="$TMPDIR/zfs_mount_test_race_disk1"
+DISK2="$TMPDIR/zfs_mount_test_race_disk2"
+
+TESTPOOL1=zfs_mount_test_race_tp1
+TESTPOOL2=zfs_mount_test_race_tp2
+
+export __ZFS_POOL_RESTRICT="$TESTPOOL1 $TESTPOOL2"
+log_must zfs $unmountall
+unset __ZFS_POOL_RESTRICT
+
+function cleanup
+{
+ zpool destroy $TESTPOOL1
+ zpool destroy $TESTPOOL2
+ rm -rf $MNTPT
+ rm -rf /$TESTPOOL1
+ rm -rf /$TESTPOOL2
+ rm -f $DISK1
+ rm -f $DISK2
+ export __ZFS_POOL_RESTRICT="$TESTPOOL1 $TESTPOOL2"
+ log_must zfs $mountall
+ unset __ZFS_POOL_RESTRICT
+}
+log_onexit cleanup
+
+log_note "Verify parallel mount ordering is consistent"
+
+log_must truncate -s $MINVDEVSIZE $DISK1
+log_must truncate -s $MINVDEVSIZE $DISK2
+
+log_must zpool create -f $TESTPOOL1 $DISK1
+log_must zpool create -f $TESTPOOL2 $DISK2
+
+log_must zfs create $TESTPOOL1/$TESTFS1
+log_must zfs create $TESTPOOL2/$TESTFS2
+
+log_must zfs set mountpoint=none $TESTPOOL1
+log_must zfs set mountpoint=$MNTPT $TESTPOOL1/$TESTFS1
+
+# Note that unmount can fail (due to race condition on `zfs mount -a`) with or
+# without `canmount=off`. The race has nothing to do with canmount property,
+# but turn it off for convenience of mount layout used in this test case.
+log_must zfs set canmount=off $TESTPOOL2
+log_must zfs set mountpoint=$MNTPT $TESTPOOL2
+
+# At this point, layout of datasets in two pools will look like below.
+# Previously, on next `zfs mount -a`, pthreads assigned to TESTFS1 and TESTFS2
+# could race, and TESTFS2 usually (actually always) won in ZoL. Note that the
+# problem is how two or more threads could initially be assigned to the same
+# top level directory, not this specific layout. This layout is just an example
+# that can reproduce race, and is also the layout reported in #8833.
+#
+# NAME MOUNTED MOUNTPOINT
+# ----------------------------------------------
+# /$TESTPOOL1 no none
+# /$TESTPOOL1/$TESTFS1 yes $MNTPT
+# /$TESTPOOL2 no $MNTPT
+# /$TESTPOOL2/$TESTFS2 yes $MNTPT/$TESTFS2
+
+# Apparently two datasets must be mounted.
+log_must ismounted $TESTPOOL1/$TESTFS1
+log_must ismounted $TESTPOOL2/$TESTFS2
+# This unmount always succeeds, because potential race hasn't happened yet.
+log_must zfs unmount -a
+# This mount always succeeds, whether threads are under race condition or not.
+log_must zfs mount -a
+
+# Verify datasets are mounted (TESTFS2 fails if the race broke mount order).
+log_must ismounted $TESTPOOL1/$TESTFS1
+log_must ismounted $TESTPOOL2/$TESTFS2
+# Verify unmount succeeds (fails if the race broke mount order).
+log_must zfs unmount -a
+
+log_pass "Verify parallel mount ordering is consistent passed"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_multi_mount.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_multi_mount.ksh
new file mode 100755
index 000000000000..bd86eaa16bb4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_multi_mount.ksh
@@ -0,0 +1,109 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy is of the CDDL is also available via the Internet
+# at http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright(c) 2018 Datto Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify multi mount functionality
+#
+# STRATEGY:
+# 1. Create fs
+# 2. Create and hold open file in filesystem
+# 3. Lazy unmount
+# 4. Verify remounting fs that was lazily unmounted is possible
+# 5. Verify multiple mounts of the same dataset are possible
+# 6. Verify bind mount doesn't prevent rename
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ ismounted $MNTPFS && log_must umount $MNTPFS
+ ismounted $MNTPFS2 && log_must umount $MNTPFS2
+ ismounted $MNTPFS3 && log_must umount $MNTPFS3
+ ismounted $MNTPFS4 && log_must umount $MNTPFS4
+ ismounted $RENAMEMNT && log_must umount $RENAMEMNT
+ datasetexists $TESTDS && log_must destroy_dataset "$TESTDS" "-f"
+}
+log_onexit cleanup
+
+log_assert "Verify multiple mounts into one namespace are possible"
+
+# 1. Create fs
+TESTDS="$TESTPOOL/multi-mount-test"
+log_must zfs create $TESTDS
+
+# 2. Create and hold open file in filesystem
+MNTPFS="$(get_prop mountpoint $TESTDS)"
+FILENAME="$MNTPFS/file"
+log_must mkfile 128k $FILENAME
+log_must exec 9<> $FILENAME # open file
+
+# 3. Lazy umount
+if is_freebsd; then
+ # FreeBSD does not support lazy unmount
+ log_must umount $MNTPFS
+else
+ log_must umount -l $MNTPFS
+fi
+if [ -f $FILENAME ]; then
+ log_fail "Lazy unmount failed"
+fi
+
+# 4. Verify remounting fs that was lazily unmounted is possible
+log_must zfs mount $TESTDS
+if [ ! -f $FILENAME ]; then
+ log_fail "Lazy remount failed"
+fi
+log_must exec 9>&- # close fd
+
+# 5. Verify multiple mounts of the same dataset are possible
+MNTPFS2="$MNTPFS-second"
+FILENAME="$MNTPFS2/file"
+log_must mkdir $MNTPFS2
+log_must mount -t zfs -o zfsutil $TESTDS $MNTPFS2
+if [ ! -f $FILENAME ]; then
+ log_fail "First multi mount failed"
+fi
+
+MNTPFS3="$MNTPFS-third"
+FILENAME="$MNTPFS3/file"
+log_must mkdir $MNTPFS3
+log_must mount -t zfs -o zfsutil $TESTDS $MNTPFS3
+if [ ! -f $FILENAME ]; then
+ log_fail "Second multi mount failed"
+fi
+
+# 6. Verify bind mount doesn't prevent rename
+RENAMEFS="$TESTDS-newname"
+MNTPFS4="$MNTPFS-fourth"
+log_must mkdir $MNTPFS4
+log_must mount --bind $MNTPFS $MNTPFS4
+log_must zfs rename $TESTDS $RENAMEFS
+RENAMEMNT="$(get_prop mountpoint $RENAMEFS)"
+FILENAME="$RENAMEMNT/file"
+if [ ! -f $FILENAME ]; then
+ log_fail "Rename failed"
+fi
+log_must zfs rename $RENAMEFS $TESTDS
+
+log_pass "Multiple mounts are possible"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_program/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_program/Makefile.am
new file mode 100644
index 000000000000..d797a636b347
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_program/Makefile.am
@@ -0,0 +1,5 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_program
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_program_json.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_program/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_program/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_program/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_program/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_program/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_program/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_program/zfs_program_json.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_program/zfs_program_json.ksh
new file mode 100755
index 000000000000..3788543b0b2f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_program/zfs_program_json.ksh
@@ -0,0 +1,148 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy is of the CDDL is also available via the Internet
+# at http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2018 Datto Inc.
+# Copyright (c) 2019 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# STRATEGY:
+# 1. Compare JSON output formatting for a channel program to template
+# 2. Using bad command line option (-Z) gives correct error output
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy $TESTDS
+ return 0
+}
+log_onexit cleanup
+
+log_assert "Channel programs output valid JSON"
+
+TESTDS="$TESTPOOL/zcp-json"
+log_must zfs create $TESTDS
+
+TESTZCP="/$TESTDS/zfs_rlist.zcp"
+cat > "$TESTZCP" << EOF
+ succeeded = {}
+ failed = {}
+
+ function list_recursive(root, prop)
+ for child in zfs.list.children(root) do
+ list_recursive(child, prop)
+ end
+ val, src = zfs.get_prop(root, prop)
+ if (val == nil) then
+ failed[root] = val
+ else
+ succeeded[root] = val
+ end
+ end
+
+ args = ...
+
+ argv = args["argv"]
+
+ list_recursive(argv[1], argv[2])
+
+ results = {}
+ results["succeeded"] = succeeded
+ results["failed"] = failed
+ return results
+EOF
+
+# 1. Compare JSON output formatting for a channel program to template
+typeset -a pos_cmds=("recordsize" "type")
+typeset -a pos_cmds_out=(
+"{
+ \"return\": {
+ \"failed\": {},
+ \"succeeded\": {
+ \"$TESTDS\": 131072
+ }
+ }
+}"
+"{
+ \"return\": {
+ \"failed\": {},
+ \"succeeded\": {
+ \"$TESTDS\": \"filesystem\"
+ }
+ }
+}")
+
+#
+# N.B. json.tool is needed to guarantee consistent ordering of fields,
+# sed is needed to trim trailing space in CentOS 6's json.tool output
+#
+# As of Python 3.5 the behavior of json.tool changed to keep the order
+# the same as the input and the --sort-keys option was added. Detect when
+# --sort-keys is supported and apply the option to ensure the expected order.
+#
+if python -m json.tool --sort-keys <<< "{}"; then
+ JSON_TOOL_CMD="python -m json.tool --sort-keys"
+else
+ JSON_TOOL_CMD="python -m json.tool"
+fi
+
+typeset -i cnt=0
+typeset cmd
+for cmd in ${pos_cmds[@]}; do
+ log_must zfs program $TESTPOOL $TESTZCP $TESTDS $cmd 2>&1
+ log_must zfs program -j $TESTPOOL $TESTZCP $TESTDS $cmd 2>&1
+ OUTPUT=$(zfs program -j $TESTPOOL $TESTZCP $TESTDS $cmd 2>&1 |
+ $JSON_TOOL_CMD | sed 's/[[:space:]]*$//')
+ if [ "$OUTPUT" != "${pos_cmds_out[$cnt]}" ]; then
+ log_note "Got :$OUTPUT"
+ log_note "Expected:${pos_cmds_out[$cnt]}"
+ log_fail "Unexpected channel program output";
+ fi
+ cnt=$((cnt + 1))
+done
+
+# 2. Using bad command line option (-Z) gives correct error output
+typeset -a neg_cmds=("-Z")
+typeset -a neg_cmds_out=(
+"invalid option 'Z'
+usage:
+ program [-jn] [-t <instruction limit>] [-m <memory limit (b)>]
+ <pool> <program file> [lua args...]
+
+For the property list, run: zfs set|get
+
+For the delegated permission list, run: zfs allow|unallow")
+cnt=0
+for cmd in ${neg_cmds[@]}; do
+ log_mustnot zfs program $cmd $TESTPOOL $TESTZCP $TESTDS 2>&1
+ log_mustnot zfs program -j $cmd $TESTPOOL $TESTZCP $TESTDS 2>&1
+ OUTPUT=$(zfs program -j $cmd $TESTPOOL $TESTZCP $TESTDS 2>&1)
+ if [ "$OUTPUT" != "${neg_cmds_out[$cnt]}" ]; then
+ log_note "Got :$OUTPUT"
+ log_note "Expected:${neg_cmds_out[$cnt]}"
+ log_fail "Unexpected channel program error output";
+ fi
+ cnt=$((cnt + 1))
+done
+
+log_pass "Channel programs output valid JSON"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/Makefile.am
new file mode 100644
index 000000000000..8a8c56a093d2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/Makefile.am
@@ -0,0 +1,16 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_promote
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_promote_001_pos.ksh \
+ zfs_promote_002_pos.ksh \
+ zfs_promote_003_pos.ksh \
+ zfs_promote_004_pos.ksh \
+ zfs_promote_005_pos.ksh \
+ zfs_promote_006_neg.ksh \
+ zfs_promote_007_neg.ksh \
+ zfs_promote_008_pos.ksh \
+ zfs_promote_encryptionroot.ksh
+
+dist_pkgdata_DATA = \
+ zfs_promote.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/setup.ksh
new file mode 100755
index 000000000000..3e2e2ce319a6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_volume_setup ${DISK}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote.cfg
new file mode 100644
index 000000000000..6407328efd91
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote.cfg
@@ -0,0 +1,43 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+export FILESIZE=1m
+
+export TESTSNAP3=testsnap3.promote
+export TESTSNAP4=testsnap4.promote
+export TESTSNAP5=testsnap5.promote
+export TESTFILE3=testfile3.promote
+
+export CLONEFILE=clonefile.promote
+export CLONEFILE1=clonefile1.promote
+export CLONEFILE2=clonefile2.promote
+export CLONEFILE3=clonefile3.promote
+
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_001_pos.ksh
new file mode 100755
index 000000000000..0bf7c5b6a176
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_001_pos.ksh
@@ -0,0 +1,127 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_promote/zfs_promote.cfg
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs promote' can promote a clone filesystem to no longer be dependent
+# on its "origin" snapshot.
+#
+# STRATEGY:
+# 1. Create a snapshot and a clone of the snapshot
+# 2. Promote the clone filesystem
+# 3. Verify the promoted filesystem become independent
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if snapexists $csnap; then
+ log_must zfs promote $fs
+ fi
+ snapexists $snap && \
+ log_must zfs destroy -rR $snap
+
+ typeset data
+ for data in $file0 $file1; do
+ [[ -e $data ]] && rm -f $data
+ done
+}
+
+function testing_verify
+{
+ typeset ds=$1
+ typeset ds_file=$2
+ typeset snap_file=$3
+ typeset c_ds=$4
+ typeset c_file=$5
+ typeset csnap_file=$6
+ typeset origin_prop=""
+
+
+ snapexists $ds@$TESTSNAP && \
+ log_fail "zfs promote cannot promote $ds@$TESTSNAP."
+ ! snapexists $c_ds@$TESTSNAP && \
+ log_fail "The $c_ds@$TESTSNAP after zfs promote doesn't exist."
+
+ origin_prop=$(get_prop origin $ds)
+ [[ "$origin_prop" != "$c_ds@$TESTSNAP" ]] && \
+ log_fail "The dependency of $ds is not correct."
+ origin_prop=$(get_prop origin $c_ds)
+ [[ "$origin_prop" != "-" ]] && \
+ log_fail "The dependency of $c_ds is not correct."
+
+ if [[ -e $snap_file ]] || [[ ! -e $csnap_file ]]; then
+ log_fail "Data file $snap_file cannot be correctly promoted."
+ fi
+ if [[ ! -e $ds_file ]] || [[ ! -e $c_file ]]; then
+ log_fail "There exists data file losing after zfs promote."
+ fi
+
+ log_mustnot zfs destroy -r $c_ds
+}
+
+log_assert "'zfs promote' can promote a clone filesystem."
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+file0=$TESTDIR/$TESTFILE0
+file1=$TESTDIR/$TESTFILE1
+snap=$fs@$TESTSNAP
+snapfile=$TESTDIR/.zfs/snapshot/$TESTSNAP/$TESTFILE0
+clone=$TESTPOOL/$TESTCLONE
+cfile=/$clone/$CLONEFILE
+csnap=$clone@$TESTSNAP
+csnapfile=/$clone/.zfs/snapshot/$TESTSNAP/$TESTFILE0
+
+# setup for promte testing
+log_must mkfile $FILESIZE $file0
+log_must zfs snapshot $snap
+log_must mkfile $FILESIZE $file1
+log_must rm -f $file0
+log_must zfs clone $snap $clone
+log_must mkfile $FILESIZE $cfile
+
+log_must zfs promote $clone
+# verify the 'promote' operation
+testing_verify $fs $file1 $snapfile $clone $cfile $csnapfile
+
+log_note "Verify 'zfs promote' can change back the dependency relationship."
+log_must zfs promote $fs
+#verify the result
+testing_verify $clone $cfile $csnapfile $fs $file1 $snapfile
+
+log_pass "'zfs promote' reverses the clone parent-child dependency relationship"\
+ "as expected."
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_002_pos.ksh
new file mode 100755
index 000000000000..1a774da2c15c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_002_pos.ksh
@@ -0,0 +1,102 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_promote/zfs_promote.cfg
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs promote' can deal with multiple snapshots in the origin filesystem.
+#
+# STRATEGY:
+# 1. Create multiple snapshots and a clone of the last snapshot
+# 2. Promote the clone filesystem
+# 3. Verify the promoted filesystem included all snapshots
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if snapexists $csnap1; then
+ log_must zfs promote $fs
+ fi
+
+ typeset ds
+ typeset data
+ for ds in $snap $snap1; do
+ log_must zfs destroy -rR $ds
+ done
+ for file in $TESTDIR/$TESTFILE0 $TESTDIR/$TESTFILE1; do
+ [[ -e $file ]] && rm -f $file
+ done
+}
+
+log_assert "'zfs promote' can deal with multiple snapshots in a filesystem."
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+snap=$fs@$TESTSNAP
+snap1=$fs@$TESTSNAP1
+clone=$TESTPOOL/$TESTCLONE
+csnap=$clone@$TESTSNAP
+csnap1=$clone@$TESTSNAP1
+
+# setup for promote testing
+log_must mkfile $FILESIZE $TESTDIR/$TESTFILE0
+log_must zfs snapshot $snap
+log_must mkfile $FILESIZE $TESTDIR/$TESTFILE1
+log_must rm -f $testdir/$TESTFILE0
+log_must zfs snapshot $snap1
+log_must zfs clone $snap1 $clone
+log_must mkfile $FILESIZE /$clone/$CLONEFILE
+
+log_must zfs promote $clone
+
+# verify the 'promote' operation
+for ds in $csnap $csnap1; do
+ ! snapexists $ds && \
+ log_fail "Snapshot $ds doesn't exist after zfs promote."
+done
+for ds in $snap $snap1; do
+ snapexists $ds && \
+ log_fail "Snapshot $ds is still there after zfs promote."
+done
+
+origin_prop=$(get_prop origin $fs)
+[[ "$origin_prop" != "$csnap1" ]] && \
+ log_fail "The dependency of $fs is not correct."
+origin_prop=$(get_prop origin $clone)
+[[ "$origin_prop" != "-" ]] && \
+ log_fail "The dependency of $clone is not correct."
+
+log_pass "'zfs promote' deal with multiple snapshots as expected."
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_003_pos.ksh
new file mode 100755
index 000000000000..e0d0e8457a26
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_003_pos.ksh
@@ -0,0 +1,134 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_promote/zfs_promote.cfg
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs promote' can deal with multi-point snapshots.
+#
+# STRATEGY:
+# 1. Create multiple snapshots and a clone to a middle point snapshot
+# 2. Promote the clone filesystem
+# 3. Verify the origin filesystem and promoted filesystem include
+# correct datasets separated by the clone point.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if snapexists ${csnap[2]}; then
+ log_must zfs promote $fs
+ fi
+
+ typeset ds
+ typeset data
+ for ds in ${snap[*]}; do
+ snapexists $ds && \
+ log_must zfs destroy -rR $ds
+ done
+ for data in ${file[*]}; do
+ [[ -e $data ]] && rm -f $data
+ done
+
+}
+
+log_assert "'zfs promote' can deal with multi-point snapshots."
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+clone=$TESTPOOL/$TESTCLONE
+
+# Define some arrays here to use loop to reduce code amount
+
+# Array which stores the origin snapshots created in the origin filesystem
+set -A snap "${fs}@$TESTSNAP" "${fs}@$TESTSNAP1" "${fs}@$TESTSNAP2" "${fs}@$TESTSNAP3"
+# Array which stores the snapshots existing in the clone after promote operation
+set -A csnap "${clone}@$TESTSNAP" "${clone}@$TESTSNAP1" "${clone}@$TESTSNAP2" \
+ "${clone}@$TESTSNAP3"
+# The data will inject into the origin filesystem
+set -A file "$TESTDIR/$TESTFILE0" "$TESTDIR/$TESTFILE1" "$TESTDIR/$TESTFILE2" \
+ "$TESTDIR/$TESTFILE3"
+snapdir=$TESTDIR/.zfs/snapshot
+# The data which will exist in the snapshot after creation of snapshot
+set -A snapfile "$snapdir/$TESTSNAP/$TESTFILE0" "$snapdir/$TESTSNAP1/$TESTFILE1" \
+ "$snapdir/$TESTSNAP2/$TESTFILE2" "$snapdir/$TESTSNAP3/$TESTFILE3"
+csnapdir=/$clone/.zfs/snapshot
+# The data which will exist in the snapshot of clone filesystem after promote
+set -A csnapfile "${csnapdir}/$TESTSNAP/$TESTFILE0" "${csnapdir}/$TESTSNAP1/$TESTFILE1" \
+ "${csnapdir}/$TESTSNAP2/$TESTFILE2"
+
+# setup for promote testing
+typeset -i i=0
+while (( i < 4 )); do
+ log_must mkfile $FILESIZE ${file[i]}
+ (( i>0 )) && log_must rm -f ${file[((i-1))]}
+ log_must zfs snapshot ${snap[i]}
+
+ (( i = i + 1 ))
+done
+log_must zfs clone ${snap[2]} $clone
+log_must mkfile $FILESIZE /$clone/$CLONEFILE
+log_must rm -f /$clone/$TESTFILE2
+log_must zfs snapshot ${csnap[3]}
+
+log_must zfs promote $clone
+
+# verify the 'promote' operation
+for ds in ${snap[3]} ${csnap[*]}; do
+ ! snapexists $ds && \
+ log_fail "The snapshot $ds disappear after zfs promote."
+done
+for data in ${csnapfile[*]} $TESTDIR/$TESTFILE3 /$clone/$CLONEFILE; do
+ [[ ! -e $data ]] && \
+ log_fail "The data file $data loses after zfs promote."
+done
+
+for ds in ${snap[0]} ${snap[1]} ${snap[2]}; do
+ snapexists $ds && \
+ log_fail "zfs promote cannot promote the snapshot $ds."
+done
+for data in ${snapfile[0]} ${snapfile[1]} ${snapfile[2]}; do
+ [[ -e $data ]] && \
+ log_fail "zfs promote cannot promote the data $data."
+done
+
+origin_prop=$(get_prop origin $fs)
+[[ "$origin_prop" != "${csnap[2]}" ]] && \
+ log_fail "The dependency is not correct for $fs after zfs promote."
+origin_prop=$(get_prop origin $clone)
+[[ "$origin_prop" != "-" ]] && \
+ log_fail "The dependency is not correct for $clone after zfs promote."
+
+log_pass "'zfs promote' deal with multi-point snapshots as expected."
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_004_pos.ksh
new file mode 100755
index 000000000000..23b5991084f8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_004_pos.ksh
@@ -0,0 +1,140 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_promote/zfs_promote.cfg
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs promote' can deal with multi-level clones.
+#
+# STRATEGY:
+# 1. Create multiple snapshots and multi-level clones
+# 2. Promote a clone filesystem
+# 3. Verify the dataset dependency relationships are correct after promotion.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if snapexists ${c1snap[1]}; then
+ log_must zfs promote $clone
+ fi
+
+ typeset ds
+ typeset data
+ for ds in ${snap[*]}; do
+ snapexists $ds && \
+ log_must zfs destroy -rR $ds
+ done
+ for data in ${file[*]}; do
+ [[ -e $data ]] && rm -f $data
+ done
+}
+
+log_assert "'zfs promote' can deal with multi-level clone."
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+clone=$TESTPOOL/$TESTCLONE
+clone1=$TESTPOOL/$TESTCLONE1
+
+# Define some arrays here to use loop to reduce code amount
+
+# Array which stores the origin snapshots created in the origin filesystem
+set -A snap "${fs}@$TESTSNAP" "${fs}@$TESTSNAP1" "${fs}@$TESTSNAP2" "${fs}@$TESTSNAP3"
+# Array which stores the snapshots existing in the first clone
+set -A csnap "${clone}@$TESTSNAP3" "${clone}@$TESTSNAP4" "${clone}@$TESTSNAP5"
+# Array which stores the snapshots existing in the second clone after promote operation
+set -A c1snap "${clone1}@$TESTSNAP3" "${clone1}@$TESTSNAP4" "${clone1}@$TESTSNAP5"
+# The data will inject into the origin filesystem
+set -A file "$TESTDIR/$TESTFILE0" "$TESTDIR/$TESTFILE1" "$TESTDIR/$TESTFILE2" \
+ "$TESTDIR/$TESTFILE3"
+cdir=/$TESTPOOL/$TESTCLONE
+# The data will inject into the first clone
+set -A cfile "${cdir}/$CLONEFILE" "${cdir}/$CLONEFILE1" "${cdir}/$CLONEFILE2"
+c1snapdir=/$TESTPOOL/$TESTCLONE1/.zfs/snapshot
+# The data which will exist in the snapshot of the second clone filesystem after promote
+set -A c1snapfile "${c1snapdir}/$TESTSNAP3/$CLONEFILE" \
+ "${c1snapdir}/$TESTSNAP4/$CLONEFILE1" \
+ "${c1snapdir}/$TESTSNAP5/$CLONEFILE2"
+
+# setup for promote testing
+typeset -i i=0
+while (( i < 4 )); do
+ log_must mkfile $FILESIZE ${file[i]}
+ (( i>0 )) && log_must rm -f ${file[((i-1))]}
+ log_must zfs snapshot ${snap[i]}
+
+ (( i = i + 1 ))
+done
+log_must zfs clone ${snap[2]} $clone
+
+log_must rm -f /$clone/$TESTFILE2
+i=0
+while (( i < 3 )); do
+ log_must mkfile $FILESIZE ${cfile[i]}
+ (( i>0 )) && log_must rm -f ${cfile[(( i-1 ))]}
+ log_must zfs snapshot ${csnap[i]}
+
+ (( i = i + 1 ))
+done
+
+log_must zfs clone ${csnap[1]} $clone1
+log_must mkfile $FILESIZE /$clone1/$CLONEFILE2
+log_must rm -f /$clone1/$CLONEFILE1
+log_must zfs snapshot ${c1snap[2]}
+
+log_must zfs promote $clone1
+
+# verify the 'promote' operation
+for ds in ${snap[*]} ${csnap[2]} ${c1snap[*]}; do
+ ! snapexists $ds && \
+ log_fail "The snapshot $ds disappear after zfs promote."
+done
+for data in ${c1snapfile[*]}; do
+ [[ ! -e $data ]] && \
+ log_fail "The data file $data loses after zfs promote."
+done
+
+origin_prop=$(get_prop origin $fs)
+[[ "$origin_prop" != "-" ]] && \
+ log_fail "The dependency is not correct for $fs after zfs promote."
+origin_prop=$(get_prop origin $clone)
+[[ "$origin_prop" != "${c1snap[1]}" ]] && \
+ log_fail "The dependency is not correct for $clone after zfs promote."
+origin_prop=$(get_prop origin $clone1)
+[[ "$origin_prop" != "${snap[2]}" ]] && \
+ log_fail "The dependency is not correct for $clone1 after zfs promote."
+
+log_pass "'zfs promote' deal with multi-level clones as expected."
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_005_pos.ksh
new file mode 100755
index 000000000000..c669a44eb096
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_005_pos.ksh
@@ -0,0 +1,73 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# The original fs was unmounted, 'zfs promote' still should succeed.
+#
+# STRATEGY:
+# 1. Create pool, fs and snapshot.
+# 2. Create clone of fs.
+# 3. Unmount fs, then verify 'zfs promote' clone still succeed.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $fssnap ; then
+ datasetexists $clone && log_must zfs destroy $clone
+ log_must zfs destroy $fssnap
+ fi
+ if datasetexists $clone ; then
+ log_must zfs promote $fs
+ log_must zfs destroy $clone
+ log_must zfs destroy $fssnap
+ fi
+}
+
+log_assert "The original fs was unmounted, 'zfs promote' still should succeed."
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+clone=$TESTPOOL/$TESTCLONE
+fssnap=$fs@fssnap
+
+log_must zfs snapshot $fssnap
+log_must zfs clone $fssnap $clone
+log_must zfs unmount $fs
+log_must zfs promote $clone
+log_must zfs unmount $clone
+log_must zfs promote $fs
+
+log_pass "Unmount original fs, 'zfs promote' passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_006_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_006_neg.ksh
new file mode 100755
index 000000000000..286c14ac12d9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_006_neg.ksh
@@ -0,0 +1,90 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs promote' will fail with invalid arguments:
+# (1) NULL arguments
+# (2) non-existent clone
+# (3) non-clone datasets:
+# pool, fs, snapshot,volume
+# (4) too many arguments.
+# (5) invalid options
+# (6) temporary %recv datasets
+#
+# STRATEGY:
+# 1. Create an array of invalid arguments
+# 2. For each invalid argument in the array, 'zfs promote' should fail
+# 3. Verify the return code from zfs promote
+#
+
+verify_runnable "both"
+
+snap=$TESTPOOL/$TESTFS@$TESTSNAP
+clone=$TESTPOOL/$TESTCLONE
+recvfs=$TESTPOOL/recvfs
+set -A args "" \
+ "$TESTPOOL/blah" \
+ "$TESTPOOL" "$TESTPOOL/$TESTFS" "$snap" \
+ "$TESTPOOL/$TESTVOL" "$TESTPOOL $TESTPOOL/$TESTFS" \
+ "$clone $TESTPOOL/$TESTFS" "- $clone" "-? $clone" \
+ "$recvfs/%recv"
+
+function cleanup
+{
+ if datasetexists $clone; then
+ log_must zfs destroy $clone
+ fi
+
+ if datasetexists $recvfs; then
+ log_must zfs destroy -r $recvfs
+ fi
+
+ if snapexists $snap; then
+ destroy_snapshot $snap
+ fi
+}
+
+log_assert "'zfs promote' will fail with invalid arguments. "
+log_onexit cleanup
+
+create_recv_clone $recvfs
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_mustnot zfs promote ${args[i]}
+
+ (( i = i + 1 ))
+done
+
+log_pass "'zfs promote' fails with invalid argument as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_007_neg.ksh
new file mode 100755
index 000000000000..3f8ee1941dde
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_007_neg.ksh
@@ -0,0 +1,78 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_promote/zfs_promote.cfg
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs promote' can deal with conflicts in the namespaces.
+#
+# STRATEGY:
+# 1. Create a snapshot and a clone of the snapshot
+# 2. Create the same name snapshot for the clone
+# 3. Promote the clone filesystem
+# 4. Verify the promote operation fail due to the name conflicts.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ snapexists $snap && \
+ log_must zfs destroy -rR $snap
+
+ typeset data
+ for data in $TESTDIR/$TESTFILE0 $TESTDIR/$TESTFILE1; do
+ [[ -e $data ]] && rm -f $data
+ done
+}
+
+log_assert "'zfs promote' can deal with name conflicts."
+log_onexit cleanup
+
+snap=$TESTPOOL/$TESTFS@$TESTSNAP
+clone=$TESTPOOL/$TESTCLONE
+clonesnap=$TESTPOOL/$TESTCLONE@$TESTSNAP
+
+# setup for promte testing
+log_must mkfile $FILESIZE $TESTDIR/$TESTFILE0
+log_must zfs snapshot $snap
+log_must mkfile $FILESIZE $TESTDIR/$TESTFILE1
+log_must rm -f $TESTDIR/$TESTFILE0
+log_must zfs clone $snap $clone
+log_must mkfile $FILESIZE /$clone/$CLONEFILE
+log_must zfs snapshot $clonesnap
+
+log_mustnot zfs promote $clone
+
+log_pass "'zfs promote' deals with name conflicts as expected."
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_008_pos.ksh
new file mode 100755
index 000000000000..c37c9a6269e7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_008_pos.ksh
@@ -0,0 +1,84 @@
+#!/bin/ksh
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs promote' can successfully promote a volume clone.
+#
+# STRATEGY:
+# 1. Create a volume clone
+# 2. Promote the volume clone
+# 3. Verify the dependency changed.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if snapexists $csnap; then
+ log_must zfs promote $vol
+ fi
+
+ destroy_dataset "$snap" "-rR"
+}
+
+log_assert "'zfs promote' can promote a volume clone."
+log_onexit cleanup
+
+vol=$TESTPOOL/$TESTVOL
+snap=$vol@$TESTSNAP
+clone=$TESTPOOL/volclone
+csnap=$clone@$TESTSNAP
+
+if ! snapexists $snap ; then
+ log_must zfs snapshot $snap
+ log_must zfs clone $snap $clone
+fi
+
+log_must zfs promote $clone
+
+# verify the 'promote' operation
+! snapexists $csnap && \
+ log_fail "Snapshot $csnap doesn't exist after zfs promote."
+snapexists $snap && \
+ log_fail "Snapshot $snap is still there after zfs promote."
+
+origin_prop=$(get_prop origin $vol)
+[[ "$origin_prop" != "$csnap" ]] && \
+ log_fail "The dependency of $vol is not correct."
+origin_prop=$(get_prop origin $clone)
+[[ "$origin_prop" != "-" ]] && \
+ log_fail "The dependency of $clone is not correct."
+
+log_pass "'zfs promote' can promote volume clone as expected."
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_encryptionroot.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_encryptionroot.ksh
new file mode 100755
index 000000000000..2c7584d3541d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_encryptionroot.ksh
@@ -0,0 +1,93 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# ZFS must promote clones of an encryption root.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Clone the encryption root
+# 3. Clone the clone
+# 4. Add children to each of these three datasets
+# 4. Verify the encryption root of all datasets is the origin
+# 5. Promote the clone of the clone
+# 6. Verify the encryption root of all datasets is still the origin
+# 7. Promote the dataset again, so it is now the encryption root
+# 8. Verify the encryption root of all datasets is the promoted dataset
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -Rf $TESTPOOL/$TESTFS1
+ datasetexists $TESTPOOL/clone1 && \
+ log_must zfs destroy -Rf $TESTPOOL/clone1
+ datasetexists $TESTPOOL/clone2 && \
+ log_must zfs destroy -Rf $TESTPOOL/clone2
+}
+log_onexit cleanup
+
+log_assert "ZFS must promote clones of an encryption root"
+
+passphrase="password"
+snaproot="$TESTPOOL/$TESTFS1@snap1"
+snapclone="$TESTPOOL/clone1@snap2"
+
+log_must eval "echo $passphrase | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS1"
+
+log_must zfs snap $snaproot
+log_must zfs clone $snaproot $TESTPOOL/clone1
+log_must zfs snap $snapclone
+log_must zfs clone $snapclone $TESTPOOL/clone2
+log_must zfs create $TESTPOOL/$TESTFS1/child0
+log_must zfs create $TESTPOOL/clone1/child1
+log_must zfs create $TESTPOOL/clone2/child2
+
+log_must verify_encryption_root $TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/clone1 $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/clone2 $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/child0 $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/clone1/child1 $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/clone2/child2 $TESTPOOL/$TESTFS1
+
+log_must zfs promote $TESTPOOL/clone2
+log_must verify_encryption_root $TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/clone1 $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/clone2 $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/child0 $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/clone1/child1 $TESTPOOL/$TESTFS1
+log_must verify_encryption_root $TESTPOOL/clone2/child2 $TESTPOOL/$TESTFS1
+
+log_must zfs promote $TESTPOOL/clone2
+log_must verify_encryption_root $TESTPOOL/$TESTFS1 $TESTPOOL/clone2
+log_must verify_encryption_root $TESTPOOL/clone1 $TESTPOOL/clone2
+log_must verify_encryption_root $TESTPOOL/clone2 $TESTPOOL/clone2
+log_must verify_encryption_root $TESTPOOL/$TESTFS1/child0 $TESTPOOL/clone2
+log_must verify_encryption_root $TESTPOOL/clone1/child1 $TESTPOOL/clone2
+log_must verify_encryption_root $TESTPOOL/clone2/child2 $TESTPOOL/clone2
+
+log_pass "ZFS promotes clones of an encryption root"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_property/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_property/Makefile.am
new file mode 100644
index 000000000000..d8a5687b1ea2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_property/Makefile.am
@@ -0,0 +1,5 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_property
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_written_property_001_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_property/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_property/cleanup.ksh
new file mode 100755
index 000000000000..e4998138f701
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_property/cleanup.ksh
@@ -0,0 +1,34 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_property/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_property/setup.ksh
new file mode 100755
index 000000000000..746a05015f8c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_property/setup.ksh
@@ -0,0 +1,36 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_property/zfs_written_property_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_property/zfs_written_property_001_pos.ksh
new file mode 100755
index 000000000000..cbbacace1ec6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_property/zfs_written_property_001_pos.ksh
@@ -0,0 +1,230 @@
+#!/bin/ksh
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012, 2017 by Delphix. All rights reserved.
+#
+
+#
+# DESCRIPTION
+# Verify that "zfs list" gives correct values for written and written@
+# properties for the dataset when different operations are on done on it
+#
+#
+# STRATEGY
+# 1) Create recursive datasets
+# 2) Take snapshots, write data and verify written/ written@ properties for
+# following cases
+# a) Delete data
+# b) Write Data
+# c) Clone
+# d) Delete snapshot
+# e) Recursive datasets
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+
+function cleanup
+{
+ for ds in $datasets; do
+ datasetexists $ds && log_must zfs destroy -R $TESTPOOL/$TESTFS1
+ done
+}
+function get_prop_mb
+{
+ typeset prop=$1
+ typeset dataset=$2
+ typeset -l value=$(get_prop $prop $dataset)
+ ((value = value / mb_block))
+ echo $value
+}
+
+datasets="$TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS1/$TESTFS2 \
+ $TESTPOOL/$TESTFS1/$TESTFS2/$TESTFS3"
+
+log_assert "verify zfs written and written@ property"
+log_onexit cleanup
+
+typeset -l i=1
+typeset -l blocks=50
+typeset -l expected_written=0
+typeset -l expected_writtenat=0
+typeset -l written=0
+typeset -l total=0
+typeset -l snap1_size=0
+typeset -l snap2_size=0
+typeset -l snap3_size=0
+typeset -l mb_block=0
+((mb_block = 1024 * 1024))
+
+log_note "verify written property statistics for dataset"
+log_must zfs create -p $TESTPOOL/$TESTFS1/$TESTFS2/$TESTFS3
+for i in 1 2 3; do
+ log_must zfs snapshot $TESTPOOL/$TESTFS1@snap$i
+ log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS1/testfile.$i bs=1M \
+ count=$blocks
+ sync_pool
+ written=$(get_prop written $TESTPOOL/$TESTFS1)
+ ((expected_written=blocks * mb_block))
+ within_percent $written $expected_written 99.5 || \
+ log_fail "Unexpected written value $written $expected_written"
+ ((total = total + blocks))
+ ((blocks = blocks + 50))
+done
+
+log_note "verify written property statistics for snapshots"
+blocks=0
+for i in 1 2 3; do
+ written=$(get_prop written $TESTPOOL/$TESTFS1@snap$i)
+ if [[ $blocks -eq 0 ]]; then
+ # Written value for the first non-clone snapshot is
+ # expected to be equal to the referenced value.
+ expected_written=$( \
+ get_prop referenced $TESTPOOL/$TESTFS1@snap$i)
+ else
+ ((expected_written = blocks * mb_block))
+ fi
+ within_percent $written $expected_written 99.5 || \
+ log_fail "Unexpected written value $written $expected_written $i"
+ ((blocks = blocks + 50))
+done
+
+snap1_size=$total
+((snap2_size = total-50))
+((snap3_size = total-100))
+
+log_note "verify written@ for the same dataset"
+blocks=50
+for i in 1 2 3; do
+ writtenat=$(get_prop written@snap$i $TESTPOOL/$TESTFS1)
+ ((expected_writtenat = total * mb_block))
+ within_percent $writtenat $expected_writtenat 99.5 || \
+ log_fail "Unexpected written@ value"
+ ((total = total - blocks))
+ ((blocks = blocks + 50))
+done
+log_note "delete data"
+before_written=$(get_prop written $TESTPOOL/$TESTFS1)
+log_must rm /$TESTPOOL/$TESTFS1/testfile.3
+snap3_size=0
+sync_pool
+written=$(get_prop written $TESTPOOL/$TESTFS1)
+writtenat3=$(get_prop written@snap3 $TESTPOOL/$TESTFS1)
+[[ $written -eq $writtenat3 ]] || \
+ log_fail "Written and written@ don't match $written $writtenat3"
+within_percent $written $before_written 0.1 && \
+ log_fail "Unexpected written value after delete $written $before_written"
+writtenat=$(get_prop written@snap1 $TESTPOOL/$TESTFS1)
+((snap1_size = snap1_size - 150))
+((expected_writtenat = snap1_size * mb_block))
+within_percent $writtenat $expected_writtenat 99.5 || \
+ log_fail "Unexpected written value after delete $writtenat $expected_writtenat"
+writtenat=$(get_prop written@snap2 $TESTPOOL/$TESTFS1)
+((snap2_size = snap2_size - 150))
+((expected_writtenat = snap2_size * mb_block))
+within_percent $writtenat $expected_writtenat 99.5 || \
+ log_fail "Unexpected written value after delete"
+
+log_note "write data"
+blocks=20
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS1/testfile.3 bs=1M \
+ count=$blocks
+sync_pool
+written=$(get_prop written $TESTPOOL/$TESTFS1)
+writtenat1=$(get_prop written@snap1 $TESTPOOL/$TESTFS1)
+writtenat2=$(get_prop written@snap2 $TESTPOOL/$TESTFS1)
+writtenat3=$(get_prop written@snap3 $TESTPOOL/$TESTFS1)
+((snap3_size = snap3_size + blocks))
+((expected_writtenat = snap3_size * mb_block))
+[[ $written -eq $writtenat3 ]] || \
+ log_fail "Unexpected_written value"
+within_percent $writtenat3 $expected_writtenat 99.5 || \
+ log_fail "Unexpected_written@ value for snap3"
+((snap2_size = snap2_size + blocks))
+((expected_writtenat = snap2_size * mb_block))
+within_percent $writtenat2 $expected_writtenat 99.5 || \
+ log_fail "Unexpected_written@ value for snap2"
+((snap1_size = snap1_size + blocks))
+((expected_writtenat = snap1_size * mb_block))
+within_percent $writtenat1 $expected_writtenat 99.5 || \
+ log_fail "Unexpected_written@ value for snap1"
+
+log_note "write data to a clone"
+before_clone=$(get_prop written $TESTPOOL/$TESTFS1)
+log_must zfs clone $TESTPOOL/$TESTFS1@snap1 $TESTPOOL/$TESTFS1/snap1.clone
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS1/snap1.clone/testfile bs=1M \
+ count=40
+after_clone=$(get_prop written $TESTPOOL/$TESTFS1)
+within_percent $before_clone $after_clone 99.5 || \
+ log_fail "unexpected written for clone $before_clone $after_clone"
+
+log_note "deleted snapshot"
+typeset -l before_written1=$(get_prop_mb written@snap1 $TESTPOOL/$TESTFS1)
+typeset -l before_written3=$(get_prop_mb written@snap3 $TESTPOOL/$TESTFS1)
+typeset -l snap_before_written2=$(get_prop_mb written $TESTPOOL/$TESTFS1@snap2)
+typeset -l snap_before_written3=$(get_prop_mb written $TESTPOOL/$TESTFS1@snap3)
+log_must zfs destroy $TESTPOOL/$TESTFS1@snap2
+log_mustnot snapexists $TESTPOOL/$TESTFS1@snap2
+sync_pool
+written1=$(get_prop_mb written@snap1 $TESTPOOL/$TESTFS1)
+written3=$(get_prop_mb written@snap3 $TESTPOOL/$TESTFS1)
+[[ $before_written1 -eq $written1 && $before_written3 -eq $written3 ]] || \
+ log_fail "unexpected written values $before_written1 $written1"
+typeset -l expected_written3
+((expected_written3 = snap_before_written2 + snap_before_written3))
+prev_written=$(get_prop_mb written $TESTPOOL/$TESTFS1@snap3)
+within_percent $prev_written $expected_written3 99.5 || \
+ log_fail "unexpected written value $prev_written $expected_written3"
+
+log_must zfs destroy $TESTPOOL/$TESTFS1@snap3
+log_mustnot snapexists $TESTPOOL/$TESTFS1@snap3
+written=$(get_prop written $TESTPOOL/$TESTFS1)
+writtenat1=$(get_prop written@snap1 $TESTPOOL/$TESTFS1)
+[[ $written -ne $writtenat1 ]] && \
+ log_fail "Unexpected last snapshot written value"
+
+log_note "verify written@ property for recursive datasets"
+blocks=10
+log_must zfs snapshot -r $TESTPOOL/$TESTFS1@now
+for ds in $datasets; do
+ writtenat=$(get_prop written@now $ds)
+ [[ $writtenat -ne 0 ]] && \
+ log_fail "Unexpected written@ value"
+ log_must dd if=/dev/urandom of=/$ds/testfile bs=1M count=$blocks
+ sync_pool
+ writtenat=$(get_prop written@now $ds)
+ ((expected_writtenat = blocks * mb_block))
+ within_percent $writtenat $expected_writtenat 0.1 || \
+ log_fail "Unexpected written value"
+ ((blocks = blocks + 10))
+done
+
+log_note "verify written@ output for recursive datasets"
+blocks=20
+for ds in $datasets; do
+ log_must zfs snapshot $ds@current
+ log_must dd if=/dev/urandom of=/$ds/testfile bs=1M \
+ count=$blocks
+ sync_pool
+done
+recursive_output=$(zfs get -p -r written@current $TESTPOOL | \
+ grep -v $TESTFS1@ | grep -v $TESTFS2@ | grep -v $TESTFS3@ | \
+ grep -v "VALUE" | grep -v "-")
+expected="$((20 * mb_block))"
+for ds in $datasets; do
+ writtenat=$(echo "$recursive_output" | grep -v $ds/)
+ writtenat=$(echo "$writtenat" | grep $ds | awk '{print $3}')
+ within_percent $writtenat $expected 99.5 || \
+ log_fail "Unexpected written@ value on $ds"
+done
+
+log_pass "zfs written and written@ property fields print correct values"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/Makefile.am
new file mode 100644
index 000000000000..f13a955d8373
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/Makefile.am
@@ -0,0 +1,31 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_receive
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_receive_001_pos.ksh \
+ zfs_receive_002_pos.ksh \
+ zfs_receive_003_pos.ksh \
+ zfs_receive_004_neg.ksh \
+ zfs_receive_005_neg.ksh \
+ zfs_receive_006_pos.ksh \
+ zfs_receive_007_neg.ksh \
+ zfs_receive_008_pos.ksh \
+ zfs_receive_009_neg.ksh \
+ zfs_receive_010_pos.ksh \
+ zfs_receive_011_pos.ksh \
+ zfs_receive_012_pos.ksh \
+ zfs_receive_013_pos.ksh \
+ zfs_receive_014_pos.ksh \
+ zfs_receive_015_pos.ksh \
+ zfs_receive_016_pos.ksh \
+ receive-o-x_props_override.ksh \
+ zfs_receive_from_encrypted.ksh \
+ zfs_receive_from_zstd.ksh \
+ zfs_receive_to_encrypted.ksh \
+ zfs_receive_raw.ksh \
+ zfs_receive_raw_incremental.ksh \
+ zfs_receive_raw_-d.ksh \
+ zfs_receive_-e.ksh
+
+dist_pkgdata_DATA = \
+ zstd_test_data.txt
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/cleanup.ksh
new file mode 100755
index 000000000000..cec69d4709f4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/cleanup.ksh
@@ -0,0 +1,33 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+poolexists $TESTPOOL1 && \
+ destroy_pool $TESTPOOL1
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/receive-o-x_props_override.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/receive-o-x_props_override.ksh
new file mode 100755
index 000000000000..6f897a96f3e8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/receive-o-x_props_override.ksh
@@ -0,0 +1,320 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify ZFS property override (-o) and exclude (-x) options work when
+# receiving a send stream
+#
+# STRATEGY:
+# 1. Create a filesystem with children.
+# 2. Snapshot the filesystems.
+# 3. Create various send streams (full, incremental, replication) and verify
+# we can both override and exclude native and user properties.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must rm -f $streamfile_full
+ log_must rm -f $streamfile_incr
+ log_must rm -f $streamfile_repl
+ log_must rm -f $streamfile_trun
+ destroy_dataset "$orig" "-rf"
+ destroy_dataset "$dest" "-rf"
+}
+
+log_assert "ZFS receive property override and exclude options work as expected."
+log_onexit cleanup
+
+orig=$TESTPOOL/$TESTFS1
+origsub=$orig/sub
+dest=$TESTPOOL/$TESTFS2
+destsub=$dest/sub
+typeset userprop=$(valid_user_property 8)
+typeset userval=$(user_property_value 8)
+typeset streamfile_full=$TESTDIR/streamfile_full.$$
+typeset streamfile_incr=$TESTDIR/streamfile_incr.$$
+typeset streamfile_repl=$TESTDIR/streamfile_repl.$$
+typeset streamfile_trun=$TESTDIR/streamfile_trun.$$
+
+#
+# 3.1 Verify we can't specify the same property in multiple -o or -x options
+# or an invalid value was specified.
+#
+# Create a full send stream
+log_must zfs create $orig
+log_must zfs snapshot $orig@snap1
+log_must eval "zfs send $orig@snap1 > $streamfile_full"
+# Verify we reject invalid options
+log_mustnot eval "zfs recv $dest -o atime < $streamfile_full"
+log_mustnot eval "zfs recv $dest -x atime=off < $streamfile_full"
+log_mustnot eval "zfs recv $dest -o atime=off -x atime < $streamfile_full"
+log_mustnot eval "zfs recv $dest -o atime=off -o atime=on < $streamfile_full"
+log_mustnot eval "zfs recv $dest -x atime -x atime < $streamfile_full"
+log_mustnot eval "zfs recv $dest -o version=1 < $streamfile_full"
+log_mustnot eval "zfs recv $dest -x version < $streamfile_full"
+log_mustnot eval "zfs recv $dest -x normalization < $streamfile_full"
+# Verify we also reject invalid ZVOL options
+log_must zfs create -V 32K -s $orig/zvol
+log_must eval "zfs send $orig@snap1 > $streamfile_full"
+log_mustnot eval "zfs recv $dest -x volsize < $streamfile_full"
+log_mustnot eval "zfs recv $dest -o volsize=32K < $streamfile_full"
+# Cleanup
+block_device_wait
+log_must_busy zfs destroy -r -f $orig
+
+#
+# 3.2 Verify -o property=value works on streams without properties.
+#
+# Create a full send stream
+log_must zfs create $orig
+log_must zfs snapshot $orig@snap1
+log_must eval "zfs send $orig@snap1 > $streamfile_full"
+# Receive the full stream, override some properties
+log_must eval "zfs recv -o compression=on -o '$userprop:dest'='$userval' "\
+ "$dest < $streamfile_full"
+log_must eval "check_prop_source $dest compression on local"
+log_must eval "check_prop_source $dest '$userprop:dest' '$userval' local"
+# Cleanup
+log_must zfs destroy -r -f $orig
+log_must zfs destroy -r -f $dest
+
+#
+# 3.3 Verify -o property=value and -x work on both native and user properties
+# for an incremental replication send stream.
+#
+# Create a dataset tree and receive it
+log_must zfs create $orig
+log_must zfs create $origsub
+log_must zfs snapshot -r $orig@snap1
+log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
+log_must eval "zfs recv $dest < $streamfile_repl"
+# Fill the datasets with properties and create an incremental replication stream
+log_must zfs snapshot -r $orig@snap2
+log_must zfs snapshot -r $orig@snap3
+log_must eval "zfs set copies=2 $orig"
+log_must eval "zfs set '$userprop:orig'='$userval' $orig"
+log_must eval "zfs set '$userprop:orig'='$userval' $origsub"
+log_must eval "zfs set '$userprop:snap'='$userval' $orig@snap1"
+log_must eval "zfs set '$userprop:snap'='$userval' $origsub@snap3"
+log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr"
+# Sets various combination of override and exclude options
+log_must eval "zfs recv -F -o atime=off -o '$userprop:dest2'='$userval' "\
+ "-o quota=123456789 -o checksum=sha512 -x compression "\
+ "-x '$userprop:orig' -x '$userprop:snap3' $dest < $streamfile_incr"
+# Verify we can correctly override and exclude properties
+log_must eval "check_prop_source $dest copies 2 received"
+log_must eval "check_prop_source $dest atime off local"
+log_must eval "check_prop_source $dest '$userprop:dest2' '$userval' local"
+log_must eval "check_prop_source $dest quota 123456789 local"
+log_must eval "check_prop_source $dest checksum sha512 local"
+log_must eval "check_prop_inherit $destsub copies $dest"
+log_must eval "check_prop_inherit $destsub atime $dest"
+log_must eval "check_prop_inherit $destsub checksum $dest"
+log_must eval "check_prop_inherit $destsub '$userprop:dest2' $dest"
+log_must eval "check_prop_source $destsub quota 0 default"
+log_must eval "check_prop_source $destsub compression off default"
+log_must eval "check_prop_missing $dest '$userprop:orig'"
+log_must eval "check_prop_missing $destsub '$userprop:orig'"
+log_must eval "check_prop_source " \
+ "$dest@snap1 '$userprop:snap' '$userval' received"
+log_must eval "check_prop_source " \
+ "$destsub@snap3 '$userprop:snap' '$userval' received"
+log_must eval "check_prop_missing $dest@snap3 '$userprop:snap3'"
+log_must eval "check_prop_missing $destsub@snap3 '$userprop:snap3'"
+# Cleanup
+log_must zfs destroy -r -f $orig
+log_must zfs destroy -r -f $dest
+
+#
+# 3.4 Verify '-x property' does not remove existing local properties and a
+# modified sent property is received and updated to the new value but can
+# still be excluded.
+#
+# Create a dataset tree
+log_must zfs create $orig
+log_must zfs create $origsub
+log_must zfs snapshot -r $orig@snap1
+log_must eval "zfs set copies=2 $orig"
+log_must eval "zfs set '$userprop:orig'='oldval' $orig"
+log_must eval "zfs set '$userprop:orig'='oldsubval' $origsub"
+log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
+log_must eval "zfs receive $dest < $streamfile_repl"
+log_must eval "check_prop_source $dest copies 2 received"
+log_must eval "check_prop_inherit $destsub copies $dest"
+log_must eval "check_prop_source $dest '$userprop:orig' 'oldval' received"
+log_must eval "check_prop_source $destsub '$userprop:orig' 'oldsubval' received"
+# Set new custom properties on both source and destination
+log_must eval "zfs set copies=3 $orig"
+log_must eval "zfs set '$userprop:orig'='newval' $orig"
+log_must eval "zfs set '$userprop:orig'='newsubval' $origsub"
+log_must eval "zfs set compression=gzip $dest"
+log_must eval "zfs set '$userprop:dest'='localval' $dest"
+# Receive the new stream, verify we preserve locally set properties
+log_must zfs snapshot -r $orig@snap2
+log_must zfs snapshot -r $orig@snap3
+log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr"
+log_must eval "zfs recv -F -x copies -x compression -x '$userprop:orig' " \
+ "-x '$userprop:dest' $dest < $streamfile_incr"
+log_must eval "check_prop_source $dest '$userprop:dest' 'localval' local"
+log_must eval "check_prop_received $dest '$userprop:orig' 'newval'"
+log_must eval "check_prop_received $destsub '$userprop:orig' 'newsubval'"
+log_must eval "check_prop_missing $dest '$userprop:orig'"
+log_must eval "check_prop_missing $destsub '$userprop:orig'"
+log_must eval "check_prop_source $dest copies 1 default"
+log_must eval "check_prop_received $dest copies 3"
+log_must eval "check_prop_source $destsub copies 1 default"
+log_must eval "check_prop_received $destsub copies '-'"
+log_must eval "check_prop_source $dest compression gzip local"
+log_must eval "check_prop_inherit $destsub compression $dest"
+# Cleanup
+log_must zfs destroy -r -f $orig
+log_must zfs destroy -r -f $dest
+
+#
+# 3.5 Verify we can exclude non-inheritable properties from a send stream
+#
+# Create a dataset tree and replication stream
+log_must zfs create $orig
+log_must zfs create $origsub
+log_must zfs snapshot -r $orig@snap1
+log_must eval "zfs set quota=123456789 $orig"
+log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
+# Receive the stream excluding non-inheritable properties
+log_must eval "zfs recv -F -x quota $dest < $streamfile_repl"
+log_must eval "check_prop_source $dest quota 0 default"
+log_must eval "check_prop_source $destsub quota 0 default"
+# Set some non-inheritable properties on the destination, verify we keep them
+log_must eval "zfs set quota=123456789 $dest"
+log_must eval "zfs set canmount=off $destsub"
+log_must zfs snapshot -r $orig@snap2
+log_must zfs snapshot -r $orig@snap3
+log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr"
+log_must eval "zfs recv -F -x quota -x canmount $dest < $streamfile_incr"
+log_must eval "check_prop_source $dest quota 123456789 local"
+log_must eval "check_prop_source $destsub quota 0 default"
+log_must eval "check_prop_source $destsub canmount off local"
+# Cleanup
+log_must zfs destroy -r -f $orig
+log_must zfs destroy -r -f $dest
+
+#
+# 3.6 Verify we correctly restore existing properties on a failed receive
+#
+# Receive a "clean" dataset tree
+log_must zfs create $orig
+log_must zfs create $origsub
+log_must zfs snapshot -r $orig@snap1
+log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
+log_must eval "zfs receive $dest < $streamfile_repl"
+# Set custom properties on the destination
+log_must eval "zfs set atime=off $dest"
+log_must eval "zfs set quota=123456789 $dest"
+log_must eval "zfs set '$userprop:orig'='$userval' $dest"
+log_must eval "zfs set '$userprop:origsub'='$userval' $destsub"
+# Create a truncated incremental replication stream
+mntpnt=$(get_prop mountpoint $orig)
+log_must eval "dd if=/dev/urandom of=$mntpnt/file bs=1024k count=10"
+log_must zfs snapshot -r $orig@snap2
+log_must zfs snapshot -r $orig@snap3
+log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr"
+log_must eval "dd if=$streamfile_incr of=$streamfile_trun bs=1024k count=9"
+# Receive the truncated stream, verify original properties are kept
+log_mustnot eval "zfs recv -F -o copies=3 -o quota=987654321 "\
+ "-o '$userprop:new'='badval' $dest < $streamfile_trun"
+log_must eval "check_prop_source $dest copies 1 default"
+log_must eval "check_prop_source $destsub copies 1 default"
+log_must eval "check_prop_source $dest atime off local"
+log_must eval "check_prop_inherit $destsub atime $dest"
+log_must eval "check_prop_source $dest quota 123456789 local"
+log_must eval "check_prop_source $destsub quota 0 default"
+log_must eval "check_prop_source $dest '$userprop:orig' '$userval' local"
+log_must eval "check_prop_inherit $destsub '$userprop:orig' $dest"
+log_must eval "check_prop_source $destsub '$userprop:origsub' '$userval' local"
+log_must eval "check_prop_missing $dest '$userprop:new'"
+# Cleanup
+log_must zfs destroy -r -f $orig
+log_must zfs destroy -r -f $dest
+
+#
+# 3.7 Verify we can't receive a send stream overriding or excluding properties
+# invalid for the dataset type unless the stream it's recursive, in which
+# case only the appropriate properties are set on the destination.
+#
+log_must zfs create -V 128K -s $orig
+log_must zfs snapshot $orig@snap1
+log_must eval "zfs send $orig@snap1 > $streamfile_full"
+log_mustnot eval "zfs receive -x atime $dest < $streamfile_full"
+log_mustnot eval "zfs receive -o atime=off $dest < $streamfile_full"
+log_must_busy zfs destroy -r -f $orig
+log_must zfs create $orig
+log_must zfs create -V 128K -s $origsub
+log_must zfs snapshot -r $orig@snap1
+log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
+log_must eval "zfs receive -o atime=off $dest < $streamfile_repl"
+log_must eval "check_prop_source $dest type filesystem -"
+log_must eval "check_prop_source $dest atime off local"
+log_must eval "check_prop_source $destsub type volume -"
+log_must eval "check_prop_source $destsub atime - -"
+# Cleanup
+block_device_wait
+log_must_busy zfs destroy -r -f $orig
+log_must_busy zfs destroy -r -f $dest
+
+#
+# 3.8 Verify 'zfs recv -x|-o' works correctly when used in conjunction with -d
+# and -e options.
+#
+log_must zfs create -p $orig/1/2/3/4
+log_must eval "zfs set copies=2 $orig"
+log_must eval "zfs set atime=on $orig"
+log_must eval "zfs set '$userprop:orig'='oldval' $orig"
+log_must zfs snapshot -r $orig@snap1
+log_must eval "zfs send -R $orig/1/2@snap1 > $streamfile_repl"
+# Verify 'zfs recv -e'
+log_must zfs create $dest
+log_must eval "zfs receive -e -o copies=3 -x atime "\
+ "-o '$userprop:orig'='newval' $dest < $streamfile_repl"
+log_must datasetexists $dest/2/3/4
+log_must eval "check_prop_source $dest/2 copies 3 local"
+log_must eval "check_prop_inherit $dest/2/3/4 copies $dest/2"
+log_must eval "check_prop_source $dest/2/3/4 atime on default"
+log_must eval "check_prop_source $dest/2 '$userprop:orig' 'newval' local"
+log_must eval "check_prop_inherit $dest/2/3/4 '$userprop:orig' $dest/2"
+log_must zfs destroy -r -f $dest
+# Verify 'zfs recv -d'
+log_must zfs create $dest
+typeset fs="$(echo $orig | awk -F'/' '{print $NF}')"
+log_must eval "zfs receive -d -o copies=3 -x atime "\
+ "-o '$userprop:orig'='newval' $dest < $streamfile_repl"
+log_must datasetexists $dest/$fs/1/2/3/4
+log_must eval "check_prop_source $dest/$fs/1/2 copies 3 local"
+log_must eval "check_prop_inherit $dest/$fs/1/2/3/4 copies $dest/$fs/1/2"
+log_must eval "check_prop_source $dest/$fs/1/2/3/4 atime on default"
+log_must eval "check_prop_source $dest/$fs/1/2 '$userprop:orig' 'newval' local"
+log_must eval "check_prop_inherit $dest/$fs/1/2/3/4 '$userprop:orig' $dest/$fs/1/2"
+# We don't need to cleanup here
+
+log_pass "ZFS receive property override and exclude options passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/setup.ksh
new file mode 100755
index 000000000000..878189bafa2f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/setup.ksh
@@ -0,0 +1,36 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+if is_global_zone; then
+ default_volume_setup $DISK
+else
+ default_setup $DISK
+fi
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_-e.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_-e.ksh
new file mode 100755
index 000000000000..0c535b469bf3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_-e.ksh
@@ -0,0 +1,106 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# ZFS receive '-e' option can be used to discard all but the last element of
+# the sent snapshot's file system name
+#
+# STRATEGY:
+# 1. Create a filesystem with children and snapshots
+# 2. Verify 'zfs receive -e' rejects invalid options
+# 3. Verify 'zfs receive -e' can receive the root dataset
+# 4. Verify 'zfs receive -e' can receive a replication stream
+# 5. Verify 'zfs receive -e' can receive an incremental replication stream
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_pool "$poolname"
+ log_must rm -f "$vdevfile"
+ log_must rm -f "$streamfile"
+}
+
+log_assert "ZFS receive '-e' option can be used to discard all but the last"\
+ "element of the sent snapshot's file system name"
+log_onexit cleanup
+
+poolname="$TESTPOOL-zfsrecv"
+recvfs="$poolname/recv"
+vdevfile="$TEST_BASE_DIR/vdevfile.$$"
+streamfile="$TEST_BASE_DIR/streamfile.$$"
+
+#
+# 1. Create a filesystem with children and snapshots
+# NOTE: set "mountpoint=none" just to speed up the test process
+#
+log_must truncate -s $MINVDEVSIZE "$vdevfile"
+log_must zpool create -O mountpoint=none "$poolname" "$vdevfile"
+log_must zfs create -p "$poolname/fs/a/b"
+log_must zfs create "$recvfs"
+log_must zfs snapshot -r "$poolname@full"
+log_must zfs snapshot -r "$poolname@incr"
+
+#
+# 2. Verify 'zfs receive -e' rejects invalid options
+#
+log_must eval "zfs send $poolname/fs@full > $streamfile"
+log_mustnot eval "zfs receive -e < $streamfile"
+log_mustnot eval "zfs receive -e $recvfs@snap < $streamfile"
+log_mustnot eval "zfs receive -e $recvfs/1/2/3 < $streamfile"
+log_mustnot eval "zfs receive -A -e $recvfs < $streamfile"
+log_mustnot eval "zfs receive -e -d $recvfs < $streamfile"
+
+#
+# 3. 'zfs receive -e' can receive the root dataset
+#
+recvfs_rootds="$recvfs/rootds"
+log_must zfs create "$recvfs_rootds"
+log_must eval "zfs send $poolname@full > $streamfile"
+log_must eval "zfs receive -e $recvfs_rootds < $streamfile"
+log_must datasetexists "$recvfs_rootds/$poolname"
+log_must snapexists "$recvfs_rootds/$poolname@full"
+
+#
+# 4. 'zfs receive -e' can receive a replication stream
+#
+recvfs_fs="$recvfs/fs"
+log_must zfs create "$recvfs_fs"
+log_must eval "zfs send -R $poolname/fs/a@full > $streamfile"
+log_must eval "zfs receive -e $recvfs_fs < $streamfile"
+log_must datasetexists "$recvfs_fs/a"
+log_must datasetexists "$recvfs_fs/a/b"
+log_must snapexists "$recvfs_fs/a@full"
+log_must snapexists "$recvfs_fs/a/b@full"
+
+#
+# 5. 'zfs receive -e' can receive an incremental replication stream
+#
+log_must eval "zfs send -R -i full $poolname/fs/a@incr > $streamfile"
+log_must eval "zfs receive -e $recvfs_fs < $streamfile"
+log_must snapexists "$recvfs_fs/a@incr"
+log_must snapexists "$recvfs_fs/a/b@incr"
+
+log_pass "ZFS receive '-e' discards all but the last element of the sent"\
+ "snapshot's file system name as expected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_001_pos.ksh
new file mode 100755
index 000000000000..f8439dcbbebd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_001_pos.ksh
@@ -0,0 +1,176 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/cli_common.kshlib
+
+#
+# DESCRIPTION:
+# Verifying 'zfs receive [<filesystem|snapshot>] -d <filesystem>' works.
+#
+# STRATEGY:
+# 1. Fill in fs with some data
+# 2. Create full and incremental send stream
+# 3. Receive the send stream
+# 4. Verify the restoring results.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset -i i=0
+
+ datasetexists $rst_root && \
+ log_must zfs destroy -Rf $rst_root
+ while (( i < 2 )); do
+ snapexists ${orig_snap[$i]} && \
+ log_must zfs destroy -f ${orig_snap[$i]}
+ log_must rm -f ${bkup[$i]}
+
+ (( i = i + 1 ))
+ done
+
+ log_must rm -rf $TESTDIR1
+}
+
+function recreate_root
+{
+ datasetexists $rst_root && \
+ log_must zfs destroy -Rf $rst_root
+ if [[ -d $TESTDIR1 ]] ; then
+ log_must rm -rf $TESTDIR1
+ fi
+ log_must zfs create $rst_root
+ log_must zfs set mountpoint=$TESTDIR1 $rst_root
+}
+
+log_assert "Verifying 'zfs receive [<filesystem|snapshot>] -d <filesystem>' works."
+log_onexit cleanup
+
+typeset datasets="$TESTPOOL/$TESTFS $TESTPOOL"
+set -A bkup "$TEST_BASE_DIR/fullbkup" "$TEST_BASE_DIR/incbkup"
+orig_sum=""
+rst_sum=""
+rst_root=$TESTPOOL/rst_ctr
+rst_fs=${rst_root}/$TESTFS
+
+for orig_fs in $datasets ; do
+ #
+ # Preparations for testing
+ #
+ recreate_root
+
+ set -A orig_snap "${orig_fs}@init_snap" "${orig_fs}@inc_snap"
+ typeset mntpnt=$(get_prop mountpoint ${orig_fs})
+ set -A orig_data "${mntpnt}/$TESTFILE1" "${mntpnt}/$TESTFILE2"
+
+ typeset relative_path=""
+ if [[ ${orig_fs} == *"/"* ]]; then
+ relative_path=${orig_fs#*/}
+ fi
+
+ typeset leaf_fs=${rst_root}/${relative_path}
+ leaf_fs=${leaf_fs%/}
+ rst_snap=${leaf_fs}@snap
+
+ set -A rst_snap "$rst_root/$TESTFS@init_snap" "$rst_root/$TESTFS@inc_snap"
+ set -A rst_snap2 "${leaf_fs}@init_snap" "${leaf_fs}@inc_snap"
+ set -A rst_data "$TESTDIR1/$TESTFS/$TESTFILE1" "$TESTDIR1/$TESTFS/$TESTFILE2"
+ set -A rst_data2 "$TESTDIR1/${relative_path}/$TESTFILE1" "$TESTDIR1/${relative_path}/$TESTFILE2"
+
+ typeset -i i=0
+ while (( i < ${#orig_snap[*]} )); do
+ file_write -o create -f ${orig_data[$i]} -b 512 \
+ -c 8 >/dev/null 2>&1
+ (( $? != 0 )) && \
+ log_fail "Writing data into zfs filesystem fails."
+ log_must zfs snapshot ${orig_snap[$i]}
+ if (( i < 1 )); then
+ log_must eval "zfs send ${orig_snap[$i]} > ${bkup[$i]}"
+ else
+ log_must eval "zfs send -i ${orig_snap[(( i - 1 ))]} \
+ ${orig_snap[$i]} > ${bkup[$i]}"
+ fi
+
+ (( i = i + 1 ))
+ done
+
+ log_note "Verifying 'zfs receive <filesystem>' works."
+ i=0
+ while (( i < ${#bkup[*]} )); do
+ if (( i > 0 )); then
+ log_must zfs rollback ${rst_snap[0]}
+ fi
+ log_must eval "zfs receive $rst_fs < ${bkup[$i]}"
+ snapexists ${rst_snap[$i]} || \
+ log_fail "Restoring filesystem fails. ${rst_snap[$i]} not exist"
+ compare_cksum ${orig_data[$i]} ${rst_data[$i]}
+
+ (( i = i + 1 ))
+ done
+
+ log_must zfs destroy -Rf $rst_fs
+
+ log_note "Verifying 'zfs receive <snapshot>' works."
+ i=0
+ while (( i < ${#bkup[*]} )); do
+ if (( i > 0 )); then
+ log_must zfs rollback ${rst_snap[0]}
+ fi
+ log_must eval "zfs receive ${rst_snap[$i]} <${bkup[$i]}"
+ snapexists ${rst_snap[$i]} || \
+ log_fail "Restoring filesystem fails. ${rst_snap[$i]} not exist"
+ compare_cksum ${orig_data[$i]} ${rst_data[$i]}
+
+ (( i = i + 1 ))
+ done
+
+ log_must zfs destroy -Rf $rst_fs
+
+ log_note "Verifying 'zfs receive -d <filesystem>' works."
+
+ i=0
+ while (( i < ${#bkup[*]} )); do
+ if (( i > 0 )); then
+ log_must zfs rollback ${rst_snap2[0]}
+ fi
+ log_must eval "zfs receive -d -F $rst_root <${bkup[$i]}"
+ snapexists ${rst_snap2[$i]} || \
+ log_fail "Restoring filesystem fails. ${rst_snap2[$i]} not exist"
+ compare_cksum ${orig_data[$i]} ${rst_data2[$i]}
+
+ (( i = i + 1 ))
+ done
+
+ cleanup
+done
+
+log_pass "Verifying 'zfs receive [<filesystem|snapshot>] -d <filesystem>' succeeds."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_002_pos.ksh
new file mode 100755
index 000000000000..36af37a7576d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_002_pos.ksh
@@ -0,0 +1,108 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/cli_common.kshlib
+
+#
+# DESCRIPTION:
+# Verifying 'zfs receive <volume>' works.
+#
+# STRATEGY:
+# 1. Fill in volume with some data
+# 2. Create full and incremental send stream
+# 3. Restore the send stream
+# 4. Verify the restoring results.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset -i i=0
+ typeset ds
+
+ while (( i < ${#orig_snap[*]} )); do
+ snapexists ${rst_snap[$i]} && \
+ log_must zfs destroy -f ${rst_snap[$i]}
+ snapexists ${orig_snap[$i]} && \
+ log_must zfs destroy -f ${orig_snap[$i]}
+ [[ -e ${bkup[$i]} ]] && \
+ log_must rm -rf ${bkup[$i]}
+
+ (( i = i + 1 ))
+ done
+
+ for ds in $rst_vol $rst_root; do
+ datasetexists $ds && \
+ log_must zfs destroy -Rf $ds
+ done
+}
+
+log_assert "Verifying 'zfs receive <volume>' works."
+log_onexit cleanup
+
+set -A orig_snap "$TESTPOOL/$TESTVOL@init_snap" "$TESTPOOL/$TESTVOL@inc_snap"
+set -A bkup "$TEST_BASE_DIR/fullbkup" "$TEST_BASE_DIR/incbkup"
+rst_root=$TESTPOOL/rst_ctr
+rst_vol=$rst_root/$TESTVOL
+set -A rst_snap "${rst_vol}@init_snap" "${rst_vol}@inc_snap"
+
+#
+# Preparations for testing
+#
+log_must zfs create $rst_root
+[[ ! -d $TESTDIR1 ]] && \
+ log_must mkdir -p $TESTDIR1
+log_must zfs set mountpoint=$TESTDIR1 $rst_root
+
+typeset -i i=0
+while (( i < ${#orig_snap[*]} )); do
+ log_must zfs snapshot ${orig_snap[$i]}
+ if (( i < 1 )); then
+ log_must eval "zfs send ${orig_snap[$i]} > ${bkup[$i]}"
+ else
+ log_must eval "zfs send -i ${orig_snap[(( i - 1 ))]} \
+ ${orig_snap[$i]} > ${bkup[$i]}"
+ fi
+
+ (( i = i + 1 ))
+done
+
+i=0
+while (( i < ${#bkup[*]} )); do
+ log_must eval "zfs receive $rst_vol < ${bkup[$i]}"
+ ! datasetexists $rst_vol || ! snapexists ${rst_snap[$i]} && \
+ log_fail "Restoring volume fails."
+
+ (( i = i + 1 ))
+done
+
+log_pass "Verifying 'zfs receive <volume>' succeeds."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_003_pos.ksh
new file mode 100755
index 000000000000..d5f6e0984df5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_003_pos.ksh
@@ -0,0 +1,93 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs recv -F' to force rollback.
+#
+# STRATEGY:
+# 1. Create pool and fs.
+# 2. Create some files in fs and take a snapshot1.
+# 3. Create another files in fs and take snapshot2.
+# 4. Create incremental stream from snapshot1 to snapshot2.
+# 5. fs rollback to snapshot1 and modify fs.
+# 6. Verify 'zfs recv -F' can force rollback.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for snap in $snap2 $snap1; do
+ datasetexists $snap && log_must zfs destroy -rf $snap
+ done
+ for file in $ibackup $mntpnt/file1 $mntpnt/file2; do
+ [[ -f $file ]] && log_must rm -f $file
+ done
+}
+
+log_assert "'zfs recv -F' to force rollback."
+log_onexit cleanup
+
+ibackup=$TEST_BASE_DIR/ibackup.$$
+fs=$TESTPOOL/$TESTFS; snap1=$fs@snap1; snap2=$fs@snap2
+
+mntpnt=$(get_prop mountpoint $fs) || log_fail "get_prop mountpoint $fs"
+log_must mkfile 10m $mntpnt/file1
+log_must zfs snapshot $snap1
+log_must mkfile 10m $mntpnt/file2
+log_must zfs snapshot $snap2
+
+log_must eval "zfs send -i $snap1 $snap2 > $ibackup"
+
+log_note "Verify 'zfs receive' succeed, if filesystem was not modified."
+log_must zfs rollback -r $snap1
+log_must eval "zfs receive $fs < $ibackup"
+if [[ ! -f $mntpnt/file1 || ! -f $mntpnt/file2 ]]; then
+ log_fail "'zfs receive' failed."
+fi
+
+log_note "Verify 'zfs receive' failed if filesystem was modified."
+log_must zfs rollback -r $snap1
+log_must rm -rf $mntpnt/file1
+log_mustnot eval "zfs receive $fs < $ibackup"
+
+# Verify 'zfs receive -F' to force rollback whatever filesystem was modified.
+log_must zfs rollback -r $snap1
+log_must rm -rf $mntpnt/file1
+log_must eval "zfs receive -F $fs < $ibackup"
+if [[ ! -f $mntpnt/file1 || ! -f $mntpnt/file2 ]]; then
+ log_fail "'zfs receive -F' failed."
+fi
+
+log_pass "'zfs recv -F' to force rollback passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_004_neg.ksh
new file mode 100755
index 000000000000..56f536225d74
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_004_neg.ksh
@@ -0,0 +1,110 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/cli_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify 'zfs receive' fails with malformed parameters.
+#
+# STRATEGY:
+# 1. Define malformed parameters array
+# 2. Feed the malformed parameters to 'zfs receive'
+# 3. Verify the command should be failed
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset snap
+ typeset bkup
+
+ for snap in $init_snap $inc_snap $init_topsnap $inc_topsnap ; do
+ snapexists $snap && \
+ log_must zfs destroy -Rf $snap
+ done
+
+ for bkup in $full_bkup $inc_bkup $full_topbkup $inc_topbkup; do
+ [[ -e $bkup ]] && \
+ log_must rm -f $bkup
+ done
+}
+
+log_assert "Verify that invalid parameters to 'zfs receive' are caught."
+log_onexit cleanup
+
+init_snap=$TESTPOOL/$TESTFS@initsnap
+inc_snap=$TESTPOOL/$TESTFS@incsnap
+full_bkup=$TEST_BASE_DIR/full_bkup.$$
+inc_bkup=$TEST_BASE_DIR/inc_bkup.$$
+
+init_topsnap=$TESTPOOL@initsnap
+inc_topsnap=$TESTPOOL@incsnap
+full_topbkup=$TEST_BASE_DIR/full_topbkup.$$
+inc_topbkup=$TEST_BASE_DIR/inc_topbkup.$$
+
+log_must zfs snapshot $init_topsnap
+log_must eval "zfs send $init_topsnap > $full_topbkup"
+log_must touch /$TESTPOOL/foo
+
+log_must zfs snapshot $inc_topsnap
+log_must eval "zfs send -i $init_topsnap $inc_topsnap > $inc_topbkup"
+log_must touch /$TESTPOOL/bar
+
+log_must zfs snapshot $init_snap
+log_must eval "zfs send $init_snap > $full_bkup"
+log_must touch /$TESTDIR/foo
+
+log_must zfs snapshot $inc_snap
+log_must eval "zfs send -i $init_snap $inc_snap > $inc_bkup"
+log_must touch /$TESTDIR/bar
+
+sync
+
+set -A badargs \
+ "" "nonexistent-snap" "blah@blah" "-d" "-d nonexistent-dataset" \
+ "$TESTPOOL1" "$TESTPOOL/fs@" "$TESTPOOL/fs@@mysnap" \
+ "$TESTPOOL/fs@@" "$TESTPOOL/fs/@mysnap" "$TESTPOOL/fs@/mysnap" \
+ "$TESTPOOL/nonexistent-fs/nonexistent-fs" "-d $TESTPOOL/nonexistent-fs" \
+ "-d $TESTPOOL/$TESTFS/nonexistent-fs"
+
+typeset -i i=0
+while (( i < ${#badargs[*]} ))
+do
+ for bkup in $full_bkup $inc_bkup $full_topbkup $inc_topbkup ; do
+ log_mustnot eval "zfs receive ${badargs[i]} < $bkup"
+ done
+
+ (( i = i + 1 ))
+done
+
+log_pass "Invalid parameters to 'zfs receive' are caught as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_005_neg.ksh
new file mode 100755
index 000000000000..4cbc7e339031
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_005_neg.ksh
@@ -0,0 +1,99 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/cli_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify 'zfs receive' fails with unsupported scenarios.
+# including:
+# (1) Invalid send streams;
+# (2) The received incremental send doesn't match the filesystem
+# latest status.
+#
+# STRATEGY:
+# 1. Preparation for unsupported scenarios
+# 2. Execute 'zfs receive'
+# 3. Verify the results are failed
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset snap
+ typeset bkup
+
+ for snap in $init_snap $inc_snap; do
+ snapexists $snap && \
+ log_must zfs destroy -f $snap
+ done
+
+ datasetexists $rst_root && \
+ log_must zfs destroy -Rf $rst_root
+
+ for bkup in $full_bkup $inc_bkup; do
+ [[ -e $bkup ]] && \
+ log_must rm -f $bkup
+ done
+}
+
+log_assert "Verify 'zfs receive' fails with unsupported scenarios."
+log_onexit cleanup
+
+init_snap=$TESTPOOL/$TESTFS@initsnap
+inc_snap=$TESTPOOL/$TESTFS@incsnap
+rst_root=$TESTPOOL/rst_ctr
+rst_init_snap=$rst_root/$TESTFS@init_snap
+rst_inc_snap=$rst_root/$TESTFS@inc_snap
+full_bkup=$TEST_BASE_DIR/full_bkup.$$
+inc_bkup=$TEST_BASE_DIR/inc_bkup.$$
+
+log_must zfs create $rst_root
+log_must zfs snapshot $init_snap
+log_must eval "zfs send $init_snap > $full_bkup"
+
+log_note "'zfs receive' fails with invalid send streams."
+log_mustnot eval "zfs receive $rst_init_snap < /dev/zero"
+log_mustnot eval "zfs receive -d $rst_root </dev/zero"
+
+log_must eval "zfs receive $rst_init_snap < $full_bkup"
+
+log_note "Unmatched send stream with restoring filesystem" \
+ " cannot be received."
+log_must zfs snapshot $inc_snap
+log_must eval "zfs send -i $init_snap $inc_snap > $inc_bkup"
+#make changes on the restoring filesystem
+log_must touch $ZFSROOT/$rst_root/$TESTFS/tmpfile
+log_mustnot eval "zfs receive $rst_inc_snap < $inc_bkup"
+log_mustnot eval "zfs receive -d $rst_root < $inc_bkup"
+
+log_pass "Unsupported scenarios to 'zfs receive' fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_006_pos.ksh
new file mode 100755
index 000000000000..7338fd2b9fb2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_006_pos.ksh
@@ -0,0 +1,108 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs recv -d <fs>' should create ancestor filesystem if it does not
+# exist and it should not fail if it exists
+#
+# STRATEGY:
+# 1. Create pool and fs.
+# 2. Create some files in fs and take snapshots.
+# 3. Keep the stream and restore the stream to the pool
+# 4. Verify receiving the stream succeeds, and the ancestor filesystem
+# is created if it did not exist
+# 5. Verify receiving the stream still succeeds when ancestor filesystem
+# exists
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for snap in $snap2 $snap1; do
+ datasetexists $snap && log_must zfs destroy -rf $snap
+ done
+ for file in $fbackup1 $fbackup2 $mntpnt/file1 $mntpnt/file2; do
+ [[ -f $file ]] && log_must rm -f $file
+ done
+
+ if is_global_zone; then
+ datasetexists $TESTPOOL/$TESTFS/$TESTFS1 && \
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS/$TESTFS1
+ else
+ datasetexists $TESTPOOL/${ZONE_CTR}0 && \
+ log_must zfs destroy -rf $TESTPOOL/${ZONE_CTR}0
+ fi
+
+}
+
+log_assert "'zfs recv -d <fs>' should succeed no matter ancestor filesystem \
+ exists."
+log_onexit cleanup
+
+ancestor_fs=$TESTPOOL/$TESTFS
+fs=$TESTPOOL/$TESTFS/$TESTFS1
+snap1=$fs@snap1
+snap2=$fs@snap2
+fbackup1=$TEST_BASE_DIR/fbackup1.$$
+fbackup2=$TEST_BASE_DIR/fbackup2.$$
+
+datasetexists $ancestor_fs || \
+ log_must zfs create $ancestor_fs
+log_must zfs create $fs
+
+mntpnt=$(get_prop mountpoint $fs) || log_fail "get_prop mountpoint $fs"
+log_must mkfile 10m $mntpnt/file1
+log_must zfs snapshot $snap1
+log_must mkfile 10m $mntpnt/file2
+log_must zfs snapshot $snap2
+
+log_must eval "zfs send $snap1 > $fbackup1"
+log_must eval "zfs send $snap2 > $fbackup2"
+
+log_note "Verify 'zfs receive -d' succeed and create ancestor filesystem \
+ if it did not exist. "
+log_must zfs destroy -rf $ancestor_fs
+log_must eval "zfs receive -d $TESTPOOL < $fbackup1"
+is_global_zone || ancestor_fs=$TESTPOOL/${ZONE_CTR}0/$TESTFS
+datasetexists $ancestor_fs || \
+ log_fail "ancestor filesystem is not created"
+
+log_note "Verify 'zfs receive -d' still succeed if ancestor filesystem exists"
+is_global_zone || fs=$TESTPOOL/${ZONE_CTR}0/$TESTFS/$TESTFS1
+log_must zfs destroy -rf $fs
+log_must eval "zfs receive -d $TESTPOOL < $fbackup2"
+
+log_pass "'zfs recv -d <fs>' should succeed no matter ancestor filesystem \
+ exists."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_007_neg.ksh
new file mode 100755
index 000000000000..57454dcbc6f2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_007_neg.ksh
@@ -0,0 +1,84 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs recv -F' should fail if the incremental stream does not match
+#
+# STRATEGY:
+# 1. Create pool and fs.
+# 2. Create some files in fs and take snapshots.
+# 3. Keep the incremental stream and restore the stream to the pool
+# 4. Verify receiving the stream fails
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for snap in $snap2 $snap1; do
+ datasetexists $snap && log_must zfs destroy -rf $snap
+ done
+ for file in $ibackup $mntpnt/file1 $mntpnt/file2; do
+ [[ -f $file ]] && log_must rm -f $file
+ done
+}
+
+log_assert "'zfs recv -F' should fail if the incremental stream does not match"
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+snap1=$fs@snap1
+snap2=$fs@snap2
+ibackup=$TEST_BASE_DIR/ibackup.$$
+
+datasetexists $fs || log_must zfs create $fs
+
+mntpnt=$(get_prop mountpoint $fs) || log_fail "get_prop mountpoint $fs"
+log_must mkfile 10m $mntpnt/file1
+log_must zfs snapshot $snap1
+log_must mkfile 10m $mntpnt/file2
+log_must zfs snapshot $snap2
+
+log_must eval "zfs send -i $snap1 $snap2 > $ibackup"
+
+log_must zfs destroy $snap1
+log_must zfs destroy $snap2
+log_mustnot eval "zfs receive -F $fs < $ibackup"
+
+log_must mkfile 20m $mntpnt/file1
+log_must rm -rf $mntpnt/file2
+log_must zfs snapshot $snap1
+log_mustnot eval "zfs receive -F $snap2 < $ibackup"
+
+log_pass "'zfs recv -F' should fail if the incremental stream does not match"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_008_pos.ksh
new file mode 100755
index 000000000000..1729b59b2bfd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_008_pos.ksh
@@ -0,0 +1,148 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/cli_common.kshlib
+
+#
+# DESCRIPTION:
+# Verifying 'zfs receive -vn [<filesystem|snapshot>]
+# and zfs receive -vn -d <filesystem>'
+#
+# STRATEGY:
+# 1. Fill in fs with some data
+# 2. Create full and incremental send stream
+# 3. run zfs receive with -v option
+# 3. Dryrun zfs receive with -vn option
+# 3. Dryrun zfs receive with -vn -d option
+# 4. Verify receive output and result
+#
+function cleanup
+{
+ for dset in $rst_snap $rst_fs $orig_snap; do
+ if datasetexists $dset; then
+ log_must zfs destroy -fr $dset
+ fi
+ done
+
+ for file in $fbackup $mnt_file $tmp_out; do
+ if [[ -f $file ]]; then
+ log_must rm -f $file
+ fi
+ done
+
+ if datasetexists $TESTPOOL/$TESTFS; then
+ log_must zfs destroy -Rf $TESTPOOL/$TESTFS
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+ fi
+}
+
+verify_runnable "both"
+log_assert "Verifying 'zfs receive -vn [<filesystem|snapshot>] " \
+ "and zfs receive -vn -d <filesystem>'"
+
+log_onexit cleanup
+
+typeset datasets="$TESTPOOL/$TESTFS $TESTPOOL"
+typeset rst_fs=$TESTPOOL/$TESTFS/$TESTFS
+typeset fbackup=$TEST_BASE_DIR/fbackup.$$
+typeset tmp_out=$TEST_BASE_DIR/tmpout.$$
+
+for orig_fs in $datasets ; do
+ typeset rst_snap=$rst_fs@snap
+ typeset orig_snap=$orig_fs@snap
+ typeset verb_msg="receiving full stream of ${orig_snap} into ${rst_snap}"
+ typeset dryrun_msg="would receive full stream of ${orig_snap} into ${rst_snap}"
+
+ if ! datasetexists $orig_fs; then
+ log_must zfs create $orig_fs
+ fi
+
+ typeset mntpnt
+ mntpnt=$(get_prop mountpoint $orig_fs)
+ if [[ $? -ne 0 ]] ; then
+ log_fail "get_prop mountpoint $orig_fs failed"
+ fi
+
+ typeset mnt_file=$mntpnt/file1
+
+ log_must mkfile 100m $mnt_file
+ log_must zfs snapshot $orig_snap
+ log_must eval "zfs send $orig_snap > $fbackup"
+
+ for opt in "-v" "-vn"; do
+ if datasetexists $rst_fs; then
+ log_must zfs destroy -fr $rst_fs
+ fi
+ log_note "Check ZFS receive $opt [<filesystem|snapshot>]"
+ log_must eval "zfs receive $opt $rst_fs < $fbackup > $tmp_out 2>&1"
+ if [[ $opt == "-v" ]]; then
+ log_must eval "grep \"$verb_msg\" $tmp_out >/dev/null 2>&1"
+ if ! datasetexists $rst_snap; then
+ log_fail "dataset was not received, even though the"\
+ " -v flag was used."
+ fi
+ else
+ log_must eval "grep \"$dryrun_msg\" $tmp_out >/dev/null 2>&1"
+ if datasetexists $rst_snap; then
+ log_fail "dataset was received, even though the -nv"\
+ " flag was used."
+ fi
+ fi
+ done
+
+ log_note "Check ZFS receive -vn -d <filesystem>"
+ if ! datasetexists $rst_fs; then
+ log_must zfs create $rst_fs
+ fi
+ log_must eval "zfs receive -vn -d -F $rst_fs <$fbackup >$tmp_out 2>&1"
+ typeset relative_path=""
+ if [[ ${orig_fs} == *"/"* ]]; then
+ relative_path=${orig_fs#*/}
+ fi
+
+ typeset leaf_fs=${rst_fs}/${relative_path}
+ leaf_fs=${leaf_fs%/}
+ rst_snap=${leaf_fs}@snap
+ dryrun_msg="would receive full stream of ${orig_snap} into ${rst_snap}"
+
+ log_must eval "grep \"$dryrun_msg\" $tmp_out > /dev/null 2>&1"
+
+ if datasetexists $rst_snap; then
+ log_fail "dataset $rst_snap should not existed."
+ fi
+ log_must zfs destroy -Rf $rst_fs
+
+ cleanup
+done
+
+log_pass "zfs receive -vn [<filesystem|snapshot>] and " \
+ "zfs receive -vn -d <filesystem>' succeed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_009_neg.ksh
new file mode 100755
index 000000000000..d028acafada0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_009_neg.ksh
@@ -0,0 +1,118 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/cli_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify 'zfs receive' fails with bad options, missing argument or too many
+# arguments.
+#
+# STRATEGY:
+# 1. Set a array of illegal arguments
+# 2. Execute 'zfs receive' with illegal arguments
+# 3. Verify the command should be failed
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset ds
+
+ if snapexists $snap; then
+ log_must zfs destroy $snap
+ fi
+ for ds in $ctr1 $ctr2 $fs1; do
+ if datasetexists $ds; then
+ log_must zfs destroy -rf $ds
+ fi
+ done
+ if [[ -d $TESTDIR2 ]]; then
+ rm -rf $TESTDIR2
+ fi
+}
+
+log_assert "Verify 'zfs receive' fails with bad option, missing or too many arguments"
+log_onexit cleanup
+
+set -A badopts "v" "n" "F" "d" "-V" "-N" "-f" "-D" "-VNfD" "-vNFd" "-vnFD" "-dVnF" \
+ "-vvvNfd" "-blah" "-12345" "-?" "-*" "-%"
+set -A validopts "" "-v" "-n" "-F" "-vn" "-nF" "-vnF" "-vd" "-nd" "-Fd" "-vnFd"
+
+ctr1=$TESTPOOL/$TESTCTR1
+ctr2=$TESTPOOL/$TESTCTR2
+fs1=$TESTPOOL/$TESTFS1
+fs2=$TESTPOOL/$TESTFS2
+fs3=$TESTPOOL/$TESTFS3
+snap=$TESTPOOL/$TESTFS@$TESTSNAP
+bkup=$TESTDIR2/bkup.$$
+
+# Preparations for negative testing
+for ctr in $ctr1 $ctr2; do
+ log_must zfs create $ctr
+done
+if [[ -d $TESTDIR2 ]]; then
+ rm -rf $TESTDIR2
+fi
+log_must zfs create -o mountpoint=$TESTDIR2 $fs1
+log_must zfs snapshot $snap
+log_must eval "zfs send $snap > $bkup"
+
+#Testing zfs receive fails with input from terminal
+log_mustnot eval "zfs recv $fs3 </dev/console"
+
+# Testing with missing argument and too many arguments
+typeset -i i=0
+while (( i < ${#validopts[*]} )); do
+ log_mustnot eval "zfs recv < $bkup"
+
+ echo ${validopts[i]} | grep "d" >/dev/null 2>&1
+ if (( $? != 0 )); then
+ log_mustnot eval "zfs recv ${validopts[i]} $fs2 $fs3 < $bkup"
+ else
+ log_mustnot eval "zfs recv ${validopts[i]} $ctr1 $ctr2 < $bkup"
+ fi
+
+ (( i += 1 ))
+done
+
+# Testing with bad options
+i=0
+while (( i < ${#badopts[*]} ))
+do
+ log_mustnot eval "zfs recv ${badopts[i]} $ctr1 < $bkup"
+ log_mustnot eval "zfs recv ${badopts[i]} $fs2 < $bkup"
+
+ (( i = i + 1 ))
+done
+
+log_pass "'zfs receive' as expected with bad options, missing or too many arguments."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_pos.ksh
new file mode 100755
index 000000000000..84485977aa23
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_pos.ksh
@@ -0,0 +1,177 @@
+#!/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) 2015, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Test that receiving a full send as a clone works correctly.
+#
+# STRATEGY:
+# 1. Create pool and filesystems.
+# 2. Send filesystem, receive as clone of itself.
+# 3. Verify that nop-write saves space.
+# 4. Send filesystem, receive as clone of other filesystem.
+# 5. Verify that contents are correct.
+# 6. Repeat steps 4 and 5 with filesystems swapped.
+#
+
+verify_runnable "both"
+
+fs=$TESTPOOL/$TESTFS/base/fs
+fs2=$TESTPOOL/$TESTFS/base/fs2
+rfs=$TESTPOOL/$TESTFS/base/rfs
+
+function make_object
+{
+ typeset objnum=$1
+ typeset mntpnt=$2
+ typeset type=$3
+ if [[ $type == "file" ]]; then
+ dd if=/dev/urandom of=${mntpnt}/f$objnum bs=512 count=16
+ elif [[ $type == "hole1" ]]; then
+ dd if=/dev/zero of=${mntpnt}/fh$objnum bs=512 count=5 seek=4 conv=notrunc
+ elif [[ $type == "hole2" ]]; then
+ dd if=/dev/zero of=${mntpnt}/fh$objnum bs=512 count=4 seek=5 conv=notrunc
+ elif [[ $type == "directory" ]]; then
+ mkdir ${mntpnt}/d$objnum
+ elif [[ $type == "missing" ]]; then
+ touch ${mntpnt}/h$objnum
+ fi
+}
+
+function create_pair
+{
+ typeset objnum=$1
+ typeset mntpnt1=$2
+ typeset mntpnt2=$3
+ typeset type1=$4
+ typeset type2=$5
+ make_object $objnum $mntpnt1 $type1
+ make_object $objnum $mntpnt2 $type2
+}
+
+function cleanup
+{
+ zfs destroy -Rf $TESTPOOL/$TESTFS/base
+ rm $TESTDIR/zr010p*
+}
+
+log_assert "zfs receive of full send as clone should work"
+log_onexit cleanup
+log_must zfs create -o checksum=sha256 -o compression=gzip -o recordsize=512 \
+ $TESTPOOL/$TESTFS/base
+
+log_must zfs create $fs
+log_must zfs create $fs2
+mntpnt=$(get_prop mountpoint $fs)
+mntpnt2=$(get_prop mountpoint $fs2)
+
+#
+# Now, we create the two filesystems. By creating objects with
+# different types and the same object number in each filesystem, we
+# create a situation where, when you receive the full send of each as
+# a clone of the other, we will test to ensure that the code correctly
+# handles receiving all object types onto all other object types.
+#
+
+# Receive a file onto a file (and vice versa).
+create_pair 8 $mntpnt $mntpnt2 "file" "file"
+
+# Receive a file onto a file with holes (and vice versa).
+create_pair 9 $mntpnt $mntpnt2 "file" "hole1"
+
+# Receive a file onto a directory (and vice versa).
+create_pair 10 $mntpnt $mntpnt2 "file" "directory"
+
+# Receive a file onto a missing object (and vice versa).
+create_pair 11 $mntpnt $mntpnt2 "file" "missing"
+
+# Receive a file with holes onto a file with holes (and vice versa).
+create_pair 12 $mntpnt $mntpnt2 "hole1" "hole2"
+
+# Receive a file with holes onto a directory (and vice versa).
+create_pair 13 $mntpnt $mntpnt2 "hole1" "directory"
+
+# Receive a file with holes onto a missing object (and vice versa).
+create_pair 14 $mntpnt $mntpnt2 "hole1" "missing"
+
+# Receive a directory onto a directory (and vice versa).
+create_pair 15 $mntpnt $mntpnt2 "directory" "directory"
+
+# Receive a directory onto a missing object (and vice versa).
+create_pair 16 $mntpnt $mntpnt2 "directory" "missing"
+
+# Receive a missing object onto a missing object (and vice versa).
+create_pair 17 $mntpnt $mntpnt2 "missing" "missing"
+
+# Receive a file with a different record size onto a file (and vice versa).
+log_must zfs set recordsize=128k $fs
+dd if=/dev/urandom of=$mntpnt/f18 bs=128k count=64
+touch $mntpnt2/f18
+
+# Remove objects that are intended to be missing.
+rm $mntpnt/h17
+rm $mntpnt2/h*
+
+# Add empty objects to $fs to exercise dmu_traverse code
+for i in {1..100}; do
+ log_must touch $mntpnt/uf$i
+done
+
+log_must zfs snapshot $fs@s1
+log_must zfs snapshot $fs2@s1
+
+log_must zfs send $fs@s1 > $TESTDIR/zr010p
+log_must zfs send $fs2@s1 > $TESTDIR/zr010p2
+
+
+#
+# Test that, when we receive a full send as a clone of itself,
+# nop-write saves us all the space used by data blocks.
+#
+cat $TESTDIR/zr010p | log_must zfs receive -o origin=$fs@s1 $rfs
+size=$(get_prop used $rfs)
+size2=$(get_prop used $fs)
+if [[ $size -ge $(($size2 / 10)) ]] then
+ log_fail "nop-write failure; expected usage less than "\
+ "$(($size2 / 10)), but is using $size"
+fi
+log_must zfs destroy -fr $rfs
+
+# Correctness testing: receive each full send as a clone of the other fiesystem.
+cat $TESTDIR/zr010p | log_must zfs receive -o origin=$fs2@s1 $rfs
+mntpnt_old=$(get_prop mountpoint $fs)
+mntpnt_new=$(get_prop mountpoint $rfs)
+log_must diff -r $mntpnt_old $mntpnt_new
+log_must zfs destroy -r $rfs
+
+cat $TESTDIR/zr010p2 | log_must zfs receive -o origin=$fs@s1 $rfs
+mntpnt_old=$(get_prop mountpoint $fs2)
+mntpnt_new=$(get_prop mountpoint $rfs)
+log_must diff -r $mntpnt_old $mntpnt_new
+
+log_pass "zfs receive of full send as clone works"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_011_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_011_pos.ksh
new file mode 100755
index 000000000000..afae804a15c2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_011_pos.ksh
@@ -0,0 +1,88 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# refquota should be sent-and-received, but it should not interfere with
+# the receipt of intermediate snapshots that may have preceded the
+# final snapshot, where the refquota should hold.
+#
+# STRATEGY:
+# 1. Create a filesystem.
+# 2. Create two equal-sized large files.
+# 3. Snapshot the filesystem.
+# 4. Remove one of the two large files.
+# 5. Create a refquota larger than one file, but smaller than both.
+# 6. Snapshot the filesystem again.
+# 7. Send a replication stream of the second snapshot to a new filesystem.
+#
+#
+
+verify_runnable "both"
+
+typeset streamfile=$TEST_BASE_DIR/streamfile.$$
+
+function cleanup
+{
+ log_must rm $streamfile
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS1
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS2
+}
+
+log_assert "refquota is properly sent-and-received, regardless of any " \
+ "intermediate snapshots sent by a replication stream."
+log_onexit cleanup
+
+orig=$TESTPOOL/$TESTFS1
+dest=$TESTPOOL/$TESTFS2
+# 1. Create a filesystem.
+log_must zfs create $orig
+origdir=$(get_prop mountpoint $orig)
+
+# 2. Create two equal-sized large files.
+log_must mkfile 5M $origdir/file1
+log_must mkfile 5M $origdir/file2
+log_must sync
+
+# 3. Snapshot the filesystem.
+log_must zfs snapshot $orig@1
+
+# 4. Remove one of the two large files.
+log_must rm $origdir/file2
+log_must sync
+
+# 5. Create a refquota larger than one file, but smaller than both.
+log_must zfs set refquota=8M $orig
+
+# 6. Snapshot the filesystem again.
+log_must zfs snapshot $orig@2
+
+# 7. Send a replication stream of the second snapshot to a new filesystem.
+log_must eval "zfs send -R $orig@2 > $streamfile"
+log_must eval "zfs recv $dest < $streamfile"
+
+log_pass "refquota is properly sent-and-received, regardless of any " \
+ "intermediate snapshots sent by a replication stream."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_012_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_012_pos.ksh
new file mode 100755
index 000000000000..4e72a66d49c8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_012_pos.ksh
@@ -0,0 +1,83 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2016, OmniTI Computer Consulting, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# refquota, like regular quota, is loosely enforced. A dataset
+# can exceed its refquota by one transaction. This loose enforcement
+# used to cause problems upon receiving a datastream where its
+# refquota is slightly exceeded. This test confirms that we can
+# successfully receive a slightly over refquota stream.
+#
+# STRATEGY:
+# 1. Create a filesystem.
+# 2. Set a refquota.
+# 3. Snapshot the filesystem.
+# 4. Send a replication stream to a new filesystem.
+# 5. On the original filesystem, fill it up to its quota.
+# 6. Snapshot the original filesystem again.
+# 7. Send an incremental stream to the same new filesystem.
+#
+
+verify_runnable "both"
+
+typeset streamfile=$TEST_BASE_DIR/streamfile.$$
+
+function cleanup
+{
+ log_must rm $streamfile
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS1
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS2
+}
+
+log_assert "The allowable slight refquota overage is properly sent-and-" \
+ "received."
+log_onexit cleanup
+
+orig=$TESTPOOL/$TESTFS1
+dest=$TESTPOOL/$TESTFS2
+
+# 1. Create a filesystem.
+log_must zfs create $orig
+origdir=$(get_prop mountpoint $orig)
+
+# 2. Set a refquota.
+log_must zfs set refquota=50M $orig
+
+# 3. Snapshot the filesystem.
+log_must zfs snapshot $orig@1
+
+# 4. Send a replication stream to a new filesystem.
+log_must eval "zfs send -R $orig@1 > $streamfile"
+log_must eval "zfs recv $dest < $streamfile"
+
+# 5. On the original filesystem, fill it up to its quota.
+cat < /dev/urandom > $origdir/fill-it-up
+
+# 6. Snapshot the original filesystem again.
+log_must zfs snapshot $orig@2
+
+# 7. Send an incremental stream to the same new filesystem.
+log_must eval "zfs send -I 1 -R $orig@2 > $streamfile"
+log_must eval "zfs recv $dest < $streamfile"
+
+log_pass "Verified receiving a slightly-over-refquota stream succeeds."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_013_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_013_pos.ksh
new file mode 100755
index 000000000000..be8f49809d47
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_013_pos.ksh
@@ -0,0 +1,75 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2015, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/cli_common.kshlib
+
+#
+# DESCRIPTION:
+# Verifying 'zfs receive' works correctly on deduplicated streams
+#
+# STRATEGY:
+# 1. Create some snapshots with duplicated data
+# 2. Send a deduplicated stream of the last snapshot
+# 3. Attempt to receive the deduplicated stream
+#
+
+src_fs=$TESTPOOL/drecvsrc
+temppool=recvtank
+dst_fs=$temppool/drecvdest
+streamfile=$TEST_BASE_DIR/drecvstream.$$
+tpoolfile=$TEST_BASE_DIR/temptank.$$
+
+function cleanup
+{
+ for fs in $src_fs $dst_fs; do
+ datasetexists $fs && log_must zfs destroy -rf $fs
+ done
+ zpool destroy $temppool
+ [[ -f $streamfile ]] && log_must rm -f $streamfile
+ [[ -f $tpoolfile ]] && log_must rm -f $tpoolfile
+}
+
+log_assert "Verifying 'zfs receive' works correctly on deduplicated streams"
+log_onexit cleanup
+
+truncate -s 100M $tpoolfile
+log_must zpool create $temppool $tpoolfile
+log_must zfs create $src_fs
+src_mnt=$(get_prop mountpoint $src_fs) || log_fail "get_prop mountpoint $src_fs"
+
+echo blah > $src_mnt/blah
+zfs snapshot $src_fs@base
+
+echo grumble > $src_mnt/grumble
+echo blah > $src_mnt/blah2
+zfs snapshot $src_fs@snap2
+
+echo grumble > $src_mnt/mumble
+echo blah > $src_mnt/blah3
+zfs snapshot $src_fs@snap3
+
+log_must eval "zfs send -D -R $src_fs@snap3 > $streamfile"
+log_must eval "zfs receive -v $dst_fs < $streamfile"
+log_must zfs destroy -r $dst_fs
+log_must eval "zstream redup $streamfile | zfs receive -v $dst_fs"
+
+cleanup
+
+log_pass "Verifying 'zfs receive' works correctly on deduplicated streams"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_014_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_014_pos.ksh
new file mode 100755
index 000000000000..be04aed2b24c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_014_pos.ksh
@@ -0,0 +1,122 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2016, loli10K. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify ZFS successfully receive and restore properties.
+#
+# STRATEGY:
+# 1. Create a filesystem.
+# 2. Create a full stream with properties and receive it.
+# 3. Create also an incremental stream without some properties and a truncated
+# stream.
+# 4. Fail to receive the truncated incremental stream and verify previously
+# received properties are still present.
+# 5. Receive the complete incremental send stream and verify that sent
+# properties are successfully received.
+#
+
+verify_runnable "both"
+
+orig=$TESTPOOL/$TESTFS1
+dest=$TESTPOOL/$TESTFS2
+typeset userprop=$(valid_user_property 8)
+typeset userval=$(user_property_value 8)
+typeset streamfile_full=$TESTDIR/streamfile_full.$$
+typeset streamfile_incr=$TESTDIR/streamfile_incr.$$
+typeset streamfile_trun=$TESTDIR/streamfile_trun.$$
+
+function cleanup
+{
+ log_must rm $streamfile_full
+ log_must rm $streamfile_incr
+ log_must rm $streamfile_trun
+ log_must zfs destroy -rf $orig
+ log_must zfs destroy -rf $dest
+}
+
+#
+# Verify property $2 is set from source $4 on dataset $1 and has value $3.
+#
+# $1 checked dataset
+# $2 user property
+# $3 property value
+# $4 source
+#
+function check_prop_source
+{
+ typeset dataset=$1
+ typeset prop=$2
+ typeset value=$3
+ typeset source=$4
+ typeset chk_value=$(get_prop "$prop" "$dataset")
+ typeset chk_source=$(get_source "$prop" "$dataset")
+ if [[ "$chk_value" != "$value" || \
+ "$chk_source" != "$4" ]]
+ then
+ return 1
+ else
+ return 0
+ fi
+}
+
+log_assert "ZFS successfully receive and restore properties."
+log_onexit cleanup
+
+# 1. Create a filesystem.
+log_must eval "zfs create $orig"
+mntpnt=$(get_prop mountpoint $orig)
+
+# 2. Create a full stream with properties and receive it.
+log_must eval "zfs set compression='gzip-1' $orig"
+log_must eval "zfs set '$userprop'='$userval' $orig"
+log_must eval "zfs snapshot $orig@snap1"
+log_must eval "zfs send -p $orig@snap1 > $streamfile_full"
+log_must eval "zfs recv $dest < $streamfile_full"
+log_must eval "check_prop_source $dest compression 'gzip-1' received"
+log_must eval "check_prop_source $dest '$userprop' '$userval' received"
+
+# 3. Create also an incremental stream without some properties and a truncated
+# stream.
+log_must eval "zfs set compression='gzip-2' $orig"
+log_must eval "zfs inherit '$userprop' $orig"
+log_must eval "dd if=/dev/urandom of=$mntpnt/file bs=1024k count=10"
+log_must eval "zfs snapshot $orig@snap2"
+log_must eval "zfs send -p -i $orig@snap1 $orig@snap2 > $streamfile_incr"
+log_must eval "dd if=$streamfile_incr of=$streamfile_trun bs=1024k count=9"
+log_must eval "zfs snapshot $orig@snap3"
+log_must eval "zfs send -p -i $orig@snap1 $orig@snap3 > $streamfile_incr"
+
+# 4. Fail to receive the truncated incremental stream and verify previously
+# received properties are still present.
+log_mustnot eval "zfs recv -F $dest < $streamfile_trun"
+log_must eval "check_prop_source $dest compression 'gzip-1' received"
+log_must eval "check_prop_source $dest '$userprop' '$userval' received"
+
+# 5. Receive the complete incremental send stream and verify that sent
+# properties are successfully received.
+log_must eval "zfs recv -F $dest < $streamfile_incr"
+log_must eval "check_prop_source $dest compression 'gzip-2' received"
+log_must eval "check_prop_source $dest '$userprop' '-' '-'"
+
+log_pass "ZFS properties are successfully received and restored."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_015_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_015_pos.ksh
new file mode 100755
index 000000000000..ead3c43117b6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_015_pos.ksh
@@ -0,0 +1,83 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2016, loli10K. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify ZFS can receive custom properties on both filesystems and
+# snapshots from full and incremental streams.
+#
+# STRATEGY:
+# 1. Create a filesystem.
+# 2. Snapshot the filesystem.
+# 3. Set custom properties on both the fs and snapshots.
+# 4. Create different send streams with the properties.
+# 5. Receive the send streams and verify the properties.
+#
+
+verify_runnable "both"
+
+typeset streamfile_full=$TEST_BASE_DIR/streamfile_full.$$
+typeset streamfile_incr=$TEST_BASE_DIR/streamfile_incr.$$
+orig=$TESTPOOL/$TESTFS1
+dest=$TESTPOOL/$TESTFS2
+typeset user_prop=$(valid_user_property 8)
+typeset value=$(user_property_value 8)
+
+function cleanup
+{
+ log_must rm $streamfile_full
+ log_must rm $streamfile_incr
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS1
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS2
+}
+
+log_assert "ZFS can receive custom properties."
+log_onexit cleanup
+
+# 1. Create a filesystem.
+log_must zfs create $orig
+
+# 2. Snapshot the filesystem.
+log_must zfs snapshot $orig@snap1
+log_must zfs snapshot $orig@snap2
+log_must zfs snapshot $orig@snap3
+
+# 3. Set custom properties on both the fs and snapshots.
+log_must eval "zfs set '$user_prop'='$value' $orig"
+log_must eval "zfs set '$user_prop:snap1'='$value:snap1' $orig@snap1"
+log_must eval "zfs set '$user_prop:snap2'='$value:snap2' $orig@snap2"
+log_must eval "zfs set '$user_prop:snap3'='$value:snap3' $orig@snap3"
+
+# 4. Create different send streams with the properties.
+log_must eval "zfs send -p $orig@snap1 > $streamfile_full"
+log_must eval "zfs send -p -I $orig@snap1 $orig@snap3 > $streamfile_incr"
+
+# 5. Receive the send streams and verify the properties.
+log_must eval "zfs recv $dest < $streamfile_full"
+log_must eval "check_user_prop $dest $user_prop '$value'"
+log_must eval "check_user_prop $dest@snap1 '$user_prop:snap1' '$value:snap1'"
+log_must eval "zfs recv $dest < $streamfile_incr"
+log_must eval "check_user_prop $dest@snap2 '$user_prop:snap2' '$value:snap2'"
+log_must eval "check_user_prop $dest@snap3 '$user_prop:snap3' '$value:snap3'"
+
+log_pass "ZFS can receive custom properties passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_016_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_016_pos.ksh
new file mode 100755
index 000000000000..04d20ebd39e1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_016_pos.ksh
@@ -0,0 +1,85 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2020 by Mariusz Zaborski <oshogbo@FreeBSD.org>.
+
+#
+# DESCRIPTION:
+# Verify 'zfs recv' can forcibly unmount filesystem while receiving
+# stream.
+#
+# STRATEGY:
+# 1. Create snapshot of file system
+# 2. Make a zfs filesystem mountpoint busy
+# 3. Receive filesystem with force flag.
+# 4. Verify that stream was received or failed on Linux.
+#
+
+. $STF_SUITE/tests/functional/cli_root/cli_common.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ cd $curpath
+
+ for snap in $init_snap $rst_snap; do
+ snapexists $snap && \
+ destroy_snapshot $snap
+ done
+
+ datasetexists $rst_root && \
+ destroy_dataset $rst_root
+
+ for file in $full_bkup
+ do
+ [[ -e $file ]] && \
+ log_must rm -f $file
+ done
+
+ [[ -d $TESTDIR1 ]] && \
+ log_must rm -rf $TESTDIR1
+}
+
+log_assert "Verify 'zfs recv' can forcibly unmount busy filesystem."
+log_onexit cleanup
+
+curpath=`dirname $0`
+init_snap=$TESTPOOL/$TESTFS@init_snap
+full_bkup=$TEST_BASE_DIR/fullbkup.$$
+rst_root=$TESTPOOL/rst_ctr
+rst_snap=$rst_root@init_snap
+
+log_note "Verify 'zfs recv' can forcible unmount busy filesystem."
+
+# Preparation
+log_must zfs create $rst_root
+[[ ! -d $TESTDIR1 ]] && \
+ log_must mkdir -p $TESTDIR1
+log_must zfs set mountpoint=$TESTDIR1 $rst_root
+
+log_must zfs snapshot $init_snap
+log_must eval "zfs send $init_snap > $full_bkup"
+
+# Test
+log_must cd $TESTDIR1
+if is_linux; then
+ # Linux does not support it.
+ log_mustnot zfs receive -MF $rst_snap < $full_bkup
+else
+ log_must zfs receive -MF $rst_snap < $full_bkup
+fi
+
+log_pass "The busy filesystem was unmounted or busy as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_from_encrypted.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_from_encrypted.ksh
new file mode 100755
index 000000000000..a1d094bdb4ba
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_from_encrypted.ksh
@@ -0,0 +1,83 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# ZFS should receive an unencrypted stream from an encrypted dataset
+#
+# STRATEGY:
+# 1. Create an unencrypted dataset
+# 2. Create an encrypted dataset
+# 3. Create and checksum a file on the encrypted dataset
+# 4. Snapshot the encrypted dataset
+# 5. Attempt to receive the snapshot into an unencrypted child
+# 6. Verify encryption is not enabled
+# 7. Verify the checksum of the file is the same as the original
+# 8. Attempt to receive the snapshot into an encrypted child
+# 9. Verify the checksum of the file is the same as the original
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+
+ datasetexists $TESTPOOL/$TESTFS2 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS2
+}
+
+log_onexit cleanup
+
+log_assert "ZFS should receive an unencrypted stream from an encrypted dataset"
+
+typeset passphrase="password"
+typeset snap="$TESTPOOL/$TESTFS2@snap"
+
+log_must zfs create $TESTPOOL/$TESTFS1
+log_must eval "echo $passphrase | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS2"
+
+log_must mkfile 1M /$TESTPOOL/$TESTFS2/$TESTFILE0
+typeset checksum=$(md5digest /$TESTPOOL/$TESTFS2/$TESTFILE0)
+
+log_must zfs snapshot $snap
+
+log_note "Verify ZFS can receive into an unencrypted child"
+log_must eval "zfs send $snap | zfs receive $TESTPOOL/$TESTFS1/c1"
+
+crypt=$(get_prop encryption $TESTPOOL/$TESTFS1/c1)
+[[ "$crypt" == "off" ]] || log_fail "Received unencrypted stream as encrypted"
+
+typeset cksum1=$(md5digest /$TESTPOOL/$TESTFS1/c1/$TESTFILE0)
+[[ "$cksum1" == "$checksum" ]] || \
+ log_fail "Checksums differ ($cksum1 != $checksum)"
+
+log_note "Verify ZFS can receive into an encrypted child"
+log_must eval "zfs send $snap | zfs receive $TESTPOOL/$TESTFS2/c1"
+
+typeset cksum2=$(md5digest /$TESTPOOL/$TESTFS2/c1/$TESTFILE0)
+[[ "$cksum2" == "$checksum" ]] || \
+ log_fail "Checksums differ ($cksum2 != $checksum)"
+
+log_pass "ZFS can receive an unencrypted stream from an encrypted dataset"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_from_zstd.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_from_zstd.ksh
new file mode 100755
index 000000000000..14a175912bb2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_from_zstd.ksh
@@ -0,0 +1,112 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2020 The FreeBSD Foundation [1]
+#
+# [1] Portions of this software were developed by Allan Jude
+# under sponsorship from the FreeBSD Foundation.
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# ZFS should receive a ZSTD compressed block and be able to determine the level
+#
+# STRATEGY:
+# 1. Create a ZSTD compressed dataset (random level)
+# 2. Create and checksum a file on the compressed dataset
+# 3. Snapshot the compressed dataset
+# 4. Attempt to receive the snapshot into a new dataset
+# 5. Verify the checksum of the file is the same as the original
+# 6. Verify the compression level is correctly stored
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+
+ datasetexists $TESTPOOL/$TESTFS2 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS2
+}
+
+log_onexit cleanup
+
+log_assert "ZFS should track compression level when receiving a ZSTD stream"
+
+typeset src_data="$STF_SUITE/tests/functional/cli_root/zfs_receive/zstd_test_data.txt"
+typeset snap="$TESTPOOL/$TESTFS1@snap"
+
+random_level=$((RANDOM%19 + 1))
+log_note "Randomly selected ZSTD level: $random_level"
+
+log_must zfs create -o compress=zstd-$random_level $TESTPOOL/$TESTFS1
+# Make a 5kb compressible file
+log_must cat $src_data $src_data $src_data $src_data $src_data \
+ > /$TESTPOOL/$TESTFS1/$TESTFILE0
+typeset checksum=$(md5digest /$TESTPOOL/$TESTFS1/$TESTFILE0)
+
+log_must zfs snapshot $snap
+
+# get object number of file
+listing=$(ls -i /$TESTPOOL/$TESTFS1/$TESTFILE0)
+set -A array $listing
+obj=${array[0]}
+log_note "file /$TESTPOOL/$TESTFS1/$TESTFILE0 has object number $obj"
+
+output=$(zdb -Zddddddbbbbbb $TESTPOOL/$TESTFS1 $obj 2> /dev/null \
+ |grep -m 1 "L0 DVA" |head -n1)
+dva=$(sed -Ene 's/^.+DVA\[0\]=<([^>]+)>.*$/\1/p' <<< "$output")
+log_note "block 0 of /$TESTPOOL/$TESTFS1/$TESTFILE0 has a DVA of $dva"
+
+zstd_str=$(sed -Ene 's/^.+ ZSTD:size=([^:]+):version=([^:]+):level=([^:]+):.*$/\1:\2:\3/p' <<< "$output")
+zstd_size1=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[1]}')
+zstd_version1=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[2]}')
+zstd_level1=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[3]}')
+log_note "ZSTD src: size=$zstd_size1 version=$zstd_version1 level=$zstd_level1"
+
+log_note "Verify ZFS can receive the ZSTD compressed stream"
+log_must eval "zfs send -ec $snap | zfs receive $TESTPOOL/$TESTFS2"
+
+typeset cksum1=$(md5digest /$TESTPOOL/$TESTFS2/$TESTFILE0)
+[[ "$cksum1" == "$checksum" ]] || \
+ log_fail "Checksums differ ($cksum1 != $checksum)"
+
+# get object number of file
+listing=$(ls -i /$TESTPOOL/$TESTFS2/$TESTFILE0)
+set -A array $listing
+obj=${array[0]}
+log_note "file /$TESTPOOL/$TESTFS2/$TESTFILE0 has object number $obj"
+
+output=$(zdb -Zddddddbbbbbb $TESTPOOL/$TESTFS2 $obj 2> /dev/null \
+ |grep -m 1 "L0 DVA" |head -n1)
+dva=$(sed -Ene 's/^.+DVA\[0\]=<([^>]+)>.*$/\1/p' <<< "$output")
+log_note "block 0 of /$TESTPOOL/$TESTFS2/$TESTFILE0 has a DVA of $dva"
+
+zstd_str=$(sed -Ene 's/^.+ ZSTD:size=([^:]+):version=([^:]+):level=([^:]+):.*$/\1:\2:\3/p' <<< "$output")
+zstd_size2=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[1]}')
+(( $zstd_size2 != $zstd_size1 )) && log_fail \
+"ZFS recv failed: compressed size differs ($zstd_size2 != $zstd_size1)"
+zstd_version2=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[2]}')
+zstd_level2=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[3]}')
+log_note "ZSTD dest: size=$zstd_size2 version=$zstd_version2 level=$zstd_level2"
+(( $zstd_level2 != $zstd_level1 )) && log_fail \
+"ZFS recv failed: compression level did not match header level ($zstd_level2 != $zstd_level1)"
+
+log_pass "ZFS can receive a ZSTD stream and determine the compression level"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_raw.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_raw.ksh
new file mode 100755
index 000000000000..9740caf72508
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_raw.ksh
@@ -0,0 +1,94 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# ZFS should receive streams from raw sends.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Create a file and get its checksum
+# 3. Snapshot the dataset
+# 4. Attempt to receive a raw send stream as a child of an unencrypted dataset
+# 5. Verify the key is unavailable
+# 6. Attempt to load the key and mount the dataset
+# 7. Verify the checksum of the file is the same as the original
+# 8. Attempt to receive a raw send stream as a child of an encrypted dataset
+# 9. Verify the key is unavailable
+# 10. Attempt to load the key and mount the dataset
+# 11. Verify the checksum of the file is the same as the original
+# 12. Verify 'zfs receive -n' works with the raw stream
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+
+ datasetexists $TESTPOOL/$TESTFS2 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS2
+}
+
+log_onexit cleanup
+
+log_assert "ZFS should receive streams from raw sends"
+
+typeset passphrase="password"
+typeset snap="$TESTPOOL/$TESTFS1@snap"
+
+log_must eval "echo $passphrase | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS1"
+
+log_must mkfile 1M /$TESTPOOL/$TESTFS1/$TESTFILE0
+typeset checksum=$(md5digest /$TESTPOOL/$TESTFS1/$TESTFILE0)
+
+log_must zfs snapshot $snap
+
+log_note "Verify ZFS can receive a raw send stream from an encrypted dataset"
+log_must eval "zfs send -w $snap | zfs receive $TESTPOOL/$TESTFS2"
+
+keystatus=$(get_prop keystatus $TESTPOOL/$TESTFS2)
+[[ "$keystatus" == "unavailable" ]] || \
+ log_fail "Expected keystatus unavailable, got $keystatus"
+
+log_must eval "echo $passphrase | zfs mount -l $TESTPOOL/$TESTFS2"
+
+typeset cksum1=$(md5digest /$TESTPOOL/$TESTFS2/$TESTFILE0)
+[[ "$cksum1" == "$checksum" ]] || \
+ log_fail "Checksums differ ($cksum1 != $checksum)"
+
+log_must eval "zfs send -w $snap | zfs receive $TESTPOOL/$TESTFS1/c1"
+
+keystatus=$(get_prop keystatus $TESTPOOL/$TESTFS1/c1)
+[[ "$keystatus" == "unavailable" ]] || \
+ log_fail "Expected keystatus unavailable, got $keystatus"
+
+log_must eval "echo $passphrase | zfs mount -l $TESTPOOL/$TESTFS1/c1"
+typeset cksum2=$(md5digest /$TESTPOOL/$TESTFS1/c1/$TESTFILE0)
+[[ "$cksum2" == "$checksum" ]] || \
+ log_fail "Checksums differ ($cksum2 != $checksum)"
+
+log_must eval "zfs send -w $snap | zfs receive -n $TESTPOOL/$TESTFS3"
+
+log_pass "ZFS can receive streams from raw sends"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_raw_-d.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_raw_-d.ksh
new file mode 100755
index 000000000000..a909f2788ba1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_raw_-d.ksh
@@ -0,0 +1,62 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# zfs receive -d should create the expected encryption hierarchy.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset and a inheriting child
+# 2. Snapshot the child dataset
+# 2. Create a recursive raw send file from the snapshot
+# 3. Destroy the original child filesystem
+# 4. Receive the snapshot as a child of the second dataset with '-d'
+# 5. Verify the new child can be mounted
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+ rm -f $sendfile
+}
+
+log_onexit cleanup
+
+log_assert "zfs receive -d should create the expected encryption hierarchy"
+
+typeset passphrase="password1"
+
+sendfile=$TEST_BASE_DIR/sendfile.$$
+
+log_must eval "echo $passphrase | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS1"
+log_must zfs create $TESTPOOL/$TESTFS1/child
+log_must zfs snapshot $TESTPOOL/$TESTFS1/child@snap
+log_must eval "zfs send -Rw $TESTPOOL/$TESTFS1/child@snap > $sendfile"
+log_must zfs destroy -r $TESTPOOL/$TESTFS1/child
+log_must zfs receive -Fd $TESTPOOL < $sendfile
+log_must eval "echo $passphrase | zfs mount -l $TESTPOOL/$TESTFS1/child"
+
+log_pass "zfs receive -d creates the expected encryption hierarchy"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_raw_incremental.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_raw_incremental.ksh
new file mode 100755
index 000000000000..964c80657da3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_raw_incremental.ksh
@@ -0,0 +1,96 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# ZFS should receive streams from raw incremental sends.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Snapshot the dataset
+# 3. Create a file and get its checksum
+# 4. Snapshot the dataset
+# 5. Attempt to receive a raw send stream of the first snapshot
+# 6. Change the passphrase required to unlock the original filesystem
+# 7. Attempt and intentionally fail to receive the second snapshot
+# 8. Verify that the required passphrase hasn't changed on the receive side
+# 9. Attempt a real raw incremental send stream of the second snapshot
+# 10. Attempt load the key and mount the dataset
+# 11. Verify the checksum of the file is the same as the original
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+
+ datasetexists $TESTPOOL/$TESTFS2 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS2
+
+ [[ -f $ibackup ]] && log_must rm -f $ibackup
+ [[ -f $ibackup_trunc ]] && log_must rm -f $ibackup_trunc
+}
+
+log_onexit cleanup
+
+log_assert "ZFS should receive streams from raw incremental sends"
+
+typeset ibackup="$TEST_BASE_DIR/ibackup.$$"
+typeset ibackup_trunc="$TEST_BASE_DIR/ibackup_trunc.$$"
+typeset passphrase="password"
+typeset passphrase2="password2"
+typeset snap1="$TESTPOOL/$TESTFS1@snap1"
+typeset snap2="$TESTPOOL/$TESTFS1@snap2"
+
+log_must eval "echo $passphrase | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS1"
+
+log_must zfs snapshot $snap1
+
+log_must mkfile 1M /$TESTPOOL/$TESTFS1/$TESTFILE0
+typeset checksum=$(md5digest /$TESTPOOL/$TESTFS1/$TESTFILE0)
+
+log_must zfs snapshot $snap2
+
+log_must eval "zfs send -w $snap1 | zfs receive $TESTPOOL/$TESTFS2"
+log_must eval "echo $passphrase2 | zfs change-key $TESTPOOL/$TESTFS1"
+log_must eval "zfs send -w -i $snap1 $snap2 > $ibackup"
+
+typeset trunc_size=$(stat_size $ibackup)
+trunc_size=$(expr $trunc_size - 64)
+log_must cp $ibackup $ibackup_trunc
+log_must truncate -s $trunc_size $ibackup_trunc
+log_mustnot eval "zfs receive $TESTPOOL/$TESTFS2 < $ibackup_trunc"
+log_mustnot eval "echo $passphrase2 | zfs load-key $TESTPOOL/$TESTFS2"
+log_must eval "echo $passphrase | zfs load-key $TESTPOOL/$TESTFS2"
+log_must zfs unload-key $TESTPOOL/$TESTFS2
+
+log_must eval "zfs receive $TESTPOOL/$TESTFS2 < $ibackup"
+log_must eval "echo $passphrase2 | zfs mount -l $TESTPOOL/$TESTFS2"
+
+typeset cksum1=$(md5digest /$TESTPOOL/$TESTFS2/$TESTFILE0)
+[[ "$cksum1" == "$checksum" ]] || \
+ log_fail "Checksums differ ($cksum1 != $checksum)"
+
+log_pass "ZFS can receive streams from raw incremental sends"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh
new file mode 100755
index 000000000000..f8e53f02c23d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh
@@ -0,0 +1,77 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# ZFS should receive to an encrypted child dataset.
+#
+# STRATEGY:
+# 1. Snapshot the default dataset
+# 2. Create an encrypted dataset
+# 3. Attempt to receive a stream to an encrypted child
+# 4. Attempt to receive a stream with properties to an encrypted child
+# 5. Attempt to receive a replication stream to an encrypted child
+# 6. Unmount and unload the encrypted dataset keys
+# 7. Attempt to receive a snapshot stream to an encrypted child
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ snapexists $snap && log_must_busy zfs destroy -f $snap
+
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+}
+
+log_onexit cleanup
+
+log_assert "ZFS should receive encrypted filesystems into child dataset"
+
+typeset passphrase="password"
+typeset snap="$TESTPOOL/$TESTFS@snap"
+typeset testfile="testfile"
+
+log_must zfs snapshot $snap
+
+log_must eval "echo $passphrase | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS1"
+
+log_note "Verifying ZFS will receive to an encrypted child"
+log_must eval "zfs send $snap | zfs receive $TESTPOOL/$TESTFS1/c1"
+
+log_note "Verifying 'send -p' will receive to an encrypted child"
+log_must eval "zfs send -p $snap | zfs receive $TESTPOOL/$TESTFS1/c2"
+log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS1/c2)" == "off"
+
+log_note "Verifying 'send -R' will receive to an encrypted child"
+log_must eval "zfs send -R $snap | zfs receive $TESTPOOL/$TESTFS1/c3"
+log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS1/c3)" == "off"
+
+log_note "Verifying ZFS will not receive to an encrypted child when the" \
+ "parent key is unloaded"
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+log_mustnot eval "zfs send $snap | zfs receive $TESTPOOL/$TESTFS1/c4"
+
+log_pass "ZFS can receive encrypted filesystems into child dataset"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zstd_test_data.txt b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zstd_test_data.txt
new file mode 100644
index 000000000000..da6a0c7d6e85
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zstd_test_data.txt
@@ -0,0 +1 @@
+Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim..
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/Makefile.am
new file mode 100644
index 000000000000..406e27881523
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/Makefile.am
@@ -0,0 +1,25 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_rename
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_rename_001_pos.ksh \
+ zfs_rename_002_pos.ksh \
+ zfs_rename_003_pos.ksh \
+ zfs_rename_004_neg.ksh \
+ zfs_rename_005_neg.ksh \
+ zfs_rename_006_pos.ksh \
+ zfs_rename_007_pos.ksh \
+ zfs_rename_008_pos.ksh \
+ zfs_rename_009_neg.ksh \
+ zfs_rename_010_neg.ksh \
+ zfs_rename_011_pos.ksh \
+ zfs_rename_012_neg.ksh \
+ zfs_rename_013_pos.ksh \
+ zfs_rename_014_neg.ksh \
+ zfs_rename_encrypted_child.ksh \
+ zfs_rename_to_encrypted.ksh \
+ zfs_rename_mountpoint.ksh
+
+dist_pkgdata_DATA = \
+ zfs_rename.cfg \
+ zfs_rename.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/cleanup.ksh
new file mode 100755
index 000000000000..4638b63d72ea
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/cleanup.ksh
@@ -0,0 +1,43 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup_noexit
+
+if [[ -d $TESTDIR2 ]]; then
+ rm -rf $TESTDIR2
+ if (( $? != 0 )); then
+ log_unresolved Could not remove $TESTDIR2
+ fi
+fi
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/setup.ksh
new file mode 100755
index 000000000000..60acbe07acbe
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/setup.ksh
@@ -0,0 +1,49 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib
+
+DISK=${DISKS%% *}
+
+default_setup_noexit "$DISK" "true" "true"
+
+if [[ -d $TESTDIR2 ]]; then
+ rm -rf $TESTDIR2
+ if (( $? != 0 )); then
+ log_unresolved Could not remove $TESTDIR2
+ fi
+fi
+log_must zfs create $TESTPOOL/$DATAFS
+log_must zfs set mountpoint=$TESTDIR2 $TESTPOOL/$DATAFS
+log_must eval "dd if=$IF of=$OF bs=$BS count=$CNT >/dev/null 2>&1"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.cfg
new file mode 100644
index 000000000000..9a8f38dc2443
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.cfg
@@ -0,0 +1,39 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+export DATAFS=datafs.rename
+export DATA=$TESTDIR2/data.rename
+export IF=/dev/urandom
+export OF=$DATA
+export BS=512
+export CNT=2048
+export VOL_R_PATH=$ZVOL_RDEVDIR/$TESTPOOL/$TESTVOL
+export VOLDATA=$TESTDIR2/voldata.rename
+export RECVFS=recvfs
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib
new file mode 100644
index 000000000000..9b8fb6b0edc1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib
@@ -0,0 +1,129 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_rename/zfs_rename.cfg
+
+function additional_setup
+{
+ # Create testfile
+ log_must cp $DATA $TESTDIR/$TESTFILE0
+ log_must cp $DATA $TESTDIR1/$TESTFILE0
+
+ # Create snapshot
+ if ! snapexists $TESTPOOL/$TESTFS@snapshot; then
+ log_must zfs snapshot $TESTPOOL/$TESTFS@snapshot
+ log_must zfs clone $TESTPOOL/$TESTFS@snapshot \
+ $TESTPOOL/$TESTFS-clone
+ fi
+
+ # Create file system
+ datasetexists $TESTPOOL/$TESTFS1 || \
+ log_must zfs create $TESTPOOL/$TESTFS1
+
+ # Create testfile
+ log_must cp $DATA $(get_prop mountpoint $TESTPOOL/$TESTFS1)/$TESTFILE0
+
+ # Create container
+ datasetexists $TESTPOOL/$TESTCTR1 || \
+ log_must zfs create $TESTPOOL/$TESTCTR1
+ log_must cp $DATA $(get_prop mountpoint $TESTPOOL/$TESTCTR1)/$TESTFILE0
+
+ # Create data in zvol
+ if is_global_zone; then
+ log_must eval "dd if=$DATA of=$VOL_R_PATH bs=$BS count=$CNT \
+ >/dev/null 2>&1"
+ else
+ log_must cp $DATA $(get_prop mountpoint $TESTPOOL/$TESTVOL)/$TESTFILE0
+ fi
+
+ # Create temporary %recv clone
+ create_recv_clone $TESTPOOL/$RECVFS
+}
+
+function rename_dataset # src dest
+{
+ typeset src=$1
+ typeset dest=$2
+
+ log_must zfs rename $src $dest
+ block_device_wait
+
+ #
+ # Verify src name no longer in use
+ #
+ log_mustnot datasetexists $src
+ log_must datasetexists $dest
+}
+
+function cleanup
+{
+ typeset -i i=0
+ while ((i < ${#dataset[*]} )); do
+ if ! datasetexists ${dataset[i]}-new ; then
+ ((i = i + 1))
+ continue
+ fi
+
+ if [[ ${dataset[i]}-new != *@* ]] ; then
+ zfs rename ${dataset[i]}-new ${dataset[i]}
+ if [[ $? -ne 0 ]]; then
+ typeset newfs=${dataset[i]}-new
+ typeset oldfs=${dataset[i]}
+ typeset mntp=$(get_prop mountpoint $newfs)
+ log_must zfs destroy -f $newfs
+ log_must zfs create -p $oldfs
+ log_must zfs set mountpoint=$mntp $oldfs
+ fi
+ else
+ log_must zfs destroy -fR ${dataset[i]}-new
+ fi
+
+ ((i = i + 1))
+ done
+
+ if snapexists $TESTPOOL/$TESTFS@snapshot; then
+ log_must zfs destroy -fR $TESTPOOL/$TESTFS@snapshot
+ fi
+
+ if datasetexists $TESTPOOL/$RECVFS; then
+ log_must zfs destroy -r $TESTPOOL/$RECVFS
+ fi
+}
+
+function cmp_data #<$1 src data, $2 tgt data>
+{
+ typeset src=$1
+ typeset tgt=$2
+
+ cmp $src $tgt >/dev/null 2>&1
+
+ return $?
+}
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_001_pos.ksh
new file mode 100755
index 000000000000..c76b5a2fe5c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_001_pos.ksh
@@ -0,0 +1,109 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs rename' should successfully rename valid datasets.
+# As a sub-assertion we check to ensure the datasets that can
+# be mounted are mounted.
+#
+# STRATEGY:
+# 1. Given a file system, snapshot and volume.
+# 2. Rename each dataset object to a new name.
+# 3. Verify that only the new name is displayed by zfs list.
+# 4. Verify mountable datasets are mounted.
+#
+###############################################################################
+
+verify_runnable "both"
+
+set -A dataset "$TESTPOOL/$TESTFS@snapshot" "$TESTPOOL/$TESTFS1" \
+ "$TESTPOOL/$TESTCTR/$TESTFS1" "$TESTPOOL/$TESTCTR1" \
+ "$TESTPOOL/$TESTVOL" "$TESTPOOL/$TESTFS-clone"
+set -A mountable "$TESTPOOL/$TESTFS1-new" "$TESTPOOL/$TESTFS@snapshot-new" \
+ "$TESTPOOL/$TESTCTR/$TESTFS1-new" "$TESTPOOL/$TESTFS-clone-new"
+
+#
+# cleanup defined in zfs_rename.kshlib
+#
+log_onexit cleanup
+
+log_assert "'zfs rename' should successfully rename valid datasets"
+
+additional_setup
+
+typeset -i i=0
+while (( i < ${#dataset[*]} )); do
+ rename_dataset ${dataset[i]} ${dataset[i]}-new
+
+ ((i = i + 1))
+done
+
+log_note "Verify mountable datasets are mounted in their new namespace."
+typeset mtpt
+i=0
+while (( i < ${#mountable[*]} )); do
+ # Snapshot have no mountpoint
+ if [[ ${mountable[i]} != *@* ]]; then
+ log_must mounted ${mountable[i]}
+ mtpt=$(get_prop mountpoint ${mountable[i]})
+ else
+ mtpt=$(snapshot_mountpoint ${mountable[i]})
+ fi
+
+ if ! cmp_data $DATA $mtpt/$TESTFILE0 ; then
+ log_fail "$mtpt/$TESTFILE0 gets corrupted after rename operation."
+ fi
+
+ ((i = i + 1))
+done
+
+#verify the data integrity in zvol
+if is_global_zone; then
+ log_must eval "dd if=${VOL_R_PATH}-new of=$VOLDATA bs=$BS count=$CNT >/dev/null 2>&1"
+ if ! cmp_data $VOLDATA $DATA ; then
+ log_fail "$VOLDATA gets corrupted after rename operation."
+ fi
+fi
+
+# rename back fs
+typeset -i i=0
+while ((i < ${#dataset[*]} )); do
+ if datasetexists ${dataset[i]}-new ; then
+ log_must zfs rename ${dataset[i]}-new ${dataset[i]}
+ fi
+ ((i = i + 1))
+done
+
+log_pass "'zfs rename' successfully renamed each dataset type."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_002_pos.ksh
new file mode 100755
index 000000000000..6d51f612b311
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_002_pos.ksh
@@ -0,0 +1,92 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs rename' should successfully be capable of renaming
+# valid datasets back and forth multiple times.
+#
+# STRATEGY:
+# 1. Given a file system, snapshot and volume.
+# 2. Rename each dataset object to a new name.
+# 3. Rename each dataset back to its original name.
+# 4. Repeat steps 2 and 3 multiple times.
+# 5. Verify that the correct name is displayed by zfs list.
+#
+###############################################################################
+
+verify_runnable "both"
+
+set -A dataset "$TESTPOOL/$TESTFS@snapshot" "$TESTPOOL/$TESTFS1" \
+ "$TESTPOOL/$TESTCTR/$TESTFS1" "$TESTPOOL/$TESTCTR1" \
+ "$TESTPOOL/$TESTVOL" "$TESTPOOL/$TESTFS-clone"
+
+#
+# cleanup defined in zfs_rename.kshlib
+#
+log_onexit cleanup
+
+log_assert "'zfs rename' should successfully rename valid datasets"
+
+additional_setup
+
+typeset -i i=0
+typeset -i iters=10
+
+while ((i < ${#dataset[*]} )); do
+ j=0
+ while ((j < iters )); do
+ rename_dataset ${dataset[i]} ${dataset[i]}-new
+ rename_dataset ${dataset[i]}-new ${dataset[i]}
+
+ ((j = j + 1))
+ done
+
+ if [[ ${dataset[i]} == *@* ]]; then
+ data=$(snapshot_mountpoint ${dataset[i]})/$TESTFILE0
+ elif [[ ${dataset[i]} == "$TESTPOOL/$TESTVOL" ]] && is_global_zone; then
+ log_must eval "dd if=$VOL_R_PATH of=$VOLDATA bs=$BS count=$CNT >/dev/null 2>&1"
+ data=$VOLDATA
+ else
+ data=$(get_prop mountpoint ${dataset[i]})/$TESTFILE0
+ fi
+
+ if ! cmp_data $DATA $data; then
+ log_fail "$data gets corrupted after $iters times rename operations."
+ fi
+
+ ((i = i + 1))
+done
+
+log_pass "'zfs rename' renamed each dataset type multiple times as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_003_pos.ksh
new file mode 100755
index 000000000000..56c06cfe857d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_003_pos.ksh
@@ -0,0 +1,68 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs rename' can address the abbreviated snapshot name.
+#
+# STRATEGY:
+# 1. Create pool, fs and snap.
+# 2. Verify 'zfs rename' support the abbreviated snapshot name.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $snap && log_must zfs destroy $snap
+}
+
+log_assert "'zfs rename' can address the abbreviated snapshot name."
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS; snap=$fs@snap
+set -A newname "$fs@new-snap" "@new-snap" "new-snap"
+
+log_must zfs snapshot $snap
+log_must datasetexists $snap
+
+typeset -i i=0
+while ((i < ${#newname[*]} )); do
+ log_must zfs rename $snap ${newname[$i]}
+ log_must datasetexists ${snap%%@*}@${newname[$i]##*@}
+ log_must zfs rename ${snap%%@*}@${newname[$i]##*@} $snap
+
+ ((i += 1))
+done
+
+log_pass "'zfs rename' address the abbreviated snapshot name passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_004_neg.ksh
new file mode 100755
index 000000000000..b1438e8663e3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_004_neg.ksh
@@ -0,0 +1,112 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs rename' should fail when this dataset was changed to an existed
+# dataset name or datasets are of different types.
+# For example, a filesystem cannot be renamed as a volume.
+#
+# STRATEGY:
+# 1. Given a file system, snapshot and volume.
+# 2. Rename each dataset object to a different type.
+# 3. Verify that only the original name is displayed by zfs list.
+#
+
+verify_runnable "both"
+
+#
+# This array is a list of pairs:
+# item i: original type
+# item i + 1: new type
+#
+set -A bad_dataset $TESTPOOL/$TESTFS1 $TESTPOOL/$TESTCTR1 \
+ $TESTPOOL/$TESTFS1 $TESTPOOL/$TESTCTR/$TESTFS1 \
+ $TESTPOOL/$TESTFS1 $TESTPOOL/$TESTVOL \
+ $TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS1/$TESTFS1 \
+ $TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS@snapshot \
+ $TESTPOOL/$TESTCTR1 $TESTPOOL/$TESTVOL \
+ $TESTPOOL/$TESTCTR1 $TESTPOOL/$TESTFS@snapshot \
+ $TESTPOOL/$TESTCTR1 $TESTPOOL/$TESTFS1 \
+ $TESTPOOL/$TESTCTR1 $TESTPOOL/$TESTCTR/$TESTFS1 \
+ $TESTPOOL/$TESTCTR/$TESTFS1 $TESTPOOL/$TESTVOL \
+ $TESTPOOL/$TESTCTR/$TESTFS1 $TESTPOOL/$TESTFS@snapshot \
+ $TESTPOOL/$TESTCTR/$TESTFS1 $TESTPOOL/$TESTFS1 \
+ $TESTPOOL/$TESTCTR/$TESTFS1 $TESTPOOL/$TESTCTR1 \
+ $TESTPOOL/$TESTVOL $TESTPOOL/$TESTCTR1 \
+ $TESTPOOL/$TESTVOL $TESTPOOL/$TESTFS@snapshot \
+ $TESTPOOL/$TESTVOL $TESTPOOL/$TESTFS1 \
+ $TESTPOOL/$TESTVOL $TESTPOOL/$TESTCTR/$TESTFS1 \
+ $TESTPOOL/$TESTFS@snapshot $TESTPOOL/$TESTCTR1 \
+ $TESTPOOL/$TESTFS@snapshot $TESTPOOL/$TESTVOL \
+ $TESTPOOL/$TESTFS@snapshot $TESTPOOL/$TESTFS1 \
+ $TESTPOOL/$TESTFS@snapshot $TESTPOOL/$TESTCTR/$TESTFS1 \
+ $TESTPOOL/$TESTFS1 $TESTPOOL/${TESTFS1}%c \
+ $TESTPOOL/$TESTFS1 $TESTPOOL/${TESTFS1}%d \
+ $TESTPOOL/$TESTFS1 $TESTPOOL/${TESTFS1}%x \
+ $TESTPOOL/$TESTFS1 $TESTPOOL/${TESTFS1}%p \
+ $TESTPOOL/$TESTFS1 $TESTPOOL/${TESTFS1}%s \
+ $TESTPOOL/$TESTFS@snapshot $TESTPOOL/$TESTFS@snapshot/fs \
+ $TESTPOOL/$RECVFS/%recv $TESTPOOL/renamed.$$
+
+#
+# cleanup defined in zfs_rename.kshlib
+#
+log_onexit cleanup
+
+log_assert "'zfs rename' should fail when datasets are of a different type."
+
+additional_setup
+
+typeset -i i=0
+while ((i < ${#bad_dataset[*]} )); do
+ log_mustnot zfs rename ${bad_dataset[i]} ${bad_dataset[((i + 1))]}
+ log_must datasetexists ${bad_dataset[i]}
+
+ log_mustnot zfs rename -p ${bad_dataset[i]} ${bad_dataset[((i + 1))]}
+ log_must datasetexists ${bad_dataset[i]}
+
+ ((i = i + 2))
+done
+
+#verify 'rename -p' can not work with snapshots
+
+log_mustnot zfs rename -p $TESTPOOL/$TESTFS@snapshot \
+ $TESTPOOL/$TESTFS@snapshot2
+log_must datasetexists $TESTPOOL/$TESTFS@snapshot
+log_mustnot zfs rename -p $TESTPOOL/$TESTFS@snapshot \
+ $TESTPOOL/$TESTFS/$TESTFS@snapshot2
+log_must datasetexists $TESTPOOL/$TESTFS@snapshot
+
+log_pass "'zfs rename' fails as expected when given different dataset types."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_005_neg.ksh
new file mode 100755
index 000000000000..5ef77de0c751
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_005_neg.ksh
@@ -0,0 +1,91 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs rename' should fail when the dataset are not within the same pool
+#
+# STRATEGY:
+# 1. Given a file system, snapshot and volume.
+# 2. Rename each dataset object to a different pool.
+# 3. Verify the operation fails, and only the original name
+# is displayed by zfs list.
+#
+
+verify_runnable "global"
+
+function my_cleanup
+{
+ poolexists $TESTPOOL1 && \
+ destroy_pool $TESTPOOL1
+ [[ -e $TESTDIR/$TESTFILE1 ]] && \
+ log_must rm -f $TESTDIR/$TESTFILE1
+ cleanup
+}
+
+set -A src_dataset \
+ "$TESTPOOL/$TESTFS1" "$TESTPOOL/$TESTCTR1" \
+ "$TESTPOOL/$TESTCTR/$TESTFS1" "$TESTPOOL/$TESTVOL" \
+ "$TESTPOOL/$TESTFS@snapshot" "$TESTPOOL/$TESTFS-clone"
+
+#
+# cleanup defined in zfs_rename.kshlib
+#
+log_onexit my_cleanup
+
+log_assert "'zfs rename' should fail while datasets are within different pool."
+
+additional_setup
+
+log_must mkfile $MINVDEVSIZE $TESTDIR/$TESTFILE1
+create_pool $TESTPOOL1 $TESTDIR/$TESTFILE1
+
+for src in ${src_dataset[@]} ; do
+ dest=${src#$TESTPOOL/}
+ if [[ $dest == *"@"* ]]; then
+ dest=${dest#*@}
+ dest=${TESTPOOL1}@$dest
+ else
+ dest=${TESTPOOL1}/$dest
+ fi
+ log_mustnot zfs rename $src $dest
+ log_mustnot zfs rename -p $src $dest
+
+ #
+ # Verify original dataset name still in use
+ #
+ log_must datasetexists $src
+done
+
+log_pass "'zfs rename' fail while datasets are within different pool."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_006_pos.ksh
new file mode 100755
index 000000000000..3ad7d4e80562
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_006_pos.ksh
@@ -0,0 +1,85 @@
+#!/bin/ksh
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2015, 2016 by Delphix. All rights reserved.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs rename' can successfully rename a volume snapshot.
+#
+# STRATEGY:
+# 1. Create a snapshot of volume.
+# 2. Rename volume snapshot to a new one.
+# 3. Rename volume to a new one.
+# 4. Create a clone of the snapshot.
+# 5. Verify that the rename operations are successful and zfs list can
+# list them.
+#
+###############################################################################
+
+verify_runnable "global"
+
+#
+# cleanup defined in zfs_rename.kshlib
+#
+log_onexit cleanup
+
+log_assert "'zfs rename' can successfully rename a volume snapshot."
+
+vol=$TESTPOOL/$TESTVOL
+snap=$TESTSNAP
+
+log_must eval "dd if=$DATA of=$VOL_R_PATH bs=$BS count=$CNT >/dev/null 2>&1"
+if ! snapexists $vol@$snap; then
+ log_must zfs snapshot $vol@$snap
+fi
+
+rename_dataset $vol@$snap $vol@${snap}-new
+rename_dataset $vol ${vol}-new
+rename_dataset ${vol}-new@${snap}-new ${vol}-new@$snap
+rename_dataset ${vol}-new $vol
+
+clone=$TESTPOOL/${snap}_clone
+create_clone $vol@$snap $clone
+block_device_wait
+
+#verify data integrity
+for input in $VOL_R_PATH $ZVOL_RDEVDIR/$clone; do
+ log_must eval "dd if=$input of=$VOLDATA bs=$BS count=$CNT >/dev/null 2>&1"
+ if ! cmp_data $VOLDATA $DATA ; then
+ log_fail "$input gets corrupted after rename operation."
+ fi
+done
+
+destroy_clone $clone
+log_must zfs destroy $vol@$snap
+
+log_pass "'zfs rename' can rename volume snapshot as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_007_pos.ksh
new file mode 100755
index 000000000000..3623d2bca1c9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_007_pos.ksh
@@ -0,0 +1,155 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib
+
+#
+# DESCRIPTION:
+# Rename dataset, verify that the data haven't changed.
+#
+# STRATEGY:
+# 1. Create random data and copy to dataset.
+# 2. Perform renaming commands.
+# 3. Verify that the data haven't changed.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $TESTPOOL/$TESTFS ; then
+ log_must zfs destroy -Rf $TESTPOOL/$TESTFS
+ fi
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+
+ rm -f $SRC_FILE $DST_FILE
+}
+
+function target_obj
+{
+ typeset dtst=$1
+
+ typeset obj
+ typeset type=$(get_prop type $dtst)
+ if [[ $type == "filesystem" ]]; then
+ obj=$(get_prop mountpoint $dtst)/${SRC_FILE##*/}
+ elif [[ $type == "volume" ]]; then
+ obj=$ZVOL_DEVDIR/$dtst
+ fi
+
+ echo $obj
+}
+
+log_assert "Rename dataset, verify that the data haven't changed."
+log_onexit cleanup
+
+# Generate random data
+#
+BS=512 ; CNT=2048
+SRC_FILE=$TESTDIR/srcfile.$$
+DST_FILE=$TESTDIR/dstfile.$$
+log_must dd if=/dev/urandom of=$SRC_FILE bs=$BS count=$CNT
+
+fs=$TESTPOOL/$TESTFS/fs.$$
+fsclone=$TESTPOOL/$TESTFS/fsclone.$$
+log_must zfs create $fs
+
+obj=$(target_obj $fs)
+log_must cp $SRC_FILE $obj
+
+snap=${fs}@snap.$$
+log_must zfs snapshot $snap
+log_must zfs clone $snap $fsclone
+
+# Rename dataset & clone
+#
+log_must zfs rename $fs ${fs}-new
+log_must zfs rename $fsclone ${fsclone}-new
+
+# Compare source file and target file
+#
+obj=$(target_obj ${fs}-new)
+log_must diff $SRC_FILE $obj
+obj=$(target_obj ${fsclone}-new)
+log_must diff $SRC_FILE $obj
+
+# Rename snapshot and re-clone dataset
+#
+log_must zfs rename ${fs}-new $fs
+log_must zfs rename $snap ${snap}-new
+log_must zfs clone ${snap}-new $fsclone
+
+# Compare source file and target file
+#
+obj=$(target_obj $fsclone)
+log_must diff $SRC_FILE $obj
+
+if is_global_zone; then
+ vol=$TESTPOOL/$TESTFS/vol.$$ ; volclone=$TESTPOOL/$TESTFS/volclone.$$
+ log_must zfs create -V 100M $vol
+ block_device_wait
+
+ obj=$(target_obj $vol)
+ log_must dd if=$SRC_FILE of=$obj bs=$BS count=$CNT
+
+ snap=${vol}@snap.$$
+ log_must zfs snapshot $snap
+ log_must zfs clone $snap $volclone
+ block_device_wait
+
+ # Rename dataset & clone
+ log_must zfs rename $vol ${vol}-new
+ log_must zfs rename $volclone ${volclone}-new
+ block_device_wait
+
+ # Compare source file and target file
+ obj=$(target_obj ${vol}-new)
+ log_must dd if=$obj of=$DST_FILE bs=$BS count=$CNT
+ log_must diff $SRC_FILE $DST_FILE
+ obj=$(target_obj ${volclone}-new)
+ log_must dd if=$obj of=$DST_FILE bs=$BS count=$CNT
+ log_must diff $SRC_FILE $DST_FILE
+
+ # Rename snapshot and re-clone dataset
+ log_must zfs rename ${vol}-new $vol
+ log_must zfs rename $snap ${snap}-new
+ log_must zfs clone ${snap}-new $volclone
+ block_device_wait
+
+ # Compare source file and target file
+ obj=$(target_obj $volclone)
+ log_must dd if=$obj of=$DST_FILE bs=$BS count=$CNT
+ log_must diff $SRC_FILE $DST_FILE
+fi
+
+log_pass "Rename dataset, the data haven't changed passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_008_pos.ksh
new file mode 100755
index 000000000000..3fc099d79f8a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_008_pos.ksh
@@ -0,0 +1,88 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# zfs rename -r can rename snapshot recursively.
+#
+# STRATEGY:
+# 1. Create snapshot recursively.
+# 2. Rename snapshot recursively.
+# 3. Verify rename -r snapshot correctly.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset -i i=0
+ while ((i < ${#datasets[@]})); do
+ if datasetexists ${datasets[$i]}@snap ; then
+ log_must zfs destroy ${datasets[$i]}@snap
+ fi
+ if datasetexists ${datasets[$i]}@snap-new ; then
+ log_must zfs destroy ${datasets[$i]}@snap-new
+ fi
+
+ ((i += 1))
+ done
+}
+
+log_assert "zfs rename -r can rename snapshot recursively."
+log_onexit cleanup
+
+set -A datasets $TESTPOOL $TESTPOOL/$TESTCTR \
+ $TESTPOOL/$TESTCTR/$TESTFS1 $TESTPOOL/$TESTFS
+if is_global_zone; then
+ datasets[${#datasets[@]}]=$TESTPOOL/$TESTVOL
+fi
+
+log_must zfs snapshot -r ${TESTPOOL}@snap
+typeset -i i=0
+while ((i < ${#datasets[@]})); do
+ log_must datasetexists ${datasets[$i]}@snap
+
+ ((i += 1))
+done
+
+log_must zfs rename -r ${TESTPOOL}@snap ${TESTPOOL}@snap-new
+i=0
+while ((i < ${#datasets[@]})); do
+ log_must datasetexists ${datasets[$i]}@snap-new
+
+ ((i += 1))
+done
+
+log_must zfs destroy -rf ${TESTPOOL}@snap-new
+
+log_pass "Verify zfs rename -r passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_009_neg.ksh
new file mode 100755
index 000000000000..7e8119766bf7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_009_neg.ksh
@@ -0,0 +1,86 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# When renaming a set of snapshots, if a snapshot already exists with
+# the new name, then none of the snapshots is renamed.
+#
+# STRATEGY:
+# 1. Create a snapshot for a set of datasets.
+# 2. Create a new snapshot for one of datasets.
+# 3. Attempt to "zfs rename -r" with the second snapshot's name.
+# 4. Verify none of the snapshots is renamed.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for poolname in $(get_all_pools); do
+ for snap in $(zfs list -H -t snapshot -o name -r $poolname); do
+ log_must zfs destroy $snap
+ done
+ done
+}
+
+log_assert "Verify zfs rename -r failed when the snapshot name already exists."
+log_onexit cleanup
+
+set -A datasets $TESTPOOL $TESTPOOL/$TESTCTR \
+ $TESTPOOL/$TESTCTR/$TESTFS1 $TESTPOOL/$TESTFS
+if is_global_zone; then
+ datasets[${#datasets[@]}]=$TESTPOOL/$TESTVOL
+fi
+
+log_must zfs snapshot -r ${TESTPOOL}@snap
+typeset -i i=0
+while ((i < ${#datasets[@]})); do
+ # Create one more snapshot
+ log_must zfs snapshot ${datasets[$i]}@snap2
+ log_mustnot zfs rename -r ${TESTPOOL}@snap ${TESTPOOL}@snap2
+ log_must zfs destroy ${datasets[$i]}@snap2
+
+ # Check datasets, make sure none of them have snap2.
+ typeset -i j=0
+ while ((j < ${#datasets[@]})); do
+ if datasetexists ${datasets[$j]}@snap2 ; then
+ log_fail "${datasets[$j]}@snap2 should not exist."
+ fi
+ ((j += 1))
+ done
+
+ ((i += 1))
+done
+
+log_pass "zfs rename -r failed when the snapshot name already exists."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_010_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_010_neg.ksh
new file mode 100755
index 000000000000..171770fa32a1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_010_neg.ksh
@@ -0,0 +1,73 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# The recursive flag -r can only be used for snapshots and not for
+# volumes/filesystems.
+#
+# STRATEGY:
+# 1. Loop pool, fs, container and volume.
+# 2. Verify none of them can be rename by rename -r.
+#
+
+verify_runnable "both"
+
+log_assert "The recursive flag -r can only be used for snapshots."
+
+set -A datasets $TESTPOOL $TESTPOOL/$TESTCTR \
+ $TESTPOOL/$TESTCTR/$TESTFS1 $TESTPOOL/$TESTFS
+if is_global_zone; then
+ datasets[${#datasets[@]}]=$TESTPOOL/$TESTVOL
+fi
+
+for opts in "-r" "-r -p"; do
+ typeset -i i=0
+ while ((i < ${#datasets[@]})); do
+ log_mustnot zfs rename $opts ${datasets[$i]} \
+ ${datasets[$i]}-new
+
+ # Check datasets, make sure none of them was renamed.
+ typeset -i j=0
+ while ((j < ${#datasets[@]})); do
+ if datasetexists ${datasets[$j]}-new ; then
+ log_fail "${datasets[$j]}-new should not exists."
+ fi
+ ((j += 1))
+ done
+
+ ((i += 1))
+ done
+done
+
+log_pass "The recursive flag -r can only be used for snapshots passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_011_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_011_pos.ksh
new file mode 100755
index 000000000000..2d1220e334c9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_011_pos.ksh
@@ -0,0 +1,78 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib
+
+#
+# DESCRIPTION
+# 'zfs rename -p' should work as expected
+#
+# STRATEGY:
+# 1. Make sure the upper level of $newdataset does not exist
+# 2. Make sure without -p option, 'zfs rename' will fail
+# 3. With -p option, rename works
+#
+
+verify_runnable "both"
+
+function additional_cleanup
+{
+ if datasetexists $TESTPOOL/notexist ; then
+ log_must zfs destroy -Rf $TESTPOOL/notexist
+ fi
+
+ if datasetexists $TESTPOOL/$TESTFS ; then
+ log_must zfs destroy -Rf $TESTPOOL/$TESTFS
+ fi
+ log_must zfs create $TESTPOOL/$TESTFS
+
+ if is_global_zone ; then
+ if datasetexists $TESTPOOL/$TESTVOL ; then
+ log_must zfs destroy -Rf $TESTPOOL/$TESTVOL
+ fi
+ log_must zfs create -V $VOLSIZE $TESTPOOL/$TESTVOL
+ fi
+}
+
+log_onexit additional_cleanup
+
+log_assert "'zfs rename -p' should work as expected"
+
+log_must verify_opt_p_ops "rename" "fs" "$TESTPOOL/$TESTFS" \
+ "$TESTPOOL/notexist/new/$TESTFS1"
+
+if is_global_zone; then
+ log_must verify_opt_p_ops "rename" "vol" "$TESTPOOL/$TESTVOL" \
+ "$TESTPOOL/notexist/new/$TESTVOL1"
+fi
+
+log_pass "'zfs rename -p' should work as expected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_012_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_012_neg.ksh
new file mode 100755
index 000000000000..6daf001797e6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_012_neg.ksh
@@ -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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs rename' should be failed with bad option, null target dataset,
+# too many datasets and long target dataset name.
+#
+# STRATEGY:
+# 1. Create a set of ZFS datasets;
+# 2. Try 'zfs rename' with various illegal scenarios;
+# 3. Verify 'zfs rename' command should be failed.
+#
+
+verify_runnable "both"
+
+log_assert "'zfs rename' should fail with bad option, null target dataset and" \
+ "too long target dataset name."
+
+badopts=( "r" "R" "-R" "-rR" "-Rr" "-P" "-pP" "-Pp" "-r*" "-p*" "-?" "-*" "-"
+ "-o")
+datasets=("$TESTPOOL" "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTFS@$TESTSNAP"
+ "$TESTPOOL/$TESTCTR" "$TESTPOOL/$TESTCTR/$TESTFS1" "$TESTPOOL/$TESTVOL")
+
+longname="$(gen_dataset_name 260 abcdefg)"
+
+log_must zfs snapshot $TESTPOOL/$TESTFS@$TESTSNAP
+for ds in ${datasets[@]}; do
+ for opt in ${badopts[@]}; do
+ log_mustnot zfs rename $opt $ds ${ds}-new
+ done
+ log_mustnot zfs rename $ds
+ log_mustnot zfs rename $ds ${ds}-new ${ds}-new1
+ log_mustnot zfs rename $ds ${ds}.$longname
+done
+
+log_pass "'zfs rename' fails with illegal scenarios as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_013_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_013_pos.ksh
new file mode 100755
index 000000000000..b2e01006fdd1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_013_pos.ksh
@@ -0,0 +1,85 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# zfs rename -r can rename snapshot when child datasets
+# don't have a snapshot of the given name.
+#
+# STRATEGY:
+# 1. Create snapshot.
+# 2. Rename snapshot recursively.
+# 3. Verify rename -r snapshot correctly.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $TESTPOOL/$TESTCTR@snap-new ; then
+ log_must zfs destroy -f $TESTPOOL/$TESTCTR@snap-new
+ fi
+
+ if datasetexists $TESTPOOL/$TESTCTR@snap ; then
+ log_must zfs destroy -f $TESTPOOL/$TESTCTR@snap
+ fi
+
+ if datasetexists $TESTPOOL@snap-new ; then
+ log_must zfs destroy -f $TESTPOOL@snap-new
+ fi
+
+ if datasetexists $TESTPOOL@snap ; then
+ log_must zfs destroy -f $TESTPOOL@snap
+ fi
+}
+
+log_assert "zfs rename -r can rename snapshot when child datasets" \
+ "don't have a snapshot of the given name."
+
+log_onexit cleanup
+
+log_must zfs snapshot $TESTPOOL/$TESTCTR@snap
+log_must zfs rename -r $TESTPOOL/$TESTCTR@snap $TESTPOOL/$TESTCTR@snap-new
+log_must datasetexists $TESTPOOL/$TESTCTR@snap-new
+
+log_must zfs snapshot $TESTPOOL@snap
+log_must zfs rename -r $TESTPOOL@snap $TESTPOOL@snap-new
+log_must datasetexists $TESTPOOL/$TESTCTR@snap-new
+log_must datasetexists $TESTPOOL@snap-new
+
+log_must zfs destroy -f $TESTPOOL/$TESTCTR@snap-new
+log_must zfs destroy -f $TESTPOOL@snap-new
+
+log_pass "Verify zfs rename -r passed when child datasets" \
+ "don't have a snapshot of the given name."
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_014_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_014_neg.ksh
new file mode 100755
index 000000000000..1c962608d784
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_014_neg.ksh
@@ -0,0 +1,110 @@
+#!/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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# zfs rename should work on existing datasets that exceed
+# zfs_max_dataset_nesting (our nesting limit) except in the
+# scenario that we try to rename it to something deeper
+# than it already is.
+#
+# STRATEGY:
+# 1. Create a set of ZFS datasets within our nesting limit.
+# 2. Try renaming one of them on top of the other so its
+# children pass the limit - it should fail.
+# 3. Increase the nesting limit.
+# 4. Check that renaming a dataset on top of the other
+# cannot exceed the new nesting limit but can exceed
+# the old one.
+# 5. Bring back the old nesting limit so you can simulate
+# the scenario of existing datasets that exceed our
+# nesting limit.
+# 6. Make sure that 'zfs rename' can work only if we are
+# trying to keep existing datasets that exceed the limit
+# at the same nesting level or less. Making it even
+# deeper should not work.
+#
+
+verify_runnable "both"
+
+dsA01="a"
+dsA02="a/a"
+dsA49=$(printf 'a/%.0s' {1..48})"a"
+
+dsB01="b"
+dsB49=$(printf 'b/%.0s' {1..48})"b"
+
+dsC01="c"
+dsC16=$(printf 'c/%.0s' {1..15})"c"
+
+dsB16A=$(printf 'b/%.0s' {1..16})"a"
+dsB15A=$(printf 'b/%.0s' {1..15})"a"
+
+dsB15A47A=$(printf 'b/%.0s' {1..15})$(printf 'a/%.0s' {1..47})"a"
+dsB15A47C=$(printf 'b/%.0s' {1..15})$(printf 'a/%.0s' {1..47})"c"
+
+dsB15A40B=$(printf 'b/%.0s' {1..15})$(printf 'a/%.0s' {1..40})"b"
+dsB15A47B=$(printf 'b/%.0s' {1..15})$(printf 'a/%.0s' {1..47})"b"
+
+function nesting_cleanup
+{
+ log_must zfs destroy -fR $TESTPOOL/$dsA01
+ log_must zfs destroy -fR $TESTPOOL/$dsB01
+ log_must zfs destroy -fR $TESTPOOL/$dsC01
+
+ # If the test fails after increasing the limit and
+ # before resetting it, it will be left at the modified
+ # value for the remaining tests. That's the reason
+ # we reset it again here just in case.
+ log_must set_tunable_impl MAX_DATASET_NESTING 50 Z zcommon
+}
+
+log_onexit nesting_cleanup
+
+log_must zfs create -p $TESTPOOL/$dsA49
+log_must zfs create -p $TESTPOOL/$dsB49
+log_must zfs create -p $TESTPOOL/$dsC16
+
+log_mustnot zfs rename $TESTPOOL/$dsA02 $TESTPOOL/$dsB15A
+
+# extend limit
+log_must set_tunable_impl MAX_DATASET_NESTING 64 Z zcommon
+
+log_mustnot zfs rename $TESTPOOL/$dsA02 $TESTPOOL/$dsB16A
+log_must zfs rename $TESTPOOL/$dsA02 $TESTPOOL/$dsB15A
+
+# bring back old limit
+log_must set_tunable_impl MAX_DATASET_NESTING 50 Z zcommon
+
+log_mustnot zfs rename $TESTPOOL/$dsC01 $TESTPOOL/$dsB15A47C
+log_must zfs rename $TESTPOOL/$dsB15A47A $TESTPOOL/$dsB15A47B
+log_must zfs rename $TESTPOOL/$dsB15A47B $TESTPOOL/$dsB15A40B
+
+log_pass "Verify 'zfs rename' limits datasets so they don't pass " \
+ "the nesting limit. For existing ones that do, it should " \
+ "not allow them to grow anymore."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_encrypted_child.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_encrypted_child.ksh
new file mode 100755
index 000000000000..fa57658f185b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_encrypted_child.ksh
@@ -0,0 +1,78 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs rename' should not move an encrypted child dataset outside of its
+# encryption root.
+#
+# STRATEGY:
+# 1. Create two encryption roots, and a child and grandchild of the first
+# encryption root
+# 2. Attempt to rename the grandchild under an unencrypted parent
+# 3. Attempt to rename the grandchild under a different encrypted parent
+# 4. Attempt to rename the grandchild under the current parent
+# 5. Verify the encryption root of the dataset
+# 6. Attempt to rename the grandchild to a child
+# 7. Verify the encryption root of the dataset
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS2 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS2
+ datasetexists $TESTPOOL/$TESTFS3 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS3
+}
+log_onexit cleanup
+
+log_assert "'zfs rename' should not move an encrypted child outside of its" \
+ "encryption root"
+
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS2"
+log_must zfs create $TESTPOOL/$TESTFS2/child
+log_must zfs create $TESTPOOL/$TESTFS2/child/grandchild
+log_must eval "echo $PASSPHRASE1 | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS3"
+
+log_mustnot zfs rename $TESTPOOL/$TESTFS2/child/grandchild \
+ $TESTPOOL/grandchild
+
+log_mustnot zfs rename $TESTPOOL/$TESTFS2/child/grandchild \
+ $TESTPOOL/$TESTFS3/grandchild
+
+log_must zfs rename $TESTPOOL/$TESTFS2/child/grandchild \
+ $TESTPOOL/$TESTFS2/child/grandchild2
+log_must verify_encryption_root $TESTPOOL/$TESTFS2/child/grandchild2 \
+ $TESTPOOL/$TESTFS2
+
+log_must zfs rename $TESTPOOL/$TESTFS2/child/grandchild2 \
+ $TESTPOOL/$TESTFS2/grandchild2
+log_must verify_encryption_root $TESTPOOL/$TESTFS2/grandchild2 \
+ $TESTPOOL/$TESTFS2
+
+log_pass "'zfs rename' does not move an encrypted child outside of its" \
+ "encryption root"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_mountpoint.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_mountpoint.ksh
new file mode 100755
index 000000000000..4d2b94dc887f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_mountpoint.ksh
@@ -0,0 +1,88 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy is of the CDDL is also available via the Internet
+# at http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2018 Datto Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# zfs rename should rename datasets even for mountpoint=none children
+#
+# STRATEGY:
+# 1. Create a set of nested datasets with mountpoint=none
+# 2. Verify datasets aren't mounted except for the parent
+# 3. Rename mountpoint and verify all child datasets are renamed
+#
+
+verify_runnable "both"
+
+function rename_cleanup
+{
+ log_note zfs destroy -fR $TESTPOOL/rename_test
+ log_note zfs destroy -fR $TESTPOOL/renamed
+}
+
+log_onexit rename_cleanup
+
+
+log_must zfs create $TESTPOOL/rename_test
+log_must zfs create $TESTPOOL/rename_test/ds
+log_must zfs create -o mountpoint=none $TESTPOOL/rename_test/child
+log_must zfs create $TESTPOOL/rename_test/child/grandchild
+
+if ! ismounted $TESTPOOL/rename_test; then
+ log_fail "$TESTPOOL/rename_test is not mounted"
+fi
+if ! ismounted $TESTPOOL/rename_test/ds; then
+ log_fail "$TESTPOOL/rename_test/ds is not mounted"
+fi
+if ismounted $TESTPOOL/rename_test/child; then
+ log_fail "$TESTPOOL/rename_test/child is mounted"
+fi
+if ismounted $TESTPOOL/rename_test/child/grandchild; then
+ log_fail "$TESTPOOL/rename_test/child/grandchild is mounted"
+fi
+
+log_must zfs rename $TESTPOOL/rename_test $TESTPOOL/renamed
+
+log_mustnot zfs list $TESTPOOL/rename_test
+log_mustnot zfs list $TESTPOOL/rename_test/ds
+log_mustnot zfs list $TESTPOOL/rename_test/child
+log_mustnot zfs list $TESTPOOL/rename_test/child/grandchild
+
+log_must zfs list $TESTPOOL/renamed
+log_must zfs list $TESTPOOL/renamed/ds
+log_must zfs list $TESTPOOL/renamed/child
+log_must zfs list $TESTPOOL/renamed/child/grandchild
+
+if ! ismounted $TESTPOOL/renamed; then
+ log_must zfs get all $TESTPOOL/renamed
+ log_fail "$TESTPOOL/renamed is not mounted"
+fi
+if ! ismounted $TESTPOOL/renamed/ds; then
+ log_fail "$TESTPOOL/renamed/ds is not mounted"
+fi
+if ismounted $TESTPOOL/renamed/child; then
+ log_fail "$TESTPOOL/renamed/child is mounted"
+fi
+if ismounted $TESTPOOL/renamed/child/grandchild; then
+ log_fail "$TESTPOOL/renamed/child/grandchild is mounted"
+fi
+
+log_pass "Verified rename for mountpoint=none children."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_to_encrypted.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_to_encrypted.ksh
new file mode 100755
index 000000000000..1b9c6e3c704f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_to_encrypted.ksh
@@ -0,0 +1,53 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs rename' should be able to move an unencrypted dataset to a child
+# of an encrypted dataset
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Rename the default dataset to a child of the encrypted dataset
+# 3. Confirm the child dataset doesn't have any encryption properties
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS2 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS2
+}
+log_onexit cleanup
+
+log_assert "'zfs rename' should allow renaming an unencrypted dataset to a" \
+ "child of an encrypted dataset"
+
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS2"
+log_must zfs rename $TESTPOOL/$TESTFS $TESTPOOL/$TESTFS2/$TESTFS
+log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS2/$TESTFS)" == "off"
+
+log_pass "'zfs rename' allows renaming an unencrypted dataset to a child" \
+ "of an encrypted dataset"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/Makefile.am
new file mode 100644
index 000000000000..5b7b758a056a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_reservation
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_reservation_001_pos.ksh \
+ zfs_reservation_002_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_001_pos.ksh
new file mode 100755
index 000000000000..7ec55ce0f3d2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_001_pos.ksh
@@ -0,0 +1,64 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Exceed the maximum limit for a reservation and ensure it fails.
+#
+# STRATEGY:
+# 1. Create a reservation file system.
+# 2. Set the reservation to an absurd value.
+# 3. Verify the return code is an error.
+#
+
+verify_runnable "both"
+
+RESERVATION="reserve"
+
+function cleanup
+{
+ if datasetexists $TESTPOOL/$RESERVATION ; then
+ log_must zfs unmount $TESTPOOL/$RESERVATION
+ log_must zfs destroy $TESTPOOL/$RESERVATION
+ fi
+}
+
+log_onexit cleanup
+
+log_assert "Verify that a reservation > 2^64 -1 fails."
+
+log_must zfs create $TESTPOOL/$RESERVATION
+
+log_mustnot zfs set reservation=18446744073709551615 $TESTPOOL/$RESERVATION
+
+log_pass "Unable to set a reservation > 2^64 - 1"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_002_pos.ksh
new file mode 100755
index 000000000000..c482f9c3c7df
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_reservation/zfs_reservation_002_pos.ksh
@@ -0,0 +1,88 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# A reservation of 'none' (which is an alias for 0) should be allowed. This
+# test verifies that is true.
+#
+# STRATEGY:
+# 1. Create a new file system in the test pool.
+# 2. Set the reservation to 'none'.
+# 3. Verify the associated reservation is indeed 0.
+# 4. Repeat with reservation set to 0.
+#
+
+verify_runnable "both"
+
+# Use a unique value so earlier test failures will not impact this test.
+RESERVATION="reserve"-$$
+RESERVATION2="reserve2"-$$
+
+function cleanup
+{
+ typeset FS
+ for FS in $TESTPOOL/$RESERVATION $TESTPOOL/$RESERVATION2
+ do
+ if datasetexists $FS ; then
+ log_must zfs unmount $FS
+ log_must zfs destroy $FS
+ fi
+ done
+}
+
+log_onexit cleanup
+
+log_assert "Ensure a reservation of 0 or 'none' is allowed."
+
+log_must zfs create $TESTPOOL/$RESERVATION
+log_must zfs create $TESTPOOL/$RESERVATION2
+
+log_must zfs set reservation=0 $TESTPOOL/$RESERVATION
+log_must zfs set reservation=none $TESTPOOL/$RESERVATION2
+
+for FS in $TESTPOOL/$RESERVATION $TESTPOOL/$RESERVATION2
+do
+
+ reserve=`zfs get -pH reservation $FS | awk '{print $3}'`
+ if [[ $reserve -ne 0 ]]; then
+ log_fail "ZFS get -p reservation did not return 0"
+ fi
+
+ reserve=`zfs get -H reservation $FS | awk '{print $3}'`
+ if [[ $reserve != "none" ]]; then
+ log_fail "ZFS get reservation did not return 'none'"
+ fi
+done
+
+log_pass "Successfully set reservation to 0 and 'none'"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/Makefile.am
new file mode 100644
index 000000000000..4d278f724527
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/Makefile.am
@@ -0,0 +1,12 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_rollback
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_rollback_001_pos.ksh \
+ zfs_rollback_002_pos.ksh \
+ zfs_rollback_003_neg.ksh \
+ zfs_rollback_004_neg.ksh
+
+dist_pkgdata_DATA = \
+ zfs_rollback.cfg \
+ zfs_rollback_common.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/cleanup.ksh
new file mode 100755
index 000000000000..707e8f121ddb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/cleanup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib
+
+cleanup_env
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/setup.ksh
new file mode 100755
index 000000000000..d3341b1c27fc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/setup.ksh
@@ -0,0 +1,31 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_volume_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback.cfg
new file mode 100644
index 000000000000..d6c8934d9753
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback.cfg
@@ -0,0 +1,45 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+. $STF_SUITE/include/libtest.shlib
+
+export FS=$TESTPOOL/$TESTFS
+export VOL=$TESTPOOL/$TESTVOL
+
+export FSSNAP0=$FS@$TESTSNAP
+export FSSNAP1=$FS@$TESTSNAP1
+export FSSNAP2=$FS@$TESTSNAP2
+
+export VOLSNAP0=$VOL@$TESTSNAP
+export VOLSNAP1=$VOL@$TESTSNAP1
+export VOLSNAP2=$VOL@$TESTSNAP2
+
+export FSCLONE0=$FS$TESTCLONE
+export FSCLONE1=$FS$TESTCLONE1
+export FSCLONE2=$FS$TESTCLONE2
+
+export VOLCLONE0=$VOL$TESTCLONE
+export VOLCLONE1=$VOL$TESTCLONE1
+export VOLCLONE2=$VOL$TESTCLONE2
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_001_pos.ksh
new file mode 100755
index 000000000000..5511f6ad6db6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_001_pos.ksh
@@ -0,0 +1,174 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs rollback -r|-rf|-R|-Rf' will recursively destroy any snapshots
+# more recent than the one specified.
+#
+# STRATEGY:
+# 1. Create pool, fs & volume.
+# 2. Separately create three snapshots or clones for fs & volume
+# 3. Roll back to the second snapshot and check the results.
+# 4. Create the third snapshot or clones for fs & volume again.
+# 5. Roll back to the first snapshot and check the results.
+# 6. Separately create two snapshots for fs & volume.
+# 7. Roll back to the first snapshot and check the results.
+#
+
+verify_runnable "both"
+
+log_assert "'zfs rollback -r|-rf|-R|-Rf' will recursively destroy any " \
+ "snapshots more recent than the one specified."
+log_onexit cleanup_env
+
+#
+# Create suitable test environment and run 'zfs rollback', then compare with
+# expected value to check the system status.
+#
+# $1 option.
+# $2 the number of snapshots or clones.
+# $3 the number of snapshot point which we want to rollback.
+#
+function test_n_check #opt num_snap_clone num_rollback
+{
+ typeset opt=$1
+ typeset -i cnt=$2
+ typeset -i pointcnt=$3
+ typeset dtst
+
+ (( cnt > 3 || pointcnt > cnt )) && \
+ log_fail "Unsupported testing condition."
+
+ # Clean up the test environment
+ if pgrep -x dd 2>/dev/null; then
+ pkill -x dd
+ fi
+
+ datasetexists $FS && log_must zfs destroy -Rf $FS
+ if datasetexists $VOL; then
+ if ismounted $TESTDIR1 $NEWFS_DEFAULT_FS; then
+ log_must umount -f $TESTDIR1
+ fi
+
+ log_must zfs destroy -Rf $VOL
+ fi
+
+ # Create specified test environment
+ case $opt in
+ *r*) setup_snap_env $cnt ;;
+ *R*) setup_clone_env $cnt ;;
+ esac
+
+ all_snap="$TESTSNAP $TESTSNAP1 $TESTSNAP2"
+ all_clone="$TESTCLONE $TESTCLONE1 $TESTCLONE2"
+ typeset snap_point
+ typeset exist_snap
+ typeset exist_clone
+ case $pointcnt in
+ 1) snap_point=$TESTSNAP
+ exist_snap=$TESTSNAP
+ [[ $opt == *R* ]] && exist_clone=$TESTCLONE
+ ;;
+ 2) snap_point=$TESTSNAP1
+ exist_snap="$TESTSNAP $TESTSNAP1"
+ [[ $opt == *R* ]] && exist_clone="$TESTCLONE $TESTCLONE1"
+ ;;
+ esac
+
+ typeset snap
+ for dtst in $FS $VOL; do
+ # Volume is not available in Local Zone.
+ if [[ $dtst == $VOL ]]; then
+ if ! is_global_zone; then
+ break
+ fi
+ fi
+ if [[ $opt == *f* ]]; then
+ # To write data to the mountpoint directory,
+ write_mountpoint_dir $dtst
+ opt=${opt%f}
+ fi
+
+ if [[ $dtst == $VOL ]]; then
+ if ismounted $TESTDIR1 $NEWFS_DEFAULT_FS; then
+ log_must umount -f $TESTDIR1
+ fi
+ log_must zfs rollback $opt $dtst@$snap_point
+ log_must mount \
+ $ZVOL_DEVDIR/$TESTPOOL/$TESTVOL $TESTDIR1
+ else
+ log_must zfs rollback $opt $dtst@$snap_point
+ fi
+
+ for snap in $all_snap; do
+ if [[ " $exist_snap " == *" $snap "* ]]; then
+ log_must datasetexists $dtst@$snap
+ else
+ log_must datasetnonexists $dtst@$snap
+ fi
+ done
+ for clone in $all_clone; do
+ if [[ " $exist_clone " == *" $clone "* ]]; then
+ log_must datasetexists $dtst$clone
+ else
+ log_must datasetnonexists $dtst$clone
+ fi
+ done
+
+ check_files $dtst@$snap_point
+ done
+}
+
+typeset opt
+for opt in "-r" "-rf" "-R" "-Rf"; do
+ #
+ # Currently, the test case was limited to create and rollback
+ # in three snapshots
+ #
+ log_note "Create 3 snapshots, rollback to the 2nd snapshot " \
+ "using $opt."
+ test_n_check "$opt" 3 2
+
+ log_note "Create 3 snapshots and rollback to the 1st snapshot " \
+ "using $opt."
+ test_n_check "$opt" 3 1
+
+ log_note "Create 2 snapshots and rollback to the 1st snapshot " \
+ "using $opt."
+ test_n_check "$opt" 2 1
+done
+
+log_pass "'zfs rollback -r|-rf|-R|-Rf' recursively destroy any snapshots more "\
+ "recent than the one specified passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_002_pos.ksh
new file mode 100755
index 000000000000..659660dc0fe7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_002_pos.ksh
@@ -0,0 +1,68 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs rollback -f' will force unmount any filesystems.
+#
+# STRATEGY:
+# 1. Create pool & fs.
+# 2. Create the snapshot of this file system.
+# 3. Write the mountpoint directory of this file system.
+# 4. Make sure 'zfs rollback -f' succeeds.
+#
+
+verify_runnable "both"
+
+log_assert "'zfs rollback -f' will force unmount any filesystems."
+log_onexit cleanup_env
+
+# Create a snapshot of this file system: FSSNAP0
+setup_snap_env 1
+
+#
+# Write file and make the mountpoint directory busy when try to unmount
+# the file system that was mounted on it.
+#
+write_mountpoint_dir ${FSSNAP0%%@*}
+
+log_must zfs rollback $FSSNAP0
+log_must zfs rollback -f $FSSNAP0
+log_must datasetexists $FSSNAP0
+
+pkill ${DD##*/}
+
+check_files $FSSNAP0
+
+log_pass "'zfs rollback -f' force unmount any filesystem passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_003_neg.ksh
new file mode 100755
index 000000000000..0ae13d3a9bad
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_003_neg.ksh
@@ -0,0 +1,84 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib
+
+#
+# DESCRIPTION:
+# Separately verify 'zfs rollback ''|-f|-r|-rf|-R|-rR will fail in
+# different conditions.
+#
+# STRATEGY:
+# 1. Create pool and file system
+# 2. Create 'snap' and 'snap1' of this file system.
+# 3. Run 'zfs rollback ""|-f <snap>' and it should fail.
+# 4. Create 'clone1' based on 'snap1'.
+# 5. Run 'zfs rollback -r|-rf <snap>' and it should fail.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ pkill ${DD##*/}
+ for snap in $FSSNAP0 $FSSNAP1 $FSSNAP2; do
+ if snapexists $snap; then
+ log_must zfs destroy -Rf $snap
+ fi
+ done
+}
+
+log_assert "Separately verify 'zfs rollback ''|-f|-r|-rf will fail in " \
+ "different conditions."
+log_onexit cleanup
+
+# Create snapshot1 and snapshot2 for this file system.
+#
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP1
+
+# Run 'zfs rollback ""|-f <snap>' and it should fail.
+#
+log_mustnot zfs rollback $TESTPOOL/$TESTFS@$TESTSNAP
+log_mustnot zfs rollback -f $TESTPOOL/$TESTFS@$TESTSNAP
+
+# Create 'clone1' based on 'snap1'.
+#
+create_clone $TESTPOOL/$TESTFS@$TESTSNAP1 $TESTPOOL/$TESTCLONE1
+
+# Run 'zfs rollback -r|-rf <snap>' and it should fail.
+#
+log_mustnot zfs rollback -r $TESTPOOL/$TESTFS@$TESTSNAP
+log_mustnot zfs rollback -rf $TESTPOOL/$TESTFS@$TESTSNAP
+
+log_pass "zfs rollback ''|-f|-r|-rf will fail in different conditions " \
+ "passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_004_neg.ksh
new file mode 100755
index 000000000000..0c1bb730e77c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_004_neg.ksh
@@ -0,0 +1,86 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs rollback' should fail when passing invalid options, too many
+# arguments,non-snapshot datasets or missing datasets
+#
+# STRATEGY:
+# 1. Create an array of invalid options
+# 2. Execute 'zfs rollback' with invalid options, too many arguments
+# or missing datasets
+# 3. Verify 'zfs rollback' return with errors
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset ds
+
+ for ds in $TESTPOOL $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL; do
+ if snapexists ${ds}@$TESTSNAP; then
+ log_must zfs destroy ${ds}@$TESTSNAP
+ fi
+ done
+}
+
+log_assert "'zfs rollback' should fail with bad options,too many arguments," \
+ "non-snapshot datasets or missing datasets."
+log_onexit cleanup
+
+set -A badopts "r" "R" "f" "-F" "-rF" "-RF" "-fF" "-?" "-*" "-blah" "-1" "-2"
+
+for ds in $TESTPOOL $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL; do
+ log_must zfs snapshot ${ds}@$TESTSNAP
+done
+
+for ds in $TESTPOOL $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL; do
+ for opt in "" "-r" "-R" "-f" "-rR" "-rf" "-rRf"; do
+ log_mustnot eval "zfs rollback $opt $ds >/dev/null 2>&1"
+ log_mustnot eval "zfs rollback $opt ${ds}@$TESTSNAP \
+ ${ds}@$TESTSNAP >/dev/null 2>&1"
+ log_mustnot eval "zfs rollback $opt >/dev/null 2>&1"
+ # zfs rollback should fail with non-existen snapshot
+ log_mustnot eval "zfs rollback $opt ${ds}@nosnap >/dev/null 2>&1"
+ done
+
+ for badopt in ${badopts[@]}; do
+ log_mustnot eval "zfs rollback $badopt ${ds}@$TESTSNAP \
+ >/dev/null 2>&1"
+ done
+done
+
+log_pass "'zfs rollback' fails as expected with illegal arguments."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib
new file mode 100644
index 000000000000..b2f4b2b8a3ca
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib
@@ -0,0 +1,321 @@
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_rollback/zfs_rollback.cfg
+
+# Get file sum
+#
+# $1 full file name
+function getsum #fname
+{
+ (( ${#1} == 0 )) && \
+ log_fail "Need give file name."
+ return $(sum $1 | awk '{print $1}')
+}
+
+# Define global variable checksum, get the original file sum.
+#
+origsum=$(getsum /etc/passwd)
+
+#
+# Setup or recover the test environment. Firstly, copy /etc/passwd to ZFS file
+# system or volume, then make a snapshot or clone. Repeat up to three times.
+#
+# $1 number of snapshot. Note: Currently only support three snapshots.
+# $2 indicate if it is necessary to create clone
+#
+function setup_snap_env
+{
+ typeset -i cnt=${1:-3}
+ typeset createclone=${2:-"false"}
+
+ if datasetnonexists $FS; then
+ log_must zfs create $FS
+ log_must zfs set mountpoint=$TESTDIR $FS
+ fi
+ # Volume can't be created in Local Zone.
+ if datasetnonexists $VOL && is_global_zone; then
+ log_must zfs create -V $VOLSIZE $VOL
+ block_device_wait
+ fi
+
+ # Make sure $VOL is volume
+ typeset type=$(get_prop type $VOL)
+ if datasetexists $VOL && \
+ [[ $type == 'volume' ]]; then
+ #
+ # At the first time, Make a UFS file system in volume and
+ # mount it. Otherwise, only check if this ufs|ext file system
+ # was mounted.
+ #
+ log_must new_fs $ZVOL_DEVDIR/$VOL
+
+ [[ ! -d $TESTDIR1 ]] && log_must mkdir $TESTDIR1
+
+ # Make sure the ufs|ext filesystem hasn't been mounted,
+ # then mount the new ufs|ext filesystem.
+ if ! ismounted $TESTDIR1 $NEWFS_DEFAULT_FS; then
+ log_must mount $ZVOL_DEVDIR/$VOL $TESTDIR1
+ fi
+ fi
+
+ # Separately Create three snapshots for file system & volume
+ typeset -i ind=0
+ typeset dtst
+ for dtst in $FS $VOL; do
+ # Volume can be created in Local Zone.
+ if [[ $dtst == $VOL ]]; then
+ if ! is_global_zone; then
+ break
+ fi
+ fi
+
+ ind=0
+ while (( ind < cnt )); do
+ case $dtst in
+ $FS)
+ eval typeset snap=\$FSSNAP$ind
+ eval typeset clone=\$FSCLONE$ind
+ eval typeset fname=\$TESTDIR/\$TESTFILE$ind
+ ;;
+ $VOL)
+ eval typeset snap=\$VOLSNAP$ind
+ eval typeset clone=\$VOLCLONE$ind
+ eval typeset fname=\$TESTDIR1/\$TESTFILE$ind
+ ;;
+ esac
+
+ if datasetnonexists $snap; then
+ log_must cp /etc/passwd $fname
+ if is_linux || is_freebsd; then
+ log_must sync
+ else
+ #
+ # using 'lockfs -f' to flush the writes
+ # to disk before taking a snapshot.
+ #
+ if [[ $dtst == $VOL ]]; then
+ log_must lockfs -f $TESTDIR1
+ fi
+ fi
+ if is_freebsd && [[ $dtst == $VOL ]]; then
+ # Though sync does start a fs sync on
+ # FreeBSD, it does not wait for it to
+ # finish. We can force a blocking sync
+ # by updating the fs mount instead.
+ # Otherwise, the snapshot might occur
+ # with the fs in an unmountable state.
+ log_must mount -ur \
+ $ZVOL_DEVDIR/$VOL $TESTDIR1
+ fi
+ log_must zfs snapshot $snap
+ if is_freebsd && [[ $dtst == $VOL ]]; then
+ log_must mount -uw \
+ $ZVOL_DEVDIR/$VOL $TESTDIR1
+ fi
+ fi
+ if [[ $createclone == "true" ]]; then
+ if datasetnonexists $clone; then
+ log_must zfs clone $snap $clone
+ block_device_wait
+ fi
+ fi
+ (( ind += 1 ))
+ done
+ done
+}
+
+function setup_clone_env
+{
+ setup_snap_env $1 "true"
+}
+
+#
+# Clean up the test environment
+#
+# $1 number of snapshot Note: Currently only support three snapshots.
+#
+function cleanup_env
+{
+ typeset -i cnt=${1:-3}
+ typeset -i ind=0
+ typeset dtst
+ typeset snap
+
+ pkill -x dd
+
+ if ismounted $TESTDIR1 $NEWFS_DEFAULT_FS; then
+ log_must umount -f $TESTDIR1
+ fi
+
+ [[ -d $TESTDIR ]] && log_must rm -rf $TESTDIR/*
+ [[ -d $TESTDIR1 ]] && log_must rm -rf $TESTDIR1/*
+
+ for dtst in $FS $VOL; do
+ for snap in $TESTSNAP $TESTSNAP1 $TESTSNAP2; do
+ if snapexists $dtst@$snap; then
+ log_must zfs destroy -Rf $dtst@$snap
+ fi
+ done
+ done
+
+ # Restore original test environment
+ if datasetnonexists $FS ; then
+ log_must zfs create $FS
+ fi
+ if datasetnonexists $VOL ; then
+ if is_global_zone ; then
+ log_must zfs create -V $VOLSIZE $VOL
+ else
+ log_must zfs create $VOL
+ fi
+ fi
+}
+
+#
+# check if the specified files have specified status.
+#
+# $1 expected status
+# $2-n full file name
+# If it is true return 0, else return 1
+#
+function file_status
+{
+ (( $# == 0 )) && \
+ log_fail "The file name is not defined."
+
+ typeset opt
+ case $1 in
+ exist) opt="-e" ;;
+ nonexist) opt="! -e" ;;
+ *) log_fail "Unsupported file status." ;;
+ esac
+
+ shift
+ while (( $# > 0 )); do
+ eval [[ $opt $1 ]] || return 1
+ shift
+ done
+
+ return 0
+}
+
+function files_exist
+{
+ file_status "exist" $@
+}
+
+function files_nonexist
+{
+ file_status "nonexist" $@
+}
+
+#
+# According to snapshot check if the file system was recovered to the right
+# point.
+#
+# $1 snapshot. fs@snap or vol@snap
+#
+function check_files
+{
+ typeset dtst=$1
+
+ if [[ $(get_prop type $dtst) != snapshot ]]; then
+ log_fail "Parameter must be a snapshot."
+ fi
+
+ typeset fsvol=${dtst%%@*}
+ typeset snap=${dtst##*@}
+ if [[ $(get_prop type $fsvol) == "filesystem" ]]; then
+ ind=""
+ else
+ ind="1"
+ fi
+
+ eval typeset file0=\$TESTDIR$ind/\$TESTFILE0
+ eval typeset file1=\$TESTDIR$ind/\$TESTFILE1
+ eval typeset file2=\$TESTDIR$ind/\$TESTFILE2
+
+ case $snap in
+ $TESTSNAP2)
+ log_must files_exist $file0 $file1 $file2
+
+ typeset sum0=$(getsum $file0)
+ typeset sum1=$(getsum $file1)
+ typeset sum2=$(getsum $file2)
+ if [[ $sum0 != $origsum || \
+ $sum1 != $origsum || sum2 != $origsum ]]
+ then
+ log_fail "After rollback, file sum is changed."
+ fi
+ ;;
+ $TESTSNAP1)
+ log_must files_exist $file0 $file1
+ log_must files_nonexist $file2
+
+ typeset sum0=$(getsum $file0)
+ typeset sum1=$(getsum $file1)
+ if [[ $sum0 != $origsum || $sum1 != $origsum ]]
+ then
+ log_fail "After rollback, file sum is changed."
+ fi
+ ;;
+ $TESTSNAP)
+ log_must files_exist $file0
+ log_must files_nonexist $file1 $file2
+
+ typeset sum0=$(getsum $file0)
+ if [[ $sum0 != $origsum ]]; then
+ log_fail "After rollback, file sum is changed."
+ fi
+ ;;
+ esac
+}
+
+# According to dataset type, write file to different directories.
+#
+# $1 dataset
+#
+function write_mountpoint_dir
+{
+ typeset dtst=$1
+ typeset dir
+
+ if [[ $dtst == $FS ]]; then
+ dir=$TESTDIR
+ log_must ismounted $dir
+ else
+ dir=$TESTDIR1
+ log_must ismounted $dir $NEWFS_DEFAULT_FS
+ fi
+ dd if=/dev/urandom of=$dir/$TESTFILE1 &
+ log_must sleep 3
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_send/Makefile.am
new file mode 100644
index 000000000000..9a492f32311d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/Makefile.am
@@ -0,0 +1,19 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_send
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_send_001_pos.ksh \
+ zfs_send_002_pos.ksh \
+ zfs_send_003_pos.ksh \
+ zfs_send_004_neg.ksh \
+ zfs_send_005_pos.ksh \
+ zfs_send_006_pos.ksh \
+ zfs_send_007_pos.ksh \
+ zfs_send_encrypted.ksh \
+ zfs_send_encrypted_unloaded.ksh \
+ zfs_send_raw.ksh \
+ zfs_send_sparse.ksh \
+ zfs_send-b.ksh
+
+dist_pkgdata_DATA = \
+ zfs_send.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/cleanup.ksh
new file mode 100755
index 000000000000..cec69d4709f4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/cleanup.ksh
@@ -0,0 +1,33 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+poolexists $TESTPOOL1 && \
+ destroy_pool $TESTPOOL1
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send-b.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send-b.ksh
new file mode 100755
index 000000000000..87997e76c245
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send-b.ksh
@@ -0,0 +1,102 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs send -b' should works as expected.
+#
+# STRATEGY:
+# 1. Create a source dataset and set some properties
+# 2. Verify command line options interact with '-b' correctly
+# 3. Send the dataset and its properties to a new "backup" destination
+# 4. Set some properties on the new "backup" dataset
+# 5. Restore the "backup" dataset to a new destination
+# 6. Verify only original (received) properties are sent from "backup"
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for ds in "$SENDFS" "$BACKUP" "$RESTORE"; do
+ datasetexists $ds && log_must zfs destroy -r $ds
+ done
+}
+
+log_assert "'zfs send -b' should work as expected."
+log_onexit cleanup
+
+SENDFS="$TESTPOOL/sendfs"
+BACKUP="$TESTPOOL/backup"
+RESTORE="$TESTPOOL/restore"
+
+# 1. Create a source dataset and set some properties
+log_must zfs create $SENDFS
+log_must zfs snapshot "$SENDFS@s1"
+log_must zfs bookmark "$SENDFS@s1" "$SENDFS#bm"
+log_must zfs snapshot "$SENDFS@s2"
+log_must zfs set "compression=gzip" $SENDFS
+log_must zfs set "org.openzfs:prop=val" $SENDFS
+log_must zfs set "org.openzfs:snapprop=val" "$SENDFS@s1"
+
+# 2. Verify command line options interact with '-b' correctly
+typeset opts=("" "p" "Rp" "cew" "nv" "D" "DLPRcenpvw")
+for opt in ${opts[@]}; do
+ log_must eval "zfs send -b$opt $SENDFS@s1 > /dev/null"
+ log_must eval "zfs send -b$opt -i $SENDFS@s1 $SENDFS@s2 > /dev/null"
+ log_must eval "zfs send -b$opt -I $SENDFS@s1 $SENDFS@s2 > /dev/null"
+done
+for opt in ${opts[@]}; do
+ log_mustnot eval "zfs send -b$opt $SENDFS > /dev/null"
+ log_mustnot eval "zfs send -b$opt $SENDFS#bm > /dev/null"
+done
+
+# Do 3..6 in a loop to verify various combination of "zfs send" options
+typeset opts=("" "p" "R" "pR" "cew")
+for opt in ${opts[@]}; do
+ # 3. Send the dataset and its properties to a new "backup" destination
+ # NOTE: only need to send properties (-p) here
+ log_must eval "zfs send -p $SENDFS@s1 | zfs recv $BACKUP"
+
+ # 4. Set some properties on the new "backup" dataset
+ # NOTE: override "received" values and set some new properties as well
+ log_must zfs set "compression=lz4" $BACKUP
+ log_must zfs set "exec=off" $BACKUP
+ log_must zfs set "org.openzfs:prop=newval" $BACKUP
+ log_must zfs set "org.openzfs:newprop=newval" $BACKUP
+ log_must zfs set "org.openzfs:snapprop=newval" "$BACKUP@s1"
+ log_must zfs set "org.openzfs:newsnapprop=newval" "$BACKUP@s1"
+
+ # 5. Restore the "backup" dataset to a new destination
+ log_must eval "zfs send -b$opt $BACKUP@s1 | zfs recv $RESTORE"
+
+ # 6. Verify only original (received) properties are sent from "backup"
+ log_must eval "check_prop_source $RESTORE compression gzip received"
+ log_must eval "check_prop_source $RESTORE org.openzfs:prop val received"
+ log_must eval "check_prop_source $RESTORE@s1 org.openzfs:snapprop val received"
+ log_must eval "check_prop_source $RESTORE exec on default"
+ log_must eval "check_prop_missing $RESTORE org.openzfs:newprop"
+ log_must eval "check_prop_missing $RESTORE@s1 org.openzfs:newsnapprop"
+
+ # cleanup
+ log_must zfs destroy -r $BACKUP
+ log_must zfs destroy -r $RESTORE
+done
+
+log_pass "'zfs send -b' works as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send.cfg
new file mode 100644
index 000000000000..bbc4d3ac833e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send.cfg
@@ -0,0 +1,32 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+export BLOCK_SIZE=512
+export WRITE_COUNT=8
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_001_pos.ksh
new file mode 100755
index 000000000000..2c6e3fdd6d2f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_001_pos.ksh
@@ -0,0 +1,127 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/cli_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_send/zfs_send.cfg
+
+#
+# DESCRIPTION:
+# Verify 'zfs send' can create valid send streams as expected.
+#
+# STRATEGY:
+# 1. Fill in fs with some data
+# 2. Create a full send streams with the fs
+# 3. Receive the send stream and verify the data integrity
+# 4. Fill in fs with some new data
+# 5. Create an incremental send stream with the fs
+# 6. Receive the incremental send stream and verify the data integrity.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for snap in $init_snap $inc_snap $rst_snap $rst_inc_snap; do
+ snapexists $snap && \
+ log_must zfs destroy -f $snap
+ done
+
+ datasetexists $rst_root && \
+ log_must zfs destroy -Rf $rst_root
+
+ for file in $full_bkup $inc_bkup \
+ $init_data $inc_data
+ do
+ [[ -e $file ]] && \
+ log_must rm -f $file
+ done
+
+ [[ -d $TESTDIR1 ]] && \
+ log_must rm -rf $TESTDIR1
+
+}
+
+log_assert "Verify 'zfs send' can create valid send streams as expected."
+log_onexit cleanup
+
+init_snap=$TESTPOOL/$TESTFS@init_snap
+inc_snap=$TESTPOOL/$TESTFS@inc_snap
+full_bkup=$TEST_BASE_DIR/fullbkup.$$
+inc_bkup=$TEST_BASE_DIR/incbkup.$$
+init_data=$TESTDIR/$TESTFILE1
+inc_data=$TESTDIR/$TESTFILE2
+orig_sum=""
+rst_sum=""
+rst_root=$TESTPOOL/rst_ctr
+rst_snap=$rst_root/$TESTFS@init_snap
+rst_inc_snap=$rst_root/$TESTFS@inc_snap
+rst_data=$TESTDIR1/$TESTFS/$TESTFILE1
+rst_inc_data=$TESTDIR1/$TESTFS/$TESTFILE2
+
+
+log_note "Verify 'zfs send' can create full send stream."
+
+#Pre-paration
+log_must zfs create $rst_root
+[[ ! -d $TESTDIR1 ]] && \
+ log_must mkdir -p $TESTDIR1
+log_must zfs set mountpoint=$TESTDIR1 $rst_root
+
+file_write -o create -f $init_data -b $BLOCK_SIZE -c $WRITE_COUNT
+
+log_must zfs snapshot $init_snap
+zfs send $init_snap > $full_bkup
+(( $? != 0 )) && \
+ log_fail "'zfs send' fails to create full send"
+
+log_note "Verify the send stream is valid to receive."
+
+log_must zfs receive $rst_snap <$full_bkup
+receive_check $rst_snap ${rst_snap%%@*}
+compare_cksum $init_data $rst_data
+
+log_note "Verify 'zfs send -i' can create incremental send stream."
+
+file_write -o create -f $inc_data -b $BLOCK_SIZE -c $WRITE_COUNT -d 0
+
+log_must zfs snapshot $inc_snap
+zfs send -i $init_snap $inc_snap > $inc_bkup
+(( $? != 0 )) && \
+ log_fail "'zfs send -i' fails to create incremental send"
+
+log_note "Verify the incremental send stream is valid to receive."
+
+log_must zfs rollback $rst_snap
+log_must zfs receive $rst_inc_snap <$inc_bkup
+receive_check $rst_inc_snap
+compare_cksum $inc_data $rst_inc_data
+
+log_pass "Verifying 'zfs receive' succeed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_002_pos.ksh
new file mode 100755
index 000000000000..6359bb4f7f22
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_002_pos.ksh
@@ -0,0 +1,139 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/cli_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_send/zfs_send.cfg
+
+#
+# DESCRIPTION:
+# Verify 'zfs send' can generate valid streams with a property setup.
+#
+# STRATEGY:
+# 1. Setup property for filesystem
+# 2. Fill in some data into filesystem
+# 3. Create a full send streams
+# 4. Receive the send stream
+# 5. Verify the receive result
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ snapexists $snap && \
+ log_must zfs destroy $snap
+
+ datasetexists $ctr && \
+ log_must zfs destroy -r $ctr
+
+ [[ -e $origfile ]] && \
+ log_must rm -f $origfile
+
+ [[ -e $stream ]] && \
+ log_must rm -f $stream
+}
+
+function do_testing # <prop> <prop_value>
+{
+ typeset property=$1
+ typeset prop_val=$2
+
+ log_must zfs set $property=$prop_val $fs
+ file_write -o create -f $origfile -b $BLOCK_SIZE -c $WRITE_COUNT
+ log_must zfs snapshot $snap
+ zfs send $snap > $stream
+ (( $? != 0 )) && \
+ log_fail "'zfs send' fails to create send streams."
+ zfs receive -d $ctr <$stream
+ (( $? != 0 )) && \
+ log_fail "'zfs receive' fails to receive send streams."
+
+ #verify receive result
+ ! datasetexists $rstfs && \
+ log_fail "'zfs receive' fails to restore $rstfs"
+ ! snapexists $rstfssnap && \
+ log_fail "'zfs receive' fails to restore $rstfssnap"
+ if [[ ! -e $rstfile ]] || [[ ! -e $rstsnapfile ]]; then
+ log_fail " Data lost after receiving stream"
+ fi
+
+ compare_cksum $origfile $rstfile
+ compare_cksum $origsnapfile $rstsnapfile
+
+ #Destroy datasets and stream for next testing
+ log_must zfs destroy $snap
+ if is_global_zone ; then
+ log_must zfs destroy -r $rstfs
+ else
+ log_must zfs destroy -r $ds_path
+ fi
+ log_must rm -f $stream
+}
+
+log_assert "Verify 'zfs send' generates valid streams with a property setup"
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+snap=$fs@$TESTSNAP
+ctr=$TESTPOOL/$TESTCTR
+if is_global_zone; then
+ rstfs=$ctr/$TESTFS
+else
+ ds_path=$ctr/${ZONE_CTR}0
+ rstfs=$ds_path/$TESTFS
+fi
+rstfssnap=$rstfs@$TESTSNAP
+snapdir=".zfs/snapshot/$TESTSNAP"
+origfile=$TESTDIR/$TESTFILE1
+rstfile=/$rstfs/$TESTFILE1
+origsnapfile=$TESTDIR/$snapdir/$TESTFILE1
+rstsnapfile=/$rstfs/$snapdir/$TESTFILE1
+stream=$TEST_BASE_DIR/streamfile.$$
+
+set -A props "compression" "checksum" "recordsize"
+set -A propval "on lzjb" "on fletcher2 fletcher4 sha256" \
+ "512 1k 4k 8k 16k 32k 64k 128k"
+
+#Create a dataset to receive the send stream
+log_must zfs create $ctr
+
+typeset -i i=0
+while (( i < ${#props[*]} ))
+do
+ for value in ${propval[i]}
+ do
+ do_testing ${props[i]} $value
+ done
+
+ (( i = i + 1 ))
+done
+
+log_pass "'zfs send' generates streams with a property setup as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_003_pos.ksh
new file mode 100755
index 000000000000..825a10d0f8a2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_003_pos.ksh
@@ -0,0 +1,69 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs send -i' can deal with abbreviated snapshot name.
+#
+# STRATEGY:
+# 1. Create pool, fs and two snapshots.
+# 2. Make sure 'zfs send -i' support abbreviated snapshot name.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $snap1 && log_must zfs destroy $snap1
+ datasetexists $snap2 && log_must zfs destroy $snap2
+}
+
+log_assert "'zfs send -i' can deal with abbreviated snapshot name."
+log_onexit cleanup
+
+snap1=$TESTPOOL/$TESTFS@snap1; snap2=$TESTPOOL/$TESTFS@snap2
+
+set -A args "$snap1 $snap2" \
+ "${snap1##*@} $snap2" "@${snap1##*@} $snap2"
+
+log_must zfs snapshot $snap1
+log_must zfs snapshot $snap2
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_must eval "zfs send -i ${args[i]} > /dev/null"
+
+ (( i += 1 ))
+done
+
+log_pass "'zfs send -i' deal with abbreviated snapshot name passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_004_neg.ksh
new file mode 100755
index 000000000000..4a9d29fce1cf
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_004_neg.ksh
@@ -0,0 +1,109 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/cli_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify 'zfs send' fails with malformed parameters.
+#
+# STRATEGY:
+# 1. Define malformed parameters in array
+# 2. Feed the parameters to 'zfs send'
+# 3. Verify the result
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset snap f
+
+ for snap in $snap1 $snap2 $snap3; do
+ snapexists $snap && \
+ log_must zfs destroy -f $snap
+ done
+
+ for f in $tmpfile1 $tmpfile2; do
+ if [[ -e $f ]]; then
+ rm -f $f
+ fi
+ done
+}
+
+fs=$TESTPOOL/$TESTFS
+snap1=$fs@snap1
+snap2=$fs@snap2
+snap3=$fs@snap3
+
+set -A badargs \
+ "" "$TESTPOOL" "$TESTFS" "$fs" "$fs@nonexistent_snap" "?" \
+ "$snap1/blah" "$snap1@blah" "-i" "-x" "-i $fs" \
+ "-x $snap1 $snap2" "-i $snap1" \
+ "-i $snap2 $snap1" "$snap1 $snap2" "-i $snap1 $snap2 $snap3" \
+ "-ii $snap1 $snap2" "-iii $snap1 $snap2" " -i $snap2 $snap1/blah" \
+ "-i $snap2/blah $snap1" \
+ "-i $snap2/blah $snap1/blah" \
+ "-i $snap1 blah@blah" \
+ "-i blah@blah $snap1" \
+ "-i $snap1 ${snap2##*@}" "-i $snap1 @${snap2##*@}" \
+ "-i ${snap1##*@} ${snap2##*@}" "-i @${snap1##*@} @${snap2##*@}" \
+ "-i ${snap1##*@} $snap2/blah" "-i @${snap1##*@} $snap2/blah" \
+ "-i @@${snap1##*@} $snap2" "-i $snap1 -i $snap1 $snap2" \
+ "-i snap1 snap2" "-i $snap1 snap2" \
+ "-i $snap1 $snap2 -i $snap1 $snap2" \
+ "-i snap1 $snap2 -i snap1 $snap2"
+
+log_assert "Verify that invalid parameters to 'zfs send' are caught."
+log_onexit cleanup
+
+log_must zfs snapshot $snap1
+tmpfile1=$TESTDIR/testfile1.$$
+log_must touch $tmpfile1
+log_must zfs snapshot $snap2
+tmpfile2=$TESTDIR/testfile2.$$
+log_must touch $tmpfile2
+log_must zfs snapshot $snap3
+
+typeset -i i=0
+while (( i < ${#badargs[*]} ))
+do
+ log_mustnot eval "zfs send ${badargs[i]} >/dev/null"
+
+ (( i = i + 1 ))
+done
+
+#Testing zfs send fails by send backup stream to terminal
+for arg in "$snap1" "-i $snap1 $snap2"; do
+ log_mustnot eval "zfs send $arg >/dev/console"
+done
+
+log_pass "Invalid parameters to 'zfs send' are caught as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_005_pos.ksh
new file mode 100755
index 000000000000..9f369e372dee
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_005_pos.ksh
@@ -0,0 +1,66 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs send -R' can send from read-only imported pool. It needs to
+# detect that the pool is read-only and not try to place holds on
+# datasets being sent.
+#
+# STRATEGY:
+# 1. Create a recursive snapshot on the whole pool.
+# 2. 'zfs send -R' the recursive snapshots.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ poolexists $TESTPOOL && log_must_busy zpool export $TESTPOOL
+ log_must zpool import $TESTPOOL
+
+ datasetexists $TESTPOOL@snap && \
+ log_must zfs destroy -r $TESTPOOL@snap
+}
+
+log_assert "'zfs send -R' can send from read-only pools"
+log_onexit cleanup
+
+log_must zfs snapshot -r $TESTPOOL@snap
+
+log_must zpool export $TESTPOOL
+log_must zpool import -o readonly=on $TESTPOOL
+
+log_must eval "zfs send -R $TESTPOOL@snap >/dev/null"
+
+log_pass "'zfs send -R' can send from read-only pools"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos.ksh
new file mode 100755
index 000000000000..42628a0512e9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos.ksh
@@ -0,0 +1,202 @@
+#!/bin/ksh
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012, 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+#
+# DESCRIPTION:
+# Verify 'zfs send' can generate valid streams with different options
+#
+# STRATEGY:
+# 1. Create datasets
+# 2. Write some data to the datasets
+# 3. Create a full send streams
+# 4. Receive the send stream
+# 5. Do a dry run with different options and verify the generated size
+# estimate against the received stream
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must set_tunable32 OVERRIDE_ESTIMATE_RECORDSIZE 8192
+ for ds in $datasets; do
+ destroy_dataset $ds "-rf"
+ done
+}
+
+function cal_percentage
+{
+ typeset value=$1
+ return=$(echo "$PERCENT * $value" | bc)
+ return=$(echo "$return / 100" | bc)
+ echo $return
+}
+
+function get_estimate_size
+{
+ typeset snapshot=$1
+ typeset option=$2
+ typeset base_snapshot=${3:-""}
+ if [[ -z $3 ]]; then
+ typeset total_size=$(zfs send $option $snapshot 2>&1 | tail -1)
+ else
+ typeset total_size=$(zfs send $option $base_snapshot $snapshot \
+ 2>&1 | tail -1)
+ fi
+ total_size=$(echo "$total_size" | awk '{print $NF}')
+ if [[ $options != *"P"* ]]; then
+ total_size=${total_size%M}
+ total_size=$(echo "$total_size * $block_count" | bc)
+ fi
+ echo $total_size
+
+}
+
+function verify_size_estimates
+{
+ typeset options=$1
+ typeset file_size=$2
+ typeset refer_diff=$(echo "$refer_size - $estimate_size" | bc)
+ refer_diff=$(echo "$refer_diff / 1" | bc)
+ refer_diff=$(echo "$refer_diff" | nawk '{print ($1 < 0) ? ($1 * -1): $1'})
+ typeset file_diff=$(echo "$file_size - $estimate_size" | bc)
+ file_diff=$(echo "$file_diff / 1" | bc)
+ file_diff=$(echo "$file_diff" | nawk '{print ($1 < 0) ? ($1 * -1):$1'})
+ typeset expected_diff=$(cal_percentage $refer_size)
+
+ [[ -z $refer_diff && -z $file_diff && -z $expected_diff ]] && \
+ log_fail "zfs send $options failed"
+ [[ $refer_diff -le $expected_diff && \
+ $file_diff -le $expected_diff ]] || \
+ log_fail "zfs send $options gives wrong size estimates"
+}
+
+log_assert "Verify 'zfs send -nvP' generates valid stream estimates"
+log_onexit cleanup
+log_must set_tunable32 OVERRIDE_ESTIMATE_RECORDSIZE 0
+typeset -l block_count=0
+typeset -l block_size
+typeset -i PERCENT=1
+
+((block_count=1024*1024))
+
+# create dataset
+log_must zfs create $TESTPOOL/$TESTFS1
+
+# create multiple snapshot for the dataset with data
+for block_size in 64 128 256; do
+ log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS1/file$block_size \
+ bs=1M count=$block_size
+ log_must zfs snapshot $TESTPOOL/$TESTFS1@snap$block_size
+ log_must zfs bookmark $TESTPOOL/$TESTFS1@snap$block_size \
+ "$TESTPOOL/$TESTFS1#bmark$block_size"
+done
+
+full_snapshot="$TESTPOOL/$TESTFS1@snap64"
+incremental_snapshot="$TESTPOOL/$TESTFS1@snap256"
+full_bookmark="$TESTPOOL/$TESTFS1#bmark64"
+incremental_bookmark="$TESTPOOL/$TESTFS1#bmark256"
+
+full_size=$(zfs send $full_snapshot 2>&1 | wc -c)
+incremental_size=$(zfs send $incremental_snapshot 2>&1 | wc -c)
+incremental_send=$(zfs send -i $full_snapshot $incremental_snapshot 2>&1 | wc -c)
+
+log_note "verify zfs send -nv"
+options="-nv"
+refer_size=$(get_prop refer $full_snapshot)
+estimate_size=$(get_estimate_size $full_snapshot $options)
+log_must verify_size_estimates $options $full_size
+
+log_note "verify zfs send -Pnv"
+options="-Pnv"
+
+estimate_size=$(get_estimate_size $full_snapshot $options)
+log_must verify_size_estimates $options $full_size
+
+log_note "verify zfs send -nv for multiple snapshot send"
+options="-nv"
+refer_size=$(get_prop refer $incremental_snapshot)
+
+estimate_size=$(get_estimate_size $incremental_snapshot $options)
+log_must verify_size_estimates $options $incremental_size
+
+log_note "verify zfs send -vPn for multiple snapshot send"
+options="-vPn"
+
+estimate_size=$(get_estimate_size $incremental_snapshot $options)
+log_must verify_size_estimates $options $incremental_size
+
+log_note "verify zfs send -inv for incremental send"
+options="-nvi"
+refer_size=$(get_prop refer $incremental_snapshot)
+deduct_size=$(get_prop refer $full_snapshot)
+refer_size=$(echo "$refer_size - $deduct_size" | bc)
+
+estimate_size=$(get_estimate_size $incremental_snapshot $options $full_snapshot)
+log_must verify_size_estimates $options $incremental_send
+estimate_size=$(get_estimate_size $incremental_snapshot $options $full_bookmark)
+log_must verify_size_estimates $options $incremental_send
+
+log_note "verify zfs send -ivPn for incremental send"
+options="-vPni"
+
+estimate_size=$(get_estimate_size $incremental_snapshot $options $full_snapshot)
+log_must verify_size_estimates $options $incremental_send
+estimate_size=$(get_estimate_size $incremental_snapshot $options $full_bookmark)
+log_must verify_size_estimates $options $incremental_send
+
+log_must zfs destroy -r $TESTPOOL/$TESTFS1
+
+#setup_recursive_send
+datasets="$TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS1/$TESTFS2
+ $TESTPOOL/$TESTFS1/$TESTFS2/$TESTFS3"
+# create nested datasets
+log_must zfs create -p $TESTPOOL/$TESTFS1/$TESTFS2/$TESTFS3
+
+# verify dataset creation
+for ds in $datasets; do
+ datasetexists $ds || log_fail "Create $ds dataset fail."
+done
+for ds in $datasets; do
+ log_must dd if=/dev/urandom of=/$ds/file64 \
+ bs=1M count=64
+done
+
+# create recursive nested snapshot
+log_must zfs snapshot -r $TESTPOOL/$TESTFS1@snap64
+for ds in $datasets; do
+ datasetexists $ds@snap64 || log_fail "Create $ds@snap64 snapshot fail."
+done
+recursive_size=$(zfs send -R $full_snapshot 2>&1 | wc -c)
+log_note "verify zfs send -Rnv for recursive send"
+options="-Rnv"
+refer_size=$(get_prop refer $full_snapshot)
+refer_size=$(echo "$refer_size * 3" | bc)
+
+estimate_size=$(get_estimate_size $full_snapshot $options)
+log_must verify_size_estimates $options $recursive_size
+
+log_note "verify zfs send -RvPn for recursive send"
+options="-RvPn"
+estimate_size=$(get_estimate_size $full_snapshot $options)
+log_must verify_size_estimates $options $recursive_size
+
+log_pass "'zfs send' prints the correct size estimates using '-n' and '-P' options."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_007_pos.ksh
new file mode 100755
index 000000000000..da0aebe6b581
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_007_pos.ksh
@@ -0,0 +1,100 @@
+#!/bin/ksh
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2015, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+#
+# DESCRIPTION:
+# Verify 'zfs send' drills holes appropriately when files are replaced
+#
+# STRATEGY:
+# 1. Create dataset
+# 2. Write block 0 in a bunch of files
+# 3. Snapshot the dataset
+# 4. Remove all the files and rewrite some files with just block 1
+# 5. Snapshot the dataset
+# 6. Send both snapshots and receive them locally
+# 7. diff the received dataset and the old datasets.
+# 8. Repeat steps 1-7 above with pool that never had hole birth enabled.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ zfs destroy -rf $TESTPOOL/fs
+ zfs destroy -rf $TESTPOOL/recvfs
+ rm $streamfile
+ rm $vdev
+ zpool destroy tmp_pool
+}
+
+
+log_assert "Verify that 'zfs send' drills appropriate holes"
+log_onexit cleanup
+streamfile=$(mktemp $TESTDIR/file.XXXXXX)
+vdev=$(mktemp $TEST_BASE_DIR/file.XXXXXX)
+
+
+test_pool ()
+{
+ POOL=$1
+ log_must zfs create -o recordsize=512 $POOL/fs
+ mntpnt=$(get_prop mountpoint "$POOL/fs")
+ log_must dd if=/dev/urandom of=${mntpnt}/file bs=512 count=1 2>/dev/null
+ object=$(ls -i $mntpnt | awk '{print $1}')
+ log_must zfs snapshot $POOL/fs@a
+ while true; do
+ log_must find $mntpnt/ -type f -delete
+ sync
+ log_must mkfiles "$mntpnt/" 4000
+ sync
+ # check if we started reusing objects
+ object=$(ls -i $mntpnt | sort -n | awk -v object=$object \
+ '{if ($1 <= object) {exit 1}} END {print $1}')
+ if [[ $? -ne 0 ]]; then
+ break
+ fi
+ done
+ dd if=/dev/urandom of=${mntpnt}/$FILE bs=512 count=1 seek=1 2>/dev/null
+
+ log_must zfs snapshot $POOL/fs@b
+
+ log_must eval "zfs send $POOL/fs@a > $streamfile"
+ cat $streamfile | log_must zfs receive $POOL/recvfs
+
+ log_must eval "zfs send -i @a $POOL/fs@b > $streamfile"
+ cat $streamfile | log_must zfs receive $POOL/recvfs
+
+ recv_mntpnt=$(get_prop mountpoint "$POOL/recvfs")
+ log_must diff -r $mntpnt $recv_mntpnt
+ log_must zfs destroy -rf $POOL/fs
+ log_must zfs destroy -rf $POOL/recvfs
+}
+
+test_pool $TESTPOOL
+log_must truncate -s 1G $vdev
+log_must zpool create -o version=1 tmp_pool $vdev
+test_pool tmp_pool
+log_must zpool destroy tmp_pool
+log_must zpool create -d tmp_pool $vdev
+test_pool tmp_pool
+log_must zpool destroy tmp_pool
+
+log_pass "'zfs send' drills appropriate holes"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted.ksh
new file mode 100755
index 000000000000..490e146ba6f0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted.ksh
@@ -0,0 +1,76 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017, Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# ZFS should perform unencrypted sends of encrypted datasets, unless the '-p'
+# or '-R' options are specified.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 6. Create a child encryption root
+# 2. Snapshot the dataset
+# 3. Attempt a send
+# 4. Attempt a send with properties
+# 5. Attempt a replication send
+# 7. Unmount the parent and unload its key
+# 8. Attempt a send of the parent dataset
+# 9. Attempt a send of the child encryption root
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+}
+
+log_onexit cleanup
+
+log_assert "ZFS should perform unencrypted sends of encrypted datasets, " \
+ "unless the '-p' or '-R' options are specified"
+
+typeset passphrase="password"
+typeset passphrase1="password1"
+typeset snap="$TESTPOOL/$TESTFS1@snap"
+
+log_must eval "echo $passphrase | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS1"
+
+log_must eval "echo $passphrase1 | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS1/child"
+
+log_must zfs snapshot -r $snap
+
+log_must eval "zfs send $snap > /dev/null"
+log_mustnot eval "zfs send -p $snap > /dev/null"
+log_mustnot eval "zfs send -R $snap > /dev/null"
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+
+log_mustnot eval "zfs send $snap > /dev/null"
+log_must eval "zfs send $TESTPOOL/$TESTFS1/child@snap > /dev/null"
+
+log_pass "ZFS performs unencrypted sends of encrypted datasets, unless the" \
+ "'-p' or '-R' options are specified"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted_unloaded.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted_unloaded.ksh
new file mode 100755
index 000000000000..112ee1143d10
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted_unloaded.ksh
@@ -0,0 +1,59 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017, Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# ZFS should not perform unencrypted sends from encrypted datasets
+# with unloaded keys.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Snapshot the dataset
+# 3. Unload the dataset key
+# 4. Verify sending the stream fails
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+}
+
+log_onexit cleanup
+
+log_assert "ZFS should not perform unencrypted sends from encrypted datasets" \
+ "with unloaded keys."
+
+typeset passphrase="password"
+typeset snap="$TESTPOOL/$TESTFS1@snap"
+
+log_must eval "echo $passphrase | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS1"
+log_must zfs snapshot $snap
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+log_mustnot eval "zfs send $snap > /dev/null"
+
+log_pass "ZFS does not perform unencrypted sends from encrypted datasets" \
+ "with unloaded keys."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_raw.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_raw.ksh
new file mode 100755
index 000000000000..85cc7407e1a1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_raw.ksh
@@ -0,0 +1,79 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017, Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# ZFS should perform raw sends of datasets.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Snapshot the default dataset and the encrypted dataset
+# 3. Attempt a raw send of both datasets
+# 4. Attempt a raw send with properties of both datasets
+# 5. Attempt a raw replication send of both datasets
+# 6. Unmount and unload the encrypted dataset key
+# 7. Attempt a raw send of the encrypted dataset
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ snapexists $snap && \
+ log_must zfs destroy $snap
+
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+}
+
+log_onexit cleanup
+
+log_assert "ZFS should perform raw sends of datasets"
+
+typeset passphrase="password"
+typeset snap="$TESTPOOL/$TESTFS@snap"
+typeset snap1="$TESTPOOL/$TESTFS1@snap"
+
+log_must eval "echo $passphrase | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS1"
+
+log_must zfs snapshot $snap
+log_must zfs snapshot $snap1
+
+log_must eval "zfs send -w $snap > /dev/null"
+log_must eval "zfs send -w $snap1 > /dev/null"
+
+log_note "Verify ZFS can perform raw sends with properties"
+log_must eval "zfs send -wp $snap > /dev/null"
+log_must eval "zfs send -wp $snap1 > /dev/null"
+
+log_note "Verify ZFS can perform raw replication sends"
+log_must eval "zfs send -wR $snap > /dev/null"
+log_must eval "zfs send -wR $snap1 > /dev/null"
+
+log_note "Verify ZFS can perform a raw send of an encrypted datasets with" \
+ "its key unloaded"
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+log_must eval "zfs send -w $snap1 > /dev/null"
+
+log_pass "ZFS performs raw sends of datasets"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_sparse.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_sparse.ksh
new file mode 100755
index 000000000000..e37c3f28ae9d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_sparse.ksh
@@ -0,0 +1,83 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs send' should be able to send (big) sparse files correctly.
+#
+# STRATEGY:
+# 1. Create sparse files of various size
+# 2. Snapshot and send these sparse files
+# 3. Verify these files are received correctly and we don't trigger any issue
+# like the one described in https://github.com/zfsonlinux/zfs/pull/6760
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $SENDFS && log_must zfs destroy -r $SENDFS
+ datasetexists $RECVFS && log_must zfs destroy -r $RECVFS
+}
+
+#
+# Write 1 random byte at $offset of "source" file in $sendfs dataset
+# Snapshot and send $sendfs dataset to $recvfs
+# Compare the received file with its source
+#
+function write_compare_files # <sendfs> <recvfs> <offset>
+{
+ typeset sendfs="$1"
+ typeset recvfs="$2"
+ typeset offset="$3"
+
+ # create source filesystem
+ log_must zfs create $sendfs
+ # write sparse file
+ sendfile="$(get_prop mountpoint $sendfs)/data.bin"
+ log_must dd if=/dev/urandom of=$sendfile bs=1 count=1 seek=$offset
+ # send/receive the file
+ log_must zfs snapshot $sendfs@snap
+ log_must eval "zfs send $sendfs@snap | zfs receive $recvfs"
+ # compare sparse files
+ recvfile="$(get_prop mountpoint $recvfs)/data.bin"
+ log_must cmp $sendfile $recvfile $offset $offset
+ sendsz=$(stat_size $sendfile)
+ recvsz=$(stat_size $recvfile)
+ if [[ $sendsz -ne $recvsz ]]; then
+ log_fail "$sendfile ($sendsz) and $recvfile ($recvsz) differ."
+ fi
+ # cleanup
+ log_must zfs destroy -r $sendfs
+ log_must zfs destroy -r $recvfs
+}
+
+log_assert "'zfs send' should be able to send (big) sparse files correctly."
+log_onexit cleanup
+
+SENDFS="$TESTPOOL/sendfs"
+RECVFS="$TESTPOOL/recvfs"
+OFF_T_MAX="$(echo '2 ^ 40 * 8 - 1' | bc)"
+
+for i in {1..60}; do
+ offset=$(echo "2 ^ $i" | bc)
+ [[ is_32bit ]] && [[ $offset -ge $OFF_T_MAX ]] && continue;
+ write_compare_files $SENDFS $RECVFS $offset
+done
+
+log_pass "'zfs send' sends (big) sparse files correctly."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_set/Makefile.am
new file mode 100644
index 000000000000..f7362ff2556f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/Makefile.am
@@ -0,0 +1,35 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_set
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ cache_001_pos.ksh \
+ cache_002_neg.ksh \
+ canmount_001_pos.ksh \
+ canmount_002_pos.ksh \
+ canmount_003_pos.ksh \
+ canmount_004_pos.ksh \
+ checksum_001_pos.ksh \
+ compression_001_pos.ksh \
+ mountpoint_001_pos.ksh \
+ mountpoint_002_pos.ksh \
+ mountpoint_003_pos.ksh \
+ onoffs_001_pos.ksh \
+ property_alias_001_pos.ksh \
+ readonly_001_pos.ksh \
+ reservation_001_neg.ksh \
+ ro_props_001_pos.ksh \
+ share_mount_001_neg.ksh \
+ snapdir_001_pos.ksh \
+ user_property_001_pos.ksh \
+ user_property_002_pos.ksh \
+ user_property_003_neg.ksh \
+ user_property_004_pos.ksh \
+ version_001_neg.ksh \
+ zfs_set_001_neg.ksh \
+ zfs_set_002_neg.ksh \
+ zfs_set_003_neg.ksh \
+ zfs_set_keylocation.ksh \
+ zfs_set_feature_activation.ksh
+
+dist_pkgdata_DATA = \
+ zfs_set_common.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/cache_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/cache_001_pos.ksh
new file mode 100755
index 000000000000..bffc47f817dd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/cache_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Setting a valid primarycache and secondarycache on file system or volume.
+# It should be successful.
+#
+# STRATEGY:
+# 1. Create pool, then create filesystem & volume within it.
+# 2. Setting valid cache value, it should be successful.
+#
+
+verify_runnable "both"
+
+set -A dataset "$TESTPOOL" "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTVOL"
+set -A values "none" "all" "metadata"
+
+log_assert "Setting a valid {primary|secondary}cache on file system and volume, " \
+ "It should be successful."
+
+typeset -i i=0
+typeset -i j=0
+for propname in "primarycache" "secondarycache"
+do
+ while (( i < ${#dataset[@]} )); do
+ j=0
+ while (( j < ${#values[@]} )); do
+ set_n_check_prop "${values[j]}" "$propname" "${dataset[i]}"
+ (( j += 1 ))
+ done
+ (( i += 1 ))
+ done
+done
+
+log_pass "Setting a valid {primary|secondary}cache on file system or volume pass."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/cache_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/cache_002_neg.ksh
new file mode 100755
index 000000000000..caad211bcf65
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/cache_002_neg.ksh
@@ -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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Setting invalid primarycache and secondarycache on file system or volume.
+# It should fail.
+#
+# STRATEGY:
+# 1. Create pool, then create filesystem & volume within it.
+# 2. Setting invalid {primary|secondary}cache value, it should fail.
+#
+
+verify_runnable "both"
+
+set -A dataset "$TESTPOOL" "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTVOL"
+set -A values "12345" "null" "not_existed" "abcd1234"
+
+log_assert "Setting invalid {primary|secondary}cache on fs and volume, " \
+ "It should fail."
+
+typeset -i i=0
+typeset -i j=0
+for propname in "primarycache" "secondarycache"
+do
+ while (( i < ${#dataset[@]} )); do
+ j=0
+ while (( j < ${#values[@]} )); do
+ log_mustnot zfs set $propname=${values[j]} ${dataset[i]}
+ (( j += 1 ))
+ done
+ (( i += 1 ))
+ done
+done
+
+log_pass "Setting invalid {primary|secondary}cache on fs or volume fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_001_pos.ksh
new file mode 100755
index 000000000000..dd3397f01579
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_001_pos.ksh
@@ -0,0 +1,123 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Setting valid canmount to filesystem, it is successful.
+# Whatever is set to volume or snapshot, it is failed.
+# 'zfs set canmount=on|off <fs>'
+#
+# STRATEGY:
+# 1. Setup a pool and create fs, volume, snapshot clone within it.
+# 2. Loop all the valid mountpoint value.
+# 3. Check the return value.
+#
+
+verify_runnable "both"
+
+set -A dataset_pos \
+ "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTCTR" "$TESTPOOL/$TESTCLONE"
+
+if is_global_zone ; then
+ set -A dataset_neg \
+ "$TESTPOOL/$TESTVOL" "$TESTPOOL/$TESTFS@$TESTSNAP" \
+ "$TESTPOOL/$TESTVOL@$TESTSNAP" "$TESTPOOL/$TESTCLONE1"
+else
+ set -A dataset_neg \
+ "$TESTPOOL/$TESTFS@$TESTSNAP" "$TESTPOOL/$TESTVOL@$TESTSNAP"
+fi
+
+
+set -A values "on" "off"
+
+function cleanup
+{
+ if snapexists $TESTPOOL/$TESTFS@$TESTSNAP ; then
+ log_must zfs destroy -R $TESTPOOL/$TESTFS@$TESTSNAP
+ fi
+ if snapexists $TESTPOOL/$TESTVOL@$TESTSNAP ; then
+ log_must zfs destroy -R $TESTPOOL/$TESTVOL@$TESTSNAP
+ fi
+
+ [[ -n $old_ctr_canmount ]] && \
+ log_must zfs set canmount=$old_ctr_canmount $TESTPOOL/$TESTCTR
+ [[ -n $old_fs_canmount ]] && \
+ log_must zfs set canmount=$old_fs_canmount $TESTPOOL/$TESTFS
+
+ zfs unmount -a > /dev/null 2>&1
+ log_must zfs mount -a
+}
+
+log_assert "Setting a valid property of canmount to file system, it must be successful."
+log_onexit cleanup
+
+typeset old_fs_canmount="" old_ctr_canmount=""
+
+old_fs_canmount=$(get_prop canmount $TESTPOOL/$TESTFS)
+[[ $? != 0 ]] && \
+ log_fail "Get the $TESTPOOL/$TESTFS canmount error."
+old_ctr_canmount=$(get_prop canmount $TESTPOOL/$TESTCTR)
+[[ $? != 0 ]] && \
+ log_fail "Get the $TESTPOOL/$TESTCTR canmount error."
+
+log_must zfs snapshot $TESTPOOL/$TESTFS@$TESTSNAP
+log_must zfs snapshot $TESTPOOL/$TESTVOL@$TESTSNAP
+log_must zfs clone $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTCLONE
+log_must zfs clone $TESTPOOL/$TESTVOL@$TESTSNAP $TESTPOOL/$TESTCLONE1
+
+for dataset in "${dataset_pos[@]}" ; do
+ for value in "${values[@]}" ; do
+ set_n_check_prop "$value" "canmount" "$dataset"
+ if [[ $value == "off" ]]; then
+ log_mustnot ismounted $dataset
+ log_mustnot zfs mount $dataset
+ log_mustnot ismounted $dataset
+ else
+ if ! ismounted $dataset ; then
+ log_must zfs mount $dataset
+ fi
+ log_must ismounted $dataset
+ fi
+ done
+done
+
+for dataset in "${dataset_neg[@]}" ; do
+ for value in "${values[@]}" ; do
+ set_n_check_prop "$value" "canmount" \
+ "$dataset" "false"
+ log_mustnot ismounted $dataset
+ done
+done
+
+log_pass "Setting canmount to filesystem pass."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_002_pos.ksh
new file mode 100755
index 000000000000..1aeee44e044e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_002_pos.ksh
@@ -0,0 +1,161 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Setting valid canmount to filesystem, it is successful.
+# Whatever is set to volume or snapshot, it is failed.
+# 'zfs set canmount=noauto <fs>'
+#
+# STRATEGY:
+# 1. Setup a pool and create fs, volume, snapshot clone within it.
+# 2. Set canmount=noauto for each dataset and check the return value
+# and check if it still can be mounted by mount -a or shared by
+# share -a
+# 3. mount each dataset(except volume) to see if it can be mounted.
+# 4. verify that a mounted dataset can be shared by share -a.
+#
+
+verify_runnable "both"
+
+set -A dataset_pos \
+ "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTCTR" "$TESTPOOL/$TESTCLONE"
+
+if is_global_zone ; then
+ set -A dataset_neg \
+ "$TESTPOOL/$TESTVOL" "$TESTPOOL/$TESTFS@$TESTSNAP" \
+ "$TESTPOOL/$TESTVOL@$TESTSNAP" "$TESTPOOL/$TESTCLONE1"
+else
+ set -A dataset_neg \
+ "$TESTPOOL/$TESTFS@$TESTSNAP" "$TESTPOOL/$TESTVOL@$TESTSNAP"
+fi
+
+function cleanup
+{
+ i=0
+ while (( i < ${#dataset_pos[*]} )); do
+ ds=${dataset_pos[i]}
+ if datasetexists $ds; then
+ log_must zfs set mountpoint=${old_mnt[i]} $ds
+ log_must zfs set canmount=${old_canmount[i]} $ds
+ fi
+ (( i = i + 1 ))
+ done
+
+ ds=$TESTPOOL/$TESTCLONE
+ if datasetexists $ds; then
+ mntp=$(get_prop mountpoint $ds)
+ log_must zfs destroy $ds
+ if [[ -d $mntp ]]; then
+ rm -fr $mntp
+ fi
+ fi
+
+ if snapexists $TESTPOOL/$TESTFS@$TESTSNAP ; then
+ log_must zfs destroy -R $TESTPOOL/$TESTFS@$TESTSNAP
+ fi
+ if snapexists $TESTPOOL/$TESTVOL@$TESTSNAP ; then
+ log_must zfs destroy -R $TESTPOOL/$TESTVOL@$TESTSNAP
+ fi
+
+ zfs unmount -a > /dev/null 2>&1
+ log_must zfs mount -a
+
+ if [[ -d $tmpmnt ]]; then
+ rm -fr $tmpmnt
+ fi
+}
+
+log_assert "Setting canmount=noauto to file system, it must be successful."
+log_onexit cleanup
+
+set -A old_mnt
+set -A old_canmount
+set -A old_sharenfs
+typeset tmpmnt=/tmpmount$$
+typeset ds
+
+log_must zfs snapshot $TESTPOOL/$TESTFS@$TESTSNAP
+log_must zfs snapshot $TESTPOOL/$TESTVOL@$TESTSNAP
+log_must zfs clone $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTCLONE
+log_must zfs clone $TESTPOOL/$TESTVOL@$TESTSNAP $TESTPOOL/$TESTCLONE1
+
+typeset -i i=0
+while (( i < ${#dataset_pos[*]} )); do
+ ds=${dataset_pos[i]}
+ old_mnt[i]=$(get_prop mountpoint $ds)
+ old_canmount[i]=$(get_prop canmount $ds)
+ old_sharenfs[i]=$(get_prop sharenfs $ds)
+ (( i = i + 1 ))
+done
+
+i=0
+while (( i < ${#dataset_pos[*]} )) ; do
+ dataset=${dataset_pos[i]}
+ set_n_check_prop "noauto" "canmount" "$dataset"
+ log_must zfs set mountpoint=$tmpmnt $dataset
+ log_must zfs set sharenfs=on $dataset
+ if ismounted $dataset; then
+ zfs unmount -a > /dev/null 2>&1
+ log_must mounted $dataset
+ log_must zfs unmount $dataset
+ log_must unmounted $dataset
+ log_must zfs mount -a
+ log_must unmounted $dataset
+ log_must zfs share -a
+ log_mustnot is_exported $tmpmnt
+ else
+ log_must zfs mount -a
+ log_must unmounted $dataset
+ zfs unmount -a > /dev/null 2>&1
+ log_must unmounted $dataset
+ fi
+
+ log_must zfs mount $dataset
+ log_must mounted $dataset
+ log_must zfs share -a
+ log_must is_exported $tmpmnt
+
+ log_must zfs set sharenfs="${old_sharenfs[i]}" $dataset
+ log_must zfs set canmount="${old_canmount[i]}" $dataset
+ log_must zfs set mountpoint="${old_mnt[i]}" $dataset
+ (( i = i + 1 ))
+done
+
+for dataset in "${dataset_neg[@]}" ; do
+ set_n_check_prop "noauto" "canmount" "$dataset" "false"
+ log_mustnot ismounted $dataset
+done
+
+log_pass "Setting canmount=noauto to filesystem pass."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_003_pos.ksh
new file mode 100755
index 000000000000..a11cfb40884b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_003_pos.ksh
@@ -0,0 +1,111 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# While canmount=noauto and the dataset is mounted,
+# zfs must not attempt to unmount it.
+#
+# STRATEGY:
+# 1. Setup a pool and create fs, volume, snapshot clone within it.
+# 2. Set canmount=noauto for each dataset and check the return value
+# and check if it still can not be unmounted when the dataset is mounted
+#
+
+verify_runnable "both"
+
+set -A dataset_pos "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTCLONE"
+
+function cleanup
+{
+ i=0
+ cd $pwd
+ while (( i < ${#dataset_pos[*]} )); do
+ ds=${dataset_pos[i]}
+ if datasetexists $ds; then
+ log_must zfs set mountpoint=${old_mnt[i]} $ds
+ log_must zfs set canmount=${old_canmount[i]} $ds
+ fi
+ (( i = i + 1 ))
+ done
+
+ ds=$TESTPOOL/$TESTCLONE
+ if datasetexists $ds; then
+ mntp=$(get_prop mountpoint $ds)
+ log_must zfs destroy $ds
+ if [[ -d $mntp ]]; then
+ log_must rm -fr $mntp
+ fi
+ fi
+
+ if snapexists $TESTPOOL/$TESTFS@$TESTSNAP ; then
+ log_must zfs destroy -R $TESTPOOL/$TESTFS@$TESTSNAP
+ fi
+
+ zfs unmount -a > /dev/null 2>&1
+ log_must zfs mount -a
+}
+
+log_assert "While canmount=noauto and the dataset is mounted,"\
+ " zfs must not attempt to unmount it"
+log_onexit cleanup
+
+set -A old_mnt
+set -A old_canmount
+typeset ds
+typeset pwd=$PWD
+
+log_must zfs snapshot $TESTPOOL/$TESTFS@$TESTSNAP
+log_must zfs clone $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTCLONE
+
+typeset -i i=0
+while (( i < ${#dataset_pos[*]} )); do
+ ds=${dataset_pos[i]}
+ old_mnt[i]=$(get_prop mountpoint $ds)
+ old_canmount[i]=$(get_prop canmount $ds)
+ (( i = i + 1 ))
+done
+
+i=0
+while (( i < ${#dataset_pos[*]} )) ; do
+ dataset=${dataset_pos[i]}
+ if ismounted $dataset; then
+ log_must cd ${old_mnt[i]}
+ set_n_check_prop "noauto" "canmount" "$dataset"
+ log_must mounted $dataset
+ fi
+ (( i = i + 1 ))
+done
+
+log_pass "Setting canmount=noauto to filesystem while dataset busy pass."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_004_pos.ksh
new file mode 100755
index 000000000000..e75114efdec0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/canmount_004_pos.ksh
@@ -0,0 +1,96 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify canmount=noauto work fine when setting sharenfs or sharesmb.
+#
+# STRATEGY:
+# 1. Create a fs canmount=noauto.
+# 2. Set sharenfs or sharesmb.
+# 3. Verify the fs is umounted.
+#
+
+verify_runnable "global"
+
+# properties
+set -A sharenfs_prop "off" "on" "ro"
+set -A sharesmb_prop "off" "on"
+
+function cleanup
+{
+ log_must zfs destroy -rR $CS_FS
+}
+
+function assert_unmounted
+{
+ mnted=$(get_prop mounted $CS_FS)
+ if [[ "$mnted" == "yes" ]]; then
+ canmnt=$(get_prop canmount $CS_FS)
+ shnfs=$(get_prop sharenfs $CS_FS)
+ shsmb=$(get_prop sharesmb $CS_FS)
+ mntpt=$(get_prop mountpoint $CS_FS)
+ log_fail "$CS_FS should be unmounted" \
+ "[canmount=$canmnt,sharenfs=$shnfs,sharesmb=$shsmb,mountpoint=$mntpt]."
+ fi
+}
+
+log_assert "Verify canmount=noauto work fine when setting sharenfs or sharesmb."
+log_onexit cleanup
+
+CS_FS=$TESTPOOL/$TESTFS/cs_fs.$$
+oldmpt=$TESTDIR/old_cs_fs.$$
+newmpt=$TESTDIR/new_cs_fs.$$
+
+log_must zfs create -o canmount=noauto -o mountpoint=$oldmpt $CS_FS
+assert_unmounted
+
+for n in ${sharenfs_prop[@]}; do
+ log_must zfs set sharenfs="$n" $CS_FS
+ assert_unmounted
+ for s in ${sharesmb_prop[@]}; do
+ log_must zfs set sharesmb="$s" $CS_FS
+ assert_unmounted
+
+ mntpt=$(get_prop mountpoint $CS_FS)
+ if [[ "$mntpt" == "$oldmpt" ]]; then
+ log_must zfs set mountpoint="$newmpt" $CS_FS
+ else
+ log_must zfs set mountpoint="$oldmpt" $CS_FS
+ fi
+ assert_unmounted
+ done
+done
+
+log_pass "Verify canmount=noauto work fine when setting sharenfs or sharesmb."
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/checksum_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/checksum_001_pos.ksh
new file mode 100755
index 000000000000..f30d0052240e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/checksum_001_pos.ksh
@@ -0,0 +1,68 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Setting a valid checksum on a pool, file system, volume, it should be
+# successful.
+#
+# STRATEGY:
+# 1. Create pool, then create filesystem and volume within it.
+# 2. Setting different valid checksum to each dataset.
+# 3. Check the return value and make sure it is 0.
+#
+
+verify_runnable "both"
+
+set -A dataset "$TESTPOOL" "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTVOL"
+set -A values "on" "off" "fletcher2" "fletcher4" "sha256" "sha512" "skein" "noparity"
+if is_linux; then
+ values+=("edonr")
+fi
+
+log_assert "Setting a valid checksum on a file system, volume," \
+ "it should be successful."
+
+typeset -i i=0
+typeset -i j=0
+while (( i < ${#dataset[@]} )); do
+ j=0
+ while (( j < ${#values[@]} )); do
+ set_n_check_prop "${values[j]}" "checksum" "${dataset[i]}"
+ (( j += 1 ))
+ done
+ (( i += 1 ))
+done
+
+log_pass "Setting a valid checksum on a file system, volume pass."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/cleanup.ksh
new file mode 100755
index 000000000000..fad025cac246
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_container_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/compression_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/compression_001_pos.ksh
new file mode 100755
index 000000000000..06da5f2f3ce8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/compression_001_pos.ksh
@@ -0,0 +1,64 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/properties.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Setting a valid compression on file system or volume.
+# It should be successful.
+#
+# STRATEGY:
+# 1. Create pool, then create filesystem & volume within it.
+# 2. Setting valid value, it should be successful.
+#
+
+verify_runnable "both"
+
+set -A dataset "$TESTPOOL" "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTVOL"
+set -A values "${compress_prop_vals[@]}"
+
+log_assert "Setting a valid compression on file system and volume, " \
+ "It should be successful."
+
+typeset -i i=0
+typeset -i j=0
+for propname in "compression" "compress"
+do
+ while (( i < ${#dataset[@]} )); do
+ j=0
+ while (( j < ${#values[@]} )); do
+ set_n_check_prop "${values[j]}" "$propname" "${dataset[i]}"
+ (( j += 1 ))
+ done
+ (( i += 1 ))
+ done
+done
+
+log_pass "Setting a valid compression on file system or volume pass."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_001_pos.ksh
new file mode 100755
index 000000000000..1255ae5f5666
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_001_pos.ksh
@@ -0,0 +1,100 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Setting valid mountpoint to filesystem, it is successful.
+# Whatever is set to volume, it is failed.
+# 'zfs set mountpoint=<path>|legacy|none <fs|ctr|vol>'
+#
+# STRATEGY:
+# 1. Setup a pool and create fs, ctr within it.
+# 2. Loop all the valid mountpoint value.
+# 3. Check the return value.
+#
+
+verify_runnable "both"
+
+export TESTDIR_NOTEXISTING=${TEST_BASE_DIR%%/}/testdir_notexisting$$
+
+if is_global_zone ; then
+ set -A dataset \
+ "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTCTR" "$TESTPOOL/$TESTVOL"
+else
+ set -A dataset "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTCTR"
+fi
+
+set -A values "$TESTDIR2" "legacy" "none" "$TESTDIR_NOTEXISTING"
+
+function cleanup
+{
+ log_must zfs set mountpoint=$old_ctr_mpt $TESTPOOL/$TESTCTR
+ log_must zfs set mountpoint=$old_fs_mpt $TESTPOOL/$TESTFS
+ [[ -d $TESTDIR2 ]] && log_must rm -r $TESTDIR2
+ [[ -d $TESTDIR_NOTEXISTING ]] && log_must rm -r $TESTDIR_NOTEXISTING
+}
+
+log_assert "Setting a valid mountpoint to file system, it must be successful."
+log_onexit cleanup
+
+old_fs_mpt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+[[ $? != 0 ]] && \
+ log_fail "Get the $TESTPOOL/$TESTFS mountpoint error."
+old_ctr_mpt=$(get_prop mountpoint $TESTPOOL/$TESTCTR)
+[[ $? != 0 ]] && \
+ log_fail "Get the $TESTPOOL/$TESTCTR mountpoint error."
+
+if [[ ! -d $TESTDIR2 ]]; then
+ log_must mkdir $TESTDIR2
+fi
+
+typeset -i i=0
+typeset -i j=0
+while (( i < ${#dataset[@]} )); do
+ j=0
+ while (( j < ${#values[@]} )); do
+ if [[ ${dataset[i]} == "$TESTPOOL/$TESTVOL" ]]; then
+ set_n_check_prop "${values[j]}" "mountpoint" \
+ "${dataset[i]}" "false"
+ else
+ set_n_check_prop "${values[j]}" "mountpoint" \
+ "${dataset[i]}"
+ fi
+ (( j += 1 ))
+ done
+ cleanup
+ (( i += 1 ))
+done
+
+log_pass "Setting mountpoint to filesystem pass."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_002_pos.ksh
new file mode 100755
index 000000000000..48580cafdb31
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_002_pos.ksh
@@ -0,0 +1,98 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# If ZFS is currently managing the file system but it is currently unmounted,
+# and the mountpoint property is changed, the file system remains unmounted.
+#
+# STRATEGY:
+# 1. Setup a pool and create fs, ctr within it.
+# 2. Unmount that dataset
+# 2. Change the mountpoint to the valid mountpoint value.
+# 3. Check the file system remains unmounted.
+#
+
+verify_runnable "both"
+
+export TESTDIR_NOTEXISTING=${TEST_BASE_DIR%%/}/testdir_notexisting$$
+
+set -A dataset "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTCTR"
+
+set -A values "$TESTDIR2" "$TESTDIR_NOTEXISTING"
+
+function cleanup
+{
+ log_must zfs set mountpoint=$old_ctr_mpt $TESTPOOL/$TESTCTR
+ log_must zfs set mountpoint=$old_fs_mpt $TESTPOOL/$TESTFS
+ log_must zfs mount -a
+ [[ -d $TESTDIR2 ]] && log_must rm -r $TESTDIR2
+ [[ -d $TESTDIR_NOTEXISTING ]] && log_must rm -r $TESTDIR_NOTEXISTING
+}
+
+log_assert "Setting a valid mountpoint for an unmounted file system, \
+ it remains unmounted."
+log_onexit cleanup
+
+old_fs_mpt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+[[ $? != 0 ]] && \
+ log_fail "Unable to get the mountpoint property for $TESTPOOL/$TESTFS"
+old_ctr_mpt=$(get_prop mountpoint $TESTPOOL/$TESTCTR)
+[[ $? != 0 ]] && \
+ log_fail "Unable to get the mountpoint property for $TESTPOOL/$TESTCTR"
+
+if [[ ! -d $TESTDIR2 ]]; then
+ log_must mkdir $TESTDIR2
+fi
+
+typeset -i i=0
+typeset -i j=0
+while (( i < ${#dataset[@]} )); do
+ j=0
+ if ismounted ${dataset[i]} ; then
+ log_must zfs unmount ${dataset[i]}
+ fi
+ log_mustnot ismounted ${dataset[i]}
+ while (( j < ${#values[@]} )); do
+ set_n_check_prop "${values[j]}" "mountpoint" \
+ "${dataset[i]}"
+ log_mustnot ismounted ${dataset[i]}
+ (( j += 1 ))
+ done
+ cleanup
+ (( i += 1 ))
+done
+
+log_pass "Setting a valid mountpoint for an unmounted file system, \
+ it remains unmounted."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_003_pos.ksh
new file mode 100755
index 000000000000..4d86100c03ef
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/mountpoint_003_pos.ksh
@@ -0,0 +1,145 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify FSType-specific option works well with legacy mount.
+#
+# STRATEGY:
+# 1. Set up FSType-specific options and expected keywords array.
+# 2. Create a test ZFS file system and set mountpoint=legacy.
+# 3. Mount ZFS test filesystem with specific options.
+# 4. Verify the filesystem was mounted with specific option.
+# 5. Loop check all the options.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ ismounted $tmpmnt && log_must umount $tmpmnt
+ [[ -d $tmpmnt ]] && log_must rm -rf $tmpmnt
+ [[ -n $oldmpt ]] && log_must zfs set mountpoint=$oldmpt $testfs
+ ! ismounted $oldmpt && log_must zfs mount $testfs
+}
+
+log_assert "With legacy mount, FSType-specific option works well."
+log_onexit cleanup
+
+#
+# /mnt on pool/fs read/write/setuid/devices/noexec/xattr/atime/dev=2d9009e
+#
+# FSType- FSType-
+# specific Keyword specific Keyword
+# option option
+#
+if is_linux; then
+ set -A args \
+ "nodev" "dev" \
+ "noexec" "exec" \
+ "ro" "rw" \
+ "nosuid" "suid" \
+ "xattr" "noxattr" \
+ "atime" "noatime"
+
+ # Only older kernels support non-blocking mandatory locks
+ if [[ $(linux_version) -lt $(linux_version "4.4") ]]; then
+ args+=("mand" "nomand")
+ fi
+elif is_freebsd; then
+ # 'xattr' and 'devices' are not supported on FreeBSD
+ # Perhaps more options need to be added.
+ set -A args \
+ "noexec" "exec" \
+ "ro" "rw" \
+ "nosuid" "suid" \
+ "atime" "noatime"
+else
+ set -A args \
+ "devices" "/devices/" "nodevices" "/nodevices/" \
+ "exec" "/exec/" "noexec" "/noexec/" \
+ "nbmand" "/nbmand/" "nonbmand" "/nonbmand/" \
+ "ro" "read only" "rw" "read/write" \
+ "setuid" "/setuid/" "nosetuid" "/nosetuid/" \
+ "xattr" "/xattr/" "noxattr" "/noxattr/" \
+ "atime" "/atime/" "noatime" "/noatime/"
+fi
+
+tmpmnt=/tmpmnt.$$
+[[ -d $tmpmnt ]] && rm -rf $tmpmnt
+testfs=$TESTPOOL/$TESTFS
+log_must mkdir $tmpmnt
+oldmpt=$(get_prop mountpoint $testfs)
+log_must zfs set mountpoint=legacy $testfs
+
+typeset i=0
+while ((i < ${#args[@]})); do
+ if is_linux || is_freebsd; then
+ log_must mount -t zfs -o ${args[$i]} $testfs $tmpmnt
+
+ msg=$(mount | grep "$tmpmnt ")
+
+ echo $msg | grep "${args[((i))]}" > /dev/null 2>&1
+ if (($? != 0)) ; then
+ echo $msg | grep "${args[((i-1))]}" > /dev/null 2>&1
+ if (($? == 0)) ; then
+ log_fail "Expected option: ${args[((i))]} \n" \
+ "Real option: $msg"
+ fi
+ fi
+
+ log_must umount $tmpmnt
+ ((i += 1))
+ else
+ log_must mount -F zfs -o ${args[$i]} $testfs $tmpmnt
+
+ msg=$(mount | grep "^$tmpmnt ")
+
+ # In LZ, a user with all zone privileges can never "devices"
+ if ! is_global_zone && [[ ${args[$i]} == devices ]] ; then
+ args[((i+1))]="/nodevices/"
+ fi
+
+ echo $msg | grep "${args[((i+1))]}" > /dev/null 2>&1
+ if (($? != 0)) ; then
+ log_fail "Expected option: ${args[((i+1))]} \n" \
+ "Real option: $msg"
+ fi
+
+
+ log_must umount $tmpmnt
+ ((i += 2))
+ fi
+done
+
+log_pass "With legacy mount, FSType-specific option works well passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/onoffs_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/onoffs_001_pos.ksh
new file mode 100755
index 000000000000..7ba6d7fb659d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/onoffs_001_pos.ksh
@@ -0,0 +1,108 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Setting a valid value to atime, readonly, setuid or zoned on file
+# system or volume. It should be successful.
+#
+# STRATEGY:
+# 1. Create pool and filesystem & volume within it.
+# 2. Setting valid value, it should be successful.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs mount -a
+}
+
+log_onexit cleanup
+
+set -A props "atime" "readonly" "setuid"
+if is_freebsd; then
+ props+=("jailed")
+else
+ props+=("zoned")
+fi
+set -A values "on" "off"
+
+if is_global_zone ; then
+ set -A dataset "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTCTR" "$TESTPOOL/$TESTVOL"
+else
+ set -A dataset "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTCTR"
+fi
+
+log_assert "Setting a valid value to atime, readonly, setuid or zoned on file" \
+ "system or volume. It should be successful."
+
+typeset -i i=0
+typeset -i j=0
+typeset -i k=0
+while (( i < ${#dataset[@]} )); do
+ j=0
+ while (( j < ${#props[@]} )); do
+ k=0
+ while (( k < ${#values[@]} )); do
+ if [[ ${dataset[i]} == "$TESTPOOL/$TESTVOL" && \
+ ${props[j]} != "readonly" ]]
+ then
+ set_n_check_prop "${values[k]}" "${props[j]}" \
+ "${dataset[i]}" "false"
+ elif [[ ${props[j]} == "zoned" ]] ; then
+ if is_global_zone ; then
+ set_n_check_prop \
+ "${values[k]}" "${props[j]}" \
+ "${dataset[i]}"
+ else
+ set_n_check_prop \
+ "${values[k]}" "${props[j]}" \
+ "${dataset[i]}" "false"
+ fi
+
+ else
+ set_n_check_prop "${values[k]}" "${props[j]}" \
+ "${dataset[i]}"
+ fi
+
+ (( k += 1 ))
+ done
+ (( j += 1 ))
+ done
+ (( i += 1 ))
+done
+
+log_pass "Setting a valid value to atime, readonly, setuid or zoned on file" \
+ "system or volume pass."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/property_alias_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/property_alias_001_pos.ksh
new file mode 100755
index 000000000000..f1befe60c373
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/property_alias_001_pos.ksh
@@ -0,0 +1,142 @@
+#!/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) 2009, Sun Microsystems Inc. All rights reserved.
+# Copyright (c) 2016, 2017, Delphix. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/properties.shlib
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify the properties with aliases also work with those aliases
+#
+# STRATEGY:
+# 1. Create pool, then create filesystem & volume within it.
+# 2. Set or retrieve property via alias with datasets.
+# 3. Verify the result should be successful.
+#
+
+verify_runnable "both"
+
+function set_and_check #<dataset><set_prop_name><set_value><check_prop_name>
+{
+ typeset ds=$1
+ typeset setprop=$2
+ typeset setval=$3
+ typeset chkprop=$4
+ typeset getval
+
+ log_must zfs set $setprop=$setval $ds
+ if [[ $setval == "gzip-6" ]]; then
+ setval="gzip"
+ fi
+ getval=$(get_prop $chkprop $ds)
+
+ case $setprop in
+ reservation|reserv )
+ if [[ $setval == "none" ]]; then
+ [[ $getval != "0" ]] && \
+ log_fail "Setting the property $setprop" \
+ "with value $setval fails."
+ elif [[ $getval != $setval ]]; then
+ log_fail "Setting the property $setprop with" \
+ "with $setval fails."
+ fi
+ ;;
+ * )
+ [[ $getval != $setval ]] && \
+ log_fail "Setting the property $setprop with value \
+ $setval fails."
+ ;;
+ esac
+}
+
+log_assert "Properties with aliases also work with those aliases."
+
+set -A ro_prop "available" "avail" "referenced" "refer"
+set -A rw_prop "readonly" "rdonly" "compression" "compress" "reservation" "reserv"
+set -A chk_prop "rdonly" "readonly" "compress" "compression" "reserv" "reservation"
+set -A size "512" "1024" "2048" "4096" "8192" "16384" "32768" "65536" "131072"
+
+pool=$TESTPOOL
+fs=$TESTPOOL/$TESTFS
+vol=$TESTPOOL/$TESTVOL
+typeset -l avail_space=$(get_prop avail $pool)
+typeset -l reservsize
+typeset -i i=0
+
+for ds in $pool $fs $vol; do
+ for propname in ${ro_prop[*]}; do
+ zfs get -pH -o value $propname $ds >/dev/null 2>&1
+ (( $? != 0 )) && \
+ log_fail "Get the property $proname of $ds failed."
+ done
+ i=0
+ while (( i < ${#rw_prop[*]} )); do
+ case ${rw_prop[i]} in
+ readonly|rdonly )
+ for val in "on" "off"; do
+ set_and_check $ds ${rw_prop[i]} $val ${chk_prop[i]}
+ done
+ ;;
+ compression|compress )
+ for val in "${compress_prop_vals[@]}"; do
+ set_and_check $ds ${rw_prop[i]} $val ${chk_prop[i]}
+ done
+ ;;
+ reservation|reserv )
+ (( reservsize = $avail_space % (( $RANDOM + 1 )) ))
+ for val in "0" "$reservsize" "none"; do
+ set_and_check $ds ${rw_prop[i]} $val ${chk_prop[i]}
+ done
+ ;;
+ esac
+
+ (( i = i + 1 ))
+ done
+ if [[ $ds == $vol ]]; then
+ for propname in "volblocksize" "volblock" ; do
+ zfs get -pH -o value $propname $ds >/dev/null 2>&1
+ (( $? != 0 )) && \
+ log_fail "Get the property $propname of $ds failed."
+ done
+ fi
+done
+
+for ds in $pool $fs; do
+ for propname in "recordsize" "recsize"; do
+ for val in ${size[*]}; do
+ if [[ $propname == "recordsize" ]]; then
+ set_and_check $ds $propname $val "recsize"
+ else
+ set_and_check $ds $propname $val "recordsize"
+ fi
+ done
+ done
+done
+
+log_pass "The alias of a property works as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/readonly_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/readonly_001_pos.ksh
new file mode 100755
index 000000000000..22fb0a77c9ab
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/readonly_001_pos.ksh
@@ -0,0 +1,160 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Setting readonly on a dataset, it should keep the dataset as readonly.
+#
+# STRATEGY:
+# 1. Create pool, then create filesystem and volume within it.
+# 2. Setting readonly to each dataset.
+# 3. Check the return value and make sure it is 0.
+# 4. Verify the stuff under mountpoint is readonly.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for dataset in $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL ; do
+ snapexists ${dataset}@$TESTSNAP && \
+ log_must zfs destroy -R ${dataset}@$TESTSNAP
+ done
+}
+
+function initial_dataset # $1 dataset
+{
+ typeset dataset=$1
+
+ typeset fstype=$(get_prop type $dataset)
+
+ if [[ $fstype == "filesystem" ]] ; then
+ typeset mtpt=$(get_prop mountpoint $dataset)
+ log_must touch $mtpt/$TESTFILE0
+ log_must mkdir -p $mtpt/$TESTDIR0
+ fi
+}
+
+
+function cleanup_dataset # $1 dataset
+{
+ typeset dataset=$1
+
+ typeset fstype=$(get_prop type $dataset)
+
+ if [[ $fstype == "filesystem" ]] ; then
+ typeset mtpt=$(get_prop mountpoint $dataset)
+ log_must rm -f $mtpt/$TESTFILE0
+ log_must rm -rf $mtpt/$TESTDIR0
+ fi
+}
+
+function verify_readonly # $1 dataset, $2 on|off
+{
+ typeset dataset=$1
+ typeset value=$2
+
+ if datasetnonexists $dataset ; then
+ log_note "$dataset does not exist!"
+ return 1
+ fi
+
+ typeset fstype=$(get_prop type $dataset)
+
+ expect="log_must"
+
+ if [[ $2 == "on" ]] ; then
+ expect="log_mustnot"
+ fi
+
+ case $fstype in
+ filesystem)
+ typeset mtpt=$(get_prop mountpoint $dataset)
+ $expect touch $mtpt/$TESTFILE1
+ $expect mkdir -p $mtpt/$TESTDIR1
+ $expect eval "echo 'y' | rm $mtpt/$TESTFILE0"
+ $expect rmdir $mtpt/$TESTDIR0
+
+ if [[ $expect == "log_must" ]] ; then
+ log_must eval "echo 'y' | rm $mtpt/$TESTFILE1"
+ log_must rmdir $mtpt/$TESTDIR1
+ log_must touch $mtpt/$TESTFILE0
+ log_must mkdir -p $mtpt/$TESTDIR0
+ fi
+ ;;
+ volume)
+ $expect eval "new_fs \
+ ${ZVOL_DEVDIR}/$dataset > /dev/null 2>&1"
+ ;;
+ *)
+ ;;
+ esac
+
+ return 0
+}
+
+log_onexit cleanup
+
+log_assert "Setting a valid readonly property on a dataset succeeds."
+
+typeset all_datasets
+
+log_must zfs mount -a
+
+log_must zfs snapshot $TESTPOOL/$TESTFS@$TESTSNAP
+log_must zfs clone $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTCLONE
+
+if is_global_zone ; then
+ log_must zfs snapshot $TESTPOOL/$TESTVOL@$TESTSNAP
+ log_must zfs clone $TESTPOOL/$TESTVOL@$TESTSNAP $TESTPOOL/$TESTCLONE1
+ all_datasets="$TESTPOOL $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL "
+ all_datasets+="$TESTPOOL/$TESTCLONE $TESTPOOL/$TESTCLONE1"
+else
+ all_datasets="$TESTPOOL $TESTPOOL/$TESTFS $TESTPOOL/$TESTCLONE"
+fi
+
+
+for dataset in $all_datasets; do
+ for value in on off; do
+ set_n_check_prop "off" "readonly" "$dataset"
+ initial_dataset $dataset
+
+ set_n_check_prop "$value" "readonly" "$dataset"
+ verify_readonly $dataset $value
+
+ set_n_check_prop "off" "readonly" "$dataset"
+ cleanup_dataset $dataset
+ done
+done
+
+log_pass "Setting a valid readonly property on a dataset succeeds."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/reservation_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/reservation_001_neg.ksh
new file mode 100755
index 000000000000..de6d83d2270c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/reservation_001_neg.ksh
@@ -0,0 +1,101 @@
+#! /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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Valid reservation values should be positive integers only.
+#
+# STRATEGY:
+# 1) Form an array of invalid reservation values (negative and
+# incorrectly formed)
+# 2) Attempt to set each invalid reservation value in turn on a
+# filesystem and volume.
+# 3) Verify that attempt fails and the reservation value remains
+# unchanged
+#
+
+verify_runnable "both"
+
+log_assert "Verify invalid reservation values are rejected"
+
+set -A suffix "b" "k" "m" "t" "p" "e" "K" "M" "G" "T" "P" "E" "kb" "Mb" "Gb" \
+ "Tb" "Pb" "Eb" "KB" "MB" "GB" "TB" "PB" "EB"
+
+set -A values '' '-1' '-1.0' '-1.8' '-9999999999999999' '0x1' '0b' '1b' '1.1b'
+
+#
+# Function to loop through a series of bad reservation
+# values, checking they are when we attempt to set them
+# on a dataset.
+#
+function set_n_check # data-set
+{
+ typeset obj=$1
+ typeset -i i=0
+ typeset -i j=0
+
+ orig_resv_val=$(get_prop reservation $obj)
+
+ while (( $i < ${#values[*]} )); do
+ j=0
+ while (( $j < ${#suffix[*]} )); do
+
+ zfs set \
+ reservation=${values[$i]}${suffix[$j]} $obj \
+ > /dev/null 2>&1
+ if [ $? -eq 0 ]
+ then
+ log_note "zfs set \
+ reservation=${values[$i]}${suffix[$j]} $obj"
+ log_fail "The above reservation set returned 0!"
+ fi
+
+ new_resv_val=$(get_prop reservation $obj)
+
+ if [[ $new_resv_val != $orig_resv_val ]]; then
+ log_fail "$obj : reservation values changed " \
+ "($orig_resv_val : $new_resv_val)"
+ fi
+ (( j = j + 1 ))
+ done
+
+ (( i = i + 1 ))
+ done
+}
+
+for dataset in $TESTPOOL/$TESTFS $TESTPOOL/$TESTCTR $TESTPOOL/$TESTVOL
+do
+ set_n_check $dataset
+done
+
+log_pass "Invalid reservation values correctly rejected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/ro_props_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/ro_props_001_pos.ksh
new file mode 100755
index 000000000000..7177fac202d0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/ro_props_001_pos.ksh
@@ -0,0 +1,124 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify that read-only properties are immutable.
+# Note that we can only check properties that have no possibility of
+# changing while we are running (which excludes e.g. "available").
+#
+# STRATEGY:
+# 1. Create pool, fs, vol, fs@snap & vol@snap.
+# 2. Get the original property value and set value to those properties.
+# 3. Check return value.
+# 4. Compare the current property value with the original one.
+#
+
+verify_runnable "both"
+
+set -A values filesystem volume snapshot -3 0 1 50K 10G 80G \
+ 2005/06/17 30K 20x yes no \
+ on off default pool/fs@snap $TESTDIR
+set -A dataset $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL \
+ $TESTPOOL/$TESTCTR/$TESTFS1 $TESTPOOL/$TESTFS@$TESTSNAP \
+ $TESTPOOL/$TESTVOL@$TESTSNAP
+typeset ro_props="type used creation referenced refer compressratio \
+ mounted origin"
+typeset snap_ro_props="volsize recordsize recsize quota reservation reserv mountpoint \
+ sharenfs checksum compression compress atime devices exec readonly rdonly \
+ setuid"
+if is_freebsd; then
+ snap_ro_props+=" jailed"
+else
+ snap_ro_props+=" zoned"
+fi
+
+zfs upgrade -v > /dev/null 2>&1
+if [[ $? -eq 0 ]]; then
+ snap_ro_props="$snap_ro_props version"
+fi
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTVOL@$TESTSNAP && \
+ destroy_snapshot $TESTPOOL/$TESTVOL@$TESTSNAP
+ datasetexists $TESTPOOL/$TESTFS@$TESTSNAP && \
+ destroy_snapshot $TESTPOOL/$TESTFS@$TESTSNAP
+}
+
+log_assert "Verify that read-only properties are immutable."
+log_onexit cleanup
+
+# Create filesystem and volume's snapshot
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+create_snapshot $TESTPOOL/$TESTVOL $TESTSNAP
+sync_pool $TESTPOOL
+sleep 5
+
+typeset -i i=0
+typeset -i j=0
+typeset cur_value=""
+typeset props=""
+
+while (( i < ${#dataset[@]} )); do
+ props=$ro_props
+
+ dst_type=$(get_prop type ${dataset[i]})
+ if [[ $dst_type == 'snapshot' ]]; then
+ props="$ro_props $snap_ro_props"
+ fi
+
+ for prop in $props; do
+ cur_value=$(get_prop $prop ${dataset[i]})
+
+ j=0
+ while (( j < ${#values[@]} )); do
+ #
+ # If the current property value is equal to values[j],
+ # just expect it failed. Otherwise, set it to dataset,
+ # expecting it failed and the property value is not
+ # equal to values[j].
+ #
+ if [[ $cur_value == ${values[j]} ]]; then
+ log_mustnot zfs set $prop=${values[j]} \
+ ${dataset[i]}
+ else
+ set_n_check_prop ${values[j]} $prop \
+ ${dataset[i]} false
+ fi
+ (( j += 1 ))
+ done
+ done
+ (( i += 1 ))
+done
+
+log_pass "Setting uneditable properties should failed. It passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/setup.ksh
new file mode 100755
index 000000000000..9692385996d1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_container_volume_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/share_mount_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/share_mount_001_neg.ksh
new file mode 100755
index 000000000000..fa32c2774f8b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/share_mount_001_neg.ksh
@@ -0,0 +1,64 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify that we cannot share or mount legacy filesystems.
+#
+# STRATEGY:
+# 1. Set mountpoint as legacy or none
+# 2. Use zfs share or zfs mount to share or mount the filesystem
+# 3. Verify that the command returns error
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs set mountpoint=$oldmpt $fs
+}
+
+log_assert "Verify that we cannot share or mount legacy filesystems."
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+oldmpt=$(get_prop mountpoint $fs)
+
+for propval in "legacy" "none"; do
+ log_must zfs set mountpoint=$propval $fs
+
+ log_mustnot zfs mount $fs
+ log_mustnot zfs share $fs
+done
+
+log_pass "We cannot share or mount legacy filesystems as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/snapdir_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/snapdir_001_pos.ksh
new file mode 100755
index 000000000000..079fc770a6fe
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/snapdir_001_pos.ksh
@@ -0,0 +1,112 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Setting a valid snapdir on a dataset, it should be successful.
+#
+# STRATEGY:
+# 1. Create pool, then create filesystem and volume within it.
+# 2. Create a snapshot for each dataset.
+# 3. Setting different valid snapdir to each dataset.
+# 4. Check the return value and make sure it is 0.
+# 5. Verify .zfs directory is hidden|visible according to the snapdir setting.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for dataset in $all_datasets; do
+ snapexists ${dataset}@snap && \
+ log_must zfs destroy ${dataset}@snap
+ done
+}
+
+function verify_snapdir_visible # $1 dataset, $2 hidden|visible
+{
+ typeset dataset=$1
+ typeset value=$2
+ typeset mtpt=$(get_prop mountpoint $dataset)
+ typeset name
+
+ for name in `ls -a $mtpt`; do
+ if [[ $name == ".zfs" ]]; then
+ if [[ $value == "visible" ]]; then
+ return 0
+ else
+ return 1
+ fi
+ fi
+ done
+
+ if [[ $value == "visible" ]]; then
+ return 1
+ else
+ return 0
+ fi
+}
+
+
+typeset all_datasets
+
+if is_global_zone ; then
+ all_datasets="$TESTPOOL $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL"
+else
+ all_datasets="$TESTPOOL $TESTPOOL/$TESTFS"
+fi
+
+log_onexit cleanup
+
+for dataset in $all_datasets; do
+ log_must zfs snapshot ${dataset}@snap
+done
+
+log_assert "Setting a valid snapdir property on a dataset succeeds."
+
+for dataset in $all_datasets; do
+ for value in hidden visible; do
+ if [[ $dataset == "$TESTPOOL/$TESTVOL" ]] ; then
+ set_n_check_prop "$value" "snapdir" \
+ "$dataset" "false"
+ else
+ set_n_check_prop "$value" "snapdir" \
+ "$dataset"
+ verify_snapdir_visible $dataset $value
+ [[ $? -eq 0 ]] || \
+ log_fail "$dataset/.zfs is not $value as expect."
+ fi
+ done
+done
+
+log_pass "Setting a valid snapdir property on a dataset succeeds."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_001_pos.ksh
new file mode 100755
index 000000000000..16b9638787e2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_001_pos.ksh
@@ -0,0 +1,84 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# ZFS can set any valid user defined property to the non-readonly dataset.
+#
+# STRATEGY:
+# 1. Loop pool, fs and volume.
+# 2. Combine all kind of valid characters into a valid user defined
+# property name.
+# 3. Random get a string as the value.
+# 4. Verify all the valid user defined properties can be set to the
+# dataset in #1.
+#
+
+verify_runnable "both"
+
+log_assert "ZFS can set any valid user defined property to the non-readonly " \
+ "dataset."
+log_onexit cleanup_user_prop $TESTPOOL
+
+typeset -a names=()
+typeset -a values=()
+
+# Longest property name (255 bytes)
+names+=("$(awk 'BEGIN { printf "x:"; while (c++ < 253) printf "a" }')")
+values+=("too-long-property-name")
+# Longest property value (8191 bytes)
+names+=("too:long:property:value")
+values+=("$(awk 'BEGIN { while (c++ < 8191) printf "A" }')")
+# Valid property names
+for i in {1..10}; do
+ typeset -i len
+ ((len = RANDOM % 32))
+ names+=("$(valid_user_property $len)")
+ ((len = RANDOM % 512))
+ values+=("$(user_property_value $len)")
+done
+
+typeset -i i=0
+while ((i < ${#names[@]})); do
+ typeset name="${names[$i]}"
+ typeset value="${values[$i]}"
+
+ for dtst in $TESTPOOL $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL; do
+ log_must eval "zfs set $name='$value' $dtst"
+ log_must eval "check_user_prop $dtst $name '$value'"
+ done
+
+ ((i += 1))
+done
+
+log_pass "ZFS can set any valid user defined property passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_002_pos.ksh
new file mode 100755
index 000000000000..12cff78ea4ca
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_002_pos.ksh
@@ -0,0 +1,120 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016, 2019 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# User defined property are always inherited from its parent dataset
+# directly.
+#
+# STRATEGY:
+# 1. Create pool, fs, volume, fsclone & volclone.
+# 2. Get random user property name and set to the pool
+# 3. Verify all dataset user property inherit from pool.
+# 4. Set intermediate dataset and verify its children will inherit user
+# property from it directly.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $new_vol && log_must zfs rename $new_vol $vol
+
+ typeset dtst
+ for dtst in $new_fsclone $new_volclone $fsclone $volclone \
+ $fssnap $volsnap; do
+ destroy_dataset "$dtst" "-f"
+ done
+
+ cleanup_user_prop $pool
+}
+
+#
+# Verify options datasets (3-n) inherit from the inherited dataset $2.
+#
+# $1 user property
+# $2 inherited dataset
+# $3-n datasets
+#
+function inherit_check
+{
+ typeset prop=$1
+ typeset inherited_dtst=$2
+ shift 2
+ [[ -z $@ ]] && return 1
+
+ typeset inherited_value=$(get_prop $prop $inherited_dtst)
+ for dtst in $@; do
+ typeset value=$(get_prop $prop $dtst)
+ typeset source=$(get_source $prop $dtst)
+ if [[ "$value" != "$inherited_value" || \
+ "$source" != "inherited from $inherited_dtst" ]]
+ then
+ return 1
+ fi
+
+ shift
+ done
+
+ return 0
+}
+
+log_assert "User defined property inherited from its parent."
+log_onexit cleanup
+
+pool=$TESTPOOL; fs=$pool/$TESTFS; vol=$pool/$TESTVOL
+fssnap=$fs@snap; volsnap=$vol@snap;
+log_must zfs snapshot $fssnap
+log_must zfs snapshot $volsnap
+fsclone=$pool/fsclone; volclone=$pool/volclone
+log_must zfs clone $fssnap $fsclone
+log_must zfs clone $volsnap $volclone
+
+prop_name=$(valid_user_property 10)
+value=$(user_property_value 16)
+log_must eval "zfs set $prop_name='$value' $pool"
+log_must eval "check_user_prop $pool $prop_name '$value'"
+log_must inherit_check $prop_name $pool $fs $vol $fsclone $volclone
+
+new_fsclone=$fs/fsclone; new_volclone=$fs/volclone
+log_must zfs rename $fsclone $new_fsclone
+log_must zfs rename $volclone $new_volclone
+log_must inherit_check $prop_name $pool $fs $new_fsclone $new_volclone
+
+log_note "Set intermediate dataset will change the inherited relationship."
+new_value=$(user_property_value 16)
+log_must eval "zfs set $prop_name='$new_value' $fs"
+log_must eval "check_user_prop $fs $prop_name '$new_value'"
+log_must inherit_check $prop_name $fs $new_fsclone $new_volclone
+
+log_pass "User defined property inherited from its parent passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_003_neg.ksh
new file mode 100755
index 000000000000..3d8c1e7be18d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_003_neg.ksh
@@ -0,0 +1,82 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# ZFS can handle any invalid user defined property.
+#
+# STRATEGY:
+# 1. Loop pool, fs and volume.
+# 2. Combine all kind of invalid user property names.
+# 3. Random get a string as the value.
+# 4. Verify all the invalid user defined properties can not be set to the
+# dataset in #1.
+#
+
+verify_runnable "both"
+
+log_assert "ZFS can handle invalid user property."
+log_onexit cleanup_user_prop $TESTPOOL
+
+typeset -a names=()
+typeset -a values=()
+
+# Too long property name (256 bytes)
+names+=("$(awk 'BEGIN { printf "x:"; while (c++ < 254) printf "a" }')")
+values+=("too-long-property-name")
+# Too long property value (8K)
+names+=("too:long:property:value")
+values+=("$(awk 'BEGIN { while (c++ < 8192) printf "A" }')")
+# Invalid property names
+for i in {1..10}; do
+ typeset -i len
+ ((len = RANDOM % 32))
+ names+=("$(invalid_user_property $len)")
+ ((len = RANDOM % 512))
+ values+=("$(user_property_value $len)")
+done
+
+typeset -i i=0
+while ((i < ${#names[@]})); do
+ typeset name="${names[$i]}"
+ typeset value="${values[$i]}"
+
+ for dtst in $TESTPOOL $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL ; do
+ log_mustnot zfs set $name=$value $dtst
+ log_mustnot check_user_prop $dtst \"$name\" \"$value\"
+ done
+
+ ((i += 1))
+done
+
+log_pass "ZFS can handle invalid user property passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_004_pos.ksh
new file mode 100755
index 000000000000..1d197fa25fbd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/user_property_004_pos.ksh
@@ -0,0 +1,101 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# User property has no effect to snapshot until 'Snapshot properties' supported.
+#
+# STRATEGY:
+# 1. Verify user properties could be transformed by 'zfs snapshot'
+# 2. Verify user properties could be set upon snapshot.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for fs in $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL $TESTPOOL ; do
+ typeset fssnap=$fs@snap
+ if datasetexists $fssnap ; then
+ log_must zfs destroy -f $fssnap
+ fi
+ done
+ cleanup_user_prop $TESTPOOL
+}
+
+function nonexist_user_prop
+{
+ typeset user_prop=$1
+ typeset dtst=$2
+
+ typeset source=$(get_source $user_prop $dtst)
+ typeset value=$(get_prop $user_prop $dtst)
+ if [[ $source == '-' && $value == '-' ]]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+log_assert "User property has no effect to snapshot until 'Snapshot properties' supported."
+log_onexit cleanup
+
+typeset snap_property=
+
+zpool upgrade -v | grep "Snapshot properties" > /dev/null 2>&1
+if (( $? == 0 )) ; then
+ snap_property="true"
+fi
+
+for fs in $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL $TESTPOOL ; do
+ typeset fssnap=$fs@snap
+ prop_name=$(valid_user_property 10)
+ value=$(user_property_value 16)
+ log_must eval "zfs set $prop_name='$value' $fs"
+ log_must eval "check_user_prop $fs $prop_name '$value'"
+
+ log_must zfs snapshot $fssnap
+
+ if [[ -n $snap_property ]] ; then
+ log_mustnot nonexist_user_prop $prop_name $fssnap
+
+ log_must eval "zfs set $prop_name='$value' $fssnap"
+ log_mustnot nonexist_user_prop $prop_name $fssnap
+ else
+ log_must nonexist_user_prop $prop_name $fssnap
+ log_mustnot eval "zfs set $prop_name='$value' $fssnap"
+ log_must nonexist_user_prop $prop_name $fssnap
+ fi
+done
+
+log_pass "User properties has effect upon snapshot."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/version_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/version_001_neg.ksh
new file mode 100755
index 000000000000..cf5ef5116e90
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/version_001_neg.ksh
@@ -0,0 +1,91 @@
+#! /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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# Valid version values should be positive integers only.
+#
+# STRATEGY:
+# 1) Form an array of invalid reservation values (negative and
+# incorrectly formed)
+# 2) Attempt to set each invalid version value in turn on a
+# filesystem and volume.
+# 3) Verify that attempt fails and the version value remains
+# unchanged
+#
+
+verify_runnable "both"
+
+log_assert "Verify invalid version values are rejected"
+
+typeset values=('' '-1' '-1.0' '-1.8' '-9999999999999999' \
+ '0x1' '0b' '1b' '1.1b' '0' '0.000' '1.234')
+
+#
+# Function to loop through a series of bad reservation
+# values, checking they are when we attempt to set them
+# on a dataset.
+#
+function set_n_check # data-set
+{
+ typeset obj=$1
+ typeset -i i=0
+ typeset -i j=0
+
+ orig_val=$(get_prop version $obj)
+
+ while (($i < ${#values[*]})); do
+ zfs set version=${values[$i]} $obj > /dev/null 2>&1
+ if [[ $? -eq 0 ]]; then
+ log_note "zfs set version=${values[$i]} $obj"
+ log_fail "The above version set returned 0!"
+ fi
+
+ new_val=$(get_prop version $obj)
+
+ if [[ $new_val != $orig_val ]]; then
+ log_fail "$obj : version values changed " \
+ "($orig_val : $new_val)"
+ fi
+
+ ((i = i + 1))
+ done
+}
+
+for dataset in $TESTPOOL/$TESTFS $TESTPOOL/$TESTCTR $TESTPOOL/$TESTVOL
+do
+ set_n_check $dataset
+done
+
+log_pass "Invalid version values correctly rejected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_001_neg.ksh
new file mode 100755
index 000000000000..c9bc7565abd6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_001_neg.ksh
@@ -0,0 +1,87 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2015 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# Setting invalid value to mountpoint, checksum, atime, readonly, setuid,
+# zoned, recordsize, or canmount on a file system, volume. It should be failed.
+#
+# STRATEGY:
+# 1. Create pool, then create file system & volume within it.
+# 2. Setting invalid value, it should be failed.
+#
+
+verify_runnable "both"
+
+set -A props "" "mountpoint" "checksum" "compression" "atime" "readonly" \
+ "setuid" "canmount"
+if is_freebsd; then
+ props+=("jailed")
+else
+ props+=("zoned")
+fi
+
+set -A values "" "mountpoint" "checksum" "compression" "atime" "readonly" \
+ "setuid" "zoned" "0" "-?" "-on" "--on" "*" "?" "Legacy" "NONE" "oN" \
+ "On" "ON" "ofF" "OFf" "oFF" "Off" "OfF" "OFF" "LzJb" "lZJb" "LZjB" \
+ "blad" "default" "TESTPOOL" "$TESTPOOL/$TESTCTR" \
+ "$TESTPOOL/$TESTCTR/$TESTFS" "$TESTPOOL/$TESTFS"
+set -A dataset "$TESTPOOL" "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTVOL"
+
+log_assert "Setting invalid value to mountpoint, checksum, compression, atime,"\
+ "readonly, setuid, zoned or canmount on a file system file system or volume." \
+ "It should be failed."
+
+typeset -i i=0
+typeset -i j=0
+typeset -i k=0
+while (( i < ${#dataset[@]} )); do
+ j=0
+ while (( j < ${#props[@]} )); do
+ k=0
+ while (( k < ${#values[@]} )); do
+ set_n_check_prop "${values[k]}" "${props[j]}" \
+ "${dataset[i]}" false
+ (( k += 1 ))
+ done
+ (( j += 1 ))
+ done
+ # Additional recordsize
+ set_n_check_prop "recordsize" "2048K" "${dataset[i]}" false
+ set_n_check_prop "recordsize" "128B" "${dataset[i]}" false
+ (( i += 1 ))
+done
+
+log_pass "Setting invalid value to mountpoint, checksum, compression, atime, " \
+ "readonly, setuid, zoned or canmount on file system or volume pass."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_002_neg.ksh
new file mode 100755
index 000000000000..2178175cd5b6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_002_neg.ksh
@@ -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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2011, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs set' should fail with invalid arguments
+#
+# STRATEGY:
+# 1. Create an array of invalid arguments
+# 1. Run zfs set with each invalid argument
+# 2. Verify that zfs set returns error
+#
+
+verify_runnable "both"
+
+log_assert "'zfs set' fails with invalid arguments"
+
+set -A editable_props "quota" "reservation" "reserv" "volsize" "recordsize" "recsize" \
+ "mountpoint" "checksum" "compression" "compress" "atime" \
+ "devices" "exec" "setuid" "readonly" "snapdir" "aclmode" \
+ "aclinherit" "canmount" "xattr" "copies" "version"
+if is_freebsd; then
+ editable_props+=("jailed")
+else
+ editable_props+=("zoned")
+fi
+
+for ds in $TESTPOOL $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL \
+ $TESTPOOL/$TESTFS@$TESTSNAP; do
+ for badarg in "" "-" "-?"; do
+ for prop in ${editable_props[@]}; do
+ log_mustnot eval "zfs set $badarg $prop= $ds >/dev/null 2>&1"
+ done
+ done
+done
+
+log_pass "'zfs set' fails with invalid arguments as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_003_neg.ksh
new file mode 100755
index 000000000000..102e8874294f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_003_neg.ksh
@@ -0,0 +1,77 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs set mountpoint/sharenfs' should fail when the mountpoint is invalid
+#
+# STRATEGY:
+# 1. Create invalid scenarios
+# 2. Run zfs set mountpoint/sharenfs with invalid value
+# 3. Verify that zfs set returns expected errors
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if [ -e $badpath ]; then
+ rm -f $badpath
+ fi
+ if datasetexists $TESTPOOL/foo; then
+ log_must zfs destroy $TESTPOOL/foo
+ fi
+}
+
+log_assert "'zfs set mountpoint/sharenfs' fails with invalid scenarios"
+log_onexit cleanup
+
+badpath=$TEST_BASE_DIR/foo1.$$
+touch $badpath
+longpath=$(gen_dataset_name 1030 "abcdefg")
+
+log_must zfs create -o mountpoint=legacy $TESTPOOL/foo
+
+# Do the negative testing about "property may be set but unable to remount filesystem"
+log_mustnot eval "zfs set mountpoint=$badpath $TESTPOOL/foo >/dev/null 2>&1"
+
+# Do the negative testing about "property may be set but unable to reshare filesystem"
+log_mustnot eval "zfs set sharenfs=on $TESTPOOL/foo >/dev/null 2>&1"
+
+# Do the negative testing about "sharenfs property can not be set to null"
+log_mustnot eval "zfs set sharenfs= $TESTPOOL/foo >/dev/null 2>&1"
+
+# Do the too long pathname testing (>1024)
+log_mustnot eval "zfs set mountpoint=/$longpath $TESTPOOL/foo >/dev/null 2>&1"
+
+log_pass "'zfs set mountpoint/sharenfs' fails with invalid scenarios as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
new file mode 100644
index 000000000000..5e9f719dfcfe
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
@@ -0,0 +1,376 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+set -A VALID_NAME_CHAR a b c d e f g h i j k l m n o p q r s t u v w x y z \
+ 0 1 2 3 4 5 6 7 8 9 ':' '-' '.' '_'
+set -A INVALID_NAME_CHAR A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
+ '`' '~' '!' '@' '#' '$' '%' '^' '&' '(' ')' '+' '=' '|' "\\" '{' '[' ']' \
+ '}' ';' '"' '<' ',' '>' '?' '/' ' '
+set -A ALL_CHAR ${VALID_NAME_CHAR[*]} ${INVALID_NAME_CHAR[*]}
+
+#
+# Firstly, set the property value to dataset. Then checking if the property
+# value is equal with the expected value, according to the expected result.
+#
+# $1 property value
+# $2 property name
+# $3 dataset
+# $4 expected result
+#
+function set_n_check_prop
+{
+ typeset expect_value=$1
+ typeset prop=$2
+ typeset dataset=$3
+ typeset expect_result=${4:-true}
+
+ typeset old_value=""
+ typeset cur_value=""
+
+ [[ -n $prop ]] && old_value=$(get_prop $prop $dataset)
+
+ if [[ $expect_result == true ]]; then
+ [[ -z $prop || -z $dataset ]] && \
+ log_fail "property or dataset isn't defined."
+
+ log_must zfs set $prop=$expect_value $dataset
+ if [[ $expect_value == "gzip-6" ]]; then
+ expect_value="gzip"
+ fi
+
+ [[ -n $prop ]] && cur_value=$(get_prop $prop $dataset)
+
+ case $prop in
+ reservation|reserv|quota )
+ if [[ $expect_value == "none" ]]; then
+ [[ $cur_value != "0" ]] && \
+ log_fail "The '$dataset' '$prop' value \
+ '$cur_value' is not expected."
+ elif [[ $cur_value != $expect_value ]]; then
+ log_fail "The '$dataset' '$prop' value '$cur_value' \
+ does not equal the expected value '$expect_value'."
+ fi
+ ;;
+ * )
+ if [[ $cur_value != $expect_value ]]; then
+ log_fail "The '$dataset' '$prop' value '$cur_value' \
+ does not equal the expected value '$expect_value'."
+ fi
+ ;;
+ esac
+
+ else
+ log_mustnot zfs set $prop=$expect_value $dataset
+
+ [[ -n $prop ]] && cur_value=$(get_prop $prop $dataset)
+
+ wait_freeing
+
+ if [[ "$expect_value" != "" && "$cur_value" != "$old_value" ]];
+ then
+ log_fail "The '$dataset' '$prop' value '$cur_value' \
+ should equal with '$old_value'."
+ fi
+ fi
+}
+
+#
+# Cleanup all the user properties of the pool and the dataset reside it.
+#
+# $1 pool name
+#
+function cleanup_user_prop
+{
+ typeset pool=$1
+ typeset dtst=$(zfs list -H -r -o name -t filesystem,volume $pool)
+
+ typeset user_prop
+ for dt in $dtst; do
+ user_prop=$(zfs get -H -o property all $dtst | grep ":")
+
+ typeset prop
+ for prop in $user_prop; do
+ zfs inherit $prop $dt
+ (($? != 0)) && log_must zfs inherit $prop $dt
+ done
+ done
+}
+
+#
+# Random select character from the specified character set and combine into a
+# random string
+#
+# $1 character set name
+# $2 String length
+#
+function random_string
+{
+ typeset char_set=${1:-VALID_NAME_CHAR}
+ typeset -i len=${2:-5}
+
+ eval typeset -i count=\${#$char_set[@]}
+
+ # No consumers want an empty string.
+ ((len == 0)) && len=3
+
+ typeset str
+ typeset -i i=0
+ while ((i < len)); do
+ typeset -i ind
+ ((ind = RANDOM % count))
+ eval str=\${str}\${$char_set[\$ind]}
+
+ ((i += 1))
+ done
+
+ echo "$str"
+}
+
+#
+# Get valid user defined property name
+#
+# $1 user defined property name length
+#
+function valid_user_property
+{
+ typeset -i sumlen=${1:-10}
+ ((sumlen < 2 )) && sumlen=2
+ typeset -i len
+ ((len = RANDOM % sumlen))
+ typeset part1 part2
+
+ while true; do
+ part1="$(random_string VALID_NAME_CHAR $len)"
+ if [[ "$part1" == "-"* ]]; then
+ continue
+ fi
+ break
+ done
+ ((len = sumlen - (len + 1)))
+
+ while true; do
+ part2="$(random_string VALID_NAME_CHAR $len)"
+ if [[ -z $part1 && -z $part2 ]]; then
+ continue
+ fi
+ break
+ done
+
+ echo "${part1}:${part2}"
+}
+
+#
+# Get invalid user defined property name
+#
+# $1 user defined property name length
+#
+function invalid_user_property
+{
+ typeset -i sumlen=${1:-10}
+ ((sumlen == 0)) && sumlen=1
+ typeset -i len
+ ((len = RANDOM % sumlen))
+
+ typeset part1 part2
+ while true; do
+ part1="$(random_string VALID_NAME_CHAR $len)"
+ ((len = sumlen - len))
+ part2="$(random_string INVALID_NAME_CHAR $len)"
+
+ # Avoid $part1 is *:* and $part2 is "=*"
+ if [[ "$part1" == *":"* && "$part2" == "="* ]]; then
+ continue
+ fi
+ break
+ done
+
+ echo "${part1}${part2}"
+}
+
+#
+# Get user property value
+#
+# $1 user defined property name length
+#
+function user_property_value
+{
+ typeset -i len=${1:-100}
+
+ typeset value=$(random_string ALL_CHAR $len)
+
+ echo "$value"
+}
+
+#
+# Check if the user property is identical to the expected value.
+#
+# $1 dataset
+# $2 user property
+# $3 expected value
+#
+function check_user_prop
+{
+ typeset dtst=$1
+ typeset user_prop="$2"
+ typeset expect_value="$3"
+ typeset value=$(zfs get -p -H -o value "$user_prop" $dtst 2>&1)
+
+ if [[ "$expect_value" == "$value" ]]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+#
+# Get source of the dataset
+#
+function get_source
+{
+ typeset prop=$1
+ typeset dataset=$2
+ typeset source
+
+ source=$(zfs get -H -o source $prop $dataset)
+ if (($? != 0)); then
+ log_fail "Unable to get $prop source for dataset $dataset"
+ fi
+
+ echo "$source"
+}
+
+#
+# Verify property $2 is set from source $4 on dataset $1 and has value $3.
+#
+# $1 checked dataset
+# $2 user property
+# $3 property value
+# $4 source
+#
+# Returns: 0 if both expected source and value match, 1 otherwise
+#
+function check_prop_source
+{
+ typeset dataset="$1"
+ typeset prop="$2"
+ typeset value="$3"
+ typeset source="$4"
+ typeset chk_value=$(get_prop "$prop" "$dataset")
+ typeset chk_source=$(get_source "$prop" "$dataset")
+
+ if [[ "$chk_value" != "$value" || "$chk_source" != "$4" ]]
+ then
+ return 1
+ else
+ return 0
+ fi
+}
+
+#
+# Verify target dataset $1 inherit property $2 from dataset $3.
+#
+# $1 checked dataset
+# $2 property
+# $3 inherited dataset
+#
+# Returns: 0 if property has expected value and is inherited, 1 otherwise
+#
+function check_prop_inherit
+{
+ typeset checked_dtst="$1"
+ typeset prop="$2"
+ typeset inherited_dtst="$3"
+ typeset inherited_value=$(get_prop "$prop" "$inherited_dtst")
+ typeset value=$(get_prop "$prop" "$checked_dtst")
+ typeset source=$(get_source "$prop" "$checked_dtst")
+
+ if [[ "$value" != "$inherited_value" || \
+ "$source" != "inherited from $inherited_dtst" ]]
+ then
+ return 1
+ else
+ return 0
+ fi
+}
+
+#
+# Verify property $2 received value on dataset $1 has value $3
+#
+# $1 checked dataset
+# $2 property name
+# $3 checked value
+#
+# Returns: 0 if property has expected value and is received, 1 otherwise
+#
+function check_prop_received
+{
+ typeset dataset="$1"
+ typeset prop="$2"
+ typeset value="$3"
+
+ received=$(zfs get -H -o received "$prop" "$dataset")
+ if (($? != 0)); then
+ log_fail "Unable to get $prop received value for dataset " \
+ "$dataset"
+ fi
+ if [[ "$received" == "$value" ]]
+ then
+ return 0
+ else
+ return 1
+ fi
+}
+
+#
+# Verify user property $2 is not set on dataset $1
+#
+# $1 checked dataset
+# $2 property name
+#
+# Returns: 0 if property is missing (not set), 1 otherwise
+#
+function check_prop_missing
+{
+ typeset dataset="$1"
+ typeset prop="$2"
+
+ value=$(zfs get -H -o value "$prop" "$dataset")
+ if (($? != 0)); then
+ log_fail "Unable to get $prop value for dataset $dataset"
+ fi
+ if [[ "-" == "$value" ]]
+ then
+ return 0
+ else
+ return 1
+ fi
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_feature_activation.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_feature_activation.ksh
new file mode 100755
index 000000000000..c5e6fb9c1140
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_feature_activation.ksh
@@ -0,0 +1,98 @@
+#!/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) 2020 The FreeBSD Foundation [1]
+#
+# [1] Portions of this software were developed by Allan Jude
+# under sponsorship from the FreeBSD Foundation.
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Setting the compression property to any of the zstd levels should activate
+# the zstd feature flag. Destroying the last dataset using the zstd feature flag
+# should revert the feature to the 'enabled' state.
+#
+# STRATEGY:
+# 1. Create pool, then create a file system within it.
+# 2. Check that the zstd feature flag is 'enabled'.
+# 3. Setting the compression property to zstd.
+# 4. Check that the zstd feature flag is now 'active'.
+# 5. Destroy the dataset
+# 6. Confirm that the feature flag reverts to the 'enabled' state.
+#
+
+verify_runnable "both"
+
+log_assert "Setting compression=zstd should activate the"\
+ "org.freebsd:zstd_compress feature flag, and destroying the last"\
+ "dataset using that property, should revert the feature flag to"\
+ "the enabled state."
+
+export VDEV_ZSTD="$TEST_BASE_DIR/vdev-zstd"
+
+function cleanup
+{
+ if poolexists $TESTPOOL-zstd ; then
+ destroy_pool $TESTPOOL-zstd
+ fi
+
+ rm $VDEV_ZSTD
+}
+log_onexit cleanup
+
+log_must truncate -s $SPA_MINDEVSIZE $VDEV_ZSTD
+log_must zpool create $TESTPOOL-zstd $VDEV_ZSTD
+
+featureval="$(get_pool_prop feature@zstd_compress $TESTPOOL-zstd)"
+
+[[ "$featureval" == "disabled" ]] && \
+ log_unsupported "ZSTD feature flag unsupposed"
+
+[[ "$featureval" == "active" ]] && \
+ log_unsupported "ZSTD feature already active before test"
+
+random_level=$((RANDOM%19 + 1))
+log_note "Randomly selected ZSTD level: $random_level"
+
+log_must zfs create -o compress=zstd-$random_level $TESTPOOL-zstd/$TESTFS-zstd
+
+featureval="$(get_pool_prop feature@zstd_compress $TESTPOOL-zstd)"
+
+log_note "After zfs set, feature flag value is: $featureval"
+
+[[ "$featureval" == "active" ]] ||
+ log_fail "ZSTD feature flag not activated"
+
+log_must zfs destroy $TESTPOOL-zstd/$TESTFS-zstd
+
+featureval="$(get_pool_prop feature@zstd_compress $TESTPOOL-zstd)"
+
+log_note "After zfs destroy, feature flag value is: $featureval"
+
+[[ "$featureval" == "enabled" ]] ||
+ log_fail "ZSTD feature flag not deactivated"
+
+log_pass "Setting compression=zstd activated the feature flag, and"\
+ "destroying the dataset deactivated it."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_keylocation.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_keylocation.ksh
new file mode 100755
index 000000000000..0d2e7ab8f298
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_keylocation.ksh
@@ -0,0 +1,101 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# Unencrypted datasets should only allow keylocation of 'none', encryption
+# roots should only allow keylocation of 'prompt' and file URI, and encrypted
+# child datasets should not be able to change their keylocation.
+#
+# STRATEGY:
+# 1. Verify the key location of the default dataset is 'none'
+# 2. Attempt to change the key location of the default dataset
+# 3. Create an encrypted dataset using a key file
+# 4. Attempt to change the key location of the encrypted dataset to 'none',
+# an invalid location, its current location, and 'prompt'
+# 5. Attempt to reload the encrypted dataset key using the new key location
+# 6. Create a encrypted child dataset
+# 7. Verify the key location of the child dataset is 'none'
+# 8. Attempt to change the key location of the child dataset
+# 9. Verify the key location of the child dataset has not changed
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+}
+log_onexit cleanup
+
+log_assert "Key location can only be 'prompt' or a file path for encryption" \
+ "roots, and 'none' for unencrypted volumes"
+
+log_must eval "echo $PASSPHRASE > /$TESTPOOL/pkey"
+
+log_must verify_keylocation $TESTPOOL/$TESTFS "none"
+log_must zfs set keylocation=none $TESTPOOL/$TESTFS
+log_mustnot zfs set keylocation=/$TESTPOOL/pkey $TESTPOOL/$TESTFS
+log_mustnot zfs set keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS
+log_must verify_keylocation $TESTPOOL/$TESTFS "none"
+
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1
+
+log_mustnot zfs set keylocation=none $TESTPOOL/$TESTFS1
+if true; then
+ log_mustnot zfs set keylocation=/$TESTPOOL/pkey $TESTPOOL/$TESTFS1
+else
+ ### SOON: ###
+ # file:///$TESTPOOL/pkey and /$TESTPOOL/pkey are equivalent on FreeBSD
+ # thanks to libfetch. Eventually we want to make the other platforms
+ # work this way as well, either by porting libfetch or by other means.
+ log_must zfs set keylocation=/$TESTPOOL/pkey $TESTPOOL/$TESTFS1
+fi
+
+log_must zfs set keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1
+log_must verify_keylocation $TESTPOOL/$TESTFS1 "file:///$TESTPOOL/pkey"
+
+log_must zfs set keylocation=prompt $TESTPOOL/$TESTFS1
+log_must verify_keylocation $TESTPOOL/$TESTFS1 "prompt"
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+
+log_must rm /$TESTPOOL/pkey
+log_must eval "echo $PASSPHRASE | zfs load-key $TESTPOOL/$TESTFS1"
+log_must zfs mount $TESTPOOL/$TESTFS1
+
+log_must zfs create $TESTPOOL/$TESTFS1/child
+log_must verify_keylocation $TESTPOOL/$TESTFS1/child "none"
+
+log_mustnot zfs set keylocation=none $TESTPOOL/$TESTFS1/child
+log_mustnot zfs set keylocation=prompt $TESTPOOL/$TESTFS1/child
+log_mustnot zfs set keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1/child
+log_mustnot zfs set keylocation=/$TESTPOOL/pkey $TESTPOOL/$TESTFS1/child
+
+log_must verify_keylocation $TESTPOOL/$TESTFS1/child "none"
+
+log_pass "Key location can only be 'prompt' or a file path for encryption" \
+ "roots, and 'none' for unencrypted volumes"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_share/Makefile.am
new file mode 100644
index 000000000000..bf33ed038d78
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/Makefile.am
@@ -0,0 +1,20 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_share
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_share_001_pos.ksh \
+ zfs_share_002_pos.ksh \
+ zfs_share_003_pos.ksh \
+ zfs_share_004_pos.ksh \
+ zfs_share_005_pos.ksh \
+ zfs_share_006_pos.ksh \
+ zfs_share_007_neg.ksh \
+ zfs_share_008_neg.ksh \
+ zfs_share_009_neg.ksh \
+ zfs_share_010_neg.ksh \
+ zfs_share_011_pos.ksh \
+ zfs_share_012_pos.ksh \
+ zfs_share_concurrent_shares.ksh
+
+dist_pkgdata_DATA = \
+ zfs_share.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/setup.ksh
new file mode 100755
index 000000000000..1601087f712c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/setup.ksh
@@ -0,0 +1,36 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+check_nfs
+
+# Make sure NFS server is running before testing.
+setup_nfs_server
+
+DISK=${DISKS%% *}
+default_container_volume_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share.cfg
new file mode 100644
index 000000000000..5c31c8fbb6e7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share.cfg
@@ -0,0 +1,32 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+export SNAPROOT=".zfs/snapshot"
+export NONEXISTFSNAME="nonexistfs50charslong_0123456789012345678901234567"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_001_pos.ksh
new file mode 100755
index 000000000000..fefeb1b1cbd5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_001_pos.ksh
@@ -0,0 +1,160 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016, 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that 'zfs set sharenfs' and 'zfs share' shares a given dataset.
+#
+# STRATEGY:
+# 1. Invoke 'zfs set sharenfs'.
+# 2. Verify that the file system is shared.
+# 3. Invoke 'zfs share'.
+# 4. Verify that the file system is shared.
+# 5. Verify that a shared filesystem cannot be shared again.
+# 6. Verify that share -a succeeds.
+#
+
+verify_runnable "global"
+
+set -A fs \
+ "$TESTDIR1" "$TESTPOOL/$TESTCTR/$TESTFS1" \
+ "$TESTDIR2" "$TESTPOOL/$TESTFS-clone" \
+ "$TESTDIR" "$TESTPOOL/$TESTFS"
+
+function cleanup
+{
+ typeset -i i=0
+ while (( i < ${#fs[*]} )); do
+ log_must zfs set sharenfs=off ${fs[((i+1))]}
+ unshare_fs ${fs[i]}
+
+ ((i = i + 2))
+ done
+
+ if mounted $TESTPOOL/$TESTFS-clone; then
+ log_must zfs unmount $TESTDIR2
+ fi
+
+ datasetexists $TESTPOOL/$TESTFS-clone && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS-clone
+
+ if snapexists "$TESTPOOL/$TESTFS@snapshot"; then
+ log_must zfs destroy -f $TESTPOOL/$TESTFS@snapshot
+ fi
+
+ log_must zfs share -a
+}
+
+
+#
+# Main test routine.
+#
+# Given a mountpoint and file system this routine will attempt
+# share the mountpoint and then verify it has been shared.
+#
+function test_share # mntp filesystem
+{
+ typeset mntp=$1
+ typeset filesystem=$2
+
+ not_shared $mntp || \
+ log_fail "File system $filesystem is already shared."
+
+ log_must zfs set sharenfs=on $filesystem
+ is_shared $mntp || \
+ log_fail "File system $filesystem is not shared (set sharenfs)."
+
+ #
+ # Verify 'zfs share' works as well.
+ #
+ log_must zfs unshare $filesystem
+ is_shared $mntp && \
+ log_fail "File system $filesystem is still shared."
+
+ log_must zfs share $filesystem
+ is_shared $mntp || \
+ log_fail "file system $filesystem is not shared (zfs share)."
+
+ log_note "Sharing a shared file system fails."
+ log_mustnot zfs share $filesystem
+}
+
+log_assert "Verify that 'zfs share' succeeds as root."
+log_onexit cleanup
+
+log_must zfs snapshot $TESTPOOL/$TESTFS@snapshot
+log_must zfs clone $TESTPOOL/$TESTFS@snapshot $TESTPOOL/$TESTFS-clone
+log_must zfs set mountpoint=$TESTDIR2 $TESTPOOL/$TESTFS-clone
+
+typeset -i i=0
+while (( i < ${#fs[*]} )); do
+ test_share ${fs[i]} ${fs[((i + 1))]}
+
+ ((i = i + 2))
+done
+
+log_note "Verify 'zfs share -a' succeeds."
+
+#
+# Unshare each of the file systems.
+#
+i=0
+while (( i < ${#fs[*]} )); do
+ unshare_fs ${fs[i]}
+
+ ((i = i + 2))
+done
+
+#
+# Try a zfs share -a and verify all file systems are shared.
+#
+log_must zfs share -a
+
+#
+# We need to unset __ZFS_POOL_EXCLUDE so that we include all file systems
+# in the os-specific zfs exports file. This will be reset by the next test.
+#
+unset __ZFS_POOL_EXCLUDE
+
+i=0
+while (( i < ${#fs[*]} )); do
+ is_shared ${fs[i]} || \
+ log_fail "File system ${fs[i]} is not shared (share -a)"
+
+ is_exported ${fs[i]} || \
+ log_fail "File system ${fs[i]} is not exported (share -a)"
+
+ ((i = i + 2))
+done
+
+log_pass "'zfs share [ -a ] <filesystem>' succeeds as root."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_002_pos.ksh
new file mode 100755
index 000000000000..588a30f46de9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_002_pos.ksh
@@ -0,0 +1,73 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_share/zfs_share.cfg
+
+#
+# DESCRIPTION:
+# Verify that "zfs share" with a non-existent file system fails.
+#
+# STRATEGY:
+# 1. Make sure the NONEXISTFSNAME ZFS file system is not in 'zfs list'.
+# 2. Invoke 'zfs share <file system>'.
+# 3. Verify that share fails
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset fs
+ for fs in $NONEXISTFSNAME $TESTFS ; do
+ log_must unshare_fs $TESTPOOL/$fs
+ done
+}
+
+typeset -i ret=0
+
+log_assert "Verify that "zfs share" with a non-existent file system fails."
+
+log_onexit cleanup
+
+log_mustnot zfs list $TESTPOOL/$NONEXISTFSNAME
+
+zfs share $TESTPOOL/$NONEXISTFSNAME
+ret=$?
+(( ret == 1)) || \
+ log_fail "'zfs share $TESTPOOL/$NONEXISTFSNAME' " \
+ "failed with an unexpected return code of $ret."
+
+log_note "Make sure the file system $TESTPOOL/$NONEXISTFSNAME is unshared"
+not_shared $TESTPOOL/$NONEXISTFSNAME || \
+ log_fail "File system $TESTPOOL/$NONEXISTFSNAME is unexpectedly shared."
+
+log_pass "'zfs share' with a non-existent file system fails."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_003_pos.ksh
new file mode 100755
index 000000000000..b99c72ca14e5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_003_pos.ksh
@@ -0,0 +1,110 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Invoking "zfs share <file system>" with a file system
+# whose sharenfs property is 'off' , will fail with a
+# return code of 1 and issue an error message.
+#
+# STRATEGY:
+# 1. Make sure that the ZFS file system is unshared.
+# 2. Mount the file system using the various combinations
+# - zfs set sharenfs=off <file system>
+# - zfs set sharenfs=none <file system>
+# 3. Verify that share failed with return code of 1.
+#
+
+verify_runnable "both"
+
+set -A fs \
+ "$TESTDIR" "$TESTPOOL/$TESTFS" \
+ "$TESTDIR1" "$TESTPOOL/$TESTCTR/$TESTFS1"
+
+function cleanup
+{
+ typeset -i i=0
+ while (( i < ${#fs[*]} )); do
+ log_must zfs inherit -r sharenfs ${fs[((i + 1))]}
+ log_must unshare_fs ${fs[i]}
+
+ ((i = i + 2))
+ done
+}
+
+
+#
+# Main test routine.
+#
+# Given a mountpoint and file system this routine will attempt
+# to share a legacy mountpoint and then verify the share fails as
+# expected.
+#
+function test_legacy_share # mntp filesystem
+{
+ typeset mntp=$1
+ typeset filesystem=$2
+
+ not_shared $mntp || \
+ log_fail "File system $filesystem is already shared."
+
+ if is_global_zone ; then
+ log_must zfs set sharenfs=off $filesystem
+ not_shared $mntp || \
+ log_fail "File system $filesystem is still shared (set sharenfs)."
+ fi
+
+ zfs share $filesystem
+ ret=$?
+ (( ret == 1)) || \
+ log_fail "'zfs share $filesystem' " \
+ "unexpected return code of $ret."
+
+ not_shared $mntp || \
+ log_fail "file system $filesystem is shared (zfs share)."
+}
+
+log_assert "Verify that 'zfs share' with a file system " \
+ "whose sharenfs property is 'off' " \
+ "will fail with return code 1."
+log_onexit cleanup
+
+typeset -i i=0
+while (( i < ${#fs[*]} )); do
+ test_legacy_share ${fs[i]} ${fs[((i + 1))]}
+
+ ((i = i + 2))
+done
+
+log_pass "Verify that 'zfs share' with a file system " \
+ "whose sharenfs property is 'off' fails."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_004_pos.ksh
new file mode 100755
index 000000000000..baa5f4e41695
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_004_pos.ksh
@@ -0,0 +1,96 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_share/zfs_share.cfg
+
+#
+# DESCRIPTION:
+# Verify that a file system and its snapshot are shared.
+#
+# STRATEGY:
+# 1. Create a file system
+# 2. Set the sharenfs property on the file system
+# 3. Create a snapshot
+# 4. Verify that both are shared.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if snapexists $TESTPOOL/$TESTFS@snapshot; then
+ log_must zfs destroy $TESTPOOL/$TESTFS@snapshot
+ fi
+
+ log_must zfs set sharenfs=off $TESTPOOL/$TESTFS
+ log_must unshare_fs $TESTPOOL/$TESTFS
+}
+
+#
+# Main test routine.
+#
+# Given a mountpoint and file system this routine will attempt
+# share the mountpoint and then verify a snapshot of the mounpoint
+# is also shared.
+#
+function test_snap_share # mntp filesystem
+{
+ typeset mntp=$1
+ typeset filesystem=$2
+
+ not_shared $mntp || \
+ log_fail "File system $filesystem is already shared."
+
+ log_must zfs set sharenfs=on $filesystem
+ is_shared $mntp || \
+ log_fail "File system $filesystem is not shared (set sharenfs)."
+
+ log_must ls -l $mntp/$SNAPROOT/snapshot
+ #
+ # Verify 'zfs share' works as well.
+ #
+ log_must zfs unshare $filesystem
+ log_must zfs share $filesystem
+
+ is_shared $mntp || \
+ log_fail "file system $filesystem is not shared (zfs share)."
+
+ log_must ls -l $mntp/$SNAPROOT/snapshot
+}
+
+log_assert "Verify that a file system and its snapshot are shared."
+log_onexit cleanup
+
+log_must zfs snapshot $TESTPOOL/$TESTFS@snapshot
+test_snap_share $TESTDIR $TESTPOOL/$TESTFS
+
+log_pass "A file system and its snapshot are both shared as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_005_pos.ksh
new file mode 100755
index 000000000000..013e04ba311f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_005_pos.ksh
@@ -0,0 +1,93 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that NFS share options are propagated correctly.
+#
+# STRATEGY:
+# 1. Create a ZFS file system.
+# 2. For each option in the list, set the sharenfs property.
+# 3. Verify through the share command that the options are propagated.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must zfs set sharenfs=off $TESTPOOL/$TESTFS
+ is_shared $TESTPOOL/$TESTFS && \
+ log_must unshare_fs $TESTPOOL/$TESTFS
+}
+
+if is_linux; then
+ set -A shareopts \
+ "ro" "rw" "rw,insecure" "rw,async" "ro,crossmnt"
+else
+ set -A shareopts \
+ "ro" "ro=machine1" "ro=machine1:machine2" \
+ "rw" "rw=machine1" "rw=machine1:machine2" \
+ "ro=machine1:machine2,rw" "anon=0" "anon=0,sec=sys,rw" \
+ "nosuid" "root=machine1:machine2" "rw=.mydomain.mycompany.com" \
+ "rw=-terra:engineering" "log" "public"
+fi
+
+log_assert "Verify that NFS share options are propagated correctly."
+log_onexit cleanup
+
+cleanup
+
+typeset -i i=0
+while (( i < ${#shareopts[*]} ))
+do
+ log_must zfs set sharenfs="${shareopts[i]}" $TESTPOOL/$TESTFS
+
+ option=`get_prop sharenfs $TESTPOOL/$TESTFS`
+ if [[ $option != ${shareopts[i]} ]]; then
+ log_fail "get sharenfs failed. ($option != ${shareopts[i]})"
+ fi
+
+ # Verify the single option after the leading 'ro' or 'rw'.
+ if is_linux; then
+ option=`echo "$option" | cut -f2 -d','`
+ fi
+
+ showshares_nfs | grep $option > /dev/null 2>&1
+ if (( $? != 0 )); then
+ log_fail "The '$option' option was not found in share output."
+ fi
+
+ ((i = i + 1))
+done
+
+log_pass "NFS options were propagated correctly."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_006_pos.ksh
new file mode 100755
index 000000000000..6b06589b69e2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_006_pos.ksh
@@ -0,0 +1,105 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that a dataset could not be shared but filesystems are shared.
+#
+# STRATEGY:
+# 1. Create a dataset and file system
+# 2. Set the sharenfs property on the dataset
+# 3. Verify that the dataset is unable be shared.
+# 4. Add a new file system to the dataset.
+# 5. Verify that the newly added file system be shared.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must zfs set sharenfs=off $TESTPOOL/$TESTCTR
+ if mounted $TESTDIR2; then
+ log_must zfs unmount $TESTDIR2
+ fi
+
+ datasetexists $TESTPOOL/$TESTCTR/$TESTFS2 && \
+ log_must zfs destroy $TESTPOOL/$TESTCTR/$TESTFS2
+
+ typeset fs=""
+ for fs in $mntp $TESTDIR1 $TESTDIR2
+ do
+ log_must unshare_fs $fs
+ done
+}
+
+#
+# Main test routine.
+#
+# Given a mountpoint and a dataset, this routine will set the
+# sharenfs property on the dataset and verify that dataset
+# is unable to be shared but the existing contained file systems
+# could be shared.
+#
+function test_ctr_share # mntp ctr
+{
+ typeset mntp=$1
+ typeset ctr=$2
+
+ not_shared $mntp || \
+ log_fail "Mountpoint: $mntp is already shared."
+
+ log_must zfs set sharenfs=on $ctr
+
+ not_shared $mntp || \
+ log_fail "File system $mntp is shared (set sharenfs)."
+
+ #
+ # Add a new file system to the dataset and verify it is shared.
+ #
+ typeset mntp2=$TESTDIR2
+ log_must zfs create $ctr/$TESTFS2
+ log_must zfs set mountpoint=$mntp2 $ctr/$TESTFS2
+
+ is_shared $mntp2 || \
+ log_fail "File system $mntp2 was not shared (set sharenfs)."
+}
+
+log_assert "Verify that a dataset could not be shared, " \
+ "but its sub-filesystems could be shared."
+log_onexit cleanup
+
+typeset mntp=$(get_prop mountpoint $TESTPOOL/$TESTCTR)
+test_ctr_share $mntp $TESTPOOL/$TESTCTR
+
+log_pass "A dataset could not be shared, " \
+ "but its sub-filesystems could be shared as expect."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_007_neg.ksh
new file mode 100755
index 000000000000..29ca9a143a27
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_007_neg.ksh
@@ -0,0 +1,85 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that invalid share parameters and options are caught.
+#
+# STRATEGY:
+# 1. Create a ZFS file system.
+# 2. For each option in the list, set the sharenfs property.
+# 3. Verify that the error code and sharenfs property.
+#
+
+verify_runnable "both"
+
+function cleanup {
+ if is_global_zone; then
+ log_must zfs set sharenfs=off $TESTPOOL/$TESTFS
+ fi
+}
+
+set -A badopts \
+ "r0" "r0=machine1" "r0=machine1:machine2" \
+ "-g" "-b" "-c" "-d" "--invalid" \
+ "$TESTPOOL" "$TESTPOOL/$TESTFS" "$TESTPOOL\$TESTCTR\$TESTFS1"
+
+log_assert "Verify that invalid share parameters and options are caught."
+log_onexit cleanup
+
+typeset -i i=0
+while (( i < ${#badopts[*]} ))
+do
+ log_note "Setting sharenfs=${badopts[i]} $i "
+ log_mustnot zfs set sharenfs="${badopts[i]}" $TESTPOOL/$TESTFS
+
+ showshares_nfs | grep $option > /dev/null 2>&1
+ if (( $? == 0 )); then
+ log_fail "An invalid setting '$option' was propagated."
+ fi
+
+ #
+ # To global zone, sharenfs must be set 'off' before malformed testing.
+ # Otherwise, the malformed test return '0'.
+ #
+ # To non-global zone, sharenfs can be set even 'off' or 'on'.
+ #
+ if is_global_zone; then
+ log_note "Resetting sharenfs option"
+ log_must zfs set sharenfs=off $TESTPOOL/$TESTFS
+ fi
+
+ ((i = i + 1))
+done
+
+log_pass "Invalid share parameters and options we caught as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_008_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_008_neg.ksh
new file mode 100755
index 000000000000..34fbd389949d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_008_neg.ksh
@@ -0,0 +1,74 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that sharing a dataset other than filesystem fails.
+#
+# STRATEGY:
+# 1. Create a ZFS file system.
+# 2. For each dataset in the list, set the sharenfs property.
+# 3. Verify that the invalid datasets are not shared.
+#
+
+verify_runnable "global"
+
+if is_global_zone ; then
+ set -A datasets \
+ "$TESTPOOL/$TESTVOL" "$TESTDIR"
+fi
+
+log_assert "Verify that sharing a dataset other than filesystem fails."
+
+typeset -i i=0
+while (( i < ${#datasets[*]} ))
+do
+ log_mustnot zfs set sharenfs=on ${datasets[i]}
+
+ option=`get_prop sharenfs ${datasets[i]}`
+ if [[ $option == ${datasets[i]} ]]; then
+ log_fail "set sharenfs failed. ($option == ${datasets[i]})"
+ fi
+
+ not_shared ${datasets[i]} || \
+ log_fail "An invalid setting '$option' was propagated."
+
+ log_mustnot zfs share ${datasets[i]}
+
+ not_shared ${datasets[i]} || \
+ log_fail "An invalid dataset '${datasets[i]}' was shared."
+
+ ((i = i + 1))
+done
+
+log_pass "Sharing datasets other than filesystems failed as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_009_neg.ksh
new file mode 100755
index 000000000000..cf8c84cfe301
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_009_neg.ksh
@@ -0,0 +1,73 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that zfs share should fail when sharing a shared zfs filesystem
+#
+# STRATEGY:
+# 1. Make a zfs filesystem shared
+# 2. Use zfs share to share the filesystem
+# 3. Verify that zfs share returns error
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset val
+
+ val=$(get_prop sharenfs $fs)
+ if [[ $val == on ]]; then
+ log_must zfs set sharenfs=off $fs
+ fi
+}
+
+log_assert "zfs share fails with shared filesystem"
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+sharenfs_val=$(get_prop sharenfs $fs)
+mpt=$(get_prop mountpoint $fs)
+if [[ $sharenfs_val == off ]]; then
+ log_must zfs set sharenfs=on $fs
+fi
+
+showshares_nfs | grep $mpt >/dev/null 2>&1
+if (( $? != 0 )); then
+ log_must zfs share $fs
+fi
+
+log_mustnot zfs share $fs
+
+log_pass "zfs share fails with shared filesystem as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_010_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_010_neg.ksh
new file mode 100755
index 000000000000..238a5862920b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_010_neg.ksh
@@ -0,0 +1,60 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that zfs share should fail with bad parameters
+#
+# STRATEGY:
+# 1. Make an array of bad parameters
+# 2. Use zfs share to share the filesystem
+# 3. Verify that zfs share returns error
+#
+
+verify_runnable "both"
+
+log_assert "zfs share fails with bad parameters"
+
+fs=$TESTPOOL/$TESTFS
+set -A badargs "A" "-A" "-" "-x" "-?" "=" "-a *" "-a"
+
+for arg in "${badargs[@]}"; do
+ log_mustnot eval "zfs share $arg $fs >/dev/null 2>&1"
+done
+
+#zfs share failed when missing arguments or invalid datasetname
+for obj in "" "/$fs"; do
+ log_mustnot eval "zfs share $obj >/dev/null 2>&1"
+done
+
+log_pass "zfs share fails with bad parameters as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_011_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_011_pos.ksh
new file mode 100755
index 000000000000..f75877ee89db
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_011_pos.ksh
@@ -0,0 +1,89 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that umount and destroy fail, and do not unshare the shared
+# file system
+#
+# STRATEGY:
+# 1. Share the filesystem via 'zfs set sharenfs'.
+# 2. Try umount failure, and verify that the file system is still shared.
+# 3. Try destroy failure, and verify that the file system is still shared.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must cd $origdir
+
+ log_must zfs set sharenfs=off $TESTPOOL/$TESTFS
+ unshare_fs $TESTPOOL/$TESTFS
+
+ if snapexists "$TESTPOOL/$TESTFS@snapshot"; then
+ log_must zfs destroy -f $TESTPOOL/$TESTFS@snapshot
+ fi
+
+ if datasetexists $TESTPOOL/$TESTFS/fs2 ; then
+ log_must zfs destroy -f $TESTPOOL/$TESTFS/fs2
+ fi
+}
+
+log_assert "Verify that umount and destroy fail, and do not unshare the shared" \
+ "file system"
+log_onexit cleanup
+
+typeset origdir=$PWD
+
+# unmount fails will not unshare the shared filesystem
+log_must zfs set sharenfs=on $TESTPOOL/$TESTFS
+log_must is_shared $TESTDIR
+if cd $TESTDIR ; then
+ log_mustnot zfs umount $TESTPOOL/$TESTFS
+else
+ log_fail "cd $TESTDIR fails"
+fi
+log_must is_shared $TESTDIR
+
+# destroy fails will not unshare the shared filesystem
+log_must zfs create $TESTPOOL/$TESTFS/fs2
+if cd $TESTDIR/fs2 ; then
+ log_mustnot zfs destroy $TESTPOOL/$TESTFS/fs2
+else
+ log_fail "cd $TESTDIR/fs2 fails"
+fi
+log_must is_shared $TESTDIR/fs2
+
+log_pass "Verify that umount and destroy fail, and do not unshare the shared" \
+ "file system"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_012_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_012_pos.ksh
new file mode 100755
index 000000000000..fe38d5559542
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_012_pos.ksh
@@ -0,0 +1,85 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION: Unmounted canmount=noauto export is removed during zfs share -a
+#
+# STRATEGY:
+# 1. Share a dataset that also has canmount set to noauto
+# 2. Capture the zfs exports file when the dataset is mounted + shared
+# 3. Simulate a reboot by unmounting the dataset and restoring the exports file
+# 4. Verify that 'zfs share -a' removes the export since dataset is not mounted
+#
+
+verify_runnable "both"
+
+dataset="$TESTPOOL/$TESTFS"
+mountpt=$(get_prop mountpoint $dataset)
+
+function cleanup
+{
+ zfs set canmount=on $dataset
+ zfs set sharenfs=off $dataset
+ zfs mount -a
+
+ #
+ # unset __ZFS_POOL_EXCLUDE so that we include all file systems when
+ # rebuilding the exports file
+ #
+ unset __ZFS_POOL_EXCLUDE
+ rm /etc/exports.d/zfs.exports
+ zfs share -a
+}
+
+log_assert "Unmounted canmount=noauto export is removed during zfs share -a"
+log_onexit cleanup
+
+log_must zfs set canmount=noauto $dataset
+zfs mount $dataset > /dev/null 2>&1
+log_must mounted $dataset
+log_must zfs set sharenfs=on $dataset
+log_must is_exported $mountpt
+
+log_must cp /etc/exports.d/zfs.exports /etc/exports.d/zfs.exports.save
+log_must zfs umount $dataset
+log_must unmounted $dataset
+log_mustnot is_exported $mountpt
+
+# simulate a reboot condition
+log_must mv /etc/exports.d/zfs.exports.save /etc/exports.d/zfs.exports
+
+log_must is_exported $mountpt
+log_must zfs share -a
+log_mustnot is_exported $mountpt
+
+log_pass "Unmounted canmount=noauto export is removed during zfs share -a"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_concurrent_shares.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_concurrent_shares.ksh
new file mode 100755
index 000000000000..bc45820a1bad
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_concurrent_shares.ksh
@@ -0,0 +1,201 @@
+#!/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) 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that 'zfs set sharenfs=on', 'zfs share', and 'zfs unshare' can
+# run concurrently. The test creates 300 filesystem and 300 threads.
+# Each thread will run through the test strategy in parallel.
+#
+# STRATEGY:
+# 1. Verify that the file system is not shared.
+# 2. Enable the 'sharenfs' property
+# 3. Invoke 'zfs unshare' and verify filesystem is no longer shared
+# 4. Invoke 'zfs share'.
+# 4. Verify that the file system is shared.
+# 5. Verify that a shared filesystem cannot be shared again.
+# 6. Verify that share -a succeeds.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ wait
+ for fs in $(seq 0 100)
+ do
+ log_must zfs set sharenfs=off $TESTPOOL/$TESTFS1/$fs
+ log_must zfs set sharenfs=off $TESTPOOL/$TESTFS2/$fs
+ log_must zfs set sharenfs=off $TESTPOOL/$TESTFS3/$fs
+ unshare_fs $TESTPOOL/$TESTFS1/$fs
+ unshare_fs $TESTPOOL/$TESTFS2/$fs
+ unshare_fs $TESTPOOL/$TESTFS3/$fs
+
+ if mounted $TESTPOOL/$TESTFS1/$fs; then
+ log_must zfs unmount $TESTPOOL/$TESTFS1/$fs
+ fi
+ if mounted $TESTPOOL/$TESTFS2/$fs; then
+ log_must zfs unmount $TESTPOOL/$TESTFS2/$fs
+ fi
+ if mounted $TESTPOOL/$TESTFS3/$fs; then
+ log_must zfs unmount $TESTPOOL/$TESTFS3/$fs
+ fi
+
+ datasetexists $TESTPOOL/$TESTFS1/$fs && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS1/$fs
+ datasetexists $TESTPOOL/$TESTFS2/$fs && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS2/$fs
+ datasetexists $TESTPOOL/$TESTFS3/$fs && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS3/$fs
+ done
+
+ log_must zfs share -a
+}
+
+function create_filesystems
+{
+ for fs in $(seq 0 100)
+ do
+ log_must zfs create -p $TESTPOOL/$TESTFS1/$fs
+ log_must zfs create -p $TESTPOOL/$TESTFS2/$fs
+ log_must zfs create -p $TESTPOOL/$TESTFS3/$fs
+ done
+}
+
+#
+# Main test routine.
+#
+# Given a file system this routine will attempt
+# share the mountpoint and then verify it has been shared.
+#
+function test_share # filesystem
+{
+ typeset filesystem=$1
+ typeset mntp=$(get_prop mountpoint $filesystem)
+
+ not_shared $mntp || \
+ log_fail "File system $filesystem is already shared."
+
+ zfs set sharenfs=on $filesystem || \
+ log_fail "zfs set sharenfs=on $filesystem failed."
+ is_shared $mntp || \
+ log_fail "File system $filesystem is not shared (set sharenfs)."
+
+ #
+ # Verify 'zfs share' works as well.
+ #
+ zfs unshare $filesystem || \
+ log_fail "zfs unshare $filesystem failed."
+ is_shared $mntp && \
+ log_fail "File system $filesystem is still shared."
+
+ zfs share $filesystem || \
+ log_fail "zfs share $filesystem failed."
+ is_shared $mntp || \
+ log_fail "file system $filesystem is not shared (zfs share)."
+
+ #log_note "Sharing a shared file system fails."
+ zfs share $filesystem && \
+ log_fail "zfs share $filesystem did not fail"
+ return 0
+}
+
+#
+# Set the main process id so that we know to capture
+# failures from child processes and allow the parent process
+# to report the failure.
+#
+set_main_pid $$
+log_assert "Verify that 'zfs share' succeeds as root."
+log_onexit cleanup
+
+create_filesystems
+
+child_pids=()
+for fs in $(seq 0 100)
+do
+ test_share $TESTPOOL/$TESTFS1/$fs &
+ child_pids+=($!)
+ log_note "$TESTPOOL/$TESTFS1/$fs ==> $!"
+ test_share $TESTPOOL/$TESTFS2/$fs &
+ child_pids+=($!)
+ log_note "$TESTPOOL/$TESTFS2/$fs ==> $!"
+ test_share $TESTPOOL/$TESTFS3/$fs &
+ child_pids+=($!)
+ log_note "$TESTPOOL/$TESTFS3/$fs ==> $!"
+done
+wait_for_children "${child_pids[@]}" ||
+ log_fail "multithreaded share test failed"
+
+log_note "Verify 'zfs share -a' succeeds."
+
+#
+# Unshare each of the file systems.
+#
+child_pids=()
+for fs in $(seq 0 100)
+do
+ unshare_fs $TESTPOOL/$TESTFS1/$fs &
+ child_pids+=($!)
+ unshare_fs $TESTPOOL/$TESTFS2/$fs &
+ child_pids+=($!)
+ unshare_fs $TESTPOOL/$TESTFS3/$fs &
+ child_pids+=($!)
+done
+wait_for_children "${child_pids[@]}" ||
+ log_fail "multithreaded unshare failed"
+
+#
+# Try a zfs share -a and verify all file systems are shared.
+#
+log_must zfs share -a
+
+#
+# We need to unset __ZFS_POOL_EXCLUDE so that we include all file systems
+# in the os-specific zfs exports file. This will be reset by the next test.
+#
+unset __ZFS_POOL_EXCLUDE
+
+for fs in $(seq 0 100)
+do
+ is_shared $TESTPOOL/$TESTFS1/$fs || \
+ log_fail "File system $TESTPOOL/$TESTFS1/$fs is not shared"
+ is_shared $TESTPOOL/$TESTFS2/$fs || \
+ log_fail "File system $TESTPOOL/$TESTFS2/$fs is not shared"
+ is_shared $TESTPOOL/$TESTFS3/$fs || \
+ log_fail "File system $TESTPOOL/$TESTFS3/$fs is not shared"
+
+ is_exported $TESTPOOL/$TESTFS1/$fs || \
+ log_fail "File system $TESTPOOL/$TESTFS1/$fs is not exported"
+ is_exported $TESTPOOL/$TESTFS2/$fs || \
+ log_fail "File system $TESTPOOL/$TESTFS2/$fs is not exported"
+ is_exported $TESTPOOL/$TESTFS3/$fs || \
+ log_fail "File system $TESTPOOL/$TESTFS3/$fs is not exported"
+done
+
+log_pass "'zfs share [ -a ] <filesystem>' succeeds as root."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/Makefile.am
new file mode 100644
index 000000000000..bc5b801259c8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/Makefile.am
@@ -0,0 +1,16 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_snapshot
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_snapshot_001_neg.ksh \
+ zfs_snapshot_002_neg.ksh \
+ zfs_snapshot_003_neg.ksh \
+ zfs_snapshot_004_neg.ksh \
+ zfs_snapshot_005_neg.ksh \
+ zfs_snapshot_006_pos.ksh \
+ zfs_snapshot_007_neg.ksh \
+ zfs_snapshot_008_neg.ksh \
+ zfs_snapshot_009_pos.ksh
+
+dist_pkgdata_DATA = \
+ zfs_snapshot.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/cleanup.ksh
new file mode 100755
index 000000000000..d247991fbbdb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_container_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/setup.ksh
new file mode 100755
index 000000000000..b3f2b0262687
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_container_volume_setup ${DISK}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot.cfg
new file mode 100644
index 000000000000..fb22367be869
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot.cfg
@@ -0,0 +1,42 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+export SNAPFS="$TESTPOOL/$TESTFS@$TESTSNAP"
+export SNAPFS1="$TESTPOOL/$TESTVOL@$TESTSNAP"
+export SNAPDIR="$TESTDIR@$TESTSNAP"
+export SNAPDIR1="$ZFSROOT/$SNAPFS1"
+export SNAPDEV1="/$TESTDIR/snap1.dat"
+export SNAPDEV2="/$TESTDIR/snap2.dat"
+
+# Name lengths for snappool1 and snappool2 must the same
+export SNAPPOOL1="snappool1"
+export SNAPPOOL2="snappool2"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_001_neg.ksh
new file mode 100755
index 000000000000..8708d8b62432
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_001_neg.ksh
@@ -0,0 +1,117 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_snapshot/zfs_snapshot.cfg
+
+#
+# DESCRIPTION:
+# Try each 'zfs snapshot' with inapplicable scenarios to make sure
+# it returns an error. include:
+# * No arguments given.
+# * The argument contains invalid characters for the ZFS namesapec
+# * Leading slash in snapshot name
+# * The argument contains an empty component.
+# * Missing '@' delimiter.
+# * Multiple '@' delimiters in snapshot name.
+# * The snapshot already exist.
+# * Create snapshot upon the pool.
+# (Be removed since pool is treated as filesystem as well)
+# * Create snapshot upon a non-existent filesystem.
+# * Too many arguments.
+#
+# STRATEGY:
+# 1. Create an array of parameters
+# 2. For each parameter in the array, execute the sub-command
+# 3. Verify an error is returned.
+#
+
+verify_runnable "both"
+
+set -A args "" \
+ "$TESTPOOL/$TESTFS@blah*" "$TESTPOOL/$TESTFS@blah?" \
+ "$TESTPOOL/$TESTVOL@blah*" "$TESTPOOL/$TESTVOL@blah?" \
+ "/$TESTPOOL/$TESTFS@$TESTSNAP" "/$TESTPOOL/$TESTVOL@$TESTSNAP" \
+ "@$TESTSNAP" "$TESTPOOL/$TESTFS@" "$TESTPOOL/$TESTVOL@" \
+ "$TESTPOOL//$TESTFS@$TESTSNAP" "$TESTPOOL//$TESTVOL@$TESTSNAP" \
+ "$TESTPOOL/$TESTFS/$TESTSNAP" "$TESTPOOL/$TESTVOL/$TESTSNAP" \
+ "$TESTPOOL/$TESTFS@$TESTSNAP@$TESTSNAP1" \
+ "$TESTPOOL/$TESTVOL@$TESTSNAP@$TESTSNAP1" \
+ "$SNAPFS" "$SNAPFS1" \
+ "blah/blah@$TESTSNAP"
+
+
+
+function setup_all
+{
+ log_note "Create snapshots and mount them..."
+
+ for snap in $SNAPFS $SNAPFS1; do
+ if ! snapexists $snap; then
+ log_must zfs snapshot $snap
+ fi
+ done
+
+ return 0
+}
+
+function cleanup_all
+{
+ typeset -i i=0
+
+ while (( i < ${#args[*]} )); do
+ for snap in ${args[i]}; do
+ snapexists $snap && log_must zfs destroy -f $snap
+ done
+ (( i = i + 1 ))
+ done
+
+ for mtpt in $SNAPDIR $SNAPDIR1; do
+ [[ -d $mtpt ]] && log_must rm -rf $mtpt
+ done
+
+ return 0
+}
+
+log_assert "Badly-formed 'zfs snapshot' with inapplicable scenarios " \
+ "should return an error."
+log_onexit cleanup_all
+
+setup_all
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_mustnot zfs snapshot ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "Badly formed 'zfs snapshot' with inapplicable scenarios " \
+ "fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_002_neg.ksh
new file mode 100755
index 000000000000..5d8b6e2750f5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_002_neg.ksh
@@ -0,0 +1,98 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# "zfs snapshot -r" fails with invalid arguments or scenarios.
+# The invalid scenarios may include:
+# (1) The child filesystem already has snapshot with the same name
+# (2) The child volume already has snapshot with the same name
+#
+# STRATEGY:
+# 1. Create an array of invalid arguments
+# 2. Execute 'zfs snapshot -r' with each argument in the array,
+# 3. Verify an error is returned.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset snap
+
+ for snap in $TESTPOOL/$TESTCTR/$TESTFS1@$TESTSNAP \
+ $TESTPOOL/$TESTCTR/$TESTVOL@$TESTSNAP;
+ do
+ snapexists $snap && \
+ log_must zfs destroy $snap
+ done
+
+ datasetexists $TESTPOOL/$TESTCTR/$TESTVOL && \
+ log_must zfs destroy -rf $TESTPOOL/$TESTCTR/$TESTVOL
+
+}
+
+log_assert "'zfs snapshot -r' fails with invalid arguments or scenarios. "
+log_onexit cleanup
+
+set -A args "" \
+ "$TESTPOOL/$TESTCTR@$TESTSNAP" "$TESTPOOL/$TESTCTR@blah?" \
+ "$TESTPOOL/$TESTCTR@blah*" "@$TESTSNAP" "$TESTPOOL/$TESTCTR@" \
+ "$TESTPOOL/$TESTFS/$TESTSNAP" "blah/blah@$TESTSNAP" \
+ "$TESTPOOL/$TESTCTR@$TESTSNAP@$TESTSNAP"
+
+# setup preparations
+log_must zfs snapshot $TESTPOOL/$TESTCTR/$TESTFS1@$TESTSNAP
+
+# testing
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_mustnot zfs snapshot -r ${args[i]}
+
+ ((i = i + 1))
+done
+
+# Testing the invalid scenario: the child volume already has an
+# identical name snapshot, zfs snapshot -r should fail when
+# creating snapshot with -r for the parent
+log_must zfs destroy $TESTPOOL/$TESTCTR/$TESTFS1@$TESTSNAP
+if is_global_zone; then
+ log_must zfs create -V $VOLSIZE $TESTPOOL/$TESTCTR/$TESTVOL
+else
+ log_must zfs create $TESTPOOL/$TESTCTR/$TESTVOL
+fi
+log_must zfs snapshot $TESTPOOL/$TESTCTR/$TESTVOL@$TESTSNAP
+
+log_mustnot zfs snapshot -r $TESTPOOL/$TESTCTR@$TESTSNAP
+
+log_pass "'zfs snapshot -r' fails with invalid arguments or scenarios as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_003_neg.ksh
new file mode 100755
index 000000000000..ca8ff8ca4357
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_003_neg.ksh
@@ -0,0 +1,66 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# "zfs snapshot" fails with bad options,too many arguments or too long
+# snapshot name
+#
+# STRATEGY:
+# 1. Create an array of invalid arguments
+# 2. Execute 'zfs snapshot' with each argument in the array,
+# 3. Verify an error is returned.
+#
+
+verify_runnable "both"
+
+log_assert "'zfs snapshot' fails with bad options, or too many arguments. "
+
+set -A badopts "r" "R" "-R" "-x" "-rR" "-?" "-*" "-123"
+
+# set too long snapshot name (>256)
+l_name="$(gen_dataset_name 260 abcdefg)"
+
+for ds in $TESTPOOL/$TESTFS $TESTPOOL/$TESTCTR $TESTPOOL/$TESTVOL; do
+ for opt in ${badopts[@]}; do
+ log_mustnot zfs snapshot $opt $ds@$TESTSNAP
+ done
+
+ log_mustnot zfs snapshot $ds@snap $ds@snap1
+ log_mustnot zfs snapshot -r $ds@snap $ds@snap1
+
+ log_mustnot zfs snapshot $ds@$l_name
+ log_mustnot zfs snapshot -r $ds@$l_name
+done
+
+log_pass "'zfs snapshot' fails with bad options or too many arguments as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_004_neg.ksh
new file mode 100755
index 000000000000..96121f1c136d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_004_neg.ksh
@@ -0,0 +1,96 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify recursive snapshotting could not break ZFS.
+#
+# STRATEGY:
+# 1. Create deeply-nested filesystems until it is too long to create snap
+# 2. Verify zfs snapshot -r pool@snap will not break ZFS
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $initfs ; then
+ log_must zfs destroy -rf $initfs
+ fi
+}
+
+log_assert "Verify recursive snapshotting could not break ZFS."
+log_onexit cleanup
+
+initfs=$TESTPOOL/$TESTFS/$TESTFS
+basefs=$initfs
+typeset -i ret=0 len snaplen
+while ((ret == 0)); do
+ zfs create $basefs
+ zfs snapshot $basefs@snap1
+ ret=$?
+
+ if ((ret != 0)); then
+ len=$(echo $basefs| wc -c)
+ log_note "The deeply-nested filesystem len: $len"
+
+ #
+ # Make sure there are at lease 2 characters left
+ # for snapshot name space, otherwise snapshot name
+ # is incorrect
+ #
+ if ((len >= 255)); then
+ if datasetexists $basefs; then
+ log_must zfs destroy -r $basefs
+ fi
+ basefs=${basefs%/*}
+ len=$(echo $basefs| wc -c)
+ fi
+ break
+ fi
+
+ basefs=$basefs/$TESTFS
+done
+
+# Make snapshot name is longer than the max length
+((snaplen = 256 - len + 10))
+snap=$(gen_dataset_name $snaplen "s")
+log_mustnot zfs snapshot -r $TESTPOOL@$snap
+
+log_must datasetnonexists $TESTPOOL@$snap
+while [[ $basefs != $TESTPOOL ]]; do
+ log_must datasetnonexists $basefs@$snap
+ basefs=${basefs%/*}
+done
+
+log_pass "Verify recursive snapshotting could not break ZFS."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_005_neg.ksh
new file mode 100755
index 000000000000..d97dc0f82265
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_005_neg.ksh
@@ -0,0 +1,96 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Long name filesystem with snapshot should not break ZFS.
+#
+# STRATEGY:
+# 1. Create filesystem and snapshot.
+# 2. When the snapshot length is 256, rename the filesystem.
+# 3. Verify it does not break ZFS
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $initfs ; then
+ log_must zfs destroy -rf $initfs
+ fi
+}
+
+log_assert "Verify long name filesystem with snapshot should not break ZFS."
+log_onexit cleanup
+
+initfs=$TESTPOOL/$TESTFS/$TESTFS
+basefs=$initfs
+typeset -i ret=0 len snaplen
+while ((ret == 0)); do
+ zfs create $basefs
+ zfs snapshot $basefs@snap1
+ ret=$?
+
+ if ((ret != 0)); then
+ len=$(echo $basefs | wc -c)
+ log_note "The deeply-nested filesystem len: $len"
+
+ #
+ # Make sure there are at lease 2 characters left
+ # for snapshot name space, otherwise snapshot name
+ # is incorrect
+ #
+ if ((len >= 255)); then
+ if datasetexists $basefs; then
+ log_must zfs destroy -r $basefs
+ fi
+ basefs=${basefs%/*}
+ len=$(echo $basefs| wc -c)
+ fi
+ break
+ fi
+
+ basefs=$basefs/$TESTFS
+done
+
+# Make snapshot name length match the longest one
+((snaplen = 256 - len - 1)) # 1: @
+snap=$(gen_dataset_name $snaplen "s")
+log_must zfs snapshot $basefs@$snap
+
+log_mustnot zfs rename $basefs ${basefs}a
+log_mustnot zfs rename $basefs ${basefs}-new
+log_mustnot zfs rename $initfs ${initfs}-new
+log_mustnot zfs rename $TESTPOOL/$TESTFS $TESTPOOL/$TESTFS-new
+
+log_pass "Verify long name filesystem with snapshot should not break ZFS."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_006_pos.ksh
new file mode 100755
index 000000000000..089ebdb97924
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_006_pos.ksh
@@ -0,0 +1,124 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# User property could be set via creation time by 'zfs snapshot -o'
+#
+# STRATEGY:
+# 1. Create snapshot and give '-o property=value'
+# 2. Verify the snapshot be created and user property have been set.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for fs in $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL $TESTPOOL ; do
+ typeset fssnap=$fs@snap
+ if datasetexists $fssnap ; then
+ log_must zfs destroy -rf $fssnap
+ fi
+ done
+ cleanup_user_prop $TESTPOOL
+}
+
+function nonexist_user_prop
+{
+ typeset user_prop=$1
+ typeset dtst=$2
+
+ typeset source=$(get_source $user_prop $dtst)
+ typeset value=$(get_prop $user_prop $dtst)
+ if [[ $source == '-' && $value == '-' ]]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+log_assert "User property could be set upon snapshot via 'zfs snapshot -o'."
+log_onexit cleanup
+
+typeset snap_property=
+
+for fs in $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL $TESTPOOL ; do
+ typeset fssnap=$fs@snap
+ prop_name=$(valid_user_property 10)
+ value=$(user_property_value 16)
+
+ log_must eval "zfs snapshot -o $prop_name='$value' $fssnap"
+ log_must snapexists $fssnap
+ log_mustnot nonexist_user_prop $prop_name $fssnap
+
+ log_must zfs destroy -f $fssnap
+
+ prop_name2=$(valid_user_property 10)
+ value2=$(user_property_value 16)
+
+ log_must eval "zfs snapshot -o $prop_name='$value' -o $prop_name2='$value2' $fssnap"
+ log_must snapexists $fssnap
+ log_mustnot nonexist_user_prop $prop_name $fssnap
+ log_mustnot nonexist_user_prop $prop_name2 $fssnap
+done
+
+cleanup
+
+prop_name=$(valid_user_property 10)
+value=$(user_property_value 16)
+
+log_must eval "zfs snapshot -r -o $prop_name='$value' $TESTPOOL@snap"
+for fs in $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL $TESTPOOL ; do
+ typeset fssnap=$fs@snap
+ log_must snapexists $fssnap
+ log_mustnot nonexist_user_prop $prop_name $fssnap
+
+ log_must zfs destroy -rf $fssnap
+done
+
+cleanup
+
+prop_name2=$(valid_user_property 10)
+value2=$(user_property_value 16)
+
+log_must eval "zfs snapshot -r -o $prop_name='$value' -o $prop_name2='$value2' $TESTPOOL@snap"
+for fs in $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL $TESTPOOL ; do
+ typeset fssnap=$fs@snap
+ log_must snapexists $fssnap
+ log_mustnot nonexist_user_prop $prop_name $fssnap
+ log_mustnot nonexist_user_prop $prop_name2 $fssnap
+
+ log_must zfs destroy -rf $fssnap
+done
+
+log_pass "User property could be set upon snapshot via 'zfs snapshot -o'."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_007_neg.ksh
new file mode 100755
index 000000000000..9d8c1373f91e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_007_neg.ksh
@@ -0,0 +1,137 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs snapshot -o' cannot set properties other than user property
+#
+# STRATEGY:
+# 1. Create snapshot and give '-o property=value' with regular property.
+# 2. Verify the snapshot creation failed.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for fs in $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL $TESTPOOL/$TESTCTR $TESTPOOL ; do
+ typeset fssnap=$fs@snap
+ if datasetexists $fssnap ; then
+ log_must zfs destroy -rf $fssnap
+ fi
+ done
+ cleanup_user_prop $TESTPOOL
+}
+
+function nonexist_user_prop
+{
+ typeset user_prop=$1
+ typeset dtst=$2
+
+ typeset source=$(get_source $user_prop $dtst)
+ typeset value=$(get_prop $user_prop $dtst)
+ if [[ $source == '-' && $value == '-' ]]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+log_assert "'zfs snapshot -o' cannot set properties other than user property."
+log_onexit cleanup
+
+typeset ro_props="type used available avail creation referenced refer compressratio \
+ mounted origin"
+typeset snap_ro_props="volsize recordsize recsize quota reservation reserv mountpoint \
+ sharenfs checksum compression compress atime devices exec readonly rdonly \
+ setuid"
+if is_freebsd; then
+ snap_ro_props+=" jailed"
+else
+ snap_ro_props+=" zoned"
+fi
+
+zfs upgrade -v > /dev/null 2>&1
+if [[ $? -eq 0 ]]; then
+ snap_ro_props="$snap_ro_props version"
+fi
+
+
+for fs in $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL $TESTPOOL/$TESTCTR $TESTPOOL ; do
+ typeset fssnap=$fs@snap
+ prop_name=$(valid_user_property 10)
+ value=$(user_property_value 16)
+
+ log_must eval "zfs snapshot -o $prop_name='$value' $fssnap"
+ log_must snapexists $fssnap
+ log_mustnot nonexist_user_prop $prop_name $fssnap
+
+ log_must zfs destroy -f $fssnap
+
+ prop_name2=$(valid_user_property 10)
+ value2=$(user_property_value 16)
+
+ log_must eval "zfs snapshot -o $prop_name='$value' -o $prop_name2='$value2' $fssnap"
+ log_must snapexists $fssnap
+ log_mustnot nonexist_user_prop $prop_name $fssnap
+ log_mustnot nonexist_user_prop $prop_name2 $fssnap
+
+ log_must zfs destroy -f $fssnap
+done
+
+cleanup
+
+prop_name=$(valid_user_property 10)
+value=$(user_property_value 16)
+
+log_must eval "zfs snapshot -r -o $prop_name='$value' $TESTPOOL@snap"
+for fs in $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL $TESTPOOL/$TESTCTR $TESTPOOL ; do
+ typeset fssnap=$fs@snap
+ log_must snapexists $fssnap
+ log_mustnot nonexist_user_prop $prop_name $fssnap
+done
+
+cleanup
+
+prop_name2=$(valid_user_property 10)
+value2=$(user_property_value 16)
+
+log_must eval "zfs snapshot -r -o $prop_name='$value' -o $prop_name2='$value2' $TESTPOOL@snap"
+for fs in $TESTPOOL/$TESTFS $TESTPOOL/$TESTVOL $TESTPOOL/$TESTCTR $TESTPOOL ; do
+ typeset fssnap=$fs@snap
+ log_must snapexists $fssnap
+ log_mustnot nonexist_user_prop $prop_name $fssnap
+ log_mustnot nonexist_user_prop $prop_name2 $fssnap
+done
+
+log_pass "'zfs snapshot -o' cannot set properties other than user property."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_008_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_008_neg.ksh
new file mode 100755
index 000000000000..627910abd6ed
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_008_neg.ksh
@@ -0,0 +1,68 @@
+#!/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) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_snapshot/zfs_snapshot.cfg
+
+#
+# DESCRIPTION:
+# 'zfs snapshot pool1@snap pool2@snap' should fail since both snapshots
+# are not in the same pool.
+#
+# STRATEGY:
+# 1. Create 2 separate zpools, zpool name lengths must be the same.
+# 2. Attempt to simultaneously create a snapshot of each pool.
+# 3. Verify the snapshot creation failed.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for pool in $SNAPPOOL1 $SNAPPOOL2 ; do
+ if poolexists $pool ; then
+ log_must zpool destroy -f $pool
+ fi
+ done
+
+ for dev in $SNAPDEV1 $SNAPDEV2 ; do
+ if [[ -f $dev ]] ; then
+ log_must rm -f $dev
+ fi
+ done
+}
+
+log_assert "'zfs snapshot pool1@snap1 pool2@snap2' should fail since snapshots are in different pools."
+log_onexit cleanup
+
+log_must mkfile $MINVDEVSIZE $SNAPDEV1
+log_must mkfile $MINVDEVSIZE $SNAPDEV2
+
+log_must zpool create $SNAPPOOL1 $SNAPDEV1
+log_must zpool create $SNAPPOOL2 $SNAPDEV2
+
+log_mustnot zfs snapshot $SNAPPOOL1@snap1 $SNAPPOOL2@snap2
+
+log_pass "'zfs snapshot pool1@snap1 pool2@snap2' should fail since snapshots are in different pools."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_009_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_009_pos.ksh
new file mode 100755
index 000000000000..f0682b816ae8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_snapshot/zfs_snapshot_009_pos.ksh
@@ -0,0 +1,115 @@
+#!/bin/ksh
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+#
+# DESCRIPTION
+# verify 'zfs snapshot <list of snapshots>' works correctly
+#
+# STRATEGY
+# 1. Create multiple datasets
+# 2. Create multiple snapshots with a list of valid and invalid
+# snapshot names
+# 3. Verify the valid snapshot creation
+
+. $STF_SUITE/include/libtest.shlib
+
+ZFS_MAX_DATASET_NAME_LEN=256
+
+function cleanup
+{
+ for ds in $datasets; do
+ datasetexists $ds && log_must zfs destroy -r $ds
+ done
+ zfs destroy -r $TESTPOOL/TESTFS4
+}
+datasets="$TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS2
+ $TESTPOOL/$TESTFS3"
+
+# We subtract 3 for slash (/), at (@), and the terminating nul (\0)
+SNAPSHOT_XXX=$(printf 'x%.0s' \
+ {1..$(($ZFS_MAX_DATASET_NAME_LEN - ${#TESTPOOL} - ${#TESTFS1} - 3))})
+
+invalid_args=("$TESTPOOL/$TESTFS1@now $TESTPOOL/$TESTFS2@now \
+ $TESTPOOL/$TESTFS@blah?" "$TESTPOOL/$TESTFS1@blah* \
+ $TESTPOOL/$TESTFS2@blah? $TESTPOOL/$TESTFS3@blah%" \
+ "$TESTPOOL/$TESTFS1@x$SNAPSHOT_XXX $TESTPOOL/$TESTFS2@300 \
+ $TESTPOOL/$TESTFS3@300")
+
+valid_args=("$TESTPOOL/$TESTFS1@snap $TESTPOOL/$TESTFS2@snap \
+ $TESTPOOL/$TESTFS3@snap" "$TESTPOOL/$TESTFS1@$SNAPSHOT_XXX \
+ $TESTPOOL/$TESTFS2@2 $TESTPOOL/$TESTFS3@s")
+
+log_assert "verify zfs supports multiple consistent snapshots"
+log_onexit cleanup
+typeset -i i=1
+test_data=$STF_SUITE/tests/functional/cli_root/zpool_upgrade/blockfiles/*.bz2
+
+log_note "destroy a list of valid snapshots"
+for ds in $datasets; do
+ log_must zfs create $ds
+ log_must cp -r $test_data /$ds
+done
+i=0
+while (( i < ${#valid_args[*]} )); do
+ log_must zfs snapshot ${valid_args[i]}
+ for token in ${valid_args[i]}; do
+ log_must snapexists $token && \
+ log_must zfs destroy $token
+ done
+ ((i = i + 1))
+done
+log_note "destroy a list of invalid snapshots"
+i=0
+while (( i < ${#invalid_args[*]} )); do
+ log_mustnot zfs snapshot ${invalid_args[i]}
+ for token in ${invalid_args[i]}; do
+ log_mustnot snapexists $token
+ done
+ ((i = i + 1))
+done
+log_note "verify multiple snapshot transaction group"
+txg_group=$(zdb -Pd $TESTPOOL | grep snap | awk '{print $7}')
+for i in 1 2 3; do
+ txg_tag=$(echo "$txg_group" | nawk -v j=$i 'FNR == j {print}')
+ [[ $txg_tag != $(echo "$txg_group" | \
+ nawk -v j=$i 'FNR == j {print}') ]] \
+ && log_fail "snapshots belong to different transaction groups"
+done
+log_note "verify snapshot contents"
+for ds in $datasets; do
+ diff -q -r /$ds /$ds/.zfs/snapshot/snap > /dev/null 2>&1
+ if [[ $? -eq 1 ]]; then
+ log_fail "snapshot contents are different from" \
+ "the filesystem"
+ fi
+done
+
+# We subtract 3 + 7 + 7 + 1 = 18 for three slashes (/), strlen("TESTFSA") == 7,
+# strlen("TESTFSB") == 7, and the terminating nul (\0)
+DATASET_XXX=$(printf 'x%.0s' \
+ {1..$(($ZFS_MAX_DATASET_NAME_LEN - ${#TESTPOOL} - ${#TESTFS3} - 18))})
+
+log_note "verify multiple snapshot with -r option"
+log_must zfs create $TESTPOOL/TESTFS4
+log_must zfs create -p $TESTPOOL/$TESTFS3/TESTFSA$DATASET_XXX/TESTFSB
+log_mustnot zfs snapshot -r $TESTPOOL/$TESTFS1@snap1 $TESTPOOL/$TESTFS2@snap1 \
+ $TESTPOOL/$TESTFS3@snap1 $TESTPOOL/TESTFS4@snap1
+log_must zfs rename $TESTPOOL/$TESTFS3/TESTFSA$DATASET_XXX \
+ $TESTPOOL/$TESTFS3/TESTFSA
+log_must zfs snapshot -r $TESTPOOL/$TESTFS1@snap1 $TESTPOOL/$TESTFS2@snap1 \
+ $TESTPOOL/$TESTFS3@snap1 $TESTPOOL/TESTFS4@snap1
+
+log_pass "zfs multiple snapshot verified correctly"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/Makefile.am
new file mode 100644
index 000000000000..6a83edf2a443
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/Makefile.am
@@ -0,0 +1,10 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_sysfs
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfeature_set_unsupported.ksh \
+ zfs_get_unsupported.ksh \
+ zfs_set_unsupported.ksh \
+ zfs_sysfs_live.ksh \
+ zpool_get_unsupported.ksh \
+ zpool_set_unsupported.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/cleanup.ksh
new file mode 100755
index 000000000000..7d6a7e13db22
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/cleanup.ksh
@@ -0,0 +1,34 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+if ! is_linux ; then
+ log_unsupported "sysfs is linux-only"
+fi
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/setup.ksh
new file mode 100755
index 000000000000..261bce4386e9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/setup.ksh
@@ -0,0 +1,36 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+if ! is_linux ; then
+ log_unsupported "sysfs is linux-only"
+fi
+
+DISK=${DISKS%% *}
+
+default_container_volume_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfeature_set_unsupported.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfeature_set_unsupported.ksh
new file mode 100755
index 000000000000..c9d24224337f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfeature_set_unsupported.ksh
@@ -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) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# A feature not supported by the zfs module should fail in 'zpool set <feature>'
+#
+# STRATEGY:
+# 1. Run zpool set <featureprop> with env var 'ZFS_SYSFS_PROP_SUPPORT_TEST'
+# 2. Verify that zpool set returns error
+#
+
+verify_runnable "global"
+
+if ! is_linux ; then
+ log_unsupported "sysfs is linux-only"
+fi
+
+claim="Features not supported by zfs module should fail in 'zpool set <feature>'"
+
+unsupported_feature="feature@large_blocks"
+value="enabled"
+
+log_assert $claim
+
+log_mustnot eval "ZFS_SYSFS_PROP_SUPPORT_TEST=yes zpool set \
+ ${unsupported_feature}=${value} $TESTPOOL/$TESTFS >/dev/null 2>&1"
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_get_unsupported.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_get_unsupported.ksh
new file mode 100755
index 000000000000..59ed7e9500dd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_get_unsupported.ksh
@@ -0,0 +1,53 @@
+#!/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) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# A property not supported by the zfs module should fail in 'zfs get <prop>'
+#
+# STRATEGY:
+# 1. Run zfs get <prop> with the env variable 'ZFS_SYSFS_PROP_SUPPORT_TEST'
+# 2. Verify that zfs get returns error
+#
+
+verify_runnable "global"
+
+if ! is_linux ; then
+ log_unsupported "sysfs is linux-only"
+fi
+
+claim="Properties not supported by zfs module should fail in 'zfs get <prop>'"
+
+unsupported_prop="dnodesize"
+
+log_assert $claim
+
+log_mustnot eval "ZFS_SYSFS_PROP_SUPPORT_TEST=yes zfs get ${unsupported_prop} \
+ $TESTPOOL/$TESTFS >/dev/null 2>&1"
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_set_unsupported.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_set_unsupported.ksh
new file mode 100755
index 000000000000..5a0b88a0b14d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_set_unsupported.ksh
@@ -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) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# A property not supported by the zfs module should fail in 'zfs set <prop>'
+#
+# STRATEGY:
+# 1. Run zfs set <prop> with the env variable 'ZFS_SYSFS_PROP_SUPPORT_TEST'
+# 2. Verify that zfs get returns error
+#
+
+verify_runnable "global"
+
+if ! is_linux ; then
+ log_unsupported "sysfs is linux-only"
+fi
+
+claim="Properties not supported by zfs module should fail in 'zfs set <prop>'"
+
+unsupported_prop="dnodesize"
+value="any"
+
+log_assert $claim
+
+log_mustnot eval "ZFS_SYSFS_PROP_SUPPORT_TEST=yes zfs set \
+ ${unsupported_prop}=${value} $TESTPOOL/$TESTFS >/dev/null 2>&1"
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_sysfs_live.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_sysfs_live.ksh
new file mode 100755
index 000000000000..4bb5cc2e05ba
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zfs_sysfs_live.ksh
@@ -0,0 +1,59 @@
+#!/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) 2018, 2019 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Test if the expected '/sys/module/zfs/<dir>/<attr>' are present
+#
+
+verify_runnable "global"
+
+if ! is_linux ; then
+ log_unsupported "sysfs is linux-only"
+fi
+
+claim="Expected '/sys/module/zfs/<dir>/<attr>' attributes are present"
+
+kernel_feature_attr="/sys/module/zfs/features.kernel/org.zfsonlinux:vdev_trim/supported"
+pool_feature_attr="/sys/module/zfs/features.pool/org.open-zfs:large_blocks/guid"
+pool_prop__attr="/sys/module/zfs/properties.pool/comment/values"
+ds_prop__attr="/sys/module/zfs/properties.dataset/recordsize/values"
+
+log_assert $claim
+
+log_must cat $kernel_feature_attr
+log_must cat $pool_feature_attr
+log_must cat $pool_prop__attr
+log_must cat $ds_prop__attr
+
+# force a read of all the attributes for show func code coverage
+log_must grep -R "[a-z]" /sys/module/zfs/features.*
+log_must grep -R "[a-z]" /sys/module/zfs/properties.*
+log_mustnot grep -RE "[^[:print:]]" /sys/module/zfs/properties.*
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_get_unsupported.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_get_unsupported.ksh
new file mode 100755
index 000000000000..3ab1d941e860
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_get_unsupported.ksh
@@ -0,0 +1,55 @@
+#!/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) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# A property not supported by the zfs module should fail in 'zpool get <prop>'
+#
+# STRATEGY:
+# 1. Run zpool get <prop> with the env variable 'ZFS_SYSFS_PROP_SUPPORT_TEST'
+# 2. Verify that zfs get returns error
+#
+
+verify_runnable "global"
+
+if ! is_linux ; then
+ log_unsupported "sysfs is linux-only"
+fi
+
+export ZFS_SYSFS_PROP_SUPPORT_TEST
+
+claim="Properties not supported by zfs module should fail in 'zpool get <prop>'"
+
+unsupported_prop="comment"
+
+log_assert $claim
+
+log_mustnot eval "ZFS_SYSFS_PROP_SUPPORT_TEST=yes zpool get \
+ ${unsupported_prop} $TESTPOOL/$TESTFS >/dev/null 2>&1"
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_set_unsupported.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_set_unsupported.ksh
new file mode 100755
index 000000000000..03eb2aea3fdd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_sysfs/zpool_set_unsupported.ksh
@@ -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) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# A property not supported by the zfs module should fail in 'zpool set <prop>'
+#
+# STRATEGY:
+# 1. Run zpool set <prop> with the env variable 'ZFS_SYSFS_PROP_SUPPORT_TEST'
+# 2. Verify that zpool set returns error
+#
+
+verify_runnable "global"
+
+if ! is_linux ; then
+ log_unsupported "sysfs is linux-only"
+fi
+
+claim="Properties not supported by zfs module should fail in 'zpool set <prop>'"
+
+unsupported_prop="comment"
+value="You Shall Not Pass"
+
+log_assert $claim
+
+log_mustnot eval "ZFS_SYSFS_PROP_SUPPORT_TEST=yes zpool set \
+ ${unsupported_prop}=${value} $TESTPOOL/$TESTFS >/dev/null 2>&1"
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/Makefile.am
new file mode 100644
index 000000000000..74cdf5c2b558
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/Makefile.am
@@ -0,0 +1,7 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_unload-key
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_unload-key.ksh \
+ zfs_unload-key_all.ksh \
+ zfs_unload-key_recursive.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/zfs_unload-key.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/zfs_unload-key.ksh
new file mode 100755
index 000000000000..9e08ac69d4de
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/zfs_unload-key.ksh
@@ -0,0 +1,69 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs unload-key' should only unload the key of an unmounted dataset.
+#
+# STRATEGY:
+# 1. Attempt to unload the default dataset's key
+# 2. Unmount the dataset
+# 3. Attempt to unload the default dataset's key
+# 4. Create an encrypted dataset
+# 5. Attempt to unload the dataset's key
+# 6. Verify the key is loaded
+# 7. Unmount the dataset
+# 8. Attempt to unload the dataset's key
+# 9. Verify the key is not loaded
+# 10. Attempt to unload the dataset's key
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy $TESTPOOL/$TESTFS1
+}
+log_onexit cleanup
+
+log_assert "'zfs unload-key' should unload the key for an unmounted" \
+ "encrypted dataset"
+
+log_mustnot zfs unload-key $TESTPOOL/$TESTFS
+
+log_must zfs unmount $TESTPOOL/$TESTFS
+log_mustnot zfs unload-key $TESTPOOL/$TESTFS
+
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS1"
+log_mustnot zfs unload-key $TESTPOOL/$TESTFS1
+log_must key_available $TESTPOOL/$TESTFS1
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+log_must key_unavailable $TESTPOOL/$TESTFS1
+
+log_mustnot zfs unload-key $TESTPOOL/$TESTFS1
+
+log_pass "'zfs unload-key' unloads the key for an unmounted encrypted dataset"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/zfs_unload-key_all.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/zfs_unload-key_all.ksh
new file mode 100755
index 000000000000..ecb98d189424
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/zfs_unload-key_all.ksh
@@ -0,0 +1,76 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs unload-key -a' should unload keys for all datasets.
+#
+# STRATEGY:
+# 1. Create an encrypted filesystem, encrypted child dataset, an encrypted
+# zvol, and an encrypted pool
+# 2. Unmount all datasets
+# 3. Attempt to unload all dataset keys
+# 4. Verify each dataset has its key unloaded
+# 5. Attempt to mount each dataset
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+ datasetexists $TESTPOOL/zvol && log_must zfs destroy $TESTPOOL/zvol
+ poolexists $TESTPOOL1 && log_must destroy_pool $TESTPOOL1
+}
+log_onexit cleanup
+
+log_assert "'zfs unload-key -a' should unload keys for all datasets"
+
+log_must eval "echo $PASSPHRASE1 > /$TESTPOOL/pkey"
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1
+log_must zfs create $TESTPOOL/$TESTFS1/child
+
+log_must zfs create -V 64M -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/zvol
+
+typeset DISK2="$(echo $DISKS | awk '{ print $2}')"
+log_must zpool create -O encryption=on -O keyformat=passphrase \
+ -O keylocation=file:///$TESTPOOL/pkey $TESTPOOL1 $DISK2
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unmount $TESTPOOL1
+
+log_must zfs unload-key -a
+
+log_must key_unavailable $TESTPOOL/$TESTFS1
+log_must key_unavailable $TESTPOOL/$TESTFS1/child
+log_must key_unavailable $TESTPOOL/zvol
+log_must key_unavailable $TESTPOOL1
+
+log_mustnot zfs mount $TESTPOOL
+log_mustnot zfs mount $TESTPOOL/zvol
+log_mustnot zfs mount $TESTPOOL/$TESTFS1
+
+log_pass "'zfs unload-key -a' unloads keys for all datasets"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/zfs_unload-key_recursive.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/zfs_unload-key_recursive.ksh
new file mode 100755
index 000000000000..9766b590587f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unload-key/zfs_unload-key_recursive.ksh
@@ -0,0 +1,72 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs unload-key -r' should recursively unload keys.
+#
+# STRATEGY:
+# 1. Create a parent encrypted dataset
+# 2. Create a sibling encrypted dataset
+# 3. Create a child dataset as an encryption root
+# 4. Unmount all datasets
+# 5. Attempt to unload all dataset keys under parent
+# 6. Verify parent and child have their keys unloaded
+# 7. Verify sibling has its key loaded
+# 8. Attempt to mount all datasets
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+}
+log_onexit cleanup
+
+log_assert "'zfs unload-key -r' should recursively unload keys"
+
+log_must eval "echo $PASSPHRASE > /$TESTPOOL/pkey"
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1
+log_must zfs create -o keyformat=passphrase \
+ -o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1/child
+log_must eval "echo $PASSPHRASE1 | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS2"
+
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unmount $TESTPOOL/$TESTFS2
+
+log_must zfs unload-key -r $TESTPOOL/$TESTFS1
+
+log_must key_unavailable $TESTPOOL/$TESTFS1
+log_must key_unavailable $TESTPOOL/$TESTFS1/child
+
+log_must key_available $TESTPOOL/$TESTFS2
+
+log_mustnot zfs mount $TESTPOOL/$TESTFS1
+log_mustnot zfs mount $TESTPOOL/$TESTFS1/child
+log_must zfs mount $TESTPOOL/$TESTFS2
+
+log_pass "'zfs unload-key -r' recursively unloads keys"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/Makefile.am
new file mode 100644
index 000000000000..6507b094df47
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/Makefile.am
@@ -0,0 +1,20 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_unmount
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_unmount_001_pos.ksh \
+ zfs_unmount_002_pos.ksh \
+ zfs_unmount_003_pos.ksh \
+ zfs_unmount_004_pos.ksh \
+ zfs_unmount_005_pos.ksh \
+ zfs_unmount_006_pos.ksh \
+ zfs_unmount_007_neg.ksh \
+ zfs_unmount_008_neg.ksh \
+ zfs_unmount_009_pos.ksh \
+ zfs_unmount_all_001_pos.ksh \
+ zfs_unmount_nested.ksh \
+ zfs_unmount_unload_keys.ksh
+
+dist_pkgdata_DATA = \
+ zfs_unmount.cfg \
+ zfs_unmount.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.cfg
new file mode 100644
index 000000000000..c8e46895d2a6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.cfg
@@ -0,0 +1,39 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+export mountcmd=mount
+export mountforce="$mountcmd -f"
+export mountall="$mountcmd -a"
+
+export unmountcmd=unmount
+export unmountforce="$unmountcmd -f"
+export unmountall="$unmountcmd -a"
+
+export NONEXISTFSNAME="nonexistfs50charslong_0123456789012345678901234567"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib
new file mode 100644
index 000000000000..525dfd162957
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib
@@ -0,0 +1,77 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_unmount/zfs_unmount.cfg
+
+function do_unmount #cmd #opt #mnt #expect
+{
+ typeset cmd=$1
+ typeset opt=$2
+ typeset mnt=$3
+ typeset -i expect=${4-0}
+ typeset -i ret
+ typeset -i wasmounted=1
+
+ mounted $mnt || wasmounted=0
+
+ if (( expect == 0 )) ; then
+ log_must zfs $cmd $opt $mnt
+
+ log_must unmounted $mnt
+
+ log_note "Successfully zfs $cmd $opt $mnt"
+
+ else
+ log_note "zfs $cmd $opt $mnt"
+
+ zfs $cmd $opt $mnt
+ ret=$?
+ if (( ret != expect)); then
+ log_fail "'zfs $cmd $opt $mnt' " \
+ "unexpected return code of $ret."
+ fi
+
+ if (( wasmounted == 1 )) ; then
+ log_must mounted $mnt
+ else
+ log_must unmounted $mnt
+ fi
+ log_note "Mount status of $mnt not changed."
+ fi
+}
+
+function cleanup
+{
+ [[ -n $cwd ]] && cd $cwd
+
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+ mounted $TESTPOOL/$TESTFS || \
+ log_must zfs $mountcmd $TESTPOOL/$TESTFS
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_001_pos.ksh
new file mode 100755
index 000000000000..fb4d1d937895
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_001_pos.ksh
@@ -0,0 +1,117 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Creates a file system and verifies that it can be unmounted
+# using each of the various unmount options and sub-command
+# variants.
+#
+# STRATEGY:
+# 1. Create and mount a file system as necessary.
+# 2. Umount the file system using the various combinations.
+# - With force option.
+# - Without force option.
+# - Using the unmount sub-command.
+# - Using the umount sub-command.
+#
+
+verify_runnable "both"
+
+
+function cleanup
+{
+ mounted $TESTDIR2 && \
+ log_must zfs umount -f $TESTDIR2
+
+ datasetexists $TESTPOOL/$TESTFS2 && \
+ log_must zfs destroy $TESTPOOL/$TESTFS2
+
+ [[ -d $TESTDIR2 ]] && \
+ log_must rm -rf $TESTDIR2
+}
+function do_unmount
+{
+ typeset cmd=$1
+ typeset opt=$2
+ typeset mnt=$3
+
+ [[ ! -d $TESTDIR2 ]] && \
+ log_must mkdir $TESTDIR2
+
+ if ! datasetexists $TESTPOOL/$TESTFS2 ; then
+ log_must zfs create $TESTPOOL/$TESTFS2
+ log_must zfs set mountpoint=$TESTDIR2 \
+ $TESTPOOL/$TESTFS2
+ fi
+
+ unmounted $TESTPOOL/$TESTFS2 && \
+ log_must zfs mount $TESTPOOL/$TESTFS2
+
+ log_must zfs $cmd $options $mnt
+
+ unmounted "$mnt" || \
+ log_fail "Unable to unmount $options $mnt"
+
+ log_note "Successfully unmounted $options $mnt"
+}
+
+log_onexit cleanup
+
+set -A cmd "umount" "unmount"
+set -A options "" "-f"
+set -A dev "$TESTPOOL/$TESTFS2" "$TESTDIR2"
+
+log_assert "Verify the u[n]mount [-f] sub-command."
+
+typeset -i i=0
+typeset -i j=0
+typeset -i k=0
+while [[ $i -lt ${#cmd[*]} ]]; do
+ j=0
+ while [[ $j -lt ${#options[*]} ]]; do
+ k=0
+ while [[ $k -lt ${#dev[*]} ]]; do
+ do_unmount "${cmd[i]}" "${options[j]}" \
+ "${dev[k]}"
+
+ ((k = k + 1))
+ done
+
+ ((j = j + 1))
+ done
+
+ ((i = i + 1))
+done
+
+log_pass "zfs u[n]mount [-f] completed successfully."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_002_pos.ksh
new file mode 100755
index 000000000000..b8a50785868f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_002_pos.ksh
@@ -0,0 +1,98 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib
+
+#
+# DESCRIPTION:
+# If invoke "zfs unmount [-f]" with a filesystem|mountpoint
+# whose name is not in "zfs list",
+# it will fail with a return code of 1
+# and issue an error message.
+#
+# STRATEGY:
+# 1. Make sure that the non-existent ZFS filesystem|mountpoint
+# not in 'zfs list'.
+# 2. Unmount the file system using the various combinations.
+# - Without force option. (FAILED)
+# - With force option. (FAILED)
+# 3. Unmount the mountpoint using the various combinations.
+# - Without force option. (FAILED)
+# - With force option. (FAILED)
+# 4. Verify the above expected results of the filesystem|mountpoint.
+#
+
+verify_runnable "both"
+
+
+set -A cmd "umount" "unmount"
+set -A options "" "-f"
+set -A dev "$TESTPOOL/$NONEXISTFSNAME" "${TEST_BASE_DIR%%/}/$NONEXISTFSNAME"
+
+function do_unmount_multiple #options #expect
+{
+ typeset opt=$1
+ typeset -i expect=${2-0}
+
+ typeset -i i=0
+ typeset -i j=0
+
+ while (( i < ${#cmd[*]} )); do
+ j=0
+ while (( j < ${#dev[*]} )); do
+ log_note "Make sure ${dev[j]} is not in 'zfs list'"
+ log_mustnot zfs list ${dev[j]}
+
+ do_unmount "${cmd[i]}" "$opt" \
+ "${dev[j]}" $expect
+
+ ((j = j + 1))
+ done
+
+ ((i = i + 1))
+ done
+}
+
+log_assert "Verify that 'zfs $unmountcmd [-f] <filesystem|mountpoint>' " \
+ "whose name is not in 'zfs list' will fail with return code 1."
+
+log_onexit cleanup
+
+typeset -i i=0
+
+while (( i < ${#options[*]} )); do
+ do_unmount_multiple "${options[i]}" 1
+ ((i = i + 1))
+done
+
+log_pass "'zfs $unmountcmd [-f] <filesystem|mountpoint>' " \
+ "whose name is not in 'zfs list' failed with return code 1."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_003_pos.ksh
new file mode 100755
index 000000000000..985c3d2b1fe2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_003_pos.ksh
@@ -0,0 +1,109 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib
+
+#
+# DESCRIPTION:
+# If invoke "zfs unmount [-f]" with a filesystem|mountpoint
+# whose mountpoint property is 'legacy' or 'none',
+# it will fail with a return code of 1
+# and issue an error message.
+#
+# STRATEGY:
+# 1. Make sure that the ZFS filesystem is mounted.
+# 2. Apply 'zfs set mountpoint=legacy|none <filesystem>'.
+# 3. Unmount the file system using the various combinations.
+# - Without force option. (FAILED)
+# - With force option. (FAILED)
+# 4. Unmount the mountpoint using the various combinations.
+# - Without force option. (FAILED)
+# - With force option. (FAILED)
+# 5. Verify the above expected results of the filesystem|mountpoint.
+#
+
+verify_runnable "both"
+
+
+set -A cmd "umount" "unmount"
+set -A options "" "-f"
+set -A dev "$TESTPOOL/$TESTFS" "$TESTDIR"
+set -A mopts "legacy" "none"
+
+function do_unmount_multiple #options #expect #mountpoint
+{
+ typeset opt=$1
+ typeset -i expect=${2-0}
+ typeset mopt=$3
+
+ typeset -i i=0
+ typeset -i j=0
+
+ while (( i < ${#cmd[*]} )); do
+ j=0
+ while (( j < ${#dev[*]} )); do
+ [[ -n $mopt ]] && \
+ log_must zfs set mountpoint=$mopt ${dev[0]}
+
+ do_unmount "${cmd[i]}" "$opt" \
+ "${dev[j]}" $expect
+
+ cleanup
+
+ ((j = j + 1))
+ done
+
+ ((i = i + 1))
+ done
+}
+
+log_assert "Verify that 'zfs $unmountcmd [-f] <filesystem|mountpoint>' " \
+ "whose mountpoint property is 'legacy' or 'none' " \
+ "will fail with return code 1."
+
+log_onexit cleanup
+
+typeset -i i=0
+typeset -i j=0
+
+while (( i < ${#mopts[*]} )); do
+ j=0
+ while (( j < ${#options[*]} )); do
+ do_unmount_multiple "${options[j]}" 1 "${mopts[i]}"
+ ((j = j + 1))
+ done
+ ((i = i + 1))
+done
+
+log_pass "'zfs $unmountcmd [-f] <filesystem|mountpoint>' " \
+ "whose mountpoint property is 'legacy' or 'none' " \
+ "will fail with return code 1."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_004_pos.ksh
new file mode 100755
index 000000000000..bcc25ccd0f80
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_004_pos.ksh
@@ -0,0 +1,99 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib
+
+#
+# DESCRIPTION:
+# If invoke "zfs unmount [-f]" with a specific filesystem|mountpoint,
+# which is not currently mounted,
+# it will fail with a return code of 1
+# and issue an error message.
+#
+# STRATEGY:
+# 1. Make sure that the ZFS filesystem is mounted.
+# 2. Invoke 'zfs unmount <filesystem>'.
+# 3. Verify that the filesystem is unmounted.
+# 4. Unmount the file system using the various combinations.
+# - Without force option. (FAILED)
+# - With force option. (FAILED)
+# 5. Unmount the mountpoint using the various combinations.
+# - Without force option. (FAILED)
+# - With force option. (FAILED)
+# 6. Verify the above expected results of the filesystem|mountpoint.
+#
+
+verify_runnable "both"
+
+
+set -A cmd "umount" "unmount"
+set -A options "" "-f"
+set -A dev "$TESTPOOL/$TESTFS" "$TESTDIR"
+
+function do_unmount_multiple #options #expect
+{
+ typeset opt=$1
+ typeset -i expect=${2-0}
+
+ typeset -i i=0
+ typeset -i j=0
+
+ while (( i < ${#cmd[*]} )); do
+ j=0
+ while (( j < ${#dev[*]} )); do
+ unmounted ${dev[j]} || \
+ log_must zfs $unmountforce ${dev[j]}
+
+ do_unmount "${cmd[i]}" "$opt" \
+ "${dev[j]}" $expect
+
+ ((j = j + 1))
+ done
+
+ ((i = i + 1))
+ done
+}
+
+log_assert "Verify that 'zfs $unmountcmd [-f] <filesystem|mountpoint>' " \
+ "with an unmounted filesystem will fail with return code 1."
+
+log_onexit cleanup
+
+typeset -i i=0
+
+while (( i < ${#options[*]} )); do
+ do_unmount_multiple "${options[i]}" 1
+ ((i = i + 1))
+done
+
+log_pass "'zfs $unmountcmd [-f] <filesystem|mountpoint>' " \
+ "with an unmounted filesystem failed with return code 1."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_005_pos.ksh
new file mode 100755
index 000000000000..eaea4696dfb4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_005_pos.ksh
@@ -0,0 +1,117 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib
+
+#
+# DESCRIPTION:
+# If invoke "zfs unmount" with a specific filesystem|mountpoint
+# that have been mounted, but it's currently in use,
+# it will fail with a return code of 1
+# and issue an error message.
+# But unmount forcefully will bypass this restriction and
+# unmount that given filesystem successfully.
+#
+# STRATEGY:
+# 1. Make sure that the ZFS filesystem is mounted.
+# 2. Change directory to that given mountpoint.
+# 3. Unmount the file system using the various combinations.
+# - Without force option. (FAILED)
+# - With force option. (PASS)
+# 4. Unmount the mountpoint using the various combinations.
+# - Without force option. (FAILED)
+# - With force option. (PASS)
+# 5. Verify the above expected results of the filesystem|mountpoint.
+#
+
+verify_runnable "both"
+
+
+set -A cmd "umount" "unmount"
+set -A options "" "-f"
+set -A dev "$TESTPOOL/$TESTFS" "$TESTDIR"
+
+function do_unmount_multiple #options #expect
+{
+ typeset opt=$1
+ typeset -i expect=${2-0}
+
+ typeset -i i=0
+ typeset -i j=0
+
+ while (( i < ${#cmd[*]} )); do
+ j=0
+ while (( j < ${#dev[*]} )); do
+ mounted ${dev[j]} || \
+ log_must zfs $mountcmd ${dev[0]}
+
+ cd $TESTDIR || \
+ log_unresolved "Unable change dir to $TESTDIR"
+
+ do_unmount "${cmd[i]}" "$opt" \
+ "${dev[j]}" $expect
+
+ cleanup
+
+ ((j = j + 1))
+ done
+
+ ((i = i + 1))
+ done
+}
+
+log_assert "Verify that 'zfs $unmountcmd <filesystem|mountpoint>' " \
+ "with a filesystem which mountpoint is currently in use " \
+ "will fail with return code 1, and forcefully will succeeds as root."
+
+log_onexit cleanup
+
+cwd=$PWD
+
+typeset -i i=0
+
+while (( i < ${#options[*]} )); do
+ if [[ ${options[i]} == "-f" ]]; then
+ if is_linux; then
+ do_unmount_multiple "${options[i]}" 1
+ else
+ do_unmount_multiple "${options[i]}"
+ fi
+ else
+ do_unmount_multiple "${options[i]}" 1
+ fi
+ ((i = i + 1))
+done
+
+log_pass "'zfs $unmountcmd <filesystem|mountpoint>' " \
+ "with a filesystem which mountpoint is currently in use " \
+ "will fail with return code 1, and forcefully will succeeds as root."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_006_pos.ksh
new file mode 100755
index 000000000000..8b70e8868a02
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_006_pos.ksh
@@ -0,0 +1,71 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Re-creating zfs files, 'zfs unmount' still succeed.
+#
+# STRATEGY:
+# 1. Create pool and filesystem.
+# 2. Recreating the same file in this fs for a while, then breaking out.
+# 3. Verify the filesystem can be unmount successfully.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if ! ismounted $TESTPOOL/$TESTFS ; then
+ log_must zfs mount $TESTPOOL/$TESTFS
+ fi
+}
+
+log_assert "Re-creating zfs files, 'zfs unmount' still succeed."
+log_onexit cleanup
+
+# Call cleanup to make sure the file system are mounted.
+cleanup
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+(($? != 0)) && log_fail "get_prop mountpoint $TESTPOOL/$TESTFS"
+
+typeset -i i=0
+while (( i < 10000 )); do
+ cp $STF_SUITE/include/libtest.shlib $mntpnt
+
+ (( i += 1 ))
+done
+log_note "Recreating zfs files for 10000 times."
+
+log_must zfs unmount $TESTPOOL/$TESTFS
+
+log_pass "Re-creating zfs files, 'zfs unmount' passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_007_neg.ksh
new file mode 100755
index 000000000000..cdf4a5a26661
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_007_neg.ksh
@@ -0,0 +1,110 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib
+
+#
+# DESCRIPTION:
+# Try each 'zfs unmount' with inapplicable scenarios to make sure
+# it returns an error. include:
+# * Multiple filesystem|mountpoint specified
+# * '-a', but also with a specific filesystem|mountpoint.
+#
+# STRATEGY:
+# 1. Create an array of parameters
+# 2. For each parameter in the array, execute the sub-command
+# 3. Verify an error is returned.
+#
+
+verify_runnable "both"
+
+multifs="$TESTFS $TESTFS1"
+datasets=""
+
+for fs in $multifs ; do
+ datasets="$datasets $TESTPOOL/$fs"
+done
+
+set -A args "$unmountall $TESTPOOL/$TESTFS" \
+ "$unmountcmd $datasets"
+
+function setup_all
+{
+ typeset fs
+
+ for fs in $multifs ; do
+ setup_filesystem "$DISKS" "$TESTPOOL" \
+ "$fs" \
+ "${TEST_BASE_DIR%%/}/testroot$$/$TESTPOOL/$fs"
+ done
+ return 0
+}
+
+function cleanup_all
+{
+ typeset fs
+
+ cleanup_filesystem "$TESTPOOL" "$TESTFS1"
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+
+ [[ -d ${TEST_BASE_DIR%%/}/testroot$$ ]] && \
+ rm -rf ${TEST_BASE_DIR%%/}/testroot$$
+
+ return 0
+}
+
+function verify_all
+{
+ typeset fs
+
+ for fs in $multifs ; do
+ log_must mounted $TESTPOOL/$fs
+ done
+ return 0
+}
+
+log_assert "Badly-formed 'zfs $unmountcmd' with inapplicable scenarios " \
+ "should return an error."
+log_onexit cleanup_all
+
+log_must setup_all
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_mustnot zfs ${args[i]}
+ ((i = i + 1))
+done
+
+log_must verify_all
+
+log_pass "Badly formed 'zfs $unmountcmd' with inapplicable scenarios " \
+ "fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_008_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_008_neg.ksh
new file mode 100755
index 000000000000..209497d9c454
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_008_neg.ksh
@@ -0,0 +1,146 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that zfs unmount should fail with bad parameters or scenarios:
+# 1. bad option;
+# 2. too many arguments;
+# 3. null arguments;
+# 4. invalid datasets;
+# 5. invalid mountpoint;
+# 6. already unmounted zfs filesystem;
+# 7. legacy mounted zfs filesystem
+#
+# STRATEGY:
+# 1. Make an array of bad parameters
+# 2. Use zfs unmount to unmount the filesystem
+# 3. Verify that zfs unmount returns error
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for ds in $vol $fs1; do
+ if datasetexists $ds; then
+ log_must zfs destroy -f $ds
+ fi
+ done
+
+ if snapexists $snap; then
+ log_must zfs destroy $snap
+ fi
+
+ if [[ -e /tmp/$file ]]; then
+ rm -f /tmp/$file
+ fi
+ if [[ -d /tmp/$dir ]]; then
+ rm -rf /tmp/$dir
+ fi
+
+}
+
+log_assert "zfs unmount fails with bad parameters or scenarios"
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+vol=$TESTPOOL/vol.$$
+snap=$TESTPOOL/$TESTFS@snap.$$
+set -A badargs "A" "-A" "F" "-F" "-" "-x" "-?"
+
+if ! ismounted $fs; then
+ log_must zfs mount $fs
+fi
+
+log_must zfs snapshot $snap
+if is_global_zone; then
+ log_must zfs create -V 10m $vol
+else
+ vol=""
+fi
+
+# Testing bad options
+for arg in ${badargs[@]}; do
+ log_mustnot eval "zfs unmount $arg $fs >/dev/null 2>&1"
+done
+
+# Testing invalid datasets
+for ds in $snap $vol "blah"; do
+ for opt in "" "-f"; do
+ log_mustnot eval "zfs unmount $opt $ds >/dev/null 2>&1"
+ done
+done
+
+# Testing invalid mountpoint
+dir=foodir.$$
+file=foo.$$
+fs1=$TESTPOOL/fs.$$
+mkdir /tmp/$dir
+touch /tmp/$file
+log_must zfs create -o mountpoint=/tmp/$dir $fs1
+curpath=`dirname $0`
+cd /tmp
+for mpt in "./$dir" "./$file" "/tmp"; do
+ for opt in "" "-f"; do
+ log_mustnot eval "zfs unmount $opt $mpt >/dev/null 2>&1"
+ done
+done
+cd $curpath
+
+# Testing null argument and too many arguments
+for opt in "" "-f"; do
+ log_mustnot eval "zfs unmount $opt >/dev/null 2>&1"
+ log_mustnot eval "zfs unmount $opt $fs $fs1 >/dev/null 2>&1"
+done
+
+# Testing already unmounted filesystem
+log_must zfs unmount $fs1
+for opt in "" "-f"; do
+ log_mustnot eval "zfs unmount $opt $fs1 >/dev/null 2>&1"
+ log_mustnot eval "zfs unmount /tmp/$dir >/dev/null 2>&1"
+done
+
+# Testing legacy mounted filesystem
+log_must zfs set mountpoint=legacy $fs1
+if is_linux || is_freebsd; then
+ log_must mount -t zfs $fs1 /tmp/$dir
+else
+ log_must mount -F zfs $fs1 /tmp/$dir
+fi
+for opt in "" "-f"; do
+ log_mustnot eval "zfs unmount $opt $fs1 >/dev/null 2>&1"
+done
+umount /tmp/$dir
+
+log_pass "zfs unmount fails with bad parameters or scenarios as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_009_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_009_pos.ksh
new file mode 100755
index 000000000000..3575875c2767
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_009_pos.ksh
@@ -0,0 +1,142 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that zfs unmount and destroy in a snapshot directory will not cause error.
+#
+# STRATEGY:
+# 1. Create a file in a zfs filesystem, snapshot it and change directory to snapshot directory
+# 2. Verify that 'zfs unmount -a' will fail and 'zfs unmount -fa' will succeed
+# 3. Verify 'ls' and 'cd /' will succeed
+# 4. 'zfs mount -a' and change directory to snapshot directory again
+# 5. Verify that zfs destroy snapshot will succeed
+# 6. Verify 'ls' and 'cd /' will succeed
+# 7. Create zfs filesystem, create a file, snapshot it and change to snapshot directory
+# 8. Verify that zpool destroy the pool will succeed
+# 9. Verify 'ls' 'cd /' 'zpool list' and etc will succeed
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ DISK=${DISKS%% *}
+
+ for fs in $TESTPOOL/$TESTFS $TESTPOOL ; do
+ typeset snap=$fs@$TESTSNAP
+ if snapexists $snap; then
+ log_must zfs destroy $snap
+ fi
+ done
+
+ if ! poolexists $TESTPOOL && is_global_zone; then
+ log_must zpool create $TESTPOOL $DISK
+ fi
+
+ if ! datasetexists $TESTPOOL/$TESTFS; then
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+ fi
+}
+
+function restore_dataset
+{
+ if ! datasetexists $TESTPOOL/$TESTFS ; then
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+ log_must cd $TESTDIR
+ echo hello > world
+ log_must zfs snapshot $TESTPOOL/$TESTFS@$TESTSNAP
+ log_must cd .zfs/snapshot/$TESTSNAP
+ fi
+}
+
+
+log_assert "zfs force unmount and destroy in snapshot directory will not cause error."
+log_onexit cleanup
+
+for fs in $TESTPOOL/$TESTFS $TESTPOOL ; do
+ typeset snap=$fs@$TESTSNAP
+ typeset mtpt=$(get_prop mountpoint $fs)
+
+ log_must cd $mtpt
+ echo hello > world
+ log_must zfs snapshot $snap
+ log_must cd .zfs/snapshot/$TESTSNAP
+
+ log_mustnot zfs unmount -a
+ if is_linux; then
+ log_mustnot zfs unmount -fa
+ log_must ls
+ else
+ log_must zfs unmount -fa
+ log_mustnot ls
+ fi
+ log_must cd /
+
+ log_must zfs mount -a
+ log_must cd $mtpt
+ log_must cd .zfs/snapshot/$TESTSNAP
+
+ if is_global_zone || [[ $fs != $TESTPOOL ]] ; then
+ if is_linux; then
+ log_mustnot zfs destroy -rf $fs
+ log_must ls
+ else
+ log_must zfs destroy -rf $fs
+ log_mustnot ls
+ fi
+ log_must cd /
+ fi
+
+ restore_dataset
+done
+
+if is_global_zone ; then
+ if is_linux; then
+ log_mustnot zpool destroy -f $TESTPOOL
+ log_must ls
+ else
+ log_must zpool destroy -f $TESTPOOL
+ log_mustnot ls
+ fi
+ log_must cd /
+fi
+
+log_must eval zfs list > /dev/null 2>&1
+log_must eval zpool list > /dev/null 2>&1
+log_must eval zpool status > /dev/null 2>&1
+zpool iostat > /dev/null 2>&1
+
+log_pass "zfs force unmount and destroy in snapshot directory will not cause error."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_all_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_all_001_pos.ksh
new file mode 100755
index 000000000000..b5a01b53aeab
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_all_001_pos.ksh
@@ -0,0 +1,203 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib
+
+#
+# DESCRIPTION:
+# Verify that 'zfs unmount -a[f]' succeeds as root.
+#
+# STRATEGY:
+# 1. Create a group of pools with specified vdev.
+# 2. Create zfs filesystems within the given pools.
+# 3. Mount all the filesystems.
+# 4. Verify that 'zfs unmount -a[f]' command succeed,
+# and all available ZFS filesystems are unmounted.
+# 5. Verify that 'zfs mount' is identical with 'df -F zfs'
+#
+
+verify_runnable "both"
+
+set -A fs "$TESTFS" "$TESTFS1"
+set -A ctr "" "$TESTCTR" "$TESTCTR1" "$TESTCTR/$TESTCTR1"
+set -A vol "$TESTVOL" "$TESTVOL1"
+
+function setup_all
+{
+ typeset -i i=0
+ typeset -i j=0
+ typeset path
+
+ while (( i < ${#ctr[*]} )); do
+
+ path=${TEST_BASE_DIR%%/}/testroot$$/$TESTPOOL
+ if [[ -n ${ctr[i]} ]]; then
+ path=$path/${ctr[i]}
+
+ setup_filesystem "$DISKS" "$TESTPOOL" \
+ "${ctr[i]}" "$path" \
+ "ctr"
+ fi
+
+ if is_global_zone ; then
+ j=0
+ while (( j < ${#vol[*]} )); do
+ setup_filesystem "$DISKS" "$TESTPOOL" \
+ "${ctr[i]}/${vol[j]}" \
+ "$path/${vol[j]}" \
+ "vol"
+ ((j = j + 1))
+ done
+ fi
+ j=0
+ while (( j < ${#fs[*]} )); do
+ setup_filesystem "$DISKS" "$TESTPOOL" \
+ "${ctr[i]}/${fs[j]}" \
+ "$path/${fs[j]}"
+ ((j = j + 1))
+ done
+
+ ((i = i + 1))
+ done
+
+ return 0
+}
+
+function cleanup_all
+{
+ typeset -i i=0
+ typeset -i j=0
+
+ ((i = ${#ctr[*]} - 1))
+
+ while (( i >= 0 )); do
+ if is_global_zone ; then
+ j=0
+ while (( j < ${#vol[*]} )); do
+ cleanup_filesystem "$TESTPOOL" \
+ "${ctr[i]}/${vol[j]}"
+ ((j = j + 1))
+ done
+ fi
+
+ j=0
+ while (( j < ${#fs[*]} )); do
+ cleanup_filesystem "$TESTPOOL" \
+ "${ctr[i]}/${fs[j]}"
+ ((j = j + 1))
+ done
+
+ [[ -n ${ctr[i]} ]] && \
+ cleanup_filesystem "$TESTPOOL" "${ctr[i]}"
+
+ ((i = i - 1))
+ done
+
+ [[ -d ${TEST_BASE_DIR%%/}/testroot$$ ]] && \
+ rm -rf ${TEST_BASE_DIR%%/}/testroot$$
+}
+
+function verify_all
+{
+ typeset -i i=0
+ typeset -i j=0
+ typeset path
+
+ while (( i < ${#ctr[*]} )); do
+
+ path=$TESTPOOL
+ [[ -n ${ctr[i]} ]] && \
+ path=$path/${ctr[i]}
+
+ if is_global_zone ; then
+ j=0
+ while (( j < ${#vol[*]} )); do
+ log_must unmounted "$path/${vol[j]}"
+ ((j = j + 1))
+ done
+ fi
+
+ j=0
+ while (( j < ${#fs[*]} )); do
+ log_must unmounted "$path/${fs[j]}"
+ ((j = j + 1))
+ done
+
+ log_must unmounted "$path"
+
+ ((i = i + 1))
+ done
+
+ return 0
+}
+
+
+log_assert "Verify that 'zfs $unmountall' succeeds as root, " \
+ "and all available ZFS filesystems are unmounted."
+
+log_onexit cleanup_all
+
+log_must setup_all
+
+typeset opt
+for opt in "-a" "-fa"; do
+ export __ZFS_POOL_RESTRICT="$TESTPOOL"
+ log_must zfs $mountall
+ unset __ZFS_POOL_RESTRICT
+
+ if [[ $opt == "-fa" ]]; then
+ mntpnt=$(get_prop mountpoint ${TESTPOOL}/${TESTCTR}/${TESTFS})
+ cd $mntpnt
+ log_mustnot zfs unmount -a
+ fi
+
+ export __ZFS_POOL_RESTRICT="$TESTPOOL"
+ if [[ $opt == "-fa" ]] && is_linux; then
+ log_mustnot zfs unmount $opt
+ cd /tmp
+ fi
+ log_must zfs unmount $opt
+ unset __ZFS_POOL_RESTRICT
+
+ if [[ $opt == "-fa" ]]; then
+ cd /tmp
+ fi
+
+ log_must verify_all
+ log_note "Verify that 'zfs $mountcmd' will display " \
+ "all ZFS filesystems currently mounted."
+ log_must verify_mount_display
+
+done
+
+log_pass "'zfs mount -[f]a' succeeds as root, " \
+ "and all available ZFS filesystems are unmounted."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_nested.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_nested.ksh
new file mode 100755
index 000000000000..987ecca31396
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_nested.ksh
@@ -0,0 +1,193 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy is of the CDDL is also available via the Internet
+# at http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2018 Datto Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# zfs unmount should work on nested datasets
+#
+# STRATEGY:
+# 1. Create a set of nested datasets
+# 2. Unmount a nested dataset and make sure it is unmounted
+# 3. Ensure the dataset deeper than the one above is also unmounted
+# 4. Ensure the datasets shallower than the unmounted one is still mounted
+# 5. Repeat from step 2 with other mountpoint values and shallower nesting
+#
+
+verify_runnable "both"
+
+function nesting_cleanup
+{
+ log_must zfs destroy -fR $TESTPOOL/a
+ log_must zfs destroy -fR $TESTPOOL/b
+ log_must zfs destroy -fR $TESTPOOL/c
+ log_must zfs destroy -fR $TESTPOOL/d
+}
+
+log_onexit nesting_cleanup
+
+set -A test_depths 30 16 3
+typeset mountpoint=/$TESTPOOL/mnt
+
+dsA32=$(printf 'a/%.0s' {1..32})"a"
+log_must zfs create -p $TESTPOOL/$dsA32
+
+dsB32=$(printf 'b/%.0s' {1..32})"b"
+log_must zfs create -o mountpoint=none -p $TESTPOOL/$dsB32
+# FreeBSD's mount command ignores the mountpoint property.
+if ! is_freebsd; then
+ log_mustnot mount -t zfs $TESTPOOL/$dsB32 /mnt
+fi
+
+dsC32=$(printf 'c/%.0s' {1..32})"c"
+log_must zfs create -o mountpoint=legacy -p $TESTPOOL/$dsC32
+log_must mount -t zfs $TESTPOOL/$dsC32 /mnt
+
+dsD32=$(printf 'd/%.0s' {1..32})"d"
+log_must zfs create -o mountpoint=$mountpoint -p $TESTPOOL/$dsD32
+
+
+for d in ${test_depths[@]}; do
+ # default mountpoint
+ ds_pre=$(printf 'a/%.0s' {1..$(($d-2))})"a"
+ ds=$(printf 'a/%.0s' {1..$(($d-1))})"a"
+ ds_post=$(printf 'a/%.0s' {1..$(($d))})"a"
+ if ! ismounted $TESTPOOL/$ds_pre; then
+ log_fail "$TESTPOOL/$ds_pre (pre) not initially mounted"
+ fi
+ if ! ismounted $TESTPOOL/$ds; then
+ log_fail "$TESTPOOL/$ds not initially mounted"
+ fi
+ if ! ismounted $TESTPOOL/$ds_post; then
+ log_fail "$TESTPOOL/$ds_post (post) not initially mounted"
+ fi
+
+ log_must zfs snapshot $TESTPOOL/$ds@snap
+ # force snapshot mount in .zfs
+ log_must ls /$TESTPOOL/$ds/.zfs/snapshot/snap
+ log_must zfs unmount $TESTPOOL/$ds
+
+ if ! ismounted $TESTPOOL/$ds_pre; then
+ log_fail "$ds_pre is not mounted"
+ fi
+ if ismounted $TESTPOOL/$ds; then
+ log_fail "$ds is mounted"
+ fi
+ if ismounted $TESTPOOL/$ds_post; then
+ log_fail "$ds_post (post) is mounted"
+ fi
+
+
+ # mountpoint=none
+ ds_pre=$(printf 'b/%.0s' {1..$(($d-2))})"b"
+ ds=$(printf 'b/%.0s' {1..$(($d-1))})"b"
+ ds_post=$(printf 'b/%.0s' {1..$(($d))})"b"
+ if ! ismounted $TESTPOOL/$ds_pre; then
+ log_fail "$TESTPOOL/$ds_pre (pre) not initially mounted"
+ fi
+ if ! ismounted $TESTPOOL/$ds; then
+ log_fail "$TESTPOOL/$ds not initially mounted"
+ fi
+ if ! ismounted $TESTPOOL/$ds_post; then
+ log_fail "$TESTPOOL/$ds_post (post) not initially mounted"
+ fi
+
+ log_must zfs snapshot $TESTPOOL/$ds@snap
+ # force snapshot mount in .zfs
+ log_must ls /$TESTPOOL/$ds/.zfs/snapshot/snap
+ log_must zfs unmount $TESTPOOL/$ds
+
+ if ! ismounted $TESTPOOL/$ds_pre; then
+ log_fail "$TESTPOOL/$ds_pre (pre) not mounted"
+ fi
+ if ismounted $TESTPOOL/$ds; then
+ log_fail "$TESTPOOL/$ds is mounted"
+ fi
+ if ismounted $TESTPOOL/$ds_post; then
+ log_fail "$TESTPOOL/$ds_post (post) is mounted"
+ fi
+
+
+ # mountpoint=legacy
+ ds_pre=$(printf 'c/%.0s' {1..$(($d-2))})"c"
+ ds=$(printf 'c/%.0s' {1..$(($d-1))})"c"
+ ds_post=$(printf 'c/%.0s' {1..$(($d))})"c"
+ if ! ismounted $TESTPOOL/$ds_pre; then
+ log_fail "$TESTPOOL/$ds_pre (pre) not initially mounted"
+ fi
+ if ! ismounted $TESTPOOL/$ds; then
+ log_fail "$TESTPOOL/$ds not initially mounted"
+ fi
+ if ! ismounted $TESTPOOL/$ds_post; then
+ log_fail "$TESTPOOL/$ds_post (post) not initially mounted"
+ fi
+
+ log_must zfs snapshot $TESTPOOL/$ds@snap
+ # force snapshot mount in .zfs
+ log_must ls /$TESTPOOL/$ds/.zfs/snapshot/snap
+ log_must zfs unmount $TESTPOOL/$ds
+
+ if ! ismounted $TESTPOOL/$ds_pre; then
+ log_fail "$TESTPOOL/$ds_pre (pre) not mounted"
+ fi
+ if ismounted $TESTPOOL/$ds; then
+ log_fail "$TESTPOOL/$ds is mounted"
+ fi
+ if ismounted $TESTPOOL/$ds_post; then
+ log_fail "$TESTPOOL/$ds_post (post) is mounted"
+ fi
+
+
+ # mountpoint=/testpool/mnt
+ ds_pre=$(printf 'd/%.0s' {1..$(($d-2))})"d"
+ ds=$(printf 'd/%.0s' {1..$(($d-1))})"d"
+ ds_post=$(printf 'd/%.0s' {1..$(($d))})"d"
+ if ! ismounted $TESTPOOL/$ds_pre; then
+ log_fail "$TESTPOOL/$ds_pre (pre) not initially mounted"
+ fi
+ if ! ismounted $TESTPOOL/$ds; then
+ log_fail "$TESTPOOL/$ds not initially mounted"
+ fi
+ if ! ismounted $TESTPOOL/$ds_post; then
+ log_fail "$TESTPOOL/$ds_post (post) not initially mounted"
+ fi
+
+ log_must zfs snapshot $TESTPOOL/$ds@snap
+ # force snapshot mount in .zfs
+ log_must ls /$TESTPOOL/$ds/.zfs/snapshot/snap
+ log_must zfs unmount $TESTPOOL/$ds
+
+ if ! ismounted $TESTPOOL/$ds_pre; then
+ log_fail "$ds_pre is not mounted"
+ fi
+ if ismounted $TESTPOOL/$ds; then
+ log_fail "$ds is mounted"
+ fi
+ if ismounted $TESTPOOL/$ds_post; then
+ log_fail "$ds_post (post) is mounted"
+ fi
+done
+
+log_must rmdir $mountpoint # remove the mountpoint we created
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+
+log_pass "Verified nested dataset are unmounted."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_unload_keys.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_unload_keys.ksh
new file mode 100755
index 000000000000..d6d0a7e9a1b6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_unload_keys.ksh
@@ -0,0 +1,79 @@
+#!/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) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_unmount/zfs_unmount.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# "zfs unmount -u" should allow the user to unload their encryption
+# keys while unmounting one or more datasets
+#
+# STRATEGY:
+# 1. Create a hierarchy of encrypted datasets
+# 2. Test that 'zfs unmount -u' unloads keys as it unmounts a dataset
+# 3. Test that 'zfs unmount -u' unloads keys as it unmounts multiple datasets
+# 4. Test that 'zfs unmount -u' returns an error if the key is still in
+# use by a clone.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS2 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS2
+ datasetexists $TESTPOOL/$TESTFS2/newroot && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS2/newroot
+ datasetexists $TESTPOOL/$TESTFS2/child && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS2/child
+
+}
+log_onexit cleanup
+
+log_assert "'zfs unmount -u' should unload keys for datasets as they are unmounted"
+log_must eval "echo 'password' | zfs create -o encryption=on -o keyformat=passphrase $TESTPOOL/$TESTFS2"
+log_must eval "echo 'password' | zfs create -o encryption=on -o keyformat=passphrase $TESTPOOL/$TESTFS2/newroot"
+log_must zfs create $TESTPOOL/$TESTFS2/child
+
+log_must zfs umount -u $TESTPOOL/$TESTFS2/newroot
+log_must key_unavailable $TESTPOOL/$TESTFS2/newroot
+log_must eval "echo 'password' | zfs mount -l $TESTPOOL/$TESTFS2/newroot"
+
+log_must zfs umount -u $TESTPOOL/$TESTFS2
+log_must key_unavailable $TESTPOOL/$TESTFS2
+log_must key_unavailable $TESTPOOL/$TESTFS2/newroot
+log_must key_unavailable $TESTPOOL/$TESTFS2/child
+log_must eval "echo 'password' | zfs mount -l $TESTPOOL/$TESTFS2/newroot"
+
+log_must zfs snap $TESTPOOL/$TESTFS2/newroot@1
+log_must zfs clone $TESTPOOL/$TESTFS2/newroot@1 $TESTPOOL/$TESTFS2/clone
+log_mustnot zfs umount -u $TESTPOOL/$TESTFS2/newroot
+log_must key_available $TESTPOOL/$TESTFS2/newroot
+log_must mounted $TESTPOOL/$TESTFS2/newroot
+
+log_pass "'zfs unmount -u' unloads keys for datasets as they are unmounted"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/Makefile.am
new file mode 100644
index 000000000000..0845f1e2f9f6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/Makefile.am
@@ -0,0 +1,11 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_unshare
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_unshare_001_pos.ksh \
+ zfs_unshare_002_pos.ksh \
+ zfs_unshare_003_pos.ksh \
+ zfs_unshare_004_neg.ksh \
+ zfs_unshare_005_neg.ksh \
+ zfs_unshare_006_pos.ksh \
+ zfs_unshare_007_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/setup.ksh
new file mode 100755
index 000000000000..29f38e802c57
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/setup.ksh
@@ -0,0 +1,39 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+share -s
+if [ $? -ne 0 ]; then
+ log_unsupported "The NFS utilities are not installed"
+fi
+
+# Make sure NFS server is running before testing.
+setup_nfs_server
+
+DISK=${DISKS%% *}
+default_container_volume_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_001_pos.ksh
new file mode 100755
index 000000000000..ca625bd2278a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_001_pos.ksh
@@ -0,0 +1,177 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that 'zfs unshare <filesystem|mountpoint>' unshares a given shared
+# filesystem.
+#
+# STRATEGY:
+# 1. Share filesystems
+# 2. Invoke 'zfs unshare <filesystem|mountpoint>' to unshare zfs file system
+# 3. Verify that the file system is unshared
+# 4. Verify that unsharing an unshared file system fails
+# 5. Verify that "zfs unshare -a" succeeds to unshare all zfs file systems.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset -i i=0
+ while (( i < ${#mntp_fs[*]} )); do
+ log_must zfs set sharenfs=off ${mntp_fs[((i+1))]}
+
+ ((i = i + 2))
+ done
+
+ if mounted $TESTPOOL/$TESTCLONE; then
+ log_must zfs unmount $TESTDIR2
+ fi
+
+ [[ -d $TESTDIR2 ]] && \
+ log_must rm -rf $TESTDIR2
+
+ if datasetexists "$TESTPOOL/$TESTCLONE"; then
+ log_must zfs destroy -f $TESTPOOL/$TESTCLONE
+ fi
+
+ if snapexists "$TESTPOOL/$TESTFS2@snapshot"; then
+ log_must zfs destroy -f $TESTPOOL/$TESTFS2@snapshot
+ fi
+
+ if datasetexists "$TESTPOOL/$TESTFS2"; then
+ log_must zfs destroy -f $TESTPOOL/$TESTFS2
+ fi
+}
+
+#
+# Main test routine.
+#
+# Given a mountpoint and file system this routine will attempt
+# unshare the filesystem via <filesystem|mountpoint> argument
+# and then verify it has been unshared.
+#
+function test_unshare # <mntp> <filesystem>
+{
+ typeset mntp=$1
+ typeset filesystem=$2
+ typeset prop_value
+
+ prop_value=$(get_prop "sharenfs" $filesystem)
+
+ if [[ $prop_value == "off" ]]; then
+ not_shared $mntp ||
+ log_must eval "unshare_nfs $mntp"
+ log_must zfs set sharenfs=on $filesystem
+ is_shared $mntp || \
+ log_fail "'zfs set sharenfs=on' fails to make" \
+ "file system $filesystem shared."
+ fi
+
+ is_shared $mntp || log_must zfs share $filesystem
+
+ #
+ # Verify 'zfs unshare <filesystem>' works as well.
+ #
+ log_must zfs unshare $filesystem
+ not_shared $mntp || log_fail "'zfs unshare <filesystem>' fails"
+
+ log_must zfs share $filesystem
+
+ log_must zfs unshare $mntp
+ not_shared $mntp || log_fail "'zfs unshare <mountpoint>' fails"
+
+ log_note "Unsharing an unshared file system fails."
+ log_mustnot zfs unshare $filesystem
+ log_mustnot zfs unshare $mntp
+}
+
+set -A mntp_fs \
+ "$TESTDIR" "$TESTPOOL/$TESTFS" \
+ "$TESTDIR1" "$TESTPOOL/$TESTCTR/$TESTFS1" \
+ "$TESTDIR2" "$TESTPOOL/$TESTCLONE"
+
+log_assert "Verify that 'zfs unshare [-a] <filesystem|mountpoint>' succeeds as root."
+log_onexit cleanup
+
+log_must zfs create $TESTPOOL/$TESTFS2
+log_must zfs snapshot $TESTPOOL/$TESTFS2@snapshot
+log_must zfs clone $TESTPOOL/$TESTFS2@snapshot $TESTPOOL/$TESTCLONE
+log_must zfs set mountpoint=$TESTDIR2 $TESTPOOL/$TESTCLONE
+
+#
+# Invoke 'test_unshare' routine to test 'zfs unshare <filesystem|mountpoint>'.
+#
+typeset -i i=0
+while (( i < ${#mntp_fs[*]} )); do
+ test_unshare ${mntp_fs[i]} ${mntp_fs[((i + 1 ))]}
+
+ ((i = i + 2))
+done
+
+log_note "Verify 'zfs unshare -a' succeeds as root."
+
+i=0
+typeset sharenfs_val
+while (( i < ${#mntp_fs[*]} )); do
+ sharenfs_val=$(get_prop "sharenfs" ${mntp_fs[((i+1))]})
+ if [[ $sharenfs_val == "on" ]]; then
+ not_shared ${mntp_fs[i]} && \
+ log_must zfs share ${mntp_fs[((i+1))]}
+ else
+ log_must zfs set sharenfs=on ${mntp_fs[((i+1))]}
+ is_shared ${mntp_fs[i]} || \
+ log_fail "'zfs set sharenfs=on' fails to share filesystem."
+ fi
+
+ ((i = i + 2))
+done
+
+#
+# test 'zfs unshare -a '
+#
+log_must zfs unshare -a
+
+#
+# verify all shared filesystems become unshared
+#
+i=0
+while (( i < ${#mntp_fs[*]} )); do
+ not_shared ${mntp_fs[i]} || \
+ log_fail "'zfs unshare -a' fails to unshare all shared zfs filesystems."
+
+ ((i = i + 2))
+done
+
+log_pass "'zfs unshare [-a] <filesystem|mountpoint>' succeeds as root."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_002_pos.ksh
new file mode 100755
index 000000000000..6a9c72311c74
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_002_pos.ksh
@@ -0,0 +1,185 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that 'zfs unshare [-a] <filesystem|mountpoint>' is aware of legacy share.
+#
+# STRATEGY:
+# 1. Set 'zfs set sharenfs=off'
+# 2. Use 'share' to share given filesystem
+# 3. Verify that 'zfs unshare <filesystem|mountpoint>' is aware of legacy share
+# 4. Verify that 'zfs unshare -a' is aware of legacy share.
+#
+
+verify_runnable "global"
+
+if is_linux; then
+ log_unsupported "zfs set sharenfs=off won't unshare if already off"
+fi
+
+function cleanup
+{
+ typeset -i i=0
+ while (( i < ${#mntp_fs[*]} )); do
+ is_shared ${mntp_fs[i]} && \
+ log_must eval "unshare_nfs ${mntp_fs[i]}"
+
+ ((i = i + 2))
+ done
+
+ if mounted $TESTPOOL/$TESTCLONE; then
+ log_must zfs unmount $TESTDIR2
+ fi
+
+ [[ -d $TESTDIR2 ]] && \
+ log_must rm -rf $TESTDIR2
+
+ if datasetexists "$TESTPOOL/$TESTCLONE"; then
+ log_must zfs destroy -f $TESTPOOL/$TESTCLONE
+ fi
+
+ if snapexists "$TESTPOOL/$TESTFS2@snapshot"; then
+ log_must zfs destroy -f $TESTPOOL/$TESTFS2@snapshot
+ fi
+
+ if datasetexists "$TESTPOOL/$TESTFS2"; then
+ log_must zfs destroy -f $TESTPOOL/$TESTFS2
+ fi
+}
+
+#
+# Main test routine.
+#
+# Given a mountpoint and file system this routine will attempt
+# to verify 'zfs unshare' is aware of legacy share.
+#
+function test_legacy_unshare # <mntp> <filesystem>
+{
+ typeset mntp=$1
+ typeset filesystem=$2
+
+ log_must zfs set sharenfs=off $filesystem
+ not_shared $mntp || \
+ log_fail "'zfs set sharenfs=off' fails to make ZFS " \
+ "filesystem $filesystem unshared."
+
+ log_must eval "share_nfs $mntp"
+ is_shared $mntp || \
+ log_fail "'share' command fails to share ZFS file system."
+ #
+ # Verify 'zfs unshare <filesystem>' is aware of legacy share.
+ #
+ log_mustnot zfs unshare $filesystem
+ is_shared $mntp || \
+ log_fail "'zfs unshare <filesystem>' fails to be aware" \
+ "of legacy share."
+
+ #
+ # Verify 'zfs unshare <filesystem>' is aware of legacy share.
+ #
+ log_mustnot zfs unshare $mntp
+ is_shared $mntp || \
+ log_fail "'zfs unshare <mountpoint>' fails to be aware" \
+ "of legacy share."
+}
+
+
+set -A mntp_fs \
+ "$TESTDIR" "$TESTPOOL/$TESTFS" \
+ "$TESTDIR1" "$TESTPOOL/$TESTCTR/$TESTFS1" \
+ "$TESTDIR2" "$TESTPOOL/$TESTCLONE"
+
+log_assert "Verify that 'zfs unshare [-a]' is aware of legacy share."
+log_onexit cleanup
+
+log_must zfs create $TESTPOOL/$TESTFS2
+log_must zfs snapshot $TESTPOOL/$TESTFS2@snapshot
+log_must zfs clone $TESTPOOL/$TESTFS2@snapshot $TESTPOOL/$TESTCLONE
+log_must zfs set mountpoint=$TESTDIR2 $TESTPOOL/$TESTCLONE
+
+#
+# Invoke 'test_legacy_unshare' routine to verify.
+#
+typeset -i i=0
+while (( i < ${#mntp_fs[*]} )); do
+ test_legacy_unshare ${mntp_fs[i]} ${mntp_fs[((i + 1 ))]}
+
+ ((i = i + 2))
+done
+
+
+log_note "Verify 'zfs unshare -a' is aware of legacy share."
+
+#
+# set the 'sharenfs' property to 'off' for each filesystem
+#
+i=0
+while (( i < ${#mntp_fs[*]} )); do
+ log_must zfs set sharenfs=off ${mntp_fs[((i + 1))]}
+ not_shared ${mntp_fs[i]} || \
+ log_fail "'zfs set sharenfs=off' unshares file system failed."
+
+ ((i = i + 2))
+done
+
+#
+# Share each of the file systems via legacy share.
+#
+i=0
+while (( i < ${#mntp_fs[*]} )); do
+ share_nfs ${mntp_fs[i]}
+ is_shared ${mntp_fs[i]} || \
+ log_fail "'share' shares ZFS filesystem failed."
+
+ ((i = i + 2))
+done
+
+#
+# Verify that 'zfs unshare -a' is aware of legacy share
+#
+log_must zfs unshare -a
+
+#
+# verify ZFS filesystems are still shared
+#
+i=0
+while (( i < ${#mntp_fs[*]} )); do
+ is_shared ${mntp_fs[i]} || \
+ log_fail "'zfs unshare -a' fails to be aware of legacy share."
+
+ ((i = i + 2))
+done
+
+log_pass "'zfs unshare [-a]' succeeds to be aware of legacy share."
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_003_pos.ksh
new file mode 100755
index 000000000000..66a7e80eb783
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_003_pos.ksh
@@ -0,0 +1,94 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that a file system and its dependent are unshared when turn off sharenfs
+# property.
+#
+# STRATEGY:
+# 1. Create a file system
+# 2. Set the sharenfs property on the file system
+# 3. Create a snapshot
+# 4. Verify that both are shared
+# 5. Turn off the sharenfs property
+# 6. Verify that both are unshared.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if snapexists $TESTPOOL/$TESTFS@snapshot; then
+ log_must zfs destroy $TESTPOOL/$TESTFS@snapshot
+ fi
+
+ log_must zfs set sharenfs=off $TESTPOOL/$TESTFS
+}
+
+#
+# Main test routine.
+#
+# Given a mountpoint and file system this routine will attempt
+# unshare the mountpoint and then verify a snapshot of the mounpoint
+# is also unshared.
+#
+function test_snap_unshare # <mntp> <filesystem>
+{
+ typeset mntp=$1
+ typeset filesystem=$2
+ typeset prop_value
+
+ prop_value=$(get_prop "sharenfs" $filesystem)
+
+ if [[ $prop_value == "off" ]]; then
+ is_shared $mntp || unshare_nfs $mntp
+ log_must zfs set sharenfs=on $filesystem
+ fi
+
+ log_must zfs set sharenfs=off $filesystem
+
+ not_shared $mntp || \
+ log_fail "File system $filesystem is shared (set sharenfs)."
+
+ not_shared $mntp@snapshot || \
+ log_fail "Snapshot $mntpt@snapshot is shared (set sharenfs)."
+}
+
+log_assert "Verify that a file system and its dependent are unshared."
+log_onexit cleanup
+
+log_must zfs snapshot $TESTPOOL/$TESTFS@snapshot
+test_snap_unshare $TESTDIR $TESTPOOL/$TESTFS
+
+log_pass "A file system and its dependent are both unshared as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_004_neg.ksh
new file mode 100755
index 000000000000..fd916040b1bc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_004_neg.ksh
@@ -0,0 +1,84 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that "zfs unshare" issue error message with badly formed parameter.
+#
+# STRATEGY:
+# 1. Define badly formed parameters
+# 2. Invoke 'zfs unshare'
+# 3. Verify that unshare fails and issue error message.
+#
+
+verify_runnable "global"
+
+export NONEXISTFSNAME="nonexistfs50charslong_0123456789012345678901234567"
+export NONEXISTMOUNTPOINT="/nonexistmountpoint_0123456789"
+
+set -A opts "" "$TESTPOOL/$NONEXISTFSNAME" "$NONEXISTMOUNTPOINT" "-?" "-1" \
+ "-a blah" "$TESTPOOL/$TESTFS $TESTPOOL/$TESTFS1" \
+ "-f $TESTPOOL/$TESTFS $TESTPOOL/$TESTFS1" \
+ "$TESTPOOL/$TESTFS $TESTDIR" "-f $TESTPOOL/$TESTFS $TESTDIR" \
+ "${TESTDIR#/}" "-f ${TESTDIR#/}"
+
+log_assert "Verify that 'zfs unshare' issue error message with badly formed parameter."
+
+shareval=$(get_prop sharenfs $TESTPOOL/$TESTFS)
+if [[ $shareval == off ]]; then
+ log_must zfs set sharenfs=on $TESTPOOL/$TESTFS
+fi
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zfs unshare ${args[i]}
+
+ ((i = i + 1))
+done
+
+#Testing that unsharing unshared filesystem fails.
+mpt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+log_must zfs unshare $TESTPOOL/$TESTFS
+for opt in "" "-f"; do
+ log_mustnot eval "zfs unshare $opt $TESTPOOL/$TESTFS >/dev/null 2>&1"
+ log_mustnot eval "zfs unshare $opt $mpt >/dev/null 2>&1"
+done
+
+#Testing zfs unshare fails with legacy share set
+log_must zfs set sharenfs=off $TESTPOOL/$TESTFS
+for opt in "" "-f"; do
+ log_mustnot eval "zfs unshare $opt $TESTPOOL/$TESTFS >/dev/null 2>&1"
+ log_mustnot eval "zfs unshare $opt $mpt >/dev/null 2>&1"
+done
+
+log_pass "'zfs unshare' fails as expected with badly-formed parameters."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_005_neg.ksh
new file mode 100755
index 000000000000..7df3136dd6b4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_005_neg.ksh
@@ -0,0 +1,60 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that unsharing a dataset and mountpoint other than filesystem fails.
+#
+# STRATEGY:
+# 1. Create a volume, dataset other than a ZFS file system
+# 2. Verify that the datasets other than file system are not support by 'zfs unshare'.
+#
+
+verify_runnable "both"
+
+set -A datasets \
+ "$TESTPOOL" "$ZFSROOT/$TESTPOOL" \
+ "$TESTPOOL/$TESTCTR" "$ZFSROOT/$TESTPOOL/$TESTCTR" \
+ "$TESTPOOL/$TESTVOL" "${ZVOL_DEVDIR}/$TESTPOOL/$TESTVOL"
+
+log_assert "Verify that unsharing a dataset other than filesystem fails."
+
+typeset -i i=0
+while (( i < ${#datasets[*]} ))
+do
+ log_mustnot zfs unshare ${datasets[i]}
+
+ ((i = i + 1))
+done
+
+log_pass "Unsharing datasets other than filesystem failed as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_006_pos.ksh
new file mode 100755
index 000000000000..b4318020cc7f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_006_pos.ksh
@@ -0,0 +1,92 @@
+#!/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 2016, loli10K. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that 'zfs unshare [nfs|smb] -a' unshares only filesystems shared by the
+# specified protocol.
+#
+# STRATEGY:
+# 1. Share filesystems with different protocols.
+# 2. Invoke 'zfs unshare nfs -a' to unshare filesystems.
+# 3. Verify that only nfs filesystems are unshared.
+# 4. Share all filesystems again.
+# 5. Invoke 'zfs unshare smb -a' and verify only smb filesystems are unshared.
+#
+
+verify_runnable "global"
+
+if is_linux; then
+ log_unsupported "some distros come with Samba "user shares" disabled"
+fi
+
+function cleanup
+{
+ log_must zfs unshare -a
+ log_must zfs destroy -f $TESTPOOL/$TESTFS/shared1
+ log_must zfs destroy -f $TESTPOOL/$TESTFS/shared2
+ log_must zfs destroy -f $TESTPOOL/$TESTFS/shared3
+}
+
+log_assert "Verify 'zfs unshare [nfs|smb] -a' only works on the specified "\
+ "protocol."
+log_onexit cleanup
+
+# 1. Share filesystems with different protocols.
+log_must zfs create $TESTPOOL/$TESTFS/shared1
+log_must zfs create $TESTPOOL/$TESTFS/shared2
+log_must zfs create $TESTPOOL/$TESTFS/shared3
+log_must zfs set mountpoint=$TESTDIR/1 $TESTPOOL/$TESTFS/shared1
+log_must zfs set mountpoint=$TESTDIR/2 $TESTPOOL/$TESTFS/shared2
+log_must zfs set mountpoint=$TESTDIR/3 $TESTPOOL/$TESTFS/shared3
+log_must zfs set sharenfs=on $TESTPOOL/$TESTFS/shared1
+log_must zfs set sharenfs=on $TESTPOOL/$TESTFS/shared2
+log_must zfs set sharesmb=on $TESTPOOL/$TESTFS/shared2
+log_must zfs set sharesmb=on $TESTPOOL/$TESTFS/shared3
+log_must zfs share -a
+
+# 2. Invoke 'zfs unshare nfs -a' to unshare filesystems.
+log_must zfs unshare nfs -a
+
+# 3. Verify that only nfs filesystems are unshared.
+log_must eval "not_shared $TESTPOOL/$TESTFS/shared1"
+log_must eval "not_shared $TESTPOOL/$TESTFS/shared2"
+log_must eval "is_shared_smb $TESTPOOL/$TESTFS/shared2"
+log_must eval "is_shared_smb $TESTPOOL/$TESTFS/shared3"
+
+# 4. Share all filesystems again.
+log_must zfs share -a
+
+# 5. Invoke 'zfs unshare smb -a' and verify only smb filesystems are unshared.
+log_must zfs unshare smb -a
+log_must eval "is_shared $TESTPOOL/$TESTFS/shared1"
+log_must eval "is_shared $TESTPOOL/$TESTFS/shared2"
+log_must eval "not_shared_smb $TESTPOOL/$TESTFS/shared2"
+log_must eval "not_shared_smb $TESTPOOL/$TESTFS/shared3"
+
+log_pass "'zfs unshare [nfs|smb] -a' only works on the specified protocol."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_007_pos.ksh
new file mode 100755
index 000000000000..a5b29a89618a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_007_pos.ksh
@@ -0,0 +1,68 @@
+#!/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 2016, loli10K. All rights reserved.
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that 'zfs destroy' on a shared dataset, will unshare it.
+#
+# STRATEGY:
+# 1. Create and share a dataset with sharenfs.
+# 2. Verify the dataset is shared.
+# 3. Invoke 'zfs destroy' on the dataset.
+# 4. Verify the dataset is not shared.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if datasetexists "$TESTPOOL/$TESTFS/shared1"; then
+ log_must zfs destroy -f $TESTPOOL/$TESTFS/shared1
+ fi
+}
+
+log_assert "Verify 'zfs destroy' will unshare the dataset"
+log_onexit cleanup
+
+# 1. Create and share a dataset with sharenfs.
+log_must zfs create \
+ -o sharenfs=on -o mountpoint=$TESTDIR/1 $TESTPOOL/$TESTFS/shared1
+
+#
+# 2. Verify the datasets is shared.
+#
+log_must is_shared $TESTDIR/1
+
+# 3. Invoke 'zfs destroy' on the dataset.
+log_must zfs destroy -f $TESTPOOL/$TESTFS/shared1
+
+# 4. Verify the dataset is not shared.
+log_mustnot is_shared $TESTDIR/1
+
+log_pass "'zfs destroy' will unshare the dataset."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/Makefile.am
new file mode 100644
index 000000000000..7a71bae4bb42
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/Makefile.am
@@ -0,0 +1,14 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_upgrade
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_upgrade_001_pos.ksh \
+ zfs_upgrade_002_pos.ksh \
+ zfs_upgrade_003_pos.ksh \
+ zfs_upgrade_004_pos.ksh \
+ zfs_upgrade_005_pos.ksh \
+ zfs_upgrade_006_neg.ksh \
+ zfs_upgrade_007_neg.ksh
+
+dist_pkgdata_DATA = \
+ zfs_upgrade.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/cleanup.ksh
new file mode 100755
index 000000000000..e2d0604fded2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/cleanup.ksh
@@ -0,0 +1,33 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/setup.ksh
new file mode 100755
index 000000000000..c9f36017df9a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/setup.ksh
@@ -0,0 +1,42 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+
+# This should have been set by the .cfg script - verify it's set to something
+# (we check that something later on)
+if [ -z "$ZFS_VERSION" ]
+then
+ log_unresolved "Unable to determine ZFS Filesystem version of this machine"
+else
+ log_note "This machine is running ZFS Filesystem version $ZFS_VERSION"
+fi
+
+default_setup "$DISKS"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib
new file mode 100644
index 000000000000..9c7d273b385c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib
@@ -0,0 +1,194 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# For zfs create.
+#
+set -A zpl_create_versions 3 4 5
+set -A spa_create_versions 9 15 24
+
+#
+# For zfs upgrade
+#
+set -A zpl_upgrade_versions 3 4 5
+set -A spa_upgrade_versions 9 15 24
+
+function get_pool_version #pool
+{
+ ver=$(get_pool_prop version $1)
+
+ if [ "$ver" = "-" ]; then
+ ver="5000"
+ fi
+
+ echo "$ver"
+}
+
+function default_setup_datasets #rootfs
+{
+ typeset rootfs=$1
+ typeset pool=${rootfs%%/*}
+ typeset -i vp=$(get_pool_version $pool)
+ typeset -i version
+ typeset -i m
+ typeset -i spa_version
+ typeset -i zpl_version
+
+ for version in $ZFS_ALL_VERSIONS ; do
+ typeset verfs
+ eval verfs=\$ZFS_VERSION_$version
+ typeset current_fs=$rootfs/$verfs
+ typeset current_snap=${current_fs}@snap
+ typeset current_clone=$rootfs/clone$verfs
+
+ (( m=0 ))
+ (( spa_version=0 ))
+ while (( m < ${#zpl_create_versions[@]} )); do
+ (( zpl_version=${zpl_create_versions[m]} ))
+ if (( version == zpl_version )); then
+ (( spa_version=${spa_create_versions[m]} ))
+ break
+ fi
+ (( m+=1 ))
+ done
+ if (( spa_version != 0 )) && (( vp < spa_version )); then
+ log_mustnot zfs create -o version=${version} ${current_fs}
+ continue
+ fi
+ log_must zfs create -o version=${version} ${current_fs}
+ log_must zfs snapshot ${current_snap}
+ log_must zfs clone ${current_snap} ${current_clone}
+
+ for subversion in $ZFS_ALL_VERSIONS ; do
+ typeset subverfs
+ eval subverfs=\$ZFS_VERSION_$subversion
+
+ (( m=0 ))
+ (( spa_version=0 ))
+ while (( m < ${#zpl_create_versions[@]} )); do
+ (( zpl_version=${zpl_create_versions[m]} ))
+ if (( subversion == zpl_version )); then
+ (( spa_version=${spa_create_versions[m]} ))
+ break
+ fi
+ (( m+=1 ))
+ done
+ if (( spa_version != 0 )) && (( vp < spa_version )); then
+ log_mustnot zfs create -o \
+ version=${subversion} ${current_fs}/$subverfs
+ else
+ log_must zfs create -o \
+ version=${subversion} ${current_fs}/$subverfs
+ fi
+ done
+ done
+}
+
+function default_cleanup_datasets #rootfs
+{
+ typeset rootfs=$1
+
+ if datasetexists $rootfs ; then
+ log_must_busy zfs destroy -Rf $rootfs
+ fi
+
+ if datasetnonexists $rootfs ; then
+ log_must zfs create $rootfs
+ fi
+}
+
+function default_check_zfs_upgrade #rootfs
+{
+ typeset rootfs=$1
+ typeset pool=${rootfs%%/*}
+ typeset -i vp=$(get_pool_version $pool)
+ typeset -i m
+ typeset -i spa_version
+ typeset -i zpl_version
+ typeset newv
+ typeset -i df_ret
+
+ df -F zfs / > /dev/null 2>&1
+ df_ret=$?
+
+ for newv in "" $ZFS_VERSION; do
+ default_setup_datasets $rootfs
+ if [[ -n $newv ]]; then
+ opt="-V $newv"
+ else
+ newv=$ZFS_VERSION
+ fi
+
+ (( m=0 ))
+ (( spa_version=0 ))
+ while (( m < ${#zpl_upgrade_versions[@]} )); do
+ (( zpl_version=${zpl_upgrade_versions[m]} ))
+ if (( newv == zpl_version )); then
+ (( spa_version=${spa_upgrade_versions[m]} ))
+ break
+ fi
+ (( m+=1 ))
+ done
+
+ if (( df_ret != 0 )); then
+ if (( spa_version != 0 )) && (( vp < spa_version )); then
+ log_mustnot eval "zfs upgrade $opt -a >/dev/null"
+ log_must eval "zpool upgrade $pool >/dev/null"
+ vp=$(get_pool_version $pool)
+ fi
+
+ log_must zfs upgrade $opt -a
+
+ for fs in $(zfs list -rH -t filesystem -o name $rootfs) ; do
+ log_must check_fs_version $fs $newv
+ done
+ fi
+
+ default_cleanup_datasets $rootfs
+ done
+}
+
+function check_fs_version #filesystem version
+{
+ typeset fs=$1
+ typeset -i version=${2:-$ZFS_VERSION}
+
+ if [[ -z $fs ]]; then
+ log_fail "No filesystem specified."
+ fi
+
+ typeset -i curv=$(get_prop version $fs)
+ if (( curv != version )); then
+ return 1
+ fi
+ return 0
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_001_pos.ksh
new file mode 100755
index 000000000000..d3ed4a736cc9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_001_pos.ksh
@@ -0,0 +1,139 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# Executing 'zfs upgrade' command succeeds, it should report
+# the current system version and list all old-version filesystems.
+# If no old-version filesystems be founded, it prints out
+# "All filesystems are formatted with the current version."
+#
+# STRATEGY:
+# 1. Prepare a set of datasets which contain old-version and current version.
+# 2. Execute 'zfs upgrade', verify return 0, and it prints out
+# the current system version and list all old-version filesystems.
+# 3. Remove all old-version filesystems, then execute 'zfs upgrade' again,
+# verify return 0, and get the expected message.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $rootfs ; then
+ log_must zfs destroy -Rf $rootfs
+ fi
+ log_must zfs create $rootfs
+
+ for file in $output $oldoutput ; do
+ if [[ -f $file ]]; then
+ log_must rm -f $file
+ fi
+ done
+}
+
+log_assert "Executing 'zfs upgrade' command succeeds."
+log_onexit cleanup
+
+rootfs=$TESTPOOL/$TESTFS
+typeset output=$TEST_BASE_DIR/zfs-versions.$$
+typeset oldoutput=$TEST_BASE_DIR/zfs-versions-old.$$
+typeset expect_str1="This system is currently running ZFS filesystem version"
+typeset expect_str2="All filesystems are formatted with the current version"
+typeset expect_str3="The following filesystems are out of date, and can be upgraded"
+typeset -i COUNT OLDCOUNT
+
+zfs upgrade | nawk '$1 ~ "^[0-9]+$" {print $2}'> $oldoutput
+OLDCOUNT=$( wc -l $oldoutput | awk '{print $1}' )
+
+old_datasets=""
+for version in $ZFS_ALL_VERSIONS ; do
+ typeset verfs
+ eval verfs=\$ZFS_VERSION_$version
+ typeset current_fs=$rootfs/$verfs
+ typeset current_snap=${current_fs}@snap
+ typeset current_clone=$rootfs/clone$verfs
+ log_must zfs create -o version=${version} ${current_fs}
+ log_must zfs snapshot ${current_snap}
+ log_must zfs clone ${current_snap} ${current_clone}
+
+ if (( version != $ZFS_VERSION )); then
+ old_datasets="$old_datasets ${current_fs} ${current_clone}"
+ fi
+done
+
+if is_global_zone; then
+ log_must zfs create -V 100m $rootfs/$TESTVOL
+fi
+
+log_must eval 'zfs upgrade > $output 2>&1'
+
+# we also check that the usage message contains at least a description
+# of the current ZFS version.
+log_must eval 'grep "${expect_str1} $ZFS_VERSION" $output > /dev/null 2>&1'
+zfs upgrade | nawk '$1 ~ "^[0-9]+$" {print $2}'> $output
+COUNT=$( wc -l $output | awk '{print $1}' )
+
+typeset -i i=0
+for fs in ${old_datasets}; do
+ log_must grep "^$fs$" $output
+ (( i = i + 1 ))
+done
+
+if (( i != COUNT - OLDCOUNT )); then
+ cat $output
+ log_fail "More old-version filesystems print out than expect."
+fi
+
+for fs in $old_datasets ; do
+ if datasetexists $fs ; then
+ log_must zfs destroy -Rf $fs
+ fi
+done
+
+log_must eval 'zfs upgrade > $output 2>&1'
+log_must eval 'grep "${expect_str1} $ZFS_VERSION" $output > /dev/null 2>&1'
+if (( OLDCOUNT == 0 )); then
+ log_must eval 'grep "${expect_str2}" $output > /dev/null 2>&1'
+else
+ log_must eval 'grep "${expect_str3}" $output > /dev/null 2>&1'
+fi
+zfs upgrade | nawk '$1 ~ "^[0-9]+$" {print $2}'> $output
+COUNT=$( wc -l $output | awk '{print $1}' )
+
+if (( COUNT != OLDCOUNT )); then
+ cat $output
+ log_fail "Unexpected old-version filesystems print out."
+fi
+
+log_pass "Executing 'zfs upgrade' command succeeds."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_002_pos.ksh
new file mode 100755
index 000000000000..ba6e7c483edd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_002_pos.ksh
@@ -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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# Executing 'zfs upgrade -v ' command succeeds, it should
+# show the info of available versions.
+#
+# STRATEGY:
+# 1. Execute 'zfs upgrade -v', verify return value is 0.
+# 2, Verify all the available versions info are printed out.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if [[ -f $output ]]; then
+ log_must rm -f $output
+ fi
+}
+
+log_assert "Executing 'zfs upgrade -v' command succeeds."
+log_onexit cleanup
+
+typeset output=$TEST_BASE_DIR/zfs-versions.$$
+typeset expect_str1="Initial ZFS filesystem version"
+typeset expect_str2="Enhanced directory entries"
+
+log_must eval 'zfs upgrade -v > /dev/null 2>&1'
+
+zfs upgrade -v | nawk '$1 ~ "^[0-9]+$" {print $0}'> $output
+log_must eval 'grep "${expect_str1}" $output > /dev/null 2>&1'
+log_must eval 'grep "${expect_str2}" $output > /dev/null 2>&1'
+
+log_pass "Executing 'zfs upgrade -v' command succeeds."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_003_pos.ksh
new file mode 100755
index 000000000000..6df47b450d00
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_003_pos.ksh
@@ -0,0 +1,104 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# Executing 'zfs upgrade [-V version] filesystem' command succeeds,
+# it could upgrade a filesystem to specific version or current version.
+#
+# STRATEGY:
+# 1. Prepare a set of datasets which contain old-version and current version.
+# 2. Execute 'zfs upgrade [-V version] filesystem', verify return 0,
+# 3. Verify the filesystem be updated as expected.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $rootfs ; then
+ log_must zfs destroy -Rf $rootfs
+ fi
+ log_must zfs create $rootfs
+}
+
+function setup_datasets
+{
+ datasets=""
+ for version in $ZFS_ALL_VERSIONS ; do
+ typeset verfs
+ eval verfs=\$ZFS_VERSION_$version
+ typeset current_fs=$rootfs/$verfs
+ typeset current_snap=${current_fs}@snap
+ typeset current_clone=$rootfs/clone$verfs
+ log_must zfs create -o version=${version} ${current_fs}
+ log_must zfs snapshot ${current_snap}
+ log_must zfs clone ${current_snap} ${current_clone}
+ datasets="$datasets ${current_fs} ${current_clone}"
+ done
+}
+
+log_assert "Executing 'zfs upgrade [-V version] filesystem' command succeeds."
+log_onexit cleanup
+
+rootfs=$TESTPOOL/$TESTFS
+typeset datasets
+
+typeset newv
+for newv in "" "current" $ZFS_ALL_VERSIONS; do
+ setup_datasets
+ for fs in $datasets ; do
+ typeset -i oldv=$(get_prop version $fs)
+
+ if [[ -n $newv ]]; then
+ opt="-V $newv"
+ if [[ $newv == current ]]; then
+ newv=$ZFS_VERSION
+ fi
+ else
+ newv=$ZFS_VERSION
+ fi
+
+ if (( newv >= oldv )); then
+ log_must eval 'zfs upgrade $opt $fs > /dev/null 2>&1'
+ log_must check_fs_version $fs $newv
+ else
+ log_mustnot eval 'zfs upgrade $opt $fs > /dev/null 2>&1'
+ log_must check_fs_version $fs $oldv
+ fi
+ done
+ cleanup
+done
+
+log_pass "Executing 'zfs upgrade [-V version] filesystem' command succeeds."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_004_pos.ksh
new file mode 100755
index 000000000000..e3ff4f4b9073
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_004_pos.ksh
@@ -0,0 +1,108 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# Executing 'zfs upgrade -r [-V version] filesystem' command succeeds,
+# it upgrade filesystem recursively to specific or current version.
+#
+# STRATEGY:
+# 1. Prepare a set of datasets which contain old-version and current version.
+# 2. Execute 'zfs upgrade -r [-V version] filesystem', verify return 0,
+# 3. Verify the filesystem be updated recursively as expected.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $rootfs ; then
+ log_must zfs destroy -Rf $rootfs
+ fi
+ log_must zfs create $rootfs
+}
+
+function setup_datasets
+{
+ datasets=""
+ for version in $ZFS_ALL_VERSIONS ; do
+ typeset verfs
+ eval verfs=\$ZFS_VERSION_$version
+ typeset current_fs=$rootfs/$verfs
+ typeset current_snap=${current_fs}@snap
+ typeset current_clone=$rootfs/clone$verfs
+ log_must zfs create -o version=${version} ${current_fs}
+ log_must zfs snapshot ${current_snap}
+ log_must zfs clone ${current_snap} ${current_clone}
+
+ for subversion in $ZFS_ALL_VERSIONS ; do
+ typeset subverfs
+ eval subverfs=\$ZFS_VERSION_$subversion
+ log_must zfs create -o version=${subversion} \
+ ${current_fs}/$subverfs
+ done
+ datasets="$datasets ${current_fs}"
+ done
+}
+
+log_assert "Executing 'zfs upgrade -r [-V version] filesystem' command succeeds."
+log_onexit cleanup
+
+rootfs=$TESTPOOL/$TESTFS
+
+typeset datasets
+
+typeset newv
+for newv in "" "current" $ZFS_VERSION; do
+ setup_datasets
+ for topfs in $datasets ; do
+ if [[ -n $newv ]]; then
+ opt="-V $newv"
+ if [[ $newv == current ]]; then
+ newv=$ZFS_VERSION
+ fi
+ else
+ newv=$ZFS_VERSION
+ fi
+
+ log_must eval 'zfs upgrade -r $opt $topfs > /dev/null 2>&1'
+
+ for fs in $(zfs list -rH -t filesystem -o name $topfs) ; do
+ log_must check_fs_version $fs $newv
+ done
+ done
+ cleanup
+done
+
+log_pass "Executing 'zfs upgrade -r [-V version] filesystem' command succeeds."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_005_pos.ksh
new file mode 100755
index 000000000000..1a929918bf10
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_005_pos.ksh
@@ -0,0 +1,108 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# Executing 'zfs upgrade [-V version] -a' command succeeds,
+# it upgrade all filesystems to specific or current version.
+#
+# STRATEGY:
+# 1. Prepare a set of datasets which contain old-version and current version.
+# 2. Execute 'zfs upgrade [-V version] -a', verify return 0,
+# 3. Verify all the filesystems be updated as expected.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $rootfs ; then
+ log_must zfs destroy -Rf $rootfs
+ fi
+ log_must zfs create $rootfs
+}
+
+function setup_datasets
+{
+ datasets=""
+ for version in $ZFS_ALL_VERSIONS ; do
+ typeset verfs
+ eval verfs=\$ZFS_VERSION_$version
+ typeset current_fs=$rootfs/$verfs
+ typeset current_snap=${current_fs}@snap
+ typeset current_clone=$rootfs/clone$verfs
+ log_must zfs create -o version=${version} ${current_fs}
+ log_must zfs snapshot ${current_snap}
+ log_must zfs clone ${current_snap} ${current_clone}
+
+ for subversion in $ZFS_ALL_VERSIONS ; do
+ typeset subverfs
+ eval subverfs=\$ZFS_VERSION_$subversion
+ log_must zfs create -o version=${subversion} \
+ ${current_fs}/$subverfs
+ done
+ datasets="$datasets ${current_fs}"
+ done
+}
+
+log_assert "Executing 'zfs upgrade [-V version] -a' command succeeds."
+log_onexit cleanup
+
+rootfs=$TESTPOOL/$TESTFS
+
+typeset datasets
+
+typeset newv
+for newv in "" "current" $ZFS_VERSION; do
+ setup_datasets
+ if [[ -n $newv ]]; then
+ opt="-V $newv"
+ if [[ $newv == current ]]; then
+ newv=$ZFS_VERSION
+ fi
+ else
+ newv=$ZFS_VERSION
+ fi
+
+ export __ZFS_POOL_RESTRICT="$TESTPOOL"
+ log_must zfs upgrade $opt -a
+ unset __ZFS_POOL_RESTRICT
+
+ for fs in $(zfs list -rH -t filesystem -o name $rootfs) ; do
+ log_must check_fs_version $fs $newv
+ done
+ cleanup
+done
+
+log_pass "Executing 'zfs upgrade [-V version] -a' command succeeds."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_006_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_006_neg.ksh
new file mode 100755
index 000000000000..f5eef319330b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_006_neg.ksh
@@ -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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# Verify that invalid upgrade parameters and options are caught.
+#
+# STRATEGY:
+# 1. Create a ZFS file system.
+# 2. For each option in the list, try 'zfs upgrade'.
+# 3. Verify that the operation fails as expected.
+#
+
+verify_runnable "both"
+
+set -A args "" "-?" "-A" "-R" "-b" "-c" "-d" "--invalid" \
+ "-V" "-V $TESTPOOL/$TESTFS" "-V $TESTPOOL $TESTPOOL/$TESTFS"
+
+log_assert "Badly-formed 'zfs upgrade' should return an error."
+
+typeset -i i=1
+while (( i < ${#args[*]} )); do
+ log_mustnot zfs upgrade ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "Badly-formed 'zfs upgrade' fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_007_neg.ksh
new file mode 100755
index 000000000000..6c6f94754d3c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_upgrade/zfs_upgrade_007_neg.ksh
@@ -0,0 +1,59 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# Verify that version should only by '1' '2' or current version,
+# non-digit input are invalid.
+#
+# STRATEGY:
+# 1. For each invalid value of version in the list, try 'zfs upgrade -V version'.
+# 2. Verify that the operation fails as expected.
+#
+
+verify_runnable "both"
+
+set -A args \
+ "0" "0.000" "0.5" "-1.234" "-1" "1234b" "5678x"
+
+log_assert "Set invalid value or non-digit version should fail as expected."
+
+typeset -i i=0
+while (( i < ${#args[*]} ))
+do
+ log_mustnot zfs upgrade -V ${args[i]} $TESTPOOL/$TESTFS
+ ((i = i + 1))
+done
+
+log_pass "Set invalid value or non-digit version fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_wait/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_wait/Makefile.am
new file mode 100644
index 000000000000..d401fe68b1e8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_wait/Makefile.am
@@ -0,0 +1,8 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_wait
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_wait_deleteq.ksh
+
+dist_pkgdata_DATA = \
+ zfs_wait.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_wait/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_wait/cleanup.ksh
new file mode 100755
index 000000000000..456d2d0c2ddb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_wait/cleanup.ksh
@@ -0,0 +1,20 @@
+#!/bin/ksh -p
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_wait/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_wait/setup.ksh
new file mode 100755
index 000000000000..cca05fee7229
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_wait/setup.ksh
@@ -0,0 +1,21 @@
+#!/bin/ksh -p
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_wait/zfs_wait.kshlib b/tests/zfs-tests/tests/functional/cli_root/zfs_wait/zfs_wait.kshlib
new file mode 100644
index 000000000000..9f62a7c92e6b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_wait/zfs_wait.kshlib
@@ -0,0 +1,80 @@
+#!/bin/ksh
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018, 2019 by Delphix. All rights reserved.
+#
+
+typeset -a disk_array=($(find_disks $DISKS))
+
+typeset -r DISK1=${disk_array[0]}
+typeset -r DISK2=${disk_array[1]}
+typeset -r DISK3=${disk_array[2]}
+
+#
+# When the condition it is waiting for becomes true, 'zfs wait' should return
+# promptly. We want to enforce this, but any check will be racey because it will
+# take some small but indeterminate amount of time for the waiting thread to be
+# woken up and for the process to exit.
+#
+# To deal with this, we provide a grace period after the condition becomes true
+# during which 'zfs wait' can exit. If it hasn't exited by the time the grace
+# period expires we assume something is wrong and fail the test. While there is
+# no value that can really be correct, the idea is we choose something large
+# enough that it shouldn't cause issues in practice.
+#
+typeset -r WAIT_EXIT_GRACE=2.0
+
+function proc_exists # pid
+{
+ ps -p $1 >/dev/null
+}
+
+function proc_must_exist # pid
+{
+ proc_exists $1 || log_fail "zpool process exited too soon"
+}
+
+function proc_must_not_exist # pid
+{
+ proc_exists $1 && log_fail "zpool process took too long to exit"
+}
+
+function get_time
+{
+ date +'%H:%M:%S'
+}
+
+function kill_if_running
+{
+ typeset pid=$1
+ [[ $pid ]] && proc_exists $pid && log_must kill -s TERM $pid
+}
+
+# Log a command and then start it running in the background
+function log_bkgrnd
+{
+ log_note "$(get_time) Starting cmd in background '$@'"
+ "$@" &
+}
+
+# Check that a background process has completed and exited with a status of 0
+function bkgrnd_proc_succeeded
+{
+ typeset pid=$1
+
+ log_must sleep $WAIT_EXIT_GRACE
+
+ proc_must_not_exist $pid
+ wait $pid || log_fail "process exited with status $?"
+ log_note "$(get_time) wait completed successfully"
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_wait/zfs_wait_deleteq.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_wait/zfs_wait_deleteq.ksh
new file mode 100755
index 000000000000..00c5a109c0b2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_wait/zfs_wait_deleteq.ksh
@@ -0,0 +1,57 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_wait/zfs_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs wait' works when waiting for checkpoint discard to complete.
+#
+# STRATEGY:
+# 1. Create a file
+# 2. Open a file descriptor pointing to that file.
+# 3. Delete the file.
+# 4. Start a background process waiting for the delete queue to empty.
+# 5. Verify that the command doesn't return immediately.
+# 6. Close the open file descriptor.
+# 7. Verify that the command returns soon after the descriptor is closed.
+#
+
+function cleanup
+{
+ kill_if_running $pid
+ exec 3<&-
+}
+
+
+typeset -r TESTFILE="/$TESTPOOL/testfile"
+typeset pid
+
+log_onexit cleanup
+
+log_must touch $TESTFILE
+exec 3<> $TESTFILE
+log_must rm $TESTFILE
+log_bkgrnd zfs wait -t deleteq $TESTPOOL
+pid=$!
+proc_must_exist $pid
+
+exec 3<&-
+log_must sleep 0.5
+bkgrnd_proc_succeeded $pid
+
+log_pass "'zfs wait -t discard' works."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool/Makefile.am
new file mode 100644
index 000000000000..327f23621158
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool/Makefile.am
@@ -0,0 +1,8 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_001_neg.ksh \
+ zpool_002_pos.ksh \
+ zpool_003_pos.ksh \
+ zpool_colors.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool/setup.ksh
new file mode 100755
index 000000000000..4e3b6b0e9f47
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_mirror_setup $DISKS
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_001_neg.ksh
new file mode 100755
index 000000000000..25decd78863b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_001_neg.ksh
@@ -0,0 +1,70 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# A badly formed sub-command passed to zpool(1) should
+# return an error.
+#
+# STRATEGY:
+# 1. Create an array containing each zpool sub-command name.
+# 2. For each element, execute the sub-command.
+# 3. Verify it returns an error.
+#
+
+verify_runnable "both"
+
+
+set -A args "" "create" "add" "destroy" "import fakepool" \
+ "export fakepool" "create fakepool" "add fakepool" \
+ "create mirror" "create raidz" "create raidz1" \
+ "create mirror fakepool" "create raidz fakepool" \
+ "create raidz1 fakepool" "create raidz2 fakepool" \
+ "create fakepool mirror" "create fakepool raidz" \
+ "create fakepool raidz1" "create fakepool raidz2" \
+ "add fakepool mirror" "add fakepool raidz" \
+ "add fakepool raidz1" "add fakepool raidz2" \
+ "add mirror fakepool" "add raidz fakepool" \
+ "add raidz1 fakepool" "add raidz2 fakepool" \
+ "setvprop" "blah blah" "-%" "--" "--?" "-*" "-="
+
+log_assert "Execute zpool sub-command without proper parameters."
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zpool ${args[i]}
+
+ ((i = i + 1))
+done
+
+log_pass "Badly formed zpool sub-commands fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_002_pos.ksh
new file mode 100755
index 000000000000..9440e807f206
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_002_pos.ksh
@@ -0,0 +1,112 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# With ZFS_ABORT set, all zpool commands should be able to abort and generate a core file.
+#
+# STRATEGY:
+# 1. Create an array of zpool command
+# 2. Execute each command in the array
+# 3. Verify the command aborts and generate a core file
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ unset ZFS_ABORT
+
+ if [[ -d $corepath ]]; then
+ rm -rf $corepath
+ fi
+
+ if poolexists $pool; then
+ log_must zpool destroy -f $pool
+ fi
+}
+
+log_assert "With ZFS_ABORT set, all zpool commands can abort and generate a core file."
+log_onexit cleanup
+
+#preparation work for testing
+corepath=$TESTDIR/core
+if [[ -d $corepath ]]; then
+ rm -rf $corepath
+fi
+mkdir $corepath
+
+pool=pool.$$
+vdev1=$TESTDIR/file1
+vdev2=$TESTDIR/file2
+vdev3=$TESTDIR/file3
+for vdev in $vdev1 $vdev2 $vdev3; do
+ mkfile $MINVDEVSIZE $vdev
+done
+
+set -A cmds "create $pool mirror $vdev1 $vdev2" "list $pool" "iostat $pool" \
+ "status $pool" "upgrade $pool" "get delegation $pool" "set delegation=off $pool" \
+ "export $pool" "import -d $TESTDIR $pool" "offline $pool $vdev1" \
+ "online $pool $vdev1" "clear $pool" "detach $pool $vdev2" \
+ "attach $pool $vdev1 $vdev2" "replace $pool $vdev2 $vdev3" \
+ "scrub $pool" "destroy -f $pool"
+
+set -A badparams "" "create" "destroy" "add" "remove" "list *" "iostat" "status" \
+ "online" "offline" "clear" "attach" "detach" "replace" "scrub" \
+ "import" "export" "upgrade" "history -?" "get" "set"
+
+if is_linux; then
+ ulimit -c unlimited
+ echo "$corepath/core.zpool" >/proc/sys/kernel/core_pattern
+ echo 0 >/proc/sys/kernel/core_uses_pid
+ export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
+elif is_freebsd; then
+ ulimit -c unlimited
+ log_must sysctl kern.corefile=$corepath/core.zpool
+ export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
+else
+ coreadm -p ${corepath}/core.%f
+fi
+
+export ZFS_ABORT=yes
+
+for subcmd in "${cmds[@]}" "${badparams[@]}"; do
+ corefile=${corepath}/core.zpool
+ zpool $subcmd >/dev/null 2>&1
+ if [[ ! -e $corefile ]]; then
+ log_fail "zpool $subcmd cannot generate core file with ZFS_ABORT set."
+ fi
+ rm -f $corefile
+done
+
+log_pass "With ZFS_ABORT set, zpool command can abort and generate core file as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_003_pos.ksh
new file mode 100755
index 000000000000..d51633745d76
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_003_pos.ksh
@@ -0,0 +1,90 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify debugging features of zpool such as ABORT and freeze/unfreeze
+# should run successfully.
+#
+# STRATEGY:
+# 1. Create an array containing each zpool options.
+# 2. For each element, execute the zpool command.
+# 3. Verify it run successfully.
+#
+
+function cleanup
+{
+ if is_freebsd && [ -n "$old_corefile" ]; then
+ sysctl kern.corefile=$old_corefile
+ fi
+}
+
+verify_runnable "both"
+
+log_assert "Debugging features of zpool should succeed."
+log_onexit cleanup
+
+log_must zpool -? > /dev/null 2>&1
+
+if is_global_zone ; then
+ log_must zpool freeze $TESTPOOL
+else
+ log_mustnot zpool freeze $TESTPOOL
+ log_mustnot zpool freeze ${TESTPOOL%%/*}
+fi
+
+log_mustnot zpool freeze fakepool
+
+# Remove corefile possibly left by previous failing run of this test.
+[[ -f core ]] && log_must rm -f core
+
+if is_linux; then
+ ulimit -c unlimited
+ echo "core" >/proc/sys/kernel/core_pattern
+ echo 0 >/proc/sys/kernel/core_uses_pid
+ export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
+elif is_freebsd; then
+ ulimit -c unlimited
+ old_corefile=$(sysctl -n kern.corefile)
+ log_must sysctl kern.corefile=core
+ export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
+fi
+
+ZFS_ABORT=1; export ZFS_ABORT
+zpool > /dev/null 2>&1
+unset ZFS_ABORT
+
+[[ -f core ]] || log_fail "zpool did not dump core by request."
+[[ -f core ]] && log_must rm -f core
+
+log_pass "Debugging features of zpool succeed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_colors.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_colors.ksh
new file mode 100755
index 000000000000..18f238386374
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_colors.ksh
@@ -0,0 +1,91 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Test that zpool status colored output works.
+#
+# STRATEGY:
+# 1. Create a pool with a bunch of errors and force fault one of the vdevs.
+# 2. Look for 'pool:' in bold.
+# 3. Look for 'DEGRADED' in yellow
+# 3. Look for 'FAULTED' in red
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ zinject -c all
+}
+
+log_onexit cleanup
+
+log_assert "Test colorized zpool status output"
+
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+DISK3="$(echo $DISKS | cut -d' ' -f3)"
+
+log_must dd if=/dev/urandom of=/$TESTDIR/testfile bs=10M count=1
+
+log_must zpool sync
+
+log_must zpool offline -f $TESTPOOL $DISK3
+log_must wait_for_degraded $TESTPOOL
+log_must zinject -d $DISK2 -e io -T read -f 20 $TESTPOOL
+log_must zinject -d $DISK2 -e io -T write -f 20 $TESTPOOL
+
+
+log_must zpool scrub -w $TESTPOOL
+log_must zinject -c all
+
+
+# Use 'script' to fake zpool status into thinking it's running in a tty.
+# Log the output here in case it's needed for postmortem.
+log_note "$(faketty TERM=xterm-256color ZFS_COLOR=1 zpool status)"
+
+# Replace the escape codes with "ESC" so they're easier to grep
+out="$(faketty TERM=xterm-256color ZFS_COLOR=1 zpool status | \
+ grep -E 'pool:|DEGRADED' | \
+ sed -r 's/[[:space:]]+//g;'$(echo -e 's/\033/ESC/g'))"
+
+log_note "$(echo $out)"
+
+log_note "Look for 'pool:' in bold"
+log_must eval "echo \"$out\" | grep -q 'ESC\[1mpool:ESC\[0m' "
+
+log_note "Look for 'DEGRADED' in yellow"
+log_must eval "echo \"$out\" | grep -q 'ESC\[0;33mDEGRADEDESC\[0m'"
+
+#
+# The escape code for 'FAULTED' is a little more tricky. The line starts like
+# this:
+#
+# <start red escape code> loop2 FAULTED <end escape code>
+#
+# Luckily, awk counts the start and end escape codes as separate fields, so
+# we can easily remove the vdev field to get what we want.
+#
+out="$(faketty TERM=xterm-256color ZFS_COLOR=1 zpool status \
+ | awk '/FAULTED/{print $1$3$4}' | sed -r $(echo -e 's/\033/ESC/g'))"
+
+log_note "Look for 'FAULTED' in red"
+log_must eval "echo \"$out\" | grep -q 'ESC\[0;31mFAULTEDESC\[0m'"
+
+log_pass "zpool status displayed colors"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_add/Makefile.am
new file mode 100644
index 000000000000..a7f62b6f9f79
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/Makefile.am
@@ -0,0 +1,21 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_add
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_add_001_pos.ksh \
+ zpool_add_002_pos.ksh \
+ zpool_add_003_pos.ksh \
+ zpool_add_004_pos.ksh \
+ zpool_add_005_pos.ksh \
+ zpool_add_006_pos.ksh \
+ zpool_add_007_neg.ksh \
+ zpool_add_008_neg.ksh \
+ zpool_add_009_neg.ksh \
+ zpool_add_010_pos.ksh \
+ add-o_ashift.ksh \
+ add_prop_ashift.ksh \
+ add_nested_replacing_spare.ksh
+
+dist_pkgdata_DATA = \
+ zpool_add.cfg \
+ zpool_add.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/add-o_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add-o_ashift.ksh
new file mode 100755
index 000000000000..d9ae88e0792e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add-o_ashift.ksh
@@ -0,0 +1,85 @@
+#!/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 2017, loli10K. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool add -o ashift=<n> ...' should work with different ashift
+# values.
+#
+# STRATEGY:
+# 1. Create a pool with default values.
+# 2. Verify 'zpool add -o ashift=<n>' works with allowed values (9-16).
+# 3. Verify 'zpool add -o ashift=<n>' doesn't accept other invalid values.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -f $disk1 $disk2
+}
+
+log_assert "zpool add -o ashift=<n>' works with different ashift values"
+log_onexit cleanup
+
+disk1=$TEST_BASE_DIR/disk1
+disk2=$TEST_BASE_DIR/disk2
+log_must mkfile $SIZE $disk1
+log_must mkfile $SIZE $disk2
+
+typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16")
+for ashift in ${ashifts[@]}
+do
+ log_must zpool create $TESTPOOL $disk1
+ log_must zpool add -o ashift=$ashift $TESTPOOL $disk2
+ verify_ashift $disk2 $ashift
+ if [[ $? -ne 0 ]]
+ then
+ log_fail "Device was added without setting ashift value to "\
+ "$ashift"
+ fi
+ # clean things for the next run
+ log_must zpool destroy $TESTPOOL
+ log_must zpool labelclear $disk1
+ log_must zpool labelclear $disk2
+done
+
+typeset badvals=("off" "on" "1" "8" "17" "1b" "ff" "-")
+for badval in ${badvals[@]}
+do
+ log_must zpool create $TESTPOOL $disk1
+ log_mustnot zpool add -o ashift="$badval" $TESTPOOL $disk2
+ # clean things for the next run
+ log_must zpool destroy $TESTPOOL
+ log_must zpool labelclear $disk1
+ log_mustnot zpool labelclear $disk2
+done
+
+log_pass "zpool add -o ashift=<n>' works with different ashift values"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_nested_replacing_spare.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_nested_replacing_spare.ksh
new file mode 100755
index 000000000000..61f5f6d1ceed
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_nested_replacing_spare.ksh
@@ -0,0 +1,110 @@
+#!/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 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zpool add' works with nested replacing/spare vdevs
+#
+# STRATEGY:
+# 1. Create a redundant pool with a spare device
+# 2. Manually fault a device, wait for the hot-spare and then replace it:
+# this creates a situation where replacing and spare vdevs are nested.
+# 3. Verify 'zpool add' is able to add new devices to the pool.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ zed_stop
+ zed_cleanup
+ log_must zinject -c all
+ destroy_pool $TESTPOOL
+ log_must rm -f $DATA_DEVS $SPARE_DEVS
+}
+
+log_assert "'zpool add' works with nested replacing/spare vdevs"
+log_onexit cleanup
+
+FAULT_DEV="$TEST_BASE_DIR/fault-dev"
+SAFE_DEV1="$TEST_BASE_DIR/safe-dev1"
+SAFE_DEV2="$TEST_BASE_DIR/safe-dev2"
+SAFE_DEV3="$TEST_BASE_DIR/safe-dev3"
+SAFE_DEVS="$SAFE_DEV1 $SAFE_DEV2 $SAFE_DEV3"
+REPLACE_DEV="$TEST_BASE_DIR/replace-dev"
+ADD_DEV="$TEST_BASE_DIR/add-dev"
+DATA_DEVS="$FAULT_DEV $SAFE_DEVS $REPLACE_DEV $ADD_DEV"
+SPARE_DEV1="$TEST_BASE_DIR/spare-dev1"
+SPARE_DEV2="$TEST_BASE_DIR/spare-dev2"
+SPARE_DEVS="$SPARE_DEV1 $SPARE_DEV2"
+
+# We need ZED running to work with spares
+zed_setup
+zed_start
+# Clear events from previous runs
+zed_events_drain
+
+for type in "mirror" "raidz1" "raidz2" "raidz3"
+do
+ # 1. Create a redundant pool with a spare device
+ truncate -s $SPA_MINDEVSIZE $DATA_DEVS $SPARE_DEVS
+ log_must zpool create $TESTPOOL $type $FAULT_DEV $SAFE_DEVS
+ log_must zpool add $TESTPOOL spare $SPARE_DEV1
+
+ # 2.1 Fault a device, verify the spare is kicked in
+ log_must zinject -d $FAULT_DEV -e nxio -T all -f 100 $TESTPOOL
+ log_must zpool reopen $TESTPOOL
+ log_must wait_vdev_state $TESTPOOL $FAULT_DEV "UNAVAIL" 60
+ log_must wait_vdev_state $TESTPOOL $SPARE_DEV1 "ONLINE" 60
+ log_must wait_hotspare_state $TESTPOOL $SPARE_DEV1 "INUSE"
+ log_must check_state $TESTPOOL "" "DEGRADED"
+
+ # 2.2 Replace the faulted device: this creates a replacing vdev inside a
+ # spare vdev
+ log_must zpool replace $TESTPOOL $FAULT_DEV $REPLACE_DEV
+ log_must wait_vdev_state $TESTPOOL $REPLACE_DEV "ONLINE" 60
+ zpool status | awk -v poolname="$TESTPOOL" -v type="$type" 'BEGIN {s=""}
+ $1 ~ poolname {c=4}; (c && c--) { s=s$1":" }
+ END { if (s != poolname":"type"-0:spare-0:replacing-0:") exit 1; }'
+ if [[ $? -ne 0 ]]; then
+ log_fail "Pool does not contain nested replacing/spare vdevs"
+ fi
+
+ # 3. Verify 'zpool add' is able to add new devices
+ log_must zpool add $TESTPOOL spare $SPARE_DEV2
+ log_must wait_hotspare_state $TESTPOOL $SPARE_DEV2 "AVAIL"
+ log_must zpool add -f $TESTPOOL $ADD_DEV
+ log_must wait_vdev_state $TESTPOOL $ADD_DEV "ONLINE" 60
+
+ # Cleanup
+ log_must zinject -c all
+ destroy_pool $TESTPOOL
+ log_must rm -f $DATA_DEVS $SPARE_DEVS
+done
+
+log_pass "'zpool add' works with nested replacing/spare vdevs"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_prop_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_prop_ashift.ksh
new file mode 100755
index 000000000000..37887f3d115e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/add_prop_ashift.ksh
@@ -0,0 +1,94 @@
+#!/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 2017, loli10K. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# 'zpool add' should use the ashift pool property value as default.
+#
+# STRATEGY:
+# 1. Create a pool with default values.
+# 2. Verify 'zpool add' uses the ashift pool property value when adding
+# a new device.
+# 3. Verify the default ashift value can still be overridden by manually
+# specifying '-o ashift=<n>' from the command line.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ log_must rm -f $disk1 $disk2
+}
+
+log_assert "'zpool add' uses the ashift pool property value as default."
+log_onexit cleanup
+
+disk1=$TEST_BASE_DIR/disk1
+disk2=$TEST_BASE_DIR/disk2
+log_must mkfile $SIZE $disk1
+log_must mkfile $SIZE $disk2
+
+typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16")
+for ashift in ${ashifts[@]}
+do
+ log_must zpool create -o ashift=$ashift $TESTPOOL $disk1
+ log_must zpool add $TESTPOOL $disk2
+ verify_ashift $disk2 $ashift
+ if [[ $? -ne 0 ]]
+ then
+ log_fail "Device was added without setting ashift value to "\
+ "$ashift"
+ fi
+ # clean things for the next run
+ log_must zpool destroy $TESTPOOL
+ log_must zpool labelclear $disk1
+ log_must zpool labelclear $disk2
+done
+
+for ashift in ${ashifts[@]}
+do
+ for cmdval in ${ashifts[@]}
+ do
+ log_must zpool create -o ashift=$ashift $TESTPOOL $disk1
+ log_must zpool add -o ashift=$cmdval $TESTPOOL $disk2
+ verify_ashift $disk2 $cmdval
+ if [[ $? -ne 0 ]]
+ then
+ log_fail "Device was added without setting ashift " \
+ "value to $cmdval"
+ fi
+ # clean things for the next run
+ log_must zpool destroy $TESTPOOL
+ log_must zpool labelclear $disk1
+ log_must zpool labelclear $disk2
+ done
+done
+
+log_pass "'zpool add' uses the ashift pool property value."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/cleanup.ksh
new file mode 100755
index 000000000000..33bd94fdc4f9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/cleanup.ksh
@@ -0,0 +1,35 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.kshlib
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/setup.ksh
new file mode 100755
index 000000000000..13bd33ee42aa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/setup.ksh
@@ -0,0 +1,37 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.kshlib
+
+verify_runnable "global"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.cfg
new file mode 100644
index 000000000000..a634b8b3c617
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.cfg
@@ -0,0 +1,39 @@
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2015 by Delphix. All rights reserved.
+#
+
+export SIZE="$(((MINVDEVSIZE / (1024 * 1024)) * 2))m"
+export VOLSIZE=$MINVDEVSIZE
+
+echo $DISKS | read DISK0 DISK1 DISK2
+
+if is_linux; then
+ export DISK_ARRAY_NUM=3
+ set_device_dir
+fi
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.kshlib b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.kshlib
new file mode 100644
index 000000000000..a7a1fb330241
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.kshlib
@@ -0,0 +1,111 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.cfg
+
+#
+# Find the storage device in /etc/vfstab
+#
+function find_vfstab_dev
+{
+ typeset vfstabdev
+ typeset vfstabdevs=""
+ typeset line
+
+ if is_illumos; then
+ vfstab="/etc/vfstab"
+ tmpfile="$TEST_BASE_DIR/vfstab.tmp"
+ else
+ vfstab="/etc/fstab"
+ tmpfile="$TEST_BASE_DIR/fstab.tmp"
+ fi
+
+ cat $vfstab | grep "^${DEV_DSKDIR}" >$tmpfile
+ while read -r line
+ do
+ vfstabdev=`echo "$line" | awk '{print $1}'`
+ vfstabdev=${vfstabdev%%:}
+ vfstabdevs="$vfstabdev $vfstabdevs"
+ done <$tmpfile
+
+ rm -f $tmpfile
+ echo $vfstabdevs
+}
+
+#
+# Find the storage device in /etc/mnttab
+#
+function find_mnttab_dev
+{
+ typeset mnttabdev
+ typeset mnttabdevs=""
+ typeset line
+
+ if is_freebsd; then
+ # FreeBSD doesn't have a mnttab file.
+ mount -p | awk -v dir="^${DEV_DSKDIR}" \
+ '$1 ~ dir { print $1 }' | xargs
+ return 0
+ elif is_linux; then
+ typeset mnttab="/etc/mtab"
+ typeset tmpfile="$TEST_BASE_DIR/mtab.tmp"
+ else
+ typeset mnttab="/etc/mnttab"
+ typeset tmpfile="$TEST_BASE_DIR/mnttab.tmp"
+ fi
+
+ cat $mnttab | grep "^${DEV_DSKDIR}" >$tmpfile
+ while read -r line
+ do
+ mnttabdev=`echo "$line" | awk '{print $1}'`
+ mnttabdev=${mnttabdev%%:}
+ mnttabdevs="$mnttabdev $mnttabdevs"
+ done <$tmpfile
+
+ rm -f $tmpfile
+ echo $mnttabdevs
+}
+
+#
+# Save the system current dump device configuration
+#
+function save_dump_dev
+{
+
+ typeset dumpdev=""
+
+ if is_illumos; then
+ typeset fnd="Dump device"
+ dumpdev=`dumpadm | grep "$fnd" | cut -f2 -d : | \
+ awk '{print $1}'`
+ fi
+ echo $dumpdev
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_001_pos.ksh
new file mode 100755
index 000000000000..aa50de3be290
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_001_pos.ksh
@@ -0,0 +1,116 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool add <pool> <vdev> ...' can successfully add the specified
+# devices to the given pool
+#
+# STRATEGY:
+# 1. Create a storage pool
+# 2. Add spare devices to the pool
+# 3. Verify the devices are added to the pool successfully
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -f $disk0 $disk1
+}
+
+log_assert "'zpool add <pool> <vdev> ...' can add devices to the pool."
+
+log_onexit cleanup
+
+set -A keywords "" "mirror" "raidz" "raidz1" "spare"
+
+pooldevs="${DISK0} \
+ \"${DISK0} ${DISK1}\" \
+ \"${DISK0} ${DISK1} ${DISK2}\""
+mirrordevs="\"${DISK0} ${DISK1}\""
+raidzdevs="\"${DISK0} ${DISK1}\""
+
+disk0=$TEST_BASE_DIR/disk0
+disk1=$TEST_BASE_DIR/disk1
+truncate -s $MINVDEVSIZE $disk0 $disk1
+
+typeset -i i=0
+typeset vdev
+eval set -A poolarray $pooldevs
+eval set -A mirrorarray $mirrordevs
+eval set -A raidzarray $raidzdevs
+
+while (( $i < ${#keywords[*]} )); do
+
+ case ${keywords[i]} in
+ ""|spare)
+ for vdev in "${poolarray[@]}"; do
+ create_pool "$TESTPOOL" "$disk0"
+ log_must poolexists "$TESTPOOL"
+ log_must zpool add -f "$TESTPOOL" ${keywords[i]} $vdev
+ log_must vdevs_in_pool "$TESTPOOL" "$vdev"
+ destroy_pool "$TESTPOOL"
+ done
+
+ ;;
+ mirror)
+ for vdev in "${mirrorarray[@]}"; do
+ create_pool "$TESTPOOL" "${keywords[i]}" \
+ "$disk0" "$disk1"
+ log_must poolexists "$TESTPOOL"
+ log_must zpool add "$TESTPOOL" ${keywords[i]} $vdev
+ log_must vdevs_in_pool "$TESTPOOL" "$vdev"
+ destroy_pool "$TESTPOOL"
+ done
+
+ ;;
+ raidz|raidz1)
+ for vdev in "${raidzarray[@]}"; do
+ create_pool "$TESTPOOL" "${keywords[i]}" \
+ "$disk0" "$disk1"
+ log_must poolexists "$TESTPOOL"
+ log_must zpool add "$TESTPOOL" ${keywords[i]} $vdev
+ log_must vdevs_in_pool "$TESTPOOL" "$vdev"
+ destroy_pool "$TESTPOOL"
+ done
+
+ ;;
+ esac
+
+ (( i = i+1 ))
+done
+
+log_pass "'zpool add <pool> <vdev> ...' executes successfully"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_002_pos.ksh
new file mode 100755
index 000000000000..67810bbf985b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_002_pos.ksh
@@ -0,0 +1,68 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2014, 2016 by Delphix. All rights reserved.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool add -f <pool> <vdev> ...' can successfully add the specified
+# devices to given pool in some cases.
+#
+# STRATEGY:
+# 1. Create a mirrored pool
+# 2. Without -f option to add 1-way device the mirrored pool will fail
+# 3. Use -f to override the errors to add 1-way device to the mirrored
+# pool
+# 4. Verify the device is added successfully
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_assert "'zpool add -f <pool> <vdev> ...' can successfully add" \
+ "devices to the pool in some cases."
+
+log_onexit cleanup
+
+create_pool $TESTPOOL mirror $DISK0 $DISK1
+log_must poolexists $TESTPOOL
+
+log_mustnot zpool add $TESTPOOL $DISK2
+log_mustnot vdevs_in_pool $TESTPOOL $DISK2
+
+log_must zpool add -f $TESTPOOL $DISK2
+log_must vdevs_in_pool $TESTPOOL $DISK2
+
+log_pass "'zpool add -f <pool> <vdev> ...' executes successfully."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_003_pos.ksh
new file mode 100755
index 000000000000..f270041308b7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_003_pos.ksh
@@ -0,0 +1,97 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool add -n <pool> <vdev> ...' can display the configuration without adding
+# the specified devices to given pool
+#
+# STRATEGY:
+# 1. Create a storage pool
+# 2. Use -n to add devices to the pool
+# 3. Verify the devices are not added actually
+# 4. Add devices to the pool for real this time, verify the vdev tree is the
+# same printed by the dryrun iteration
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL
+ rm -f $TMPFILE_PREFIX* $VDEV_PREFIX*
+}
+
+log_assert "'zpool add -n <pool> <vdev> ...' can display the configuration" \
+ "without actually adding devices to the pool."
+
+log_onexit cleanup
+
+typeset TMPFILE_PREFIX="$TEST_BASE_DIR/zpool_add_003"
+typeset STR_DRYRUN="would update '$TESTPOOL' to the following configuration:"
+typeset VDEV_PREFIX="$TEST_BASE_DIR/filedev"
+typeset -a VDEV_TYPES=("" "dedup" "special" "log" "cache")
+
+vdevs=""
+config=""
+
+# 1. Create a storage pool
+log_must truncate -s $SPA_MINDEVSIZE "$VDEV_PREFIX-root"
+log_must zpool create "$TESTPOOL" "$VDEV_PREFIX-root"
+log_must poolexists "$TESTPOOL"
+for vdevtype in "${VDEV_TYPES[@]}"; do
+ log_must truncate -s $SPA_MINDEVSIZE "$VDEV_PREFIX-$vdevtype"
+ vdevs="$vdevs $VDEV_PREFIX-$vdevtype"
+ config="$config $vdevtype $VDEV_PREFIX-$vdevtype"
+done
+
+# 2. Use -n to add devices to the pool
+log_must eval "zpool add -f -n $TESTPOOL $config > $TMPFILE_PREFIX-dryrun"
+log_must grep -q "$STR_DRYRUN" "$TMPFILE_PREFIX-dryrun"
+
+# 3. Verify the devices are not added actually
+for vdev in $vdevs; do
+ log_mustnot vdevs_in_pool "$TESTPOOL" "$vdev"
+done
+
+# 4. Add devices to the pool for real this time, verify the vdev tree is the
+# same printed by the dryrun iteration
+log_must zpool add -f $TESTPOOL $config
+zpool status $TESTPOOL | awk 'NR == 1, /NAME/ { next } /^$/ {exit}
+ {print $1}' > "$TMPFILE_PREFIX-vdevtree"
+cat "$TMPFILE_PREFIX-dryrun" | awk 'NR == 1, /would/ {next}
+ {print $1}' > "$TMPFILE_PREFIX-vdevtree-n"
+log_must eval "diff $TMPFILE_PREFIX-vdevtree-n $TMPFILE_PREFIX-vdevtree"
+
+log_pass "'zpool add -n <pool> <vdev> ...' executes successfully."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_004_pos.ksh
new file mode 100755
index 000000000000..64e52960d3d6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_004_pos.ksh
@@ -0,0 +1,77 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool add <pool> <vdev> ...' can successfully add a zfs volume
+# to the given pool
+#
+# STRATEGY:
+# 1. Create a storage pool and a zfs volume
+# 2. Add the volume to the pool
+# 3. Verify the devices are added to the pool successfully
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+ if [ -n "$recursive" ]; then
+ set_tunable64 VOL_RECURSIVE $recursive
+ fi
+}
+
+log_assert "'zpool add <pool> <vdev> ...' can add zfs volume to the pool."
+
+log_onexit cleanup
+
+create_pool $TESTPOOL $DISK0
+log_must poolexists $TESTPOOL
+
+create_pool $TESTPOOL1 $DISK1
+log_must poolexists $TESTPOOL1
+log_must zfs create -V $VOLSIZE $TESTPOOL1/$TESTVOL
+block_device_wait
+
+if is_freebsd; then
+ recursive=$(get_tunable VOL_RECURSIVE)
+ log_must set_tunable64 VOL_RECURSIVE 1
+fi
+log_must zpool add $TESTPOOL $ZVOL_DEVDIR/$TESTPOOL1/$TESTVOL
+
+log_must vdevs_in_pool "$TESTPOOL" "$ZVOL_DEVDIR/$TESTPOOL1/$TESTVOL"
+
+log_pass "'zpool add <pool> <vdev> ...' adds zfs volume to the pool successfully"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_005_pos.ksh
new file mode 100755
index 000000000000..c40f8db6f026
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_005_pos.ksh
@@ -0,0 +1,91 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool add' should return fail if
+# 1. vdev is part of an active pool
+# 2. vdev is currently mounted
+# 3. vdev is in /etc/vfstab
+# 3. vdev is specified as the dedicated dump device
+#
+# STRATEGY:
+# 1. Create case scenarios
+# 2. For each scenario, try to add the device to the pool
+# 3. Verify the add operation get failed
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+
+ if [[ -n $saved_dump_dev ]]; then
+ log_must eval "dumpadm -u -d $saved_dump_dev > /dev/null"
+ fi
+}
+
+log_assert "'zpool add' should fail with inapplicable scenarios."
+
+log_onexit cleanup
+
+mnttab_dev=$(find_mnttab_dev)
+vfstab_dev=$(find_vfstab_dev)
+saved_dump_dev=$(save_dump_dev)
+dump_dev=$DISK2
+
+create_pool $TESTPOOL $DISK0
+log_must poolexists $TESTPOOL
+
+create_pool $TESTPOOL1 $DISK1
+log_must poolexists $TESTPOOL1
+
+unset NOINUSE_CHECK
+log_mustnot zpool add -f $TESTPOOL $DISK1
+log_mustnot zpool add -f $TESTPOOL $mnttab_dev
+if is_linux; then
+ log_mustnot zpool add $TESTPOOL $vfstab_dev
+else
+ log_mustnot zpool add -f $TESTPOOL $vfstab_dev
+fi
+
+if is_illumos; then
+ log_must eval "new_fs ${DEV_DSKDIR}/$dump_dev > /dev/null 2>&1"
+ log_must eval "dumpadm -u -d ${DEV_DSKDIR}/$dump_dev > /dev/null"
+ log_mustnot zpool add -f $TESTPOOL $dump_dev
+fi
+
+log_pass "'zpool add' should fail with inapplicable scenarios."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_006_pos.ksh
new file mode 100755
index 000000000000..2c3f488ea267
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_006_pos.ksh
@@ -0,0 +1,71 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.kshlib
+
+#
+# DESCRIPTION:
+# Adding a large number of file based vdevs to a zpool works.
+#
+# STRATEGY:
+# 1. Create a file based pool.
+# 2. Add 16 file based vdevs to it.
+# 3. Attempt to add a file based vdev that's too small; verify failure.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+ rm -rf $TESTDIR
+}
+
+log_assert "Adding a large number of file based vdevs to a zpool works."
+log_onexit cleanup
+
+log_must mkdir -p $TESTDIR
+log_must truncate -s $MINVDEVSIZE $TESTDIR/file.00
+create_pool "$TESTPOOL1" "$TESTDIR/file.00"
+
+vdevs_list=$(echo $TESTDIR/file.{01..16})
+log_must truncate -s $MINVDEVSIZE $vdevs_list
+
+log_must zpool add -f $TESTPOOL1 $vdevs_list
+log_must vdevs_in_pool $TESTPOOL1 "$vdevs_list"
+
+# Attempt to add a file based vdev that's too small.
+log_must truncate -s 32m $TESTDIR/broken_file
+log_mustnot zpool add -f $TESTPOOL1 ${TESTDIR}/broken_file
+log_mustnot vdevs_in_pool $TESTPOOL1 ${TESTDIR}/broken_file
+
+log_pass "Adding a large number of file based vdevs to a zpool works."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_007_neg.ksh
new file mode 100755
index 000000000000..4e9535c1c6b5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_007_neg.ksh
@@ -0,0 +1,68 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool add' should return an error with badly-formed parameters,
+#
+# STRATEGY:
+# 1. Create an array of parameters
+# 2. For each parameter in the array, execute 'zpool add'
+# 3. Verify an error is returned.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_assert "'zpool add' should return an error with badly-formed parameters."
+
+log_onexit cleanup
+
+set -A args "" "-f" "-n" "-?" "-nf" "-fn" "-f -n" "--f" "-blah" \
+ "-? $TESTPOOL $DISK1"
+
+create_pool $TESTPOOL $DISK0
+log_must poolexists $TESTPOOL
+
+typeset -i i=0
+while (( $i < ${#args[*]} )); do
+ log_mustnot zpool add ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "'zpool add' badly formed parameters fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_008_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_008_neg.ksh
new file mode 100755
index 000000000000..77a899f70c83
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_008_neg.ksh
@@ -0,0 +1,68 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool add' should return an error with nonexistent pools or vdevs
+#
+# STRATEGY:
+# 1. Create an array of parameters which contains nonexistent pools/vdevs
+# 2. For each parameter in the array, execute 'zpool add'
+# 3. Verify an error is returned
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_assert "'zpool add' should return an error with nonexistent pools and vdevs"
+
+log_onexit cleanup
+
+set -A args "" "-f nonexistent_pool $DISK1" \
+ "-f $TESTPOOL nonexistent_vdev"
+
+create_pool $TESTPOOL $DISK0
+log_must poolexists $TESTPOOL
+
+typeset -i i=0
+while (( $i < ${#args[*]} )); do
+ log_mustnot zpool add ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "'zpool add' with nonexistent pools and vdevs fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_009_neg.ksh
new file mode 100755
index 000000000000..7ffe9512afea
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_009_neg.ksh
@@ -0,0 +1,65 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool add' should return fail if vdevs are the same or vdev is
+# contained in the given pool
+#
+# STRATEGY:
+# 1. Create a storage pool
+# 2. Add the two same devices to pool A
+# 3. Add the device in pool A to pool A again
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_assert "'zpool add' should fail if vdevs are the same or vdev is " \
+ "contained in the given pool."
+
+log_onexit cleanup
+
+create_pool $TESTPOOL $DISK0
+log_must poolexists $TESTPOOL
+
+log_mustnot zpool add -f $TESTPOOL $DISK1 $DISK1
+log_mustnot zpool add -f $TESTPOOL $DISK0
+
+log_pass "'zpool add' get fail as expected if vdevs are the same or vdev is " \
+ "contained in the given pool."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh
new file mode 100755
index 000000000000..771b689c93fd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh
@@ -0,0 +1,210 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# Verify zpool add succeed when adding vdevs with matching redundancy.
+#
+# STRATEGY:
+# 1. Create several files == $MINVDEVSIZE.
+# 2. Verify 'zpool add' succeeds with matching redundancy.
+# 3. Verify 'zpool add' warns with differing redundancy.
+# 4. Verify 'zpool add' warns with differing redundancy after removal.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ datasetexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+
+ typeset -i i=0
+ while ((i < 10)); do
+ rm -f $TEST_BASE_DIR/vdev$i
+ ((i += 1))
+ done
+}
+
+
+log_assert "Verify 'zpool add' succeed with keywords combination."
+log_onexit cleanup
+
+# 1. Create several files == $MINVDEVSIZE.
+typeset -i i=0
+while ((i < 10)); do
+ log_must truncate -s $MINVDEVSIZE $TEST_BASE_DIR/vdev$i
+
+ eval vdev$i=$TEST_BASE_DIR/vdev$i
+ ((i += 1))
+done
+
+set -A redundancy0_create_args \
+ "$vdev0"
+
+set -A redundancy1_create_args \
+ "mirror $vdev0 $vdev1" \
+ "raidz1 $vdev0 $vdev1"
+
+set -A redundancy2_create_args \
+ "mirror $vdev0 $vdev1 $vdev2" \
+ "raidz2 $vdev0 $vdev1 $vdev2"
+
+set -A redundancy3_create_args \
+ "mirror $vdev0 $vdev1 $vdev2 $vdev3" \
+ "raidz3 $vdev0 $vdev1 $vdev2 $vdev3"
+
+set -A redundancy0_add_args \
+ "$vdev5" \
+ "$vdev5 $vdev6"
+
+set -A redundancy1_add_args \
+ "mirror $vdev5 $vdev6" \
+ "raidz1 $vdev5 $vdev6" \
+ "raidz1 $vdev5 $vdev6 mirror $vdev7 $vdev8" \
+ "mirror $vdev5 $vdev6 raidz1 $vdev7 $vdev8"
+
+set -A redundancy2_add_args \
+ "mirror $vdev5 $vdev6 $vdev7" \
+ "raidz2 $vdev5 $vdev6 $vdev7"
+
+set -A redundancy3_add_args \
+ "mirror $vdev5 $vdev6 $vdev7 $vdev8" \
+ "raidz3 $vdev5 $vdev6 $vdev7 $vdev8"
+
+set -A log_args "log" "$vdev4"
+set -A cache_args "cache" "$vdev4"
+set -A spare_args "spare" "$vdev4"
+
+typeset -i j=0
+
+function zpool_create_add
+{
+ typeset -n create_args=$1
+ typeset -n add_args=$2
+
+ i=0
+ while ((i < ${#create_args[@]})); do
+ j=0
+ while ((j < ${#add_args[@]})); do
+ log_must zpool create $TESTPOOL1 ${create_args[$i]}
+ log_must zpool add $TESTPOOL1 ${add_args[$j]}
+ log_must zpool destroy -f $TESTPOOL1
+
+ ((j += 1))
+ done
+ ((i += 1))
+ done
+}
+
+function zpool_create_forced_add
+{
+ typeset -n create_args=$1
+ typeset -n add_args=$2
+
+ i=0
+ while ((i < ${#create_args[@]})); do
+ j=0
+ while ((j < ${#add_args[@]})); do
+ log_must zpool create $TESTPOOL1 ${create_args[$i]}
+ log_mustnot zpool add $TESTPOOL1 ${add_args[$j]}
+ log_must zpool add -f $TESTPOOL1 ${add_args[$j]}
+ log_must zpool destroy -f $TESTPOOL1
+
+ ((j += 1))
+ done
+ ((i += 1))
+ done
+}
+
+function zpool_create_rm_add
+{
+ typeset -n create_args=$1
+ typeset -n add_args=$2
+ typeset -n rm_args=$3
+
+ i=0
+ while ((i < ${#create_args[@]})); do
+ j=0
+ while ((j < ${#add_args[@]})); do
+ log_must zpool create $TESTPOOL1 ${create_args[$i]}
+ log_must zpool add $TESTPOOL1 ${rm_args[0]} ${rm_args[1]}
+ log_must zpool add $TESTPOOL1 ${add_args[$j]}
+ log_must zpool remove $TESTPOOL1 ${rm_args[1]}
+ log_mustnot zpool add $TESTPOOL1 ${rm_args[1]}
+ log_must zpool add $TESTPOOL1 ${rm_args[0]} ${rm_args[1]}
+ log_must zpool destroy -f $TESTPOOL1
+
+ ((j += 1))
+ done
+ ((i += 1))
+ done
+}
+
+# 2. Verify 'zpool add' succeeds with matching redundancy.
+zpool_create_add redundancy0_create_args redundancy0_add_args
+zpool_create_add redundancy1_create_args redundancy1_add_args
+zpool_create_add redundancy2_create_args redundancy2_add_args
+zpool_create_add redundancy3_create_args redundancy3_add_args
+
+# 3. Verify 'zpool add' warns with differing redundancy.
+zpool_create_forced_add redundancy0_create_args redundancy1_add_args
+zpool_create_forced_add redundancy0_create_args redundancy2_add_args
+zpool_create_forced_add redundancy0_create_args redundancy3_add_args
+
+zpool_create_forced_add redundancy1_create_args redundancy0_add_args
+zpool_create_forced_add redundancy1_create_args redundancy2_add_args
+zpool_create_forced_add redundancy1_create_args redundancy3_add_args
+
+zpool_create_forced_add redundancy2_create_args redundancy0_add_args
+zpool_create_forced_add redundancy2_create_args redundancy1_add_args
+zpool_create_forced_add redundancy2_create_args redundancy3_add_args
+
+zpool_create_forced_add redundancy3_create_args redundancy0_add_args
+zpool_create_forced_add redundancy3_create_args redundancy1_add_args
+zpool_create_forced_add redundancy3_create_args redundancy2_add_args
+
+# 4. Verify 'zpool add' warns with differing redundancy after removal.
+zpool_create_rm_add redundancy1_create_args redundancy1_add_args log_args
+zpool_create_rm_add redundancy2_create_args redundancy2_add_args log_args
+zpool_create_rm_add redundancy3_create_args redundancy3_add_args log_args
+
+zpool_create_rm_add redundancy1_create_args redundancy1_add_args cache_args
+zpool_create_rm_add redundancy2_create_args redundancy2_add_args cache_args
+zpool_create_rm_add redundancy3_create_args redundancy3_add_args cache_args
+
+zpool_create_rm_add redundancy1_create_args redundancy1_add_args spare_args
+zpool_create_rm_add redundancy2_create_args redundancy2_add_args spare_args
+zpool_create_rm_add redundancy3_create_args redundancy3_add_args spare_args
+
+log_pass "'zpool add' succeed with keywords combination."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_attach/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/Makefile.am
new file mode 100644
index 000000000000..cc742f33d2aa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_attach
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_attach_001_neg.ksh \
+ attach-o_ashift.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_attach/attach-o_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/attach-o_ashift.ksh
new file mode 100755
index 000000000000..9af011cb04d8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/attach-o_ashift.ksh
@@ -0,0 +1,100 @@
+#!/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 2017, loli10K. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# 'zpool attach -o ashift=<n> ...' should work with different ashift
+# values.
+#
+# STRATEGY:
+# 1. Create various pools with different ashift values.
+# 2. Verify 'attach -o ashift=<n>' works only with allowed values.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+ rm -f $disk1 $disk2
+}
+
+log_assert "zpool attach -o ashift=<n>' works with different ashift values"
+log_onexit cleanup
+
+disk1=$TEST_BASE_DIR/disk1
+disk2=$TEST_BASE_DIR/disk2
+log_must truncate -s $SIZE $disk1
+log_must truncate -s $SIZE $disk2
+
+typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16")
+for ashift in ${ashifts[@]}
+do
+ for cmdval in ${ashifts[@]}
+ do
+ log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
+ verify_ashift $disk1 $ashift
+ if [[ $? -ne 0 ]]
+ then
+ log_fail "Pool was created without setting ashift " \
+ "value to $ashift"
+ fi
+ # ashift_of(attached_disk) <= ashift_of(existing_vdev)
+ if [[ $cmdval -le $ashift ]]
+ then
+ log_must zpool attach -o ashift=$cmdval $TESTPOOL1 \
+ $disk1 $disk2
+ verify_ashift $disk2 $ashift
+ if [[ $? -ne 0 ]]
+ then
+ log_fail "Device was attached without " \
+ "setting ashift value to $ashift"
+ fi
+ else
+ log_mustnot zpool attach -o ashift=$cmdval $TESTPOOL1 \
+ $disk1 $disk2
+ fi
+ # clean things for the next run
+ log_must zpool destroy $TESTPOOL1
+ log_must zpool labelclear $disk1
+ log_must zpool labelclear $disk2
+ done
+done
+
+typeset badvals=("off" "on" "1" "8" "17" "1b" "ff" "-")
+for badval in ${badvals[@]}
+do
+ log_must zpool create $TESTPOOL1 $disk1
+ log_mustnot zpool attach -o ashift=$badval $TESTPOOL1 $disk1 $disk2
+ log_must zpool destroy $TESTPOOL1
+ log_must zpool labelclear $disk1
+ log_mustnot zpool labelclear $disk2
+done
+
+log_pass "zpool attach -o ashift=<n>' works with different ashift values"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_attach/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/cleanup.ksh
new file mode 100755
index 000000000000..89c146249e71
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/cleanup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_attach/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/setup.ksh
new file mode 100755
index 000000000000..2229f87e6208
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/setup.ksh
@@ -0,0 +1,35 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+DISK=${DISKS%% *}
+
+default_mirror_setup $DISKS
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_attach/zpool_attach_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/zpool_attach_001_neg.ksh
new file mode 100755
index 000000000000..01b8e41ee439
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_attach/zpool_attach_001_neg.ksh
@@ -0,0 +1,83 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Executing 'zpool attach' command with bad options fails.
+#
+# STRATEGY:
+# 1. Create an array of badly formed 'zpool attach' options.
+# 2. Execute each element of the array.
+# 3. Verify an error code is returned.
+#
+
+verify_runnable "global"
+
+DISKLIST=$(get_disklist $TESTPOOL)
+
+set -A args "" "-f" "-?" "-z fakepool" "-f fakepool" "-ev fakepool" "fakepool" \
+ "$TESTPOOL" "-t $TESTPOOL/$TESTFS" "-t $TESTPOOL/$TESTFS $DISKLIST" \
+ "$TESTPOOL/$TESTCTR" "-t $TESTPOOL/$TESTCTR/$TESTFS1" \
+ "$TESTPOOL/$TESTCTR $DISKLIST" "-t $TESTPOOL/$TESTVOL" \
+ "$TESTPOOL/$TESTCTR/$TESTFS1 $DISKLIST" \
+ "$TESTPOOL/$TESTVOL $DISKLIST" \
+ "$DISKLIST" \
+ "fakepool fakedevice" "fakepool fakedevice fakenewdevice" \
+ "$TESTPOOL fakedevice" "$TESTPOOL $DISKLIST" \
+ "$TESTPOOL fakedevice fakenewdevice fakenewdevice" \
+ "-f $TESTPOOL" "-f $TESTPOOL/$TESTFS" "-f $TESTPOOL/$TESTFS $DISKLIST" \
+ "-f $TESTPOOL/$TESTCTR" "-f $TESTPOOL/$TESTCTR/$TESTFS1" \
+ "-f $TESTPOOL/$TESTCTR $DISKLIST" "-f $TESTPOOL/$TESTVOL" \
+ "-f $TESTPOOL/$TESTCTR/$TESTFS1 $DISKLIST" \
+ "-f $TESTPOOL/$TESTVOL $DISKLIST" \
+ "-f $DISKLIST" \
+ "-f fakepool fakedevice" "-f fakepool fakedevice fakenewdevice" \
+ "-f $TESTPOOL fakedevice fakenewdevice fakenewdevice" \
+ "-f $TESTPOOL fakedevice" "-f $TESTPOOL $DISKLIST"
+
+log_assert "Executing 'zpool attach' with bad options fails"
+
+if [[ -z $DISKLIST ]]; then
+ log_fail "DISKLIST is empty."
+fi
+
+typeset -i i=0
+
+while [[ $i -lt ${#args[*]} ]]; do
+
+ log_mustnot zpool attach ${args[$i]}
+
+ (( i = i + 1 ))
+done
+
+log_pass "'zpool attach' command with bad options failed as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/Makefile.am
new file mode 100644
index 000000000000..6986d38efc9d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/Makefile.am
@@ -0,0 +1,11 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_clear
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_clear_001_pos.ksh \
+ zpool_clear_002_neg.ksh \
+ zpool_clear_003_neg.ksh \
+ zpool_clear_readonly.ksh
+
+dist_pkgdata_DATA = \
+ zpool_clear.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear.cfg
new file mode 100644
index 000000000000..e6977350af90
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear.cfg
@@ -0,0 +1,33 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2015 by Delphix. All rights reserved.
+#
+
+export FILESIZE=$MINVDEVSIZE
+export BLOCKSZ=$(( 1024 * 1024 ))
+export NUM_WRITES=40
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_001_pos.ksh
new file mode 100755
index 000000000000..98b4140727c0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_001_pos.ksh
@@ -0,0 +1,207 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_clear/zpool_clear.cfg
+
+#
+# DESCRIPTION:
+# Verify 'zpool clear' can clear pool errors.
+#
+# STRATEGY:
+# 1. Create various configuration pools
+# 2. Make errors to pool
+# 3. Use zpool clear to clear errors
+# 4. Verify the errors has been cleared.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && \
+ log_must zpool destroy -f $TESTPOOL1
+
+ for file in `ls $TEST_BASE_DIR/file.*`; do
+ log_must rm -f $file
+ done
+}
+
+
+log_assert "Verify 'zpool clear' can clear errors of a storage pool."
+log_onexit cleanup
+
+#make raw files to create various configuration pools
+typeset -i i=0
+while (( i < 3 )); do
+ log_must truncate -s $FILESIZE $TEST_BASE_DIR/file.$i
+
+ (( i = i + 1 ))
+done
+
+fbase=$TEST_BASE_DIR/file
+set -A poolconf "mirror $fbase.0 $fbase.1 $fbase.2" \
+ "raidz1 $fbase.0 $fbase.1 $fbase.2" \
+ "raidz2 $fbase.0 $fbase.1 $fbase.2"
+
+function check_err # <pool> [<vdev>]
+{
+ typeset pool=$1
+ shift
+ if (( $# > 0 )); then
+ typeset checkvdev=$1
+ else
+ typeset checkvdev=""
+ fi
+ typeset -i errnum=0
+ typeset c_read=0
+ typeset c_write=0
+ typeset c_cksum=0
+ typeset tmpfile=$TEST_BASE_DIR/file.$$
+ typeset healthstr="pool '$pool' is healthy"
+ typeset output="`zpool status -x $pool`"
+
+ [[ "$output" == "$healthstr" ]] && return $errnum
+
+ zpool status -x $pool | grep -v "^$" | grep -v "pool:" \
+ | grep -v "state:" | grep -v "config:" \
+ | grep -v "errors:" > $tmpfile
+ typeset line
+ typeset -i fetchbegin=1
+ while read line; do
+ if (( $fetchbegin != 0 )); then
+ echo $line | grep "NAME" >/dev/null 2>&1
+ (( $? == 0 )) && (( fetchbegin = 0 ))
+ continue
+ fi
+
+ if [[ -n $checkvdev ]]; then
+ echo $line | grep $checkvdev >/dev/null 2>&1
+ (( $? != 0 )) && continue
+ c_read=`echo $line | awk '{print $3}'`
+ c_write=`echo $line | awk '{print $4}'`
+ c_cksum=`echo $line | awk '{print $5}'`
+ if [ $c_read != 0 ] || [ $c_write != 0 ] || \
+ [ $c_cksum != 0 ]
+ then
+ (( errnum = errnum + 1 ))
+ fi
+ break
+ fi
+
+ c_read=`echo $line | awk '{print $3}'`
+ c_write=`echo $line | awk '{print $4}'`
+ c_cksum=`echo $line | awk '{print $5}'`
+ if [ $c_read != 0 ] || [ $c_write != 0 ] || \
+ [ $c_cksum != 0 ]
+ then
+ (( errnum = errnum + 1 ))
+ fi
+ done <$tmpfile
+
+ return $errnum
+}
+
+function do_testing #<clear type> <vdevs>
+{
+ typeset FS=$TESTPOOL1/fs
+ typeset file=/$FS/f
+ typeset type=$1
+ shift
+ typeset vdev="$@"
+
+ log_must zpool create -f $TESTPOOL1 $vdev
+ log_must zfs create $FS
+ #
+ # Partially fill up the zfs filesystem in order to make data block
+ # errors. It's not necessary to fill the entire filesystem.
+ #
+ avail=$(get_prop available $FS)
+ fill_mb=$(((avail / 1024 / 1024) * 25 / 100))
+ log_must dd if=/dev/urandom of=$file.$i bs=$BLOCKSZ count=$fill_mb
+
+ #
+ # Make errors to the testing pool by overwrite the vdev device with
+ # dd command. We do not want to have a full overwrite. That
+ # may cause the system panic. So, we should skip the vdev label space.
+ #
+ (( i = $RANDOM % 3 ))
+ typeset -i wcount=0
+ typeset -i size
+ case $FILESIZE in
+ *g|*G)
+ (( size = ${FILESIZE%%[g|G]} ))
+ (( wcount = size*1024*1024 - 512 ))
+ ;;
+ *m|*M)
+ (( size = ${FILESIZE%%[m|M]} ))
+ (( wcount = size*1024 - 512 ))
+ ;;
+ *k|*K)
+ (( size = ${FILESIZE%%[k|K]} ))
+ (( wcount = size - 512 ))
+ ;;
+ *)
+ (( wcount = FILESIZE/1024 - 512 ))
+ ;;
+ esac
+ dd if=/dev/zero of=$fbase.$i seek=512 bs=1024 count=$wcount conv=notrunc \
+ > /dev/null 2>&1
+ log_must sync
+ log_must zpool scrub -w $TESTPOOL1
+
+ check_err $TESTPOOL1 && \
+ log_fail "No error generated."
+ if [[ $type == "device" ]]; then
+ log_must zpool clear $TESTPOOL1 $fbase.$i
+ ! check_err $TESTPOOL1 $fbase.$i && \
+ log_fail "'zpool clear' fails to clear error for $fbase.$i device."
+ fi
+
+ if [[ $type == "pool" ]]; then
+ log_must zpool clear $TESTPOOL1
+ ! check_err $TESTPOOL1 && \
+ log_fail "'zpool clear' fails to clear error for pool $TESTPOOL1."
+ fi
+
+ log_must zpool destroy $TESTPOOL1
+}
+
+log_note "'zpool clear' clears leaf-device error."
+for devconf in "${poolconf[@]}"; do
+ do_testing "device" $devconf
+done
+log_note "'zpool clear' clears top-level pool error."
+for devconf in "${poolconf[@]}"; do
+ do_testing "pool" $devconf
+done
+
+log_pass "'zpool clear' clears pool errors as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_002_neg.ksh
new file mode 100755
index 000000000000..91a637b3377b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_002_neg.ksh
@@ -0,0 +1,76 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_clear/zpool_clear.cfg
+
+#
+# DESCRIPTION:
+# A badly formed parameter passed to 'zpool clear' should
+# return an error.
+#
+# STRATEGY:
+# 1. Create an array containing bad 'zpool clear' parameters.
+# 2. For each element, execute the sub-command.
+# 3. Verify it returns an error.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && \
+ log_must zpool destroy -f $TESTPOOL1
+ [[ -e $file ]] && \
+ log_must rm -f $file
+}
+
+log_assert "Execute 'zpool clear' using invalid parameters."
+log_onexit cleanup
+
+# Create another pool for negative testing, which clears pool error
+# with vdev device not in the pool vdev devices.
+file=$TESTDIR/file.$$
+log_must mkfile $FILESIZE $file
+log_must zpool create $TESTPOOL1 $file
+
+set -A args "" "-?" "--%" "-1234567" "0.0001" "0.7644" "-0.7644" \
+ "blah" "blah $DISK" "$TESTPOOL c0txdx" "$TESTPOOL $file" \
+ "$TESTPOOL c0txdx blah" "$TESTPOOL $file blah"
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_mustnot zpool clear ${args[i]}
+
+ ((i = i + 1))
+done
+
+log_pass "Invalid parameters to 'zpool clear' fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_003_neg.ksh
new file mode 100755
index 000000000000..637fdd84288b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_003_neg.ksh
@@ -0,0 +1,73 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_clear/zpool_clear.cfg
+
+#
+# DESCRIPTION:
+# Verify 'zpool clear' cannot used to spare device.
+#
+# STRATEGY:
+# 1. Create a spare pool.
+# 2. Try to clear the spare device
+# 3. Verify it returns an error.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && \
+ log_must zpool destroy -f $TESTPOOL1
+
+ for file in `ls $TESTDIR/file.*`; do
+ log_must rm -f $file
+ done
+}
+
+
+log_assert "Verify 'zpool clear' cannot clear error for spare device."
+log_onexit cleanup
+
+#make raw files to create a spare pool
+typeset -i i=0
+while (( i < 5 )); do
+ log_must mkfile $FILESIZE $TESTDIR/file.$i
+
+ (( i = i + 1 ))
+done
+log_must zpool create $TESTPOOL1 raidz $TESTDIR/file.1 $TESTDIR/file.2 \
+ $TESTDIR/file.3 spare $TESTDIR/file.4
+
+log_mustnot zpool clear $TESTPOOL1 $TESTDIR/file.4
+
+log_pass "'zpool clear' works on spare device failed as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_readonly.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_readonly.ksh
new file mode 100755
index 000000000000..9eb2a3608f17
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_clear/zpool_clear_readonly.ksh
@@ -0,0 +1,71 @@
+#!/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 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_clear/zpool_clear.cfg
+
+#
+# DESCRIPTION:
+# Verify 'zpool clear' cannot be used on readonly pools.
+#
+# STRATEGY:
+# 1. Create a pool.
+# 2. Export the pool and import it readonly.
+# 3. Verify 'zpool clear' on the pool (and each device) returns an error.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL1
+ rm -f $TESTDIR/file.*
+}
+
+log_assert "Verify 'zpool clear' cannot be used on readonly pools."
+log_onexit cleanup
+
+# 1. Create a pool.
+log_must truncate -s $FILESIZE $TESTDIR/file.{1,2,3}
+log_must zpool create $TESTPOOL1 raidz $TESTDIR/file.*
+
+# 2. Export the pool and import it readonly.
+log_must zpool export $TESTPOOL1
+log_must zpool import -d $TESTDIR -o readonly=on $TESTPOOL1
+if [[ "$(get_pool_prop readonly $TESTPOOL1)" != 'on' ]]; then
+ log_fail "Pool $TESTPOOL1 was not imported readonly."
+fi
+
+# 3. Verify 'zpool clear' on the pool (and each device) returns an error.
+log_mustnot zpool clear $TESTPOOL1
+for i in {1..3}; do
+ # Device must be online
+ log_must check_state $TESTPOOL1 $TESTDIR/file.$i 'online'
+ # Device cannot be cleared if the pool was imported readonly
+ log_mustnot zpool clear $TESTPOOL1 $TESTDIR/file.$i
+done
+
+log_pass "'zpool clear' fails on readonly pools as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_create/Makefile.am
new file mode 100644
index 000000000000..3c595935a1f2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/Makefile.am
@@ -0,0 +1,40 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_create
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_create_001_pos.ksh \
+ zpool_create_002_pos.ksh \
+ zpool_create_003_pos.ksh \
+ zpool_create_004_pos.ksh \
+ zpool_create_005_pos.ksh \
+ zpool_create_006_pos.ksh \
+ zpool_create_007_neg.ksh \
+ zpool_create_008_pos.ksh \
+ zpool_create_009_neg.ksh \
+ zpool_create_010_neg.ksh \
+ zpool_create_011_neg.ksh \
+ zpool_create_012_neg.ksh \
+ zpool_create_014_neg.ksh \
+ zpool_create_015_neg.ksh \
+ zpool_create_016_pos.ksh \
+ zpool_create_017_neg.ksh \
+ zpool_create_018_pos.ksh \
+ zpool_create_019_pos.ksh \
+ zpool_create_020_pos.ksh \
+ zpool_create_021_pos.ksh \
+ zpool_create_022_pos.ksh \
+ zpool_create_023_neg.ksh \
+ zpool_create_024_pos.ksh \
+ zpool_create_encrypted.ksh \
+ zpool_create_crypt_combos.ksh \
+ zpool_create_features_001_pos.ksh \
+ zpool_create_features_002_pos.ksh \
+ zpool_create_features_003_pos.ksh \
+ zpool_create_features_004_neg.ksh \
+ zpool_create_features_005_pos.ksh \
+ create-o_ashift.ksh \
+ zpool_create_tempname.ksh
+
+dist_pkgdata_DATA = \
+ zpool_create.cfg \
+ zpool_create.shlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/cleanup.ksh
new file mode 100755
index 000000000000..a50487754053
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/cleanup.ksh
@@ -0,0 +1,37 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+cleanup_devices $DISKS
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/create-o_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/create-o_ashift.ksh
new file mode 100755
index 000000000000..2c1f6e0ca659
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/create-o_ashift.ksh
@@ -0,0 +1,135 @@
+#!/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 2016, loli10K. All rights reserved.
+# Copyright (c) 2017 Datto Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# 'zpool create -o ashift=<n> ...' should work with different ashift
+# values.
+#
+# STRATEGY:
+# 1. Create various pools with different ashift values.
+# 2. Verify -o ashift=<n> works only with allowed values (9-16).
+# Also verify that the lowest number of uberblocks in a label is 16 and
+# smallest uberblock size is 8K even with higher ashift values.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -f $disk
+}
+
+#
+# Fill the uberblock ring in every <device> label: we do this by committing
+# TXGs to the provided <pool> until every slot contains a valid uberblock.
+# NOTE: We use 'zpool sync' here because we can't force it via sync(1) like on
+# illumos
+#
+function write_device_uberblocks # <device> <pool>
+{
+ typeset device=$1
+ typeset pool=$2
+
+ while [ "$(zdb -quuul $device | grep -c 'invalid')" -ne 0 ]
+ do
+ sync_pool $pool true
+ done
+}
+
+#
+# Verify every label on <device> contains <count> (valid) uberblocks
+#
+function verify_device_uberblocks # <device> <count>
+{
+ typeset device=$1
+ typeset ubcount=$2
+
+ zdb -quuul $device | awk -v ubcount=$ubcount '
+ /Uberblock/ && ! /invalid/ { uberblocks[$0]++ }
+ END {
+ count = 0
+ for (i in uberblocks) {
+ if (uberblocks[i] != 4) {
+ printf "%s count: %s != 4\n", i, uberblocks[i]
+ exit 1
+ }
+ count++;
+ }
+ if (count != ubcount) {
+ printf "Total uberblock count: %s != %s\n", count, ubcount
+ exit 1
+ }
+ }'
+
+ return $?
+}
+
+log_assert "zpool create -o ashift=<n>' works with different ashift values"
+log_onexit cleanup
+
+disk=$(create_blockfile $SIZE)
+
+typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16")
+# since Illumos 4958 the largest uberblock is 8K so we have at least of 16/label
+typeset ubcount=("128" "128" "64" "32" "16" "16" "16" "16")
+typeset -i i=0;
+while [ $i -lt "${#ashifts[@]}" ]
+do
+ typeset ashift=${ashifts[$i]}
+ log_must zpool create -o ashift=$ashift $TESTPOOL $disk
+ typeset pprop=$(get_pool_prop ashift $TESTPOOL)
+ verify_ashift $disk $ashift
+ if [[ $? -ne 0 || "$pprop" != "$ashift" ]]
+ then
+ log_fail "Pool was created without setting ashift value to "\
+ "$ashift (current = $pprop)"
+ fi
+ write_device_uberblocks $disk $TESTPOOL
+ verify_device_uberblocks $disk ${ubcount[$i]}
+ if [[ $? -ne 0 ]]
+ then
+ log_fail "Pool was created with unexpected number of uberblocks"
+ fi
+ # clean things for the next run
+ log_must zpool destroy $TESTPOOL
+ log_must zpool labelclear $disk
+ log_must verify_device_uberblocks $disk 0
+ ((i = i + 1))
+done
+
+typeset badvals=("off" "on" "1" "8" "17" "1b" "ff" "-")
+for badval in ${badvals[@]}
+do
+ log_mustnot zpool create -o ashift="$badval" $TESTPOOL $disk
+done
+
+log_pass "zpool create -o ashift=<n>' works with different ashift values"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/setup.ksh
new file mode 100755
index 000000000000..115126b1ac5b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/setup.ksh
@@ -0,0 +1,37 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+verify_runnable "global"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.cfg
new file mode 100644
index 000000000000..976570d621b7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.cfg
@@ -0,0 +1,66 @@
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2015 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+typeset -a disk_array=($(find_disks $DISKS))
+typeset DISKSARRAY=""
+typeset -i DISK_ARRAY_LIMIT=4
+typeset -i i=0
+while (( i < ${#disk_array[*]} && i <= $DISK_ARRAY_LIMIT )); do
+ export DISK${i}="${disk_array[$i]}"
+ DISKSARRAY="$DISKSARRAY ${disk_array[$i]}"
+ (( i = i + 1 ))
+done
+export DISK_ARRAY_NUM=$i
+export DISKSARRAY
+
+export FILESIZE="$MINVDEVSIZE"
+export FILESIZE1="$(($MINVDEVSIZE * 2))"
+export SIZE="$((MINVDEVSIZE / (1024 * 1024)))"m
+export SIZE1="$(($MINVDEVSIZE * 2 / (1024 * 1024)))m"
+
+export BYND_MAX_NAME="byondmaxnamelength\
+012345678901234567890123456789\
+012345678901234567890123456789\
+012345678901234567890123456789\
+012345678901234567890123456789\
+012345678901234567890123456789\
+012345678901234567890123456789\
+012345678901234567890123456789\
+012345678901234567890123456789"
+
+export TOOSMALL="toosmall"
+
+export TESTPOOL4=testpool4.create
+export TESTPOOL5=testpool5.create
+export TESTPOOL6=testpool6.create
+
+export CPATH="$TEST_BASE_DIR/cachefile.create"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.shlib b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.shlib
new file mode 100644
index 000000000000..325f0b0360c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create.shlib
@@ -0,0 +1,109 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.cfg
+
+#
+# Given a pool vdevs list, create the pool,verify the created pool,
+# and destroy the pool
+# $1, pool name
+# $2, pool type, mirror, raidz, or none
+# $3, vdevs list
+#
+function create_pool_test
+{
+ typeset pool=$1
+ typeset keywd=$2
+ typeset vdevs
+ eval "typeset -a diskarray=($3)"
+
+ for vdevs in "${diskarray[@]}"; do
+ create_pool $pool $keywd $vdevs
+ log_must poolexists $pool
+ destroy_pool $pool
+ done
+}
+
+#
+# Create a file for storage pool vdev
+# $1, file size
+#
+function create_blockfile
+{
+ typeset size=$1
+ typeset file=$(mktemp)
+ truncate -s $size $file
+ echo $file
+}
+
+#
+# Find the storage device in /etc/vfstab
+#
+function find_vfstab_dev
+{
+ typeset vfstabdev
+ typeset vfstabdevs=""
+ typeset line
+
+ if is_illumos; then
+ vfstab="/etc/vfstab"
+ tmpfile="$TEST_BASE_DIR/vfstab.tmp"
+ else
+ vfstab="/etc/fstab"
+ tmpfile="$TEST_BASE_DIR/fstab.tmp"
+ fi
+
+ cat $vfstab | grep "^${DEV_DSKDIR}" >$tmpfile
+ while read -r line
+ do
+ vfstabdev=`echo "$line" | awk '{print $1}'`
+ vfstabdev=${vfstabdev%%:}
+ vfstabdevs="$vfstabdev $vfstabdevs"
+ done <$tmpfile
+
+ rm -f $tmpfile
+ echo $vfstabdevs
+}
+
+#
+# Save the system current dump device configuration
+#
+function save_dump_dev
+{
+ typeset dumpdev=""
+
+ if is_illumos; then
+ typeset fnd="Dump device"
+ dumpdev=`dumpadm | grep "$fnd" | cut -f2 -d : | \
+ awk '{print $1}'`
+ fi
+ echo $dumpdev
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_001_pos.ksh
new file mode 100755
index 000000000000..7991607221cb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_001_pos.ksh
@@ -0,0 +1,77 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2015 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# 'zpool create <pool> <vspec> ...' can successfully create a
+# new pool with a name in ZFS namespace.
+#
+# STRATEGY:
+# 1. Create storage pools with a name in ZFS namespace with different
+# vdev specs.
+# 2. Verify the pool created successfully
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+
+ rm -f $disk1 $disk2
+}
+
+log_assert "'zpool create <pool> <vspec> ...' can successfully create" \
+ "a new pool with a name in ZFS namespace."
+
+log_onexit cleanup
+
+typeset disk1=$(create_blockfile $FILESIZE)
+typeset disk2=$(create_blockfile $FILESIZE)
+
+pooldevs="${DISK0} \
+ \"${DISK0} ${DISK1}\" \
+ \"${DISK0} ${DISK1} ${DISK2}\" \
+ \"$disk1 $disk2\""
+raidzdevs="\"${DISK0} ${DISK1} ${DISK2}\""
+mirrordevs="\"${DISK0} ${DISK1}\" \
+ $raidzdevs \
+ \"$disk1 $disk2\""
+
+create_pool_test "$TESTPOOL" "" "$pooldevs"
+create_pool_test "$TESTPOOL" "mirror" "$mirrordevs"
+create_pool_test "$TESTPOOL" "raidz" "$raidzdevs"
+create_pool_test "$TESTPOOL" "raidz1" "$raidzdevs"
+
+log_pass "'zpool create <pool> <vspec> ...' success."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_002_pos.ksh
new file mode 100755
index 000000000000..2f709086f751
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_002_pos.ksh
@@ -0,0 +1,128 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# 'zpool create -f <pool> <vspec> ...' can successfully create a
+# new pool in some cases.
+#
+# STRATEGY:
+# 1. Prepare the scenarios for '-f' option
+# 2. Use -f to override the devices to create new pools
+# 3. Verify the pool created successfully
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ for pool in $TESTPOOL $TESTPOOL1; do
+ poolexists $pool && destroy_pool $pool
+ done
+
+ rm -f $disk1 $disk2
+ if is_freebsd; then
+ umount -f $TESTDIR
+ rm -rf $TESTDIR
+ fi
+}
+
+log_onexit cleanup
+
+log_assert "'zpool create -f <pool> <vspec> ...' can successfully create" \
+ "a new pool in some cases."
+
+create_pool $TESTPOOL $DISK0
+log_must eval "new_fs ${DEV_RDSKDIR}/${DISK1} >/dev/null 2>&1"
+typeset disk1=$(create_blockfile $FILESIZE)
+typeset disk2=$(create_blockfile $FILESIZE1)
+
+unset NOINUSE_CHECK
+log_must zpool export $TESTPOOL
+log_note "'zpool create' without '-f' will fail " \
+ "while device belongs to an exported pool."
+log_mustnot zpool create $TESTPOOL1 $DISK0
+create_pool $TESTPOOL1 $DISK0
+log_must poolexists $TESTPOOL1
+
+log_must destroy_pool $TESTPOOL1
+
+log_note "'zpool create' without '-f' will fail " \
+ "while device is in use by a ufs filesystem."
+if is_freebsd; then
+ # fs must be mounted for create to fail on FreeBSD
+ log_must mkdir -p $TESTDIR
+ log_must mount ${DEV_DSKDIR}/${DISK1} $TESTDIR
+fi
+log_mustnot zpool create $TESTPOOL $DISK1
+if is_freebsd; then
+ # fs must not be mounted to create pool even with -f
+ log_must umount -f $TESTDIR
+ log_must rm -rf $TESTDIR
+fi
+create_pool $TESTPOOL $DISK1
+log_must poolexists $TESTPOOL
+
+log_must destroy_pool $TESTPOOL
+
+log_note "'zpool create' mirror without '-f' will fail " \
+ "while devices have different size."
+log_mustnot zpool create $TESTPOOL mirror $disk1 $disk2
+create_pool $TESTPOOL mirror $disk1 $disk2
+log_must poolexists $TESTPOOL
+
+log_must destroy_pool $TESTPOOL
+
+if ! is_freebsd; then
+ log_note "'zpool create' mirror without '-f' will fail " \
+ "while devices are of different types."
+ log_mustnot zpool create $TESTPOOL mirror $disk1 $DISK0
+ create_pool $TESTPOOL mirror $disk1 $DISK0
+ log_must poolexists $TESTPOOL
+
+ log_must destroy_pool $TESTPOOL
+fi
+
+log_note "'zpool create' without '-f' will fail " \
+ "while a device is part of a potentially active pool."
+create_pool $TESTPOOL mirror $DISK0 $DISK1
+log_must zpool offline $TESTPOOL $DISK0
+log_must zpool export $TESTPOOL
+log_mustnot zpool create $TESTPOOL1 $DISK0
+create_pool $TESTPOOL1 $DISK0
+log_must poolexists $TESTPOOL1
+
+log_must destroy_pool $TESTPOOL1
+
+log_pass "'zpool create -f <pool> <vspec> ...' success."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_003_pos.ksh
new file mode 100755
index 000000000000..dd8d0107aed2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_003_pos.ksh
@@ -0,0 +1,95 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# 'zpool create -n <pool> <vspec> ...' can display the configuration without
+# actually creating the pool.
+#
+# STRATEGY:
+# 1. Create storage pool with -n option; this should only work when valid
+# properties are specified on the command line
+# 2. Verify the pool has not been actually created
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -f $tmpfile
+}
+
+tmpfile="$TEST_BASE_DIR/zpool_create_003.tmp$$"
+
+log_assert "'zpool create -n <pool> <vspec> ...' can display the configuration" \
+ "without actually creating the pool."
+
+log_onexit cleanup
+
+typeset goodprops=('' '-o comment=text' '-O checksum=on' '-O ns:prop=value')
+typeset badprops=('-o ashift=9999' '-O doesnotexist=on' '-O volsize=10M')
+
+# Verify zpool create -n with valid pool-level and fs-level options
+for prop in "${goodprops[@]}"
+do
+ #
+ # Make sure disk is clean before we use it
+ #
+ create_pool $TESTPOOL $DISK0 > $tmpfile
+ destroy_pool $TESTPOOL
+
+ log_must eval "zpool create -n $prop $TESTPOOL $DISK0 > $tmpfile"
+
+ poolexists $TESTPOOL && \
+ log_fail "'zpool create -n <pool> <vspec> ...' fail."
+
+ str="would create '$TESTPOOL' with the following layout:"
+ grep "$str" $tmpfile >/dev/null 2>&1 || \
+ log_fail "'zpool create -n <pool> <vspec>...' is executed as unexpected."
+done
+
+# Verify zpool create -n with invalid options
+for prop in "${badprops[@]}"
+do
+ #
+ # Make sure disk is clean before we use it
+ #
+ create_pool $TESTPOOL $DISK0 > $tmpfile
+ destroy_pool $TESTPOOL
+
+ log_mustnot zpool create -n $prop $TESTPOOL $DISK0
+done
+
+log_pass "'zpool create -n <pool> <vspec>...' success."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_004_pos.ksh
new file mode 100755
index 000000000000..835cd1f547bd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_004_pos.ksh
@@ -0,0 +1,76 @@
+#!/bin/ksh
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# Create a storage pool with many file based vdevs.
+#
+# STRATEGY:
+# 1. Create assigned number of files in ZFS filesystem as vdevs.
+# 2. Creating a new pool based on the vdevs should work.
+# 3. Creating a pool with a file based vdev that is too small should fail.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+
+ rm -rf $TESTDIR
+}
+
+log_assert "Storage pools with 16 file based vdevs can be created."
+log_onexit cleanup
+
+create_pool $TESTPOOL $DISK0
+log_must zfs create -o mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+
+vdevs_list=$(echo $TESTDIR/file.{01..16})
+log_must truncate -s $MINVDEVSIZE $vdevs_list
+
+create_pool $TESTPOOL1 $vdevs_list
+log_must vdevs_in_pool $TESTPOOL1 "$vdevs_list"
+
+if poolexists $TESTPOOL1; then
+ destroy_pool $TESTPOOL1
+else
+ log_fail "Creating pool with large numbers of file-vdevs failed."
+fi
+
+log_must mkfile 32m $TESTDIR/broken_file
+vdevs_list="$vdevs_list $TESTDIR/broken_file"
+log_mustnot zpool create -f $TESTPOOL1 $vdevs_list
+
+log_pass "Storage pools with many file based vdevs can be created."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_005_pos.ksh
new file mode 100755
index 000000000000..165453e8bb56
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_005_pos.ksh
@@ -0,0 +1,124 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# 'zpool create [-R root][-m mountpoint] <pool> <vdev> ...' can create an
+# alternate root pool or a new pool mounted at the specified mountpoint.
+#
+# STRATEGY:
+# 1. Create a pool with '-m' option
+# 2. Verify the pool is mounted at the specified mountpoint
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -rf $TESTDIR $TESTDIR1
+}
+
+log_assert "'zpool create [-R root][-m mountpoint] <pool> <vdev> ...' can create" \
+ "an alternate pool or a new pool mounted at the specified mountpoint."
+log_onexit cleanup
+
+set -A pooltype "" "mirror" "raidz" "raidz1" "raidz2"
+
+#
+# cleanup the pools created in previous case if zpool_create_004_pos timedout
+#
+for pool in $TESTPOOL2 $TESTPOOL1 $TESTPOOL; do
+ poolexists $pool && destroy_pool $pool
+done
+
+#prepare raw file for file disk
+rm -rf $TESTDIR
+log_must mkdir -p $TESTDIR
+typeset -i i=1
+while (( i < 4 )); do
+ log_must mkfile $FILESIZE $TESTDIR/file.$i
+
+ (( i = i + 1 ))
+done
+
+#Remove the directory with name as pool name if it exists
+rm -rf /$TESTPOOL
+file=$TESTDIR/file
+
+for opt in "-R $TESTDIR1" "-m $TESTDIR1" \
+ "-R $TESTDIR1 -m $TESTDIR1" "-m $TESTDIR1 -R $TESTDIR1"
+do
+ i=0
+ while (( i < ${#pooltype[*]} )); do
+ #Remove the testing pool and its mount directory
+ poolexists $TESTPOOL && \
+ log_must zpool destroy -f $TESTPOOL
+ [[ -d $TESTDIR1 ]] && rm -rf $TESTDIR1
+ log_must zpool create $opt $TESTPOOL ${pooltype[i]} \
+ $file.1 $file.2 $file.3
+ ! poolexists $TESTPOOL && \
+ log_fail "Creating pool with $opt fails."
+ mpt=`zfs mount | egrep "^$TESTPOOL[^/]" | awk '{print $2}'`
+ (( ${#mpt} == 0 )) && \
+ log_fail "$TESTPOOL created with $opt is not mounted."
+ mpt_val=$(get_prop "mountpoint" $TESTPOOL)
+ [[ "$mpt" != "$mpt_val" ]] && \
+ log_fail "The value of mountpoint property is different\
+ from the output of zfs mount"
+ if [[ "$opt" == "-m $TESTDIR1" ]]; then
+ [[ ! -d $TESTDIR1 ]] && \
+ log_fail "$TESTDIR1 is not created automatically."
+ [[ "$mpt" != "$TESTDIR1" ]] && \
+ log_fail "$TESTPOOL is not mounted on $TESTDIR1."
+ elif [[ "$opt" == "-R $TESTDIR1" ]]; then
+ [[ ! -d $TESTDIR1/$TESTPOOL ]] && \
+ log_fail "$TESTDIR1/$TESTPOOL is not created automatically."
+ [[ "$mpt" != "$TESTDIR1/$TESTPOOL" ]] && \
+ log_fail "$TESTPOOL is not mounted on $TESTDIR1/$TESTPOOL."
+ else
+ [[ ! -d ${TESTDIR1}$TESTDIR1 ]] && \
+ log_fail "${TESTDIR1}$TESTDIR1 is not created automatically."
+ [[ "$mpt" != "${TESTDIR1}$TESTDIR1" ]] && \
+ log_fail "$TESTPOOL is not mounted on ${TESTDIR1}$TESTDIR1."
+ fi
+ [[ -d /$TESTPOOL ]] && \
+ log_fail "The default mountpoint /$TESTPOOL is created" \
+ "while with $opt option."
+
+ (( i = i + 1 ))
+ done
+done
+
+log_pass "'zpool create [-R root][-m mountpoint] <pool> <vdev> ...' works as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_006_pos.ksh
new file mode 100755
index 000000000000..15cd23e4450a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_006_pos.ksh
@@ -0,0 +1,137 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# Verify zpool create succeed with multiple keywords combination.
+#
+# STRATEGY:
+# 1. Create base filesystem to hold virtual disk files.
+# 2. Create several files == $MINVDEVSIZE.
+# 3. Verify 'zpool create' succeed with valid keywords combination.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+
+log_assert "Verify 'zpool create' succeed with keywords combination."
+log_onexit cleanup
+
+create_pool $TESTPOOL $DISKS
+mntpnt=$(get_prop mountpoint $TESTPOOL)
+
+typeset -i i=0
+while ((i < 10)); do
+ log_must truncate -s $MINVDEVSIZE $mntpnt/vdev$i
+
+ eval vdev$i=$mntpnt/vdev$i
+ ((i += 1))
+done
+
+set -A valid_args \
+ "mirror $vdev0 $vdev1 $vdev2 mirror $vdev3 $vdev4 $vdev5" \
+ "mirror $vdev0 $vdev1 mirror $vdev2 $vdev3 mirror $vdev4 $vdev5" \
+ "mirror $vdev0 $vdev1 $vdev2 mirror $vdev3 $vdev4 $vdev5 \
+ spare $vdev6" \
+ "mirror $vdev0 $vdev1 mirror $vdev2 $vdev3 mirror $vdev4 $vdev5 \
+ spare $vdev6 $vdev7" \
+ "mirror $vdev0 $vdev1 spare $vdev2 mirror $vdev3 $vdev4" \
+ "mirror $vdev0 $vdev1 raidz $vdev2 $vdev3" \
+ "mirror $vdev0 $vdev1 raidz $vdev2 $vdev3 $vdev4" \
+ "mirror $vdev0 $vdev1 $vdev2 raidz2 $vdev3 $vdev4 $vdev5" \
+ "mirror $vdev0 $vdev1 $vdev2 $vdev3 \
+ raidz3 $vdev4 $vdev5 $vdev6 $vdev7" \
+ "raidz $vdev0 $vdev1 $vdev2 mirror $vdev3 $vdev4" \
+ "raidz $vdev0 $vdev1 $vdev2 raidz1 $vdev3 $vdev4 $vdev5" \
+ "raidz $vdev0 $vdev1 raidz1 $vdev2 $vdev3 raidz $vdev4 $vdev5" \
+ "raidz $vdev0 $vdev1 $vdev2 raidz1 $vdev3 $vdev4 $vdev5 \
+ spare $vdev6" \
+ "raidz $vdev0 $vdev1 raidz1 $vdev2 $vdev3 raidz $vdev4 $vdev5 \
+ spare $vdev6 $vdev7" \
+ "raidz $vdev0 $vdev1 spare $vdev2 raidz $vdev3 $vdev4" \
+ "raidz2 $vdev0 $vdev1 $vdev2 mirror $vdev3 $vdev4 $vdev5" \
+ "raidz2 $vdev0 $vdev1 $vdev2 raidz2 $vdev3 $vdev4 $vdev5" \
+ "raidz2 $vdev0 $vdev1 $vdev2 raidz2 $vdev3 $vdev4 $vdev5 \
+ raidz2 $vdev6 $vdev7 $vdev8" \
+ "raidz2 $vdev0 $vdev1 $vdev2 raidz2 $vdev3 $vdev4 $vdev5 \
+ spare $vdev6" \
+ "raidz2 $vdev0 $vdev1 $vdev2 raidz2 $vdev3 $vdev4 $vdev5 \
+ raidz2 $vdev6 $vdev7 $vdev8 spare $vdev9" \
+ "raidz2 $vdev0 $vdev1 $vdev2 spare $vdev3 raidz2 $vdev4 $vdev5 $vdev6" \
+ "raidz3 $vdev0 $vdev1 $vdev2 $vdev3 \
+ mirror $vdev4 $vdev5 $vdev6 $vdev7" \
+ "spare $vdev0 $vdev1 $vdev2 mirror $vdev3 $vdev4 raidz $vdev5 $vdev6"
+
+set -A forced_args \
+ "$vdev0 raidz $vdev1 $vdev2 raidz1 $vdev3 $vdev4 $vdev5" \
+ "$vdev0 raidz2 $vdev1 $vdev2 $vdev3 raidz2 $vdev4 $vdev5 $vdev6" \
+ "$vdev0 mirror $vdev1 $vdev2 mirror $vdev3 $vdev4" \
+ "$vdev0 mirror $vdev1 $vdev2 raidz $vdev3 $vdev4 \
+ raidz2 $vdev5 $vdev6 $vdev7 spare $vdev8" \
+ "$vdev0 mirror $vdev1 $vdev2 spare $vdev3 raidz $vdev4 $vdev5" \
+ "raidz $vdev0 $vdev1 raidz2 $vdev2 $vdev3 $vdev4" \
+ "raidz $vdev0 $vdev1 raidz2 $vdev2 $vdev3 $vdev4 spare $vdev5" \
+ "raidz $vdev0 $vdev1 spare $vdev2 raidz2 $vdev3 $vdev4 $vdev5" \
+ "mirror $vdev0 $vdev1 raidz $vdev2 $vdev3 raidz2 $vdev4 $vdev5 $vdev6" \
+ "mirror $vdev0 $vdev1 raidz $vdev2 $vdev3 \
+ raidz2 $vdev4 $vdev5 $vdev6 spare $vdev7" \
+ "mirror $vdev0 $vdev1 raidz $vdev2 $vdev3 \
+ spare $vdev4 raidz2 $vdev5 $vdev6 $vdev7" \
+ "spare $vdev0 $vdev1 $vdev2 mirror $vdev3 $vdev4 \
+ raidz2 $vdev5 $vdev6 $vdev7"
+
+i=0
+while ((i < ${#valid_args[@]})); do
+ log_must zpool create $TESTPOOL1 ${valid_args[$i]}
+ log_must zpool destroy -f $TESTPOOL1
+
+ ((i += 1))
+done
+
+i=0
+while ((i < ${#forced_args[@]})); do
+ log_mustnot zpool create $TESTPOOL1 ${forced_args[$i]}
+ log_must zpool create -f $TESTPOOL1 ${forced_args[$i]}
+ log_must zpool destroy -f $TESTPOOL1
+
+ ((i += 1))
+done
+
+log_pass "'zpool create' succeed with keywords combination."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_007_neg.ksh
new file mode 100755
index 000000000000..bafc238ea289
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_007_neg.ksh
@@ -0,0 +1,77 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# 'zpool create' should return an error with badly formed parameters.
+#
+# STRATEGY:
+# 1. Create an array of parameters
+# 2. For each parameter in the array, execute 'zpool create'
+# 3. Verify an error is returned.
+#
+
+verify_runnable "global"
+
+set -A args "" "-?" "-n" "-f" "-nf" "-fn" "-f -n" "--f" "-e" "-s" \
+ "-m" "-R" "-m -R" "-Rm" "-mR" "-m $TESTDIR $TESTPOOL" \
+ "-R $TESTDIR $TESTPOOL" "-m nodir $TESTPOOL $DISK0" \
+ "-R nodir $TESTPOOL $DISK0" "-m nodir -R nodir $TESTPOOL $DISK0" \
+ "-R nodir -m nodir $TESTPOOL $DISK0" "-R $TESTDIR -m nodir $TESTPOOL $DISK0" \
+ "-R nodir -m $TESTDIR $TESTPOOL $DISK0" \
+ "-blah" "$TESTPOOL" "$TESTPOOL blah" "$TESTPOOL c?t0d0" \
+ "$TESTPOOL c0txd0" "$TESTPOOL c0t0dx" "$TESTPOOL cxtxdx" \
+ "$TESTPOOL mirror" "$TESTPOOL raidz" "$TESTPOOL mirror raidz" \
+ "$TESTPOOL raidz1" "$TESTPOOL mirror raidz1" \
+ "$TESTPOOL mirror c?t?d?" "$TESTPOOL mirror $DISK0 c0t1d?" \
+ "$TESTPOOL RAIDZ $DISK0 $DISK1" \
+ "$TESTPOOL $DISK0 log $DISK1 log $DISK2" \
+ "$TESTPOOL $DISK0 spare $DISK1 spare $DISK2" \
+ "$TESTPOOL RAIDZ1 $DISK0 $DISK1" \
+ "$TESTPOOL MIRROR $DISK0" "$TESTPOOL raidz $DISK0" \
+ "$TESTPOOL raidz1 $DISK0" \
+ "1tank $DISK0" "1234 $DISK0" "?tank $DISK0" \
+ "tan%k $DISK0" "ta@# $DISK0" "tan+k $DISK0" \
+ "$BYND_MAX_NAME $DISK0"
+
+log_assert "'zpool create' should return an error with badly-formed parameters."
+log_onexit default_cleanup_noexit
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zpool create ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "'zpool create' with badly formed parameters failed as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_008_pos.ksh
new file mode 100755
index 000000000000..56bb64c64051
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_008_pos.ksh
@@ -0,0 +1,90 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# 'zpool create' have to use '-f' scenarios
+#
+# STRATEGY:
+# 1. Prepare the scenarios
+# 2. Create pool without '-f' and verify it fails
+# 3. Create pool with '-f' and verify it succeeds
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if [[ $exported_pool == true ]]; then
+ if [[ $force_pool == true ]]; then
+ log_must zpool create -f $TESTPOOL $DISK0
+ else
+ log_must zpool import $TESTPOOL
+ fi
+ fi
+
+ if poolexists $TESTPOOL ; then
+ destroy_pool $TESTPOOL
+ fi
+
+ if poolexists $TESTPOOL1 ; then
+ destroy_pool $TESTPOOL1
+ fi
+}
+
+log_assert "'zpool create' have to use '-f' scenarios"
+log_onexit cleanup
+
+typeset exported_pool=false
+typeset force_pool=false
+
+# overlapped slices as vdev need -f to create pool
+
+# Make the disk is EFI labeled first via pool creation
+create_pool $TESTPOOL $DISK0
+destroy_pool $TESTPOOL
+
+# exported device to be as spare vdev need -f to create pool
+
+log_must zpool create -f $TESTPOOL $DISK0
+destroy_pool $TESTPOOL
+create_pool $TESTPOOL $DISK0 $DISK1
+log_must zpool export $TESTPOOL
+exported_pool=true
+log_mustnot zpool create $TESTPOOL1 $DISK1 spare $DISK2
+create_pool $TESTPOOL1 $DISK1 spare $DISK2
+force_pool=true
+destroy_pool $TESTPOOL1
+
+log_pass "'zpool create' have to use '-f' scenarios"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_009_neg.ksh
new file mode 100755
index 000000000000..0d7acdb4089c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_009_neg.ksh
@@ -0,0 +1,87 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# Create a pool with same devices twice or create two pools with same
+# devices, 'zpool create' should failed.
+#
+# STRATEGY:
+# 1. Loop to create the following three kinds of pools.
+# - Regular pool
+# - Mirror
+# - Raidz
+# 2. Create two pools but using the same disks, expect failed.
+# 3. Create one pool but using the same disks twice, expect failed.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset pool
+
+ for pool in $TESTPOOL $TESTPOOL1; do
+ poolexists $pool && destroy_pool $pool
+ done
+}
+
+log_assert "Create a pool with same devices twice or create two pools with " \
+ "same devices, 'zpool create' should fail."
+log_onexit cleanup
+
+unset NOINUSE_CHECK
+typeset opt
+for opt in "" "mirror" "raidz" "raidz1"; do
+ if [[ $opt == "" ]]; then
+ typeset disks=$DISK0
+ else
+ typeset disks=$DISKS
+ fi
+
+ # Create two pools but using the same disks.
+ create_pool $TESTPOOL $opt $disks
+ log_mustnot zpool create -f $TESTPOOL1 $opt $disks
+ destroy_pool $TESTPOOL
+
+ # Create two pools and part of the devices were overlapped
+ create_pool $TESTPOOL $opt $disks
+ log_mustnot zpool create -f $TESTPOOL1 $opt $DISK0
+ destroy_pool $TESTPOOL
+
+ # Create one pool but using the same disks twice.
+ log_mustnot zpool create -f $TESTPOOL $opt $disks $disks
+done
+
+log_pass "Using overlapping or in-use disks to create a new pool fails as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_010_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_010_neg.ksh
new file mode 100755
index 000000000000..e0b3850e4a95
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_010_neg.ksh
@@ -0,0 +1,82 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# 'zpool create' should return an error with VDEVs of size SPA_MINDEVSIZE
+#
+# STRATEGY:
+# 1. Create an array of parameters
+# 2. For each parameter in the array, execute 'zpool create'
+# 3. Verify an error is returned.
+#
+
+log_assert "'zpool create' should return an error with VDEVs SPA_MINDEVSIZE"
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset pool
+
+ for pool in $TOOSMALL $TESTPOOL1 $TESTPOOL; do
+ poolexists $pool && destroy_pool $pool
+ done
+
+ rm -rf $TESTDIR
+}
+log_onexit cleanup
+
+create_pool $TESTPOOL $DISK0
+log_must zfs create $TESTPOOL/$TESTFS
+log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+
+typeset -l devsize=$(($SPA_MINDEVSIZE - 1024 * 1024))
+for files in $TESTDIR/file1 $TESTDIR/file2
+do
+ log_must mkfile $devsize $files
+done
+
+set -A args \
+ "$TOOSMALL $TESTDIR/file1" "$TESTPOOL1 $TESTDIR/file1 $TESTDIR/file2" \
+ "$TOOSMALL mirror $TESTDIR/file1 $TESTDIR/file2" \
+ "$TOOSMALL raidz $TESTDIR/file1 $TESTDIR/file2"
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zpool create ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "'zpool create' with badly formed parameters failed as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_011_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_011_neg.ksh
new file mode 100755
index 000000000000..140771d4f82d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_011_neg.ksh
@@ -0,0 +1,131 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# 'zpool create' will fail in the following cases:
+# existent pool; device is part of an active pool; nested virtual devices;
+# differently sized devices without -f option; device being currently
+# mounted; devices in /etc/vfstab; specified as the dedicated dump device.
+#
+# STRATEGY:
+# 1. Create case scenarios
+# 2. For each scenario, try to create a new pool with the virtual devices
+# 3. Verify the creation is failed.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ for pool in $TESTPOOL $TESTPOOL1
+ do
+ destroy_pool $pool
+ done
+
+ rm -rf $disk1 $disk2 $disk3
+
+ if [[ -n $saved_dump_dev ]]; then
+ log_must dumpadm -u -d $saved_dump_dev
+ fi
+}
+
+log_assert "'zpool create' should be failed with inapplicable scenarios."
+log_onexit cleanup
+
+disk1=$(create_blockfile $FILESIZE)
+disk2=$(create_blockfile $FILESIZE)
+disk3=$(create_blockfile $FILESIZE1)
+mirror1="$DISK0 $DISK1"
+mirror2="$disk1 $disk2"
+raidz1=$mirror1
+raidz2=$mirror2
+diff_size_dev="$disk2 $disk3"
+vfstab_dev=$(find_vfstab_dev)
+
+if is_illumos; then
+ specified_dump_dev=${DISK0}s0
+ saved_dump_dev=$(save_dump_dev)
+
+ cyl=$(get_endslice $DISK0 6)
+ log_must set_partition 7 "$cyl" $SIZE1 $DISK0
+fi
+create_pool $TESTPOOL $DISK0
+
+#
+# Set up the testing scenarios parameters
+#
+set -A arg \
+ "$TESTPOOL1 $DISK0" \
+ "$TESTPOOL1 mirror mirror $mirror1 mirror $mirror2" \
+ "$TESTPOOL1 raidz raidz $raidz1 raidz $raidz2" \
+ "$TESTPOOL1 raidz1 raidz1 $raidz1 raidz1 $raidz2" \
+ "$TESTPOOL1 mirror raidz $raidz1 raidz $raidz2" \
+ "$TESTPOOL1 mirror raidz1 $raidz1 raidz1 $raidz2" \
+ "$TESTPOOL1 raidz mirror $mirror1 mirror $mirror2" \
+ "$TESTPOOL1 raidz1 mirror $mirror1 mirror $mirror2" \
+ "$TESTPOOL1 mirror $diff_size_dev" \
+ "$TESTPOOL1 raidz $diff_size_dev" \
+ "$TESTPOOL1 raidz1 $diff_size_dev" \
+ "$TESTPOOL1 mirror $mirror1 spare $mirror2 spare $diff_size_dev" \
+ "$TESTPOOL1 $vfstab_dev" \
+ "$TESTPOOL1 ${DISK0}s10" \
+ "$TESTPOOL1 spare $pooldev2"
+
+unset NOINUSE_CHECK
+typeset -i i=0
+while (( i < ${#arg[*]} )); do
+ log_mustnot zpool create ${arg[i]}
+ (( i = i+1 ))
+done
+
+# now destroy the pool to be polite
+log_must zpool destroy -f $TESTPOOL
+
+if is_illumos; then
+ # create/destroy a pool as a simple way to set the partitioning
+ # back to something normal so we can use this $disk as a dump device
+ log_must zpool create -f $TESTPOOL3 $DISK1
+ log_must zpool destroy -f $TESTPOOL3
+
+ log_must dumpadm -d ${DEV_DSKDIR}/$specified_dump_dev
+ log_mustnot zpool create -f $TESTPOOL1 "$specified_dump_dev"
+
+ # Also check to see that in-use checking prevents us from creating
+ # a zpool from just the first slice on the disk.
+ log_mustnot zpool create \
+ -f $TESTPOOL1 ${specified_dump_dev}s0
+fi
+
+log_pass "'zpool create' is failed as expected with inapplicable scenarios."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_012_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_012_neg.ksh
new file mode 100755
index 000000000000..36888e497369
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_012_neg.ksh
@@ -0,0 +1,71 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+#
+# DESCRIPTION:
+# 'zpool create' will fail with formal disk slice in swap
+#
+#
+# STRATEGY:
+# 1. Get all the disk devices in swap
+# 2. For each device, try to create a new pool with this device
+# 3. Verify the creation is failed.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+if is_freebsd; then
+ typeset swap_disks=$(swapinfo -l | grep "/dev" | awk '{print $1}')
+elif is_linux; then
+ typeset swap_disks=`swapon -s | grep "/dev" | awk '{print $1}'`
+else
+ typeset swap_disks=`swap -l | grep "c[0-9].*d[0-9].*s[0-9]" | \
+ awk '{print $1}'`
+fi
+
+log_assert "'zpool create' should fail with disk slice in swap."
+log_onexit cleanup
+
+for sdisk in $swap_disks; do
+ for opt in "-n" "" "-f"; do
+ log_mustnot zpool create $opt $TESTPOOL $sdisk
+ done
+done
+
+log_pass "'zpool create' passed as expected with inapplicable scenario."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_014_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_014_neg.ksh
new file mode 100755
index 000000000000..44ed950f7870
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_014_neg.ksh
@@ -0,0 +1,86 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+#
+# DESCRIPTION:
+# 'zpool create' will fail with ordinary file in swap
+#
+# STRATEGY:
+# 1. Create a regular file on top of UFS-zvol filesystem
+# 2. Try to create a new pool with regular file in swap
+# 3. Verify the creation is failed.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if datasetexists $vol_name; then
+ swap_cleanup $TMP_FILE
+ rm -f $TMP_FILE
+ log_must umount $mntp
+ zfs destroy $vol_name
+ fi
+
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_assert "'zpool create' should fail with regular file in swap."
+log_onexit cleanup
+
+if is_linux; then
+ set -A options "" "-f"
+else
+ set -A options "-n" "" "-f"
+fi
+
+typeset vol_name=$TESTPOOL/$TESTVOL
+typeset mntp=/mnt
+typeset TMP_FILE=$mntp/tmpfile.$$
+
+create_pool $TESTPOOL $DISK0
+log_must zfs create -V 100m $vol_name
+block_device_wait
+log_must eval "new_fs ${ZVOL_DEVDIR}/$vol_name > /dev/null 2>&1"
+log_must mount ${ZVOL_DEVDIR}/$vol_name $mntp
+
+log_must mkfile 50m $TMP_FILE
+swap_setup $TMP_FILE
+
+for opt in options; do
+ log_mustnot zpool create $opt $TESTPOOL $TMP_FILE
+done
+
+log_pass "'zpool create' passed as expected with inapplicable scenario."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_015_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_015_neg.ksh
new file mode 100755
index 000000000000..babf5ca9c66d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_015_neg.ksh
@@ -0,0 +1,91 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+#
+# DESCRIPTION:
+# 'zpool create' will fail with zfs vol device in swap
+#
+#
+# STRATEGY:
+# 1. Create a zpool
+# 2. Create a zfs vol on zpool
+# 3. Add this zfs vol device to swap
+# 4. Try to create a new pool with devices in swap
+# 5. Verify the creation is failed.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ # cleanup zfs pool and dataset
+ if datasetexists $vol_name; then
+ swap_cleanup ${ZVOL_DEVDIR}/${vol_name}
+ fi
+
+ for pool in $TESTPOOL1 $TESTPOOL; do
+ poolexists $pool && destroy_pool $pool
+ done
+}
+
+unset NOINUSE_CHECK
+typeset vol_name=$TESTPOOL/$TESTVOL
+
+log_assert "'zpool create' should fail with zfs vol device in swap."
+log_onexit cleanup
+
+#
+# use zfs vol device in swap to create pool which should fail.
+#
+create_pool $TESTPOOL $DISK0
+log_must zfs create -V 100m $vol_name
+block_device_wait
+swap_setup ${ZVOL_DEVDIR}/$vol_name
+
+if is_freebsd; then
+ typeset -a opts=("" "-f")
+else
+ typeset -a opts=("-n" "" "-f")
+fi
+for opt in "${opts[@]}"; do
+ log_mustnot zpool create $opt $TESTPOOL1 ${ZVOL_DEVDIR}/${vol_name}
+done
+
+# cleanup
+swap_cleanup ${ZVOL_DEVDIR}/${vol_name}
+log_must_busy zfs destroy $vol_name
+log_must zpool destroy $TESTPOOL
+
+log_pass "'zpool create' passed as expected with inapplicable scenario."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_016_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_016_pos.ksh
new file mode 100755
index 000000000000..1fa205b0f253
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_016_pos.ksh
@@ -0,0 +1,88 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+#
+# DESCRIPTION:
+# 'zpool create' will success with no device in swap
+#
+#
+# STRATEGY:
+# 1. delete all devices in the swap
+# 2. create a zpool
+# 3. Verify the creation was successful
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+
+ #recover swap devices
+ FSTAB=$TEST_BASE_DIR/fstab_$$
+ rm -f $FSTAB
+ for sdisk in $swap_disks; do
+ echo "$sdisk - - swap - no -" >> $FSTAB
+ done
+ if [ -e $FSTAB ]
+ then
+ log_must swapadd $FSTAB
+ fi
+ rm -f $FSTAB
+ if [ $dump_device != "none" ]
+ then
+ log_must dumpadm -u -d $dump_device
+ fi
+}
+
+typeset swap_disks=$(swap -l | grep -v "swapfile" | awk '{print $1}')
+typeset dump_device=$(dumpadm | grep "Dump device" | awk '{print $3}')
+
+log_assert "'zpool create' should success with no device in swap."
+log_onexit cleanup
+
+for sdisk in $swap_disks; do
+ log_note "Executing: swap -d $sdisk"
+ swap -d $sdisk >/dev/null 2>&1;
+ if [[ $? != 0 ]]; then
+ log_untested "Unable to delete swap device $sdisk because of" \
+ "insufficient RAM"
+ fi
+done
+
+log_must zpool create $TESTPOOL $DISK0
+log_must zpool destroy $TESTPOOL
+
+log_pass "'zpool create' passed as expected with applicable scenario."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_017_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_017_neg.ksh
new file mode 100755
index 000000000000..ded1e3c3966b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_017_neg.ksh
@@ -0,0 +1,77 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+#
+# DESCRIPTION:
+# 'zpool create' will fail with mountpoint exists and is not empty.
+#
+#
+# STRATEGY:
+# 1. Prepare the mountpoint put some stuff into it.
+# 2. Verify 'zpool create' over that mountpoint fails.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -rf $TESTDIR
+}
+
+log_assert "'zpool create' should fail with mountpoint exists and not empty."
+log_onexit cleanup
+
+if [[ ! -d $TESTDIR ]]; then
+ log_must mkdir -p $TESTDIR
+fi
+
+typeset -i i=0
+
+while (( i < 2 )); do
+ log_must rm -rf $TESTDIR/*
+ if (( i == 0 )); then
+ log_must mkdir $TESTDIR/testdir
+ else
+ log_must touch $TESTDIR/testfile
+ fi
+
+ log_mustnot zpool create -m $TESTDIR -f $TESTPOOL $DISK0
+ log_mustnot poolexists $TESTPOOL
+
+ (( i = i + 1 ))
+done
+
+log_pass "'zpool create' fail as expected with mountpoint exists and not empty."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_018_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_018_pos.ksh
new file mode 100755
index 000000000000..6ad662f95011
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_018_pos.ksh
@@ -0,0 +1,98 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+#
+# zpool create can create pools with specified properties
+#
+# STRATEGY:
+# 1. Create a pool with all editable properties
+# 2. Verify those properties are set
+# 3. Create a pool with two properties set
+# 4. Verify both properties are set correctly
+#
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -f $CPATH
+}
+
+log_onexit cleanup
+log_assert "zpool create can create pools with specified properties"
+
+#
+# we don't include "root" property in this list, as it requires both "cachefile"
+# and "root" to be set at the same time. A test for this is included in
+# ../../root.
+#
+typeset props=("autoreplace" "delegation" "cachefile" "version" "autoexpand")
+typeset vals=("off" "off" "$CPATH" "3" "on")
+
+typeset -i i=0;
+while [ $i -lt "${#props[@]}" ]
+do
+ log_must zpool create -o ${props[$i]}=${vals[$i]} $TESTPOOL $DISK0
+ RESULT=$(get_pool_prop ${props[$i]} $TESTPOOL)
+ if [[ $RESULT != ${vals[$i]} ]]
+ then
+ zpool get all $TESTPOOL
+ log_fail "Pool was created without setting the ${props[$i]} " \
+ "property"
+ fi
+ log_must zpool destroy $TESTPOOL
+ ((i = i + 1))
+done
+
+# Destroy our pool
+poolexists $TESTPOOL && destroy_pool $TESTPOOL
+
+# pick two properties, and verify we can create with those as well
+log_must zpool create -o delegation=off -o cachefile=$CPATH $TESTPOOL $DISK0
+RESULT=$(get_pool_prop delegation $TESTPOOL)
+if [[ $RESULT != off ]]
+then
+ zpool get all $TESTPOOL
+ log_fail "Pool created without the delegation prop."
+fi
+
+RESULT=$(get_pool_prop cachefile $TESTPOOL)
+if [[ $RESULT != $CPATH ]]
+then
+ zpool get all $TESTPOOL
+ log_fail "Pool created without the cachefile prop."
+fi
+
+log_pass "zpool create can create pools with specified properties"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_019_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_019_pos.ksh
new file mode 100755
index 000000000000..694ea2163c94
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_019_pos.ksh
@@ -0,0 +1,68 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# zpool create cannot create pools specifying readonly properties
+#
+# STRATEGY:
+# 1. Attempt to create a pool, specifying each readonly property in turn
+# 2. Verify the pool was not created
+#
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_assert "zpool create cannot create pools specifying readonly properties"
+
+set -A props "available" "capacity" "guid" "health" "size" "used"
+set -A vals "100" "10" "12345" "HEALTHY" "10" "10"
+
+typeset -i i=0;
+while [ $i -lt "${#props[@]}" ]
+do
+ # try to set each property in the prop list with it's corresponding val
+ log_mustnot zpool create -o ${props[$i]}=${vals[$i]} $TESTPOOL $DISK0
+ if poolexists $TESTPOOL
+ then
+ log_fail "$TESTPOOL was created when setting ${props[$i]}!"
+ fi
+ i=$(( $i + 1))
+done
+
+log_pass "zpool create cannot create pools specifying readonly properties"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_020_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_020_pos.ksh
new file mode 100755
index 000000000000..104b5ec9868a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_020_pos.ksh
@@ -0,0 +1,103 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool create -R works as expected
+#
+# STRATEGY:
+# 1. Create a -R altroot pool
+# 2. Verify the pool is mounted at the correct location
+# 3. Verify that cachefile=none for the pool
+# 4. Verify that root=<mountpoint> for the pool
+# 5. Verify that no reference to the pool is found in /etc/zfs/zpool.cache
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -rf /${TESTPOOL}.root
+ rm -f $values
+}
+
+log_onexit cleanup
+
+log_assert "zpool create -R works as expected"
+
+typeset values=$TEST_BASE_DIR/values.$$
+
+log_must rm -f /etc/zfs/zpool.cache
+log_must rm -rf /${TESTPOOL}.root
+log_must zpool create -R /${TESTPOOL}.root $TESTPOOL $DISK0
+if [ ! -d /${TESTPOOL}.root ]
+then
+ log_fail "Mountpoint was not created when using zpool with -R flag!"
+fi
+
+FS=$(zfs list $TESTPOOL)
+if [ -z "$FS" ]
+then
+ log_fail "Mounted filesystem at /${TESTPOOL}.root isn't ZFS!"
+fi
+
+log_must zpool get all $TESTPOOL
+zpool get all $TESTPOOL > $values
+
+# check for the cachefile property, verifying that it's set to 'none'
+grep "$TESTPOOL[ ]*cachefile[ ]*none" $values > /dev/null 2>&1
+if [ $? -ne 0 ]
+then
+ log_fail "zpool property \'cachefile\' was not set to \'none\'."
+fi
+
+# check that the root = /mountpoint property is set correctly
+grep "$TESTPOOL[ ]*altroot[ ]*/${TESTPOOL}.root" $values > /dev/null 2>&1
+if [ $? -ne 0 ]
+then
+ log_fail "zpool property root was not found in pool output."
+fi
+
+rm $values
+
+# finally, check that the pool has no reference in /etc/zfs/zpool.cache
+if [[ -f /etc/zfs/zpool.cache ]] ; then
+ REF=$(strings /etc/zfs/zpool.cache | grep ${TESTPOOL})
+ if [ ! -z "$REF" ]
+ then
+ strings /etc/zfs/zpool.cache
+ log_fail "/etc/zfs/zpool.cache appears to have a reference to $TESTPOOL"
+ fi
+fi
+
+log_pass "zpool create -R works as expected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_021_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_021_pos.ksh
new file mode 100755
index 000000000000..6ea1573241f0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_021_pos.ksh
@@ -0,0 +1,93 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# 'zpool create -O property=value pool' can successfully create a pool
+# with correct filesystem property set.
+#
+# STRATEGY:
+# 1. Create a storage pool with -O option
+# 2. Verify the pool created successfully
+# 3. Verify the filesystem property is correctly set
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_assert "'zpool create -O property=value pool' can successfully create a pool \
+ with correct filesystem property set."
+
+set -A RW_FS_PROP "quota=536870912" \
+ "reservation=536870912" \
+ "recordsize=262144" \
+ "mountpoint=/tmp/mnt$$" \
+ "checksum=fletcher2" \
+ "compression=lzjb" \
+ "atime=off" \
+ "devices=off" \
+ "exec=off" \
+ "setuid=off" \
+ "readonly=on" \
+ "snapdir=visible" \
+ "acltype=posixacl" \
+ "aclinherit=discard" \
+ "canmount=off"
+if is_freebsd; then
+ RW_FS_PROP+=("jailed=on")
+else
+ RW_FS_PROP+=("zoned=on")
+fi
+
+typeset -i i=0
+while (( $i < ${#RW_FS_PROP[*]} )); do
+ log_must zpool create -O ${RW_FS_PROP[$i]} -f $TESTPOOL $DISKS
+ datasetexists $TESTPOOL || \
+ log_fail "zpool create $TESTPOOL fail."
+ propertycheck $TESTPOOL ${RW_FS_PROP[i]} || \
+ log_fail "${RW_FS_PROP[i]} is failed to set."
+ log_must zpool destroy $TESTPOOL
+ (( i = i + 1 ))
+done
+
+log_pass "'zpool create -O property=value pool' can successfully create a pool \
+ with correct filesystem property set."
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_022_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_022_pos.ksh
new file mode 100755
index 000000000000..349f73fecca5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_022_pos.ksh
@@ -0,0 +1,95 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# 'zpool create -O property=value pool' can successfully create a pool
+# with multiple filesystem properties set.
+#
+# STRATEGY:
+# 1. Create a storage pool with multiple -O options
+# 2. Verify the pool created successfully
+# 3. Verify the properties are correctly set
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_assert "'zpool create -O property=value pool' can successfully create a pool \
+ with multiple filesystem properties set."
+
+set -A RW_FS_PROP "quota=536870912" \
+ "reservation=536870912" \
+ "recordsize=262144" \
+ "mountpoint=/tmp/mnt$$" \
+ "checksum=fletcher2" \
+ "compression=lzjb" \
+ "atime=off" \
+ "devices=off" \
+ "exec=off" \
+ "setuid=off" \
+ "readonly=on" \
+ "snapdir=visible" \
+ "acltype=posixacl" \
+ "aclinherit=discard" \
+ "canmount=off"
+
+typeset -i i=0
+typeset opts=""
+
+while (( $i < ${#RW_FS_PROP[*]} )); do
+ opts="$opts -O ${RW_FS_PROP[$i]}"
+ (( i = i + 1 ))
+done
+
+log_must zpool create $opts -f $TESTPOOL $DISKS
+datasetexists $TESTPOOL || log_fail "zpool create $TESTPOOL fail."
+
+i=0
+while (( $i < ${#RW_FS_PROP[*]} )); do
+ propertycheck $TESTPOOL ${RW_FS_PROP[i]} || \
+ log_fail "${RW_FS_PROP[i]} is failed to set."
+ (( i = i + 1 ))
+done
+
+log_pass "'zpool create -O property=value pool' can successfully create a pool \
+ with multiple filesystem properties set."
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_023_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_023_neg.ksh
new file mode 100755
index 000000000000..f101521bd3e8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_023_neg.ksh
@@ -0,0 +1,97 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2015, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zpool create -O' should return an error with badly formed parameters.
+#
+# STRATEGY:
+# 1. Create an array of parameters with '-O'
+# 2. For each parameter in the array, execute 'zpool create -O'
+# 3. Verify an error is returned.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+set -A args "QuOta=none" "quota=non" "quota=abcd" "quota=0" "quota=" \
+ "ResErVaTi0n=none" "reserV=none" "reservation=abcd" "reserv=" \
+ "recorDSize=64k" "recordsize=2M" "recordsize=2048K" \
+ "recordsize=256" "recsize=" "recsize=zero" "recordsize=0" \
+ "mountPoint=/tmp/tmpfile$$" "mountpoint=non0" "mountpoint=" \
+ "mountpoint=LEGACY" "mounpoint=none" \
+ "sharenfs=ON" "ShareNFS=off" "sharenfs=sss" \
+ "checkSUM=on" "checksum=SHA256" "chsum=off" "checksum=aaa" \
+ "compression=of" "ComPression=lzjb" "compress=ON" "compress=a" \
+ "atime=ON" "ATime=off" "atime=bbb" \
+ "deviCes=on" "devices=OFF" "devices=aaa" \
+ "exec=ON" "EXec=off" "exec=aaa" \
+ "readonly=ON" "reADOnly=off" "rdonly=OFF" "rdonly=aaa" \
+ "snapdIR=hidden" "snapdir=VISible" "snapdir=aaa" \
+ "acltype=DIScard" "acltYPE=groupmask" "acltype=aaa" \
+ "aclinherit=deny" "aclinHerit=secure" "aclinherit=aaa" \
+ "type=volume" "type=snapshot" "type=filesystem" \
+ "creation=aaa" "used=10K" "available=10K" \
+ "referenced=10K" "compressratio=1.00x" \
+ "version=0" "version=1.234" "version=10K" "version=-1" \
+ "version=aaa" "version=999"
+if is_freebsd; then
+ args+=("jailed=ON" "JaiLed=off" "jailed=aaa")
+else
+ args+=("zoned=ON" "ZoNed=off" "zoned=aaa")
+fi
+
+log_assert "'zpool create -O' should return an error with badly formed parameters."
+
+typeset -i i=0
+while (( $i < ${#args[*]} )); do
+ typeset arg=${args[i]}
+ if is_freebsd; then
+ # FreeBSD does not strictly validate share opts (yet).
+ if [[ $arg == "sharenfs="* ]]; then
+ ((i = i + 1))
+ continue
+ fi
+ fi
+ log_mustnot zpool create -O $arg -f $TESTPOOL $DISKS
+ ((i = i + 1))
+done
+
+log_pass "'zpool create -O' should return an error with badly formed parameters."
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_024_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_024_pos.ksh
new file mode 100755
index 000000000000..5b464c3c248b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_024_pos.ksh
@@ -0,0 +1,152 @@
+#!/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) 2016, Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.cfg
+
+#
+# DESCRIPTION:
+# Many 'zpool create' and 'zpool destroy' must succeed concurrently.
+#
+# STRATEGY:
+# 1. Create N process each of which create/destroy a pool M times.
+# 2. Allow all process to run to completion.
+# 3. Verify all pools and their vdevs were destroyed.
+#
+
+verify_runnable "global"
+
+if is_32bit; then
+ log_unsupported "Test case runs slowly on 32 bit"
+fi
+
+function cleanup
+{
+ if [[ -n "$child_pids" ]]; then
+ for wait_pid in $child_pids; do
+ kill $wait_pid 2>/dev/null
+ done
+ fi
+
+ if [[ -n "$child_pools" ]]; then
+ for pool in $child_pools; do
+ typeset vdev0="$TEST_BASE_DIR/$pool-vdev0.img"
+ typeset vdev1="$TEST_BASE_DIR/$pool-vdev1.img"
+
+ if poolexists $pool; then
+ destroy_pool $pool
+ fi
+
+ rm -f $vdev0 $vdev1
+ done
+ fi
+}
+
+log_onexit cleanup
+
+log_assert "Many 'zpool create' and 'zpool destroy' must succeed concurrently."
+
+child_pids=""
+child_pools=""
+
+function zpool_stress
+{
+ typeset pool=$1
+ typeset vdev0="$TEST_BASE_DIR/$pool-vdev0.img"
+ typeset vdev1="$TEST_BASE_DIR/$pool-vdev1.img"
+ typeset -i iters=$2
+ typeset retry=10
+ typeset j=0
+
+ truncate -s $FILESIZE $vdev0
+ truncate -s $FILESIZE $vdev1
+
+ while [[ $j -lt $iters ]]; do
+ ((j = j + 1))
+ sleep 1
+
+ zpool create $pool $vdev0 $vdev1
+ if [ $? -ne 0 ]; then
+ return 1;
+ fi
+
+ # The 'zfs destroy' command is retried because it can
+ # transiently return EBUSY when blkid is concurrently
+ # probing new volumes and therefore has them open.
+ typeset k=0;
+ while [[ $k -lt $retry ]]; do
+ ((k = k + 1))
+
+ zpool destroy $pool
+ if [ $? -eq 0 ]; then
+ break;
+ elif [ $k -eq $retry ]; then
+ return 1;
+ fi
+
+ sleep 3
+ done
+ done
+
+ rm -f $vdev0 $vdev1
+ return 0
+}
+
+# 1. Create 128 process each of which create/destroy a pool 5 times.
+typeset i=0
+while [[ $i -lt 128 ]]; do
+ typeset uuid=$(uuidgen | cut -c1-13)
+
+ zpool_stress $TESTPOOL-$uuid 5 &
+ typeset pid=$!
+
+ child_pids="$child_pids $pid"
+ child_pools="$child_pools $TESTPOOL-$uuid"
+ ((i = i + 1))
+done
+
+# 2. Allow all process to run to completion.
+wait
+
+# 3. Verify all pools and their vdevs were destroyed.
+for pool in $child_pools; do
+ typeset vdev0="$TEST_BASE_DIR/$pool-vdev0.img"
+ typeset vdev1="$TEST_BASE_DIR/$pool-vdev1.img"
+
+ if poolexists $pool; then
+ log_fail "pool $pool exists"
+ fi
+
+ if [ -e $vdev0 ]; then
+ log_fail "pool vdev $vdev0 exists"
+ fi
+
+ if [ -e $vdev1 ]; then
+ log_fail "pool vdev $vdev1 exists"
+ fi
+done
+
+log_pass "Many 'zpool create' and 'zpool destroy' must succeed concurrently."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_crypt_combos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_crypt_combos.ksh
new file mode 100755
index 000000000000..63391e8adb49
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_crypt_combos.ksh
@@ -0,0 +1,90 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017, Datto, Inc. All rights reserved.
+# Copyright (c) 2019, DilOS
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool create' should create encrypted pools when using a valid encryption
+# algorithm, key format, key location, and key.
+#
+# STRATEGY:
+# 1. Create a pool for each combination of encryption type and key format
+# 2. Verify that each filesystem has the correct properties set
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+log_onexit cleanup
+
+set -A ENCRYPTION_ALGS "encryption=on" \
+ "encryption=aes-128-ccm" \
+ "encryption=aes-192-ccm" \
+ "encryption=aes-256-ccm" \
+ "encryption=aes-128-gcm" \
+ "encryption=aes-192-gcm" \
+ "encryption=aes-256-gcm"
+
+set -A ENCRYPTION_PROPS "encryption=aes-256-gcm" \
+ "encryption=aes-128-ccm" \
+ "encryption=aes-192-ccm" \
+ "encryption=aes-256-ccm" \
+ "encryption=aes-128-gcm" \
+ "encryption=aes-192-gcm" \
+ "encryption=aes-256-gcm"
+
+set -A KEYFORMATS "keyformat=raw" \
+ "keyformat=hex" \
+ "keyformat=passphrase"
+
+set -A USER_KEYS "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" \
+ "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" \
+ "abcdefgh"
+
+log_assert "'zpool create' should create encrypted pools when using a valid" \
+ "encryption algorithm, key format, key location, and key."
+
+typeset -i i=0
+while (( i < ${#ENCRYPTION_ALGS[*]} )); do
+ typeset -i j=0
+ while (( j < ${#KEYFORMATS[*]} )); do
+ log_must eval "printf '%s' ${USER_KEYS[j]} | zpool create" \
+ "-O ${ENCRYPTION_ALGS[i]} -O ${KEYFORMATS[j]}" \
+ "$TESTPOOL $DISKS"
+
+ propertycheck $TESTPOOL ${ENCRYPTION_PROPS[i]} || \
+ log_fail "failed to set ${ENCRYPTION_ALGS[i]}"
+ propertycheck $TESTPOOL ${KEYFORMATS[j]} || \
+ log_fail "failed to set ${KEYFORMATS[j]}"
+
+ log_must zpool destroy $TESTPOOL
+ (( j = j + 1 ))
+ done
+ (( i = i + 1 ))
+done
+
+log_pass "'zpool create' creates encrypted pools when using a valid" \
+ "encryption algorithm, key format, key location, and key."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_encrypted.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_encrypted.ksh
new file mode 100755
index 000000000000..e521d8f1cff0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_encrypted.ksh
@@ -0,0 +1,100 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017, Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool create' should create an encrypted dataset only if it has a valid
+# combination of encryption properties set.
+#
+# enc = encryption
+# loc = keylocation provided
+# fmt = keyformat provided
+#
+# U = unspecified
+# N = off
+# Y = on
+#
+# enc fmt loc valid notes
+# -------------------------------------------
+# U 0 1 no no crypt specified
+# U 1 0 no no crypt specified
+# U 1 1 no no crypt specified
+# N 0 0 yes explicit no encryption
+# N 0 1 no keylocation given, but crypt off
+# N 1 0 no keyformat given, but crypt off
+# N 1 1 no keyformat given, but crypt off
+# Y 0 0 no no keyformat specified for new key
+# Y 0 1 no no keyformat specified for new key
+# Y 1 1 no unsupported combination of non-encryption props
+# Y 1 0 yes new encryption root
+# Y 1 1 yes new encryption root
+#
+# STRATEGY:
+# 1. Attempt to create a dataset using all combinations of encryption
+# properties
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+log_onexit cleanup
+
+log_assert "'zpool create' should create an encrypted dataset only if it" \
+ "has a valid combination of encryption properties set."
+
+log_mustnot zpool create -O keylocation=prompt $TESTPOOL $DISKS
+log_mustnot zpool create -O keyformat=passphrase $TESTPOOL $DISKS
+log_mustnot zpool create -O keyformat=passphrase -O keylocation=prompt \
+ $TESTPOOL $DISKS
+
+log_must zpool create -O encryption=off $TESTPOOL $DISKS
+log_must zpool destroy $TESTPOOL
+
+log_mustnot zpool create -O encryption=off -O keylocation=prompt \
+ $TESTPOOL $DISKS
+log_mustnot zpool create -O encryption=off -O keyformat=passphrase \
+ $TESTPOOL $DISKS
+log_mustnot zpool create -O encryption=off -O keyformat=passphrase \
+ -O keylocation=prompt $TESTPOOL $DISKS
+
+log_mustnot zpool create -O encryption=on $TESTPOOL $DISKS
+log_mustnot zpool create -O encryption=on -O keylocation=prompt \
+ $TESTPOOL $DISKS
+
+log_mustnot eval "echo $PASSPHRASE | zpool create -O encryption=on" \
+ "-O keyformat=passphrase -O keylocation=prompt" \
+ "-o feature@lz4_compress=disabled -O compression=lz4 $TESTPOOL $DISKS"
+
+log_must eval "echo $PASSPHRASE | zpool create -O encryption=on" \
+ "-O keyformat=passphrase $TESTPOOL $DISKS"
+log_must zpool destroy $TESTPOOL
+
+log_must eval "echo $PASSPHRASE | zpool create -O encryption=on" \
+ "-O keyformat=passphrase -O keylocation=prompt $TESTPOOL $DISKS"
+log_must zpool destroy $TESTPOOL
+
+log_pass "'zpool create' creates an encrypted dataset only if it has a" \
+ "valid combination of encryption properties set."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_001_pos.ksh
new file mode 100755
index 000000000000..67eff8edcf3b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_001_pos.ksh
@@ -0,0 +1,71 @@
+#!/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) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+################################################################################
+#
+# Newly created pools should have all features enabled.
+# Specifying a feature to be enabled with '-o' should be a no-op.
+#
+# 1. Create a new pool.
+# 2. Verify that every feature@ property is in the 'enabled' or 'active' state
+# 3. Destroy the pool and create a new pool with
+# '-o feature@async_destroy=enabled'
+# 4. Verify again.
+#
+################################################################################
+
+verify_runnable "global"
+
+function cleanup
+{
+ datasetexists $TESTPOOL && log_must zpool destroy $TESTPOOL
+}
+
+function check_features
+{
+ for state in $(zpool get all $TESTPOOL | \
+ awk '$2 ~ /feature@/ { print $3 }'); do
+ if [[ "$state" != "enabled" && "$state" != "active" ]]; then
+ log_fail "some features are not enabled on new pool"
+ fi
+ done
+}
+
+log_onexit cleanup
+
+log_assert "'zpool create' creates pools with all features enabled"
+
+log_must zpool create -f $TESTPOOL $DISKS
+check_features
+log_must zpool destroy -f $TESTPOOL
+
+log_must zpool create -f -o feature@async_destroy=enabled $TESTPOOL $DISKS
+check_features
+
+log_pass "'zpool create' creates pools with all features enabled"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_002_pos.ksh
new file mode 100755
index 000000000000..7ad4ae805565
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_002_pos.ksh
@@ -0,0 +1,70 @@
+#!/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) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+################################################################################
+#
+# When using the '-d' option or specifying '-o version=X' new pools should
+# have all features disabled.
+#
+# 1. Create a new pool with '-d'.
+# 2. Verify that every feature@ property is in the 'disabled' state
+# 3. Destroy pool and re-create with -o version=28
+# 4. Verify again.
+#
+################################################################################
+
+verify_runnable "global"
+
+function cleanup
+{
+ datasetexists $TESTPOOL && log_must zpool destroy $TESTPOOL
+}
+
+function check_features
+{
+ for prop in $(zpool get all $TESTPOOL | awk '$2 ~ /feature@/ { print $2 }'); do
+ state=$(zpool list -Ho "$prop" $TESTPOOL)
+ if [[ "$state" != "disabled" ]]; then
+ log_fail "$prop is enabled on new pool"
+ fi
+ done
+}
+
+log_onexit cleanup
+
+log_assert "'zpool create -d' creates pools with all features disabled"
+
+log_must zpool create -f -d $TESTPOOL $DISKS
+check_features
+log_must zpool destroy -f $TESTPOOL
+
+log_must zpool create -f -o version=28 $TESTPOOL $DISKS
+check_features
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_003_pos.ksh
new file mode 100755
index 000000000000..c72edffde67d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_003_pos.ksh
@@ -0,0 +1,70 @@
+#!/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) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+################################################################################
+#
+# When using the '-d' option with '-o feature@XXX=enabled' only the specified
+# feature is enabled.
+#
+# 1. Create a new pool with '-d' and '-o feature@async_destroy=enabled'.
+# async_destroy does not depend on anything so it should be the only
+# feature that gets enabled.
+# 2. Verify that every feature@ property except feature@async_destroy is in
+# the 'disabled' state
+#
+################################################################################
+
+verify_runnable "global"
+
+function cleanup
+{
+ datasetexists $TESTPOOL && log_must zpool destroy $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_assert "'zpool create -d -o feature@async_destroy=enabled' only " \
+ "enables async_destroy"
+
+log_must zpool create -f -d -o feature@async_destroy=enabled $TESTPOOL $DISKS
+
+state=$(zpool list -Ho feature@async_destroy $TESTPOOL)
+if [[ "$state" != "enabled" ]]; then
+ log_fail "async_destroy has state $state"
+fi
+
+for prop in $(zpool get all $TESTPOOL | awk '$2 ~ /feature@/ { print $2 }'); do
+ state=$(zpool list -Ho "$prop" $TESTPOOL)
+ if [[ "$prop" != "feature@async_destroy" \
+ && "$state" != "disabled" ]]; then
+ log_fail "$prop is enabled on new pool"
+ fi
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_004_neg.ksh
new file mode 100755
index 000000000000..5c6b29c4939e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_004_neg.ksh
@@ -0,0 +1,62 @@
+#!/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) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+################################################################################
+#
+# Specifying invalid feature names/states should cause the create to fail.
+#
+# 1. Try to create the pool with a variety of invalid feature names/states.
+# 2. Verify no pool was created.
+#
+################################################################################
+
+verify_runnable "global"
+
+properties="\
+feature@async_destroy=disable \
+feature@async_destroy=active \
+feature@xxx_fake_xxx=enabled \
+unsupported@some_feature=inactive \
+unsupported@some_feature=readonly \
+"
+
+function cleanup
+{
+ datasetexists $TESTPOOL && log_must zpool destroy $TESTPOOL
+}
+
+log_assert "'zpool create' with invalid feature names/states fails"
+log_onexit cleanup
+
+for prop in $properties; do
+ log_mustnot zpool create -f -o "$prop" $TESTPOOL $DISKS
+ log_mustnot datasetexists $TESTPOOL
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh
new file mode 100755
index 000000000000..a8ed95109f2a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh
@@ -0,0 +1,93 @@
+#!/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) 2012 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+################################################################################
+#
+# Specifically disabling a feature, all other features should be enabled.
+#
+# 1. Loop through all existing features:
+# a. Create a new pool with '-o feature@XXX=disabled'.
+# b. Verify that every other feature is 'enabled' or 'active'.
+#
+################################################################################
+
+verify_runnable "global"
+
+function cleanup
+{
+ datasetexists $TESTPOOL && log_must zpool destroy $TESTPOOL
+}
+
+function check_features
+{
+ typeset feature="${1}"
+
+ zpool get all ${TESTPOOL} | grep feature@ | while read line; do
+ set -- $(echo "${line}")
+
+ if [[ "feature@${feature}" == "${2}" ]]; then
+ # Failure passed feature must be disabled.
+ if [[ "${3}" != "disabled" ]]; then
+ return 1;
+ fi
+ else
+ # Failure other features must be enabled or active.
+ if [[ "${3}" != "enabled" && "${3}" != "active" ]]; then
+ return 2;
+ fi
+ fi
+ done
+
+ # All features enabled or active except the expected one.
+ return 0
+}
+
+log_onexit cleanup
+
+# Several representative features are tested to keep the test time short.
+# The features 'extensible_dataset' and 'enabled_txg' are intentionally
+# excluded because other features depend on them.
+set -A features \
+ "hole_birth" \
+ "large_blocks" \
+ "large_dnode" \
+ "userobj_accounting"
+
+typeset -i i=0
+while (( $i < ${#features[*]} )); do
+ log_assert "'zpool create' creates pools with ${features[i]} disabled"
+
+ log_must zpool create -f -o "feature@${features[i]}=disabled" \
+ $TESTPOOL $DISKS
+ log_must check_features "${features[i]}"
+ log_must zpool destroy -f $TESTPOOL
+ (( i = i+1 ))
+done
+
+log_pass "'zpool create -o feature@feature=disabled' disables features"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_tempname.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_tempname.ksh
new file mode 100755
index 000000000000..8fd1cea36e28
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_tempname.ksh
@@ -0,0 +1,70 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zpool create -t <tempname>' can create a pool with the specified temporary
+# name. The pool should be present in the namespace as <tempname> until exported
+#
+# STRATEGY:
+# 1. Create a pool with '-t' option
+# 2. Verify the pool is created with the specified temporary name
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset pool
+
+ for pool in $TESTPOOL $TEMPPOOL; do
+ poolexists $pool && destroy_pool $pool
+ done
+}
+
+log_assert "'zpool create -t <tempname>' can create a pool with the specified" \
+ " temporary name."
+log_onexit cleanup
+
+TEMPPOOL="tempname.$$"
+typeset poolprops=('comment=text' 'ashift=12' 'listsnapshots=on' 'autoexpand=on'
+ 'autoreplace=on' 'delegation=off' 'failmode=continue')
+typeset fsprops=('canmount=off' 'mountpoint=none' 'utf8only=on'
+ 'casesensitivity=mixed' 'version=1' 'normalization=formKD')
+
+for poolprop in "${poolprops[@]}"; do
+ for fsprop in "${fsprops[@]}"; do
+ # 1. Create a pool with '-t' option
+ log_must zpool create -t $TEMPPOOL -O $fsprop -o $poolprop \
+ $TESTPOOL $DISKS
+ # 2. Verify the pool is created with the specified temporary name
+ log_must poolexists $TEMPPOOL
+ log_mustnot poolexists $TESTPOOL
+ propname="$(awk -F= '{print $1}' <<< $fsprop)"
+ propval="$(awk -F= '{print $2}' <<< $fsprop)"
+ log_must test "$(get_prop $propname $TEMPPOOL)" == "$propval"
+ propname="$(awk -F= '{print $1}' <<< $poolprop)"
+ propval="$(awk -F= '{print $2}' <<< $poolprop)"
+ log_must test "$(get_pool_prop $propname $TEMPPOOL)" == "$propval"
+ # Cleanup
+ destroy_pool $TEMPPOOL
+ done
+done
+
+log_pass "'zpool create -t <tempname>' successfully creates pools with" \
+ " temporary names"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/Makefile.am
new file mode 100644
index 000000000000..7f9e00d5826f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/Makefile.am
@@ -0,0 +1,8 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_destroy
+dist_pkgdata_SCRIPTS = \
+ zpool_destroy_001_pos.ksh \
+ zpool_destroy_002_pos.ksh \
+ zpool_destroy_003_neg.ksh
+
+dist_pkgdata_DATA = \
+ zpool_destroy.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy.cfg
new file mode 100644
index 000000000000..bf6026747f9a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy.cfg
@@ -0,0 +1,37 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+export DISK_ARRAY_NUM=$(echo ${DISKS} | nawk '{print NF}')
+export DISKSARRAY=$DISKS
+echo $DISKS | read DISK0 DISK1
+
+if is_linux; then
+ set_device_dir
+fi
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_001_pos.ksh
new file mode 100755
index 000000000000..3323f1db0caf
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_001_pos.ksh
@@ -0,0 +1,86 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_destroy/zpool_destroy.cfg
+
+
+#
+# DESCRIPTION:
+# 'zpool destroy <pool>' can successfully destroy the specified pool.
+#
+# STRATEGY:
+# 1. Create a storage pool
+# 2. Destroy the pool
+# 3. Verify the is destroyed successfully
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL2 && destroy_pool $TESTPOOL2
+ datasetexists $TESTPOOL1/$TESTVOL && \
+ log_must zfs destroy -f $TESTPOOL1/$TESTVOL
+
+ typeset pool
+ for pool in $TESTPOOL1 $TESTPOOL; do
+ poolexists $pool && destroy_pool $pool
+ done
+
+ [ -n "$recursive" ] && set_tunable64 VOL_RECURSIVE $recursive
+}
+
+set -A datasets "$TESTPOOL" "$TESTPOOL2"
+
+log_assert "'zpool destroy <pool>' can destroy a specified pool."
+
+log_onexit cleanup
+
+create_pool $TESTPOOL $DISK0
+create_pool $TESTPOOL1 $DISK1
+log_must zfs create -s -V $VOLSIZE $TESTPOOL1/$TESTVOL
+block_device_wait
+if is_freebsd; then
+ typeset recursive=$(get_tunable VOL_RECURSIVE)
+ log_must set_tunable64 VOL_RECURSIVE 1
+fi
+create_pool $TESTPOOL2 $ZVOL_DEVDIR/$TESTPOOL1/$TESTVOL
+
+typeset -i i=0
+while (( i < ${#datasets[*]} )); do
+ log_must poolexists "${datasets[i]}"
+ log_must zpool destroy "${datasets[i]}"
+ log_mustnot poolexists "${datasets[i]}"
+ ((i = i + 1))
+done
+
+log_pass "'zpool destroy <pool>' executes successfully"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_002_pos.ksh
new file mode 100755
index 000000000000..794a6c37c37a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_002_pos.ksh
@@ -0,0 +1,117 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_destroy/zpool_destroy.cfg
+
+#
+# DESCRIPTION:
+# 'zpool destroy -f <pool>' can forcely destroy the specified pool.
+#
+# STRATEGY:
+# 1. Create a storage pool
+# 2. Create some datasets within the pool
+# 3. Change directory to any mountpoint of these datasets,
+# Verify 'zpool destroy' without '-f' will fail.
+# 4. 'zpool destroy -f' the pool
+# 5. Verify the pool is destroyed successfully
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ [[ -n $cwd ]] && log_must cd $cwd
+
+ if [[ -d $TESTDIR ]]; then
+ ismounted $TESTDIR && log_must umount $TESTDIR
+ log_must rm -rf $TESTDIR
+ fi
+
+ typeset -i i=0
+ while (( $i < ${#datasets[*]} )); do
+ datasetexists ${datasets[i]} && \
+ log_must zfs destroy ${datasets[i]}
+ (( i = i + 1 ))
+ done
+
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+set -A datasets "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTCTR/$TESTFS1" \
+ "$TESTPOOL/$TESTCTR" "$TESTPOOL/$TESTVOL" \
+
+log_assert "'zpool destroy -f <pool>' can forcely destroy the specified pool"
+
+log_onexit cleanup
+
+create_pool $TESTPOOL $DISK0
+log_must zfs create $TESTPOOL/$TESTFS
+log_must mkdir -p $TESTDIR
+log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+log_must zfs create $TESTPOOL/$TESTCTR
+log_must zfs create $TESTPOOL/$TESTCTR/$TESTFS1
+log_must zfs create -V $VOLSIZE $TESTPOOL/$TESTVOL
+
+typeset -i i=0
+while (( $i < ${#datasets[*]} )); do
+ datasetexists "${datasets[i]}" || \
+ log_fail "Create datasets fail."
+ ((i = i + 1))
+done
+
+log_note "'zpool destroy' without '-f' will fail " \
+ "while pool is busy."
+
+for dir in $TESTDIR /$TESTPOOL/$TESTCTR /$TESTPOOL/$TESTCTR/$TESTFS1 ; do
+ log_must cd $dir
+ log_mustnot zpool destroy $TESTPOOL
+
+ # Need mount here, otherwise some dataset may be unmounted.
+ log_must zfs mount -a
+
+ i=0
+ while (( i < ${#datasets[*]} )); do
+ datasetexists "${datasets[i]}" || \
+ log_fail "Dataset ${datasets[i]} removed unexpected."
+ ((i = i + 1))
+ done
+done
+
+# 4. 'zpool destroy -f' the pool (unsupported behavior in Linux)
+if is_linux; then
+ log_must cd $cwd
+fi
+
+destroy_pool $TESTPOOL
+log_mustnot poolexists "$TESTPOOL"
+
+log_pass "'zpool destroy -f <pool>' success."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_003_neg.ksh
new file mode 100755
index 000000000000..75b77b4bde72
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_destroy/zpool_destroy_003_neg.ksh
@@ -0,0 +1,57 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zpool destroy' should return an error with badly formed parameters,
+#
+# STRATEGY:
+# 1. Create an array of parameters
+# 2. For each parameter in the array, execute 'zpool destroy'
+# 3. Verify an error is returned.
+#
+
+verify_runnable "global"
+
+set -A args "" "-f" "-? $TESTPOOL" "nonexistent_pool" \
+ "$TESTPOOL abcd" "abcd $TESTPOOL"
+
+log_assert "'zpool destroy' should return an error with badly-formed parameters."
+
+typeset -i i=0
+while (( $i < ${#args[*]} )); do
+ log_mustnot zpool destroy ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "'zpool destroy' badly formed parameters fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_detach/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_detach/Makefile.am
new file mode 100644
index 000000000000..b22018c1d550
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_detach/Makefile.am
@@ -0,0 +1,5 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_detach
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_detach_001_neg.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_detach/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_detach/cleanup.ksh
new file mode 100755
index 000000000000..89c146249e71
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_detach/cleanup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_detach/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_detach/setup.ksh
new file mode 100755
index 000000000000..2229f87e6208
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_detach/setup.ksh
@@ -0,0 +1,35 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+DISK=${DISKS%% *}
+
+default_mirror_setup $DISKS
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_detach/zpool_detach_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_detach/zpool_detach_001_neg.ksh
new file mode 100755
index 000000000000..74f8e1e664fa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_detach/zpool_detach_001_neg.ksh
@@ -0,0 +1,70 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Executing 'zpool detach' command with bad options fails.
+#
+# STRATEGY:
+# 1. Create an array of badly formed 'zpool detach' options.
+# 2. Execute each element of the array.
+# 3. Verify an error code is returned.
+#
+
+verify_runnable "global"
+
+DISKLIST=$(get_disklist $TESTPOOL)
+
+set -A args "" "-?" "-t fakepool" "-f fakepool" "-ev fakepool" "fakepool" \
+ "$TESTPOOL" "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTFS $DISKLIST" \
+ "$TESTPOOL/$TESTCTR" "$TESTPOOL/$TESTCTR/$TESTFS1" \
+ "$TESTPOOL/$TESTCTR $DISKLIST" "$TESTPOOL/$TESTVOL" \
+ "$TESTPOOL/$TESTCTR/$TESTFS1 $DISKLIST" "$TESTPOOL/$TESTVOL $DISKLIST" \
+ "$DISKLIST"
+
+log_assert "Executing 'zpool detach' with bad options fails"
+
+if [[ -z $DISKLIST ]]; then
+ log_fail "DISKLIST is empty."
+fi
+
+typeset -i i=0
+
+while [[ $i -lt ${#args[*]} ]]; do
+
+ log_mustnot zpool detach ${args[$i]}
+
+ (( i = i + 1 ))
+done
+
+log_pass "'zpool detach' command with bad options failed as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_events/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_events/Makefile.am
new file mode 100644
index 000000000000..7fb6e4f7a5c2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_events/Makefile.am
@@ -0,0 +1,13 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_events
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_events_clear.ksh \
+ zpool_events_cliargs.ksh \
+ zpool_events_follow.ksh \
+ zpool_events_poolname.ksh \
+ zpool_events_errors.ksh
+
+dist_pkgdata_DATA = \
+ zpool_events.cfg \
+ zpool_events.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_events/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_events/cleanup.ksh
new file mode 100755
index 000000000000..1adac153d740
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_events/cleanup.ksh
@@ -0,0 +1,19 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_events/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_events/setup.ksh
new file mode 100755
index 000000000000..e37841addf88
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_events/setup.ksh
@@ -0,0 +1,21 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_volume_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events.cfg
new file mode 100644
index 000000000000..6018f9d2fd97
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events.cfg
@@ -0,0 +1,16 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+export EVENTS_NUM=42
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events.kshlib b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events.kshlib
new file mode 100644
index 000000000000..b92ffb13a852
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events.kshlib
@@ -0,0 +1,39 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_events/zpool_events.cfg
+
+#
+# Wait to allow the kernel module to process ZFS events until we reach $eventnum
+# or a timeout of $timeout seconds expire, whichever comes first
+#
+function zpool_events_settle # <eventnum> [timeout]
+{
+ typeset eventnum="${1:-$EVENTS_NUM}"
+ typeset timeout="${2:-3}"
+ typeset -i count
+ typeset -i i=0
+
+ while [[ $i -lt $timeout ]]; do
+ count=$(zpool events -H | wc -l)
+ if [[ $count -ge $eventnum ]]; then
+ break
+ fi
+ i=$((i+1))
+ sleep 1
+ done
+ log_note "waited $i seconds"
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_clear.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_clear.ksh
new file mode 100755
index 000000000000..054d39be3fe9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_clear.ksh
@@ -0,0 +1,58 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_events/zpool_events.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool events -c' should successfully clear events.
+#
+# STRATEGY:
+# 1. Clear all ZFS events
+# 2. Generate some new ZFS events
+# 3. Verify 'zpool events -c' successfully clears new events
+#
+
+verify_runnable "both"
+
+log_assert "'zpool events -c' should successfully clear events."
+
+# 1. Clear all ZFS events
+# This is needed because we may already over the max number or events queued
+# (zfs_zevent_len_max) generated by previous tests: generating $EVENTS_NUM new
+# events and then counting them is racy and leads to failures, so start from 0.
+log_must zpool events -c
+
+# 2. Generate some new ZFS events
+for i in `seq 1 $EVENTS_NUM`; do
+ log_must zpool clear $TESTPOOL
+done
+# wait a bit to allow the kernel module to process new events
+zpool_events_settle
+EVENTS_NUM=$(zpool events -H | wc -l | xargs)
+
+# 3. Verify 'zpool events -c' successfully clear new events
+CLEAR_OUTPUT=$(zpool events -c)
+if [[ "$CLEAR_OUTPUT" != "cleared $EVENTS_NUM events" ]]; then
+ log_fail "Failed to clear $EVENTS_NUM events: $CLEAR_OUTPUT"
+fi
+EVENTS_NUM=$(zpool events -H | wc -l)
+if [[ $EVENTS_NUM -ne 0 ]]; then
+ log_fail "Unexpected events number: $EVENTS_NUM != 0"
+fi
+
+log_pass "'zpool events -c' successfully clears events."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_cliargs.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_cliargs.ksh
new file mode 100755
index 000000000000..1623a18e4740
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_cliargs.ksh
@@ -0,0 +1,89 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zpool events' should only work with supported options.
+#
+# STRATEGY:
+# 1. Verify every supported option is accepted
+# 2. Verify supported options raise an error with unsupported arguments
+# 3. Verify other unsupported options raise an error
+#
+
+verify_runnable "both"
+
+function log_must_follow # <command>
+{
+ typeset command="$1"
+
+ log_must eval "$command > /dev/null &"
+ pid=$!
+ sleep 3
+ kill $pid
+ if [[ $? -ne 0 ]]; then
+ log_fail "'$command' does not work as expected."
+ else
+ log_note "'$command' works successfully."
+ fi
+}
+
+log_assert "'zpool events' should only work with supported options."
+
+typeset goodopts=("" "-v" "-H" "-f" "-vH" "-vf" "-Hf" "-vHf")
+typeset badopts=("-vV" "-Hh" "-fF" "-cC" "-x" "-o" "-")
+
+# 1. Verify every supported option is accepted
+for opt in ${goodopts[@]}
+do
+ # when in 'follow' mode we can't use log_must()
+ if [[ $opt =~ 'f' ]]; then
+ log_must_follow "zpool events $opt"
+ log_must_follow "zpool events $opt $TESTPOOL"
+ else
+ log_must eval "zpool events $opt > /dev/null"
+ log_must eval "zpool events $opt $TESTPOOL > /dev/null"
+ fi
+done
+
+# 2.1 Verify supported options raise an error with unsupported arguments
+for opt in ${goodopts[@]}
+do
+ log_mustnot zpool events $opt "/tmp/"
+ log_mustnot zpool events $opt "$TESTPOOL/fs"
+ log_mustnot zpool events $opt "$TESTPOOL@snap"
+ log_mustnot zpool events $opt "$TESTPOOL#bm"
+ log_mustnot zpool events $opt "$TESTPOOL" "$TESTPOOL"
+done
+
+# 2.2 Additionally, 'zpool events -c' does not support any other option|argument
+log_must eval "zpool events -c > /dev/null"
+log_mustnot zpool events -c "$TESTPOOL"
+for opt in ${goodopts[@]}
+do
+ log_mustnot zpool events -c $opt
+done
+
+# 3. Verify other unsupported options raise an error
+for opt in ${badopts[@]}
+do
+ log_mustnot zpool events $opt
+ log_mustnot zpool events $opt "$TESTPOOL"
+done
+
+log_pass "'zpool events' only works with supported options."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_errors.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_errors.ksh
new file mode 100755
index 000000000000..4645e245c973
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_errors.ksh
@@ -0,0 +1,152 @@
+#!/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) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Verify the number of IO and checksum events match the error counters
+# in zpool status.
+#
+# STRATEGY:
+# 1. Create a raidz or mirror pool
+# 2. Inject read/write IO errors or checksum errors
+# 3. Verify the number of errors in zpool status match the corresponding
+# number of error events.
+# 4. Repeat for all combinations of raidz/mirror and io/checksum errors.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+
+MOUNTDIR=$TEST_BASE_DIR/mount
+VDEV1=$TEST_BASE_DIR/file1
+VDEV2=$TEST_BASE_DIR/file2
+VDEV3=$TEST_BASE_DIR/file3
+POOL=error_pool
+FILESIZE=$((20 * 1024 * 1024))
+OLD_CHECKSUMS=$(get_tunable CHECKSUM_EVENTS_PER_SECOND)
+OLD_LEN_MAX=$(get_tunable ZEVENT_LEN_MAX)
+
+function cleanup
+{
+ log_must set_tunable64 CHECKSUM_EVENTS_PER_SECOND $OLD_CHECKSUMS
+ log_must set_tunable64 ZEVENT_LEN_MAX $OLD_LEN_MAX
+
+ log_must zinject -c all
+ log_must zpool events -c
+ if poolexists $POOL ; then
+ log_must destroy_pool $POOL
+ fi
+ log_must rm -f $VDEV1 $VDEV2 $VDEV3
+}
+
+log_assert "Check that the number of zpool errors match the number of events"
+
+log_onexit cleanup
+
+# Set our thresholds high so we never ratelimit or drop events.
+set_tunable64 CHECKSUM_EVENTS_PER_SECOND 20000
+set_tunable64 ZEVENT_LEN_MAX 20000
+
+log_must truncate -s $MINVDEVSIZE $VDEV1 $VDEV2 $VDEV3
+log_must mkdir -p $MOUNTDIR
+
+# Run error test on a specific type of pool
+#
+# $1: pool - raidz, mirror
+# $2: test type - corrupt (checksum error), io
+# $3: read, write
+function do_test
+{
+ POOLTYPE=$1
+ ERR=$2
+ RW=$3
+
+ log_note "Testing $ERR $RW on $POOLTYPE"
+ log_must zpool create -f -m $MOUNTDIR -o failmode=continue $POOL $POOLTYPE $VDEV1 $VDEV2 $VDEV3
+ log_must zpool events -c
+ log_must zfs set compression=off $POOL
+
+ if [ "$RW" == "read" ] ; then
+ log_must mkfile $FILESIZE $MOUNTDIR/file
+ fi
+
+ log_must zinject -d $VDEV1 -e $ERR -T $RW -f 100 $POOL
+
+ if [ "$RW" == "write" ] ; then
+ log_must mkfile $FILESIZE $MOUNTDIR/file
+ log_must zpool sync $POOL
+ else
+ log_must zpool scrub $POOL
+ wait_scrubbed $POOL
+ fi
+
+ log_must zinject -c all
+
+ # Wait for the pool to settle down and finish resilvering (if
+ # necessary). We want the errors to stop incrementing before we
+ # check the error and event counts.
+ while is_pool_resilvering $POOL ; do
+ sleep 1
+ done
+
+ out="$(zpool status -p | grep $VDEV1)"
+
+ if [ "$ERR" == "corrupt" ] ; then
+ events=$(zpool events | grep checksum | wc -l)
+ val=$(echo "$out" | awk '{print $5}')
+ str="checksum"
+ elif [ "$ERR" == "io" ] ; then
+ allevents=$(zpool events | grep io)
+ events=$(echo "$allevents" | wc -l)
+ if [ "$RW" == "read" ] ; then
+ str="read IO"
+ val=$(echo "$out" | awk '{print $3}')
+ else
+ str="write IO"
+ val=$(echo "$out" | awk '{print $4}')
+ fi
+ fi
+
+ if [ -z "$val" -o $val -eq 0 -o -z "$events" -o $events -eq 0 ] ; then
+ log_fail "Didn't see any errors or events ($val/$events)"
+ fi
+
+ if [ $val -ne $events ] ; then
+ log_fail "$val $POOLTYPE $str errors != $events events"
+ else
+ log_note "$val $POOLTYPE $str errors == $events events"
+ fi
+
+ log_must zpool destroy $POOL
+}
+
+# Test all types of errors on mirror and raidz pools
+for pooltype in mirror raidz ; do
+ do_test $pooltype corrupt read
+ do_test $pooltype io read
+ do_test $pooltype io write
+done
+
+log_pass "The number of errors matched the number of events"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_follow.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_follow.ksh
new file mode 100755
index 000000000000..258de033b86c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_follow.ksh
@@ -0,0 +1,64 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_events/zpool_events.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool events -f' should successfully follow new events.
+#
+# STRATEGY:
+# 1. Clear all ZFS events
+# 2. Run 'zpool events -f' in background, saving its output to a temporary file
+# 3. Generate some ZFS events
+# 4. Verify 'zpool events -f' successfully recorded these new events
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ [[ -n $pid ]] && kill $pid 2>/dev/null
+ rm -f $EVENTS_FILE
+}
+
+log_assert "'zpool events -f' should follow new events."
+log_onexit cleanup
+
+EVENTS_FILE="$TESTDIR/zpool_events.$$"
+
+# 1. Clear all ZFS events
+log_must zpool events -c
+
+# 2. Run 'zpool events -f' in background, saving its output to a temporary file
+log_must eval "zpool events -H -f > $EVENTS_FILE &"
+pid=$!
+
+# 3. Generate some ZFS events
+for i in `seq 1 $EVENTS_NUM`; do
+ log_must zpool clear $TESTPOOL
+done
+# wait a bit to allow the kernel module to process new events
+zpool_events_settle
+
+# 4. Verify 'zpool events -f' successfully recorded these new events
+EVENTS_LOG=$(cat $EVENTS_FILE | wc -l)
+if [[ $EVENTS_LOG -ne $EVENTS_NUM ]]; then
+ log_fail "Unexpected number of events: $EVENTS_LOG != $EVENTS_NUM"
+fi
+
+log_pass "'zpool events -f' successfully follows new events."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_poolname.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_poolname.ksh
new file mode 100755
index 000000000000..42c46712f3d9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_events/zpool_events_poolname.ksh
@@ -0,0 +1,74 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_events/zpool_events.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool events poolname' should only display events from the chosen pool.
+#
+# STRATEGY:
+# 1. Create an additional pool
+# 2. Clear all ZFS events
+# 3. Generate some ZFS events on both pools
+# 4. Verify 'zpool events poolname' successfully display events
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_pool $NEWPOOL
+ rm -f $DISK
+}
+
+log_assert "'zpool events poolname' should only display events from poolname."
+log_onexit cleanup
+
+NEWPOOL="newpool"
+DISK="$TEST_BASE_DIR/$NEWPOOL.dat"
+
+# 1. Create an additional pool
+log_must truncate -s $MINVDEVSIZE $DISK
+log_must zpool create $NEWPOOL $DISK
+
+# 2. Clear all ZFS events
+log_must zpool events -c
+
+# 3. Generate some ZFS events on both pools
+for i in `seq 1 $EVENTS_NUM`; do
+ log_must zpool clear $TESTPOOL
+done
+for i in `seq 1 $EVENTS_NUM`; do
+ log_must zpool clear $NEWPOOL
+done
+# wait a bit to allow the kernel module to process new events
+zpool_events_settle
+
+# 4. Verify 'zpool events poolname' successfully display events
+zpool events -v $TESTPOOL |
+ awk -v POOL=$TESTPOOL '/pool = / {if ($3 != "\""POOL"\"") exit 1}'
+if [[ $? -ne 0 ]]; then
+ log_fail "Unexpected events for pools other than $TESTPOOL"
+fi
+zpool events -v $NEWPOOL |
+ awk -v POOL=$NEWPOOL '/pool = / {if ($3 != "\""POOL"\"") exit 1}'
+if [[ $? -ne 0 ]]; then
+ log_fail "Unexpected events for pools other than $NEWPOOL"
+fi
+
+log_pass "'zpool events poolname' display events only from the chosen pool."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/Makefile.am
new file mode 100644
index 000000000000..beaa411e37cb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/Makefile.am
@@ -0,0 +1,12 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_expand
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_expand_001_pos.ksh \
+ zpool_expand_002_pos.ksh \
+ zpool_expand_003_neg.ksh \
+ zpool_expand_004_pos.ksh \
+ zpool_expand_005_pos.ksh
+
+dist_pkgdata_DATA = \
+ zpool_expand.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/cleanup.ksh
new file mode 100755
index 000000000000..059c3839050b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/cleanup.ksh
@@ -0,0 +1,35 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+zed_stop
+zed_cleanup
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/setup.ksh
new file mode 100755
index 000000000000..9832a441c20b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/setup.ksh
@@ -0,0 +1,46 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+#
+# The pool expansion tests depend on udev change events being generated
+# when block devices change capacity. Since this functionality wasn't
+# available until the 2.6.38 kernel skip this test group.
+#
+if [[ $(linux_version) -lt $(linux_version "2.6.38") ]]; then
+ log_unsupported "Requires block device udev change events"
+fi
+
+zed_setup
+zed_start
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand.cfg
new file mode 100644
index 000000000000..bec5fb1638aa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand.cfg
@@ -0,0 +1,37 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+
+export org_size=$((1024*1024*1024))
+export exp_size=$((2*1024*1024*1024))
+export org_size_mb=$((org_size/(1024*1024)))
+
+export FILE_LO=$TEST_BASE_DIR/vdev_lo
+export FILE_RAW=$TEST_BASE_DIR/vdev_raw
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_001_pos.ksh
new file mode 100755
index 000000000000..f39e6267bc3a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_001_pos.ksh
@@ -0,0 +1,167 @@
+#! /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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+# Copyright (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_expand/zpool_expand.cfg
+
+#
+# DESCRIPTION:
+# Once zpool set autoexpand=on poolname, zpool can autoexpand by
+# Dynamic VDEV Expansion
+#
+#
+# STRATEGY:
+# 1) Create three vdevs (loopback, scsi_debug, and file)
+# 2) Create pool by using the different devices and set autoexpand=on
+# 3) Expand each device as appropriate
+# 4) Check that the pool size was expanded
+#
+# NOTE: Three different device types are used in this test to verify
+# expansion of non-partitioned block devices (loopback), partitioned
+# block devices (scsi_debug), and non-disk file vdevs. ZFS volumes
+# are not used in order to avoid a possible lock inversion when
+# layering pools on zvols.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+
+ if losetup -a | grep -q $DEV1; then
+ losetup -d $DEV1
+ fi
+
+ rm -f $FILE_LO $FILE_RAW
+
+ block_device_wait
+ unload_scsi_debug
+}
+
+log_onexit cleanup
+
+log_assert "zpool can be autoexpanded after set autoexpand=on on vdev expansion"
+
+for type in " " mirror raidz raidz2; do
+ log_note "Setting up loopback, scsi_debug, and file vdevs"
+ log_must truncate -s $org_size $FILE_LO
+ DEV1=$(losetup -f)
+ log_must losetup $DEV1 $FILE_LO
+
+ load_scsi_debug $org_size_mb 1 1 1 '512b'
+ block_device_wait
+ DEV2=$(get_debug_device)
+
+ log_must truncate -s $org_size $FILE_RAW
+ DEV3=$FILE_RAW
+
+ # The -f is required since we're mixing disk and file vdevs.
+ log_must zpool create -f -o autoexpand=on $TESTPOOL1 $type \
+ $DEV1 $DEV2 $DEV3
+
+ typeset autoexp=$(get_pool_prop autoexpand $TESTPOOL1)
+ if [[ $autoexp != "on" ]]; then
+ log_fail "zpool $TESTPOOL1 autoexpand should be on but is " \
+ "$autoexp"
+ fi
+
+ typeset prev_size=$(get_pool_prop size $TESTPOOL1)
+ typeset zfs_prev_size=$(get_prop avail $TESTPOOL1)
+
+ # Expand each device as appropriate being careful to add an artificial
+ # delay to ensure we get a single history entry for each. This makes
+ # is easier to verify each expansion for the striped pool case, since
+ # they will not be merged in to a single larger expansion.
+ log_note "Expanding loopback, scsi_debug, and file vdevs"
+ log_must truncate -s $exp_size $FILE_LO
+ log_must losetup -c $DEV1
+ sleep 3
+
+ echo "2" > /sys/bus/pseudo/drivers/scsi_debug/virtual_gb
+ echo "1" > /sys/class/block/$DEV2/device/rescan
+ block_device_wait
+ sleep 3
+
+ log_must truncate -s $exp_size $FILE_RAW
+ log_must zpool online -e $TESTPOOL1 $FILE_RAW
+
+ typeset expand_size=$(get_pool_prop size $TESTPOOL1)
+ typeset zfs_expand_size=$(get_prop avail $TESTPOOL1)
+
+ log_note "$TESTPOOL1 $type has previous size: $prev_size and " \
+ "expanded size: $expand_size"
+ # compare available pool size from zfs
+ if [[ $zfs_expand_size -gt $zfs_prev_size ]]; then
+ # check for zpool history for the pool size expansion
+ if [[ $type == " " ]]; then
+ typeset expansion_size=$(($exp_size-$org_size))
+ typeset size_addition=$(zpool history -il $TESTPOOL1 |\
+ grep "pool '$TESTPOOL1' size:" | \
+ grep "vdev online" | \
+ grep "(+${expansion_size}" | wc -l)
+
+ if [[ $size_addition -ne 3 ]]; then
+ log_fail "pool $TESTPOOL1 has not expanded, " \
+ "$size_addition/3 vdevs expanded"
+ fi
+ elif [[ $type == "mirror" ]]; then
+ typeset expansion_size=$(($exp_size-$org_size))
+ zpool history -il $TESTPOOL1 | \
+ grep "pool '$TESTPOOL1' size:" | \
+ grep "vdev online" | \
+ grep "(+${expansion_size})" >/dev/null 2>&1
+
+ if [[ $? -ne 0 ]] ; then
+ log_fail "pool $TESTPOOL1 has not expanded"
+ fi
+ else
+ typeset expansion_size=$((3*($exp_size-$org_size)))
+ zpool history -il $TESTPOOL1 | \
+ grep "pool '$TESTPOOL1' size:" | \
+ grep "vdev online" | \
+ grep "(+${expansion_size})" >/dev/null 2>&1
+
+ if [[ $? -ne 0 ]]; then
+ log_fail "pool $TESTPOOL has not expanded"
+ fi
+ fi
+ else
+ log_fail "pool $TESTPOOL1 is not autoexpanded after vdev " \
+ "expansion. Previous size: $zfs_prev_size and expanded " \
+ "size: $zfs_expand_size"
+ fi
+
+ cleanup
+done
+
+log_pass "zpool can autoexpand if autoexpand=on after vdev expansion"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_002_pos.ksh
new file mode 100755
index 000000000000..a49d4fc17068
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_002_pos.ksh
@@ -0,0 +1,168 @@
+#! /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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2018 by Delphix. All rights reserved.
+# Copyright (c) 2017 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_expand/zpool_expand.cfg
+
+#
+# DESCRIPTION:
+# After zpool online -e poolname zvol vdevs, zpool can autoexpand by
+# Dynamic VDEV Expansion
+#
+#
+# STRATEGY:
+# 1) Create 3 files
+# 2) Create a pool backed by the files
+# 3) Expand the files' size with truncate
+# 4) Use zpool reopen to check the expandsize
+# 5) Use zpool online -e to online the vdevs
+# 6) Check that the pool size was expanded
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+
+ for i in 1 2 3; do
+ [ -e ${TEMPFILE}.$i ] && log_must rm ${TEMPFILE}.$i
+ done
+}
+
+log_onexit cleanup
+
+log_assert "zpool can expand after zpool online -e zvol vdevs on vdev expansion"
+
+for type in " " mirror raidz raidz2; do
+ # Initialize the file devices and the pool
+ for i in 1 2 3; do
+ log_must truncate -s $org_size ${TEMPFILE}.$i
+ done
+
+ log_must zpool create $TESTPOOL1 $type $TEMPFILE.1 \
+ $TEMPFILE.2 $TEMPFILE.3
+
+ typeset autoexp=$(get_pool_prop autoexpand $TESTPOOL1)
+
+ if [[ $autoexp != "off" ]]; then
+ log_fail "zpool $TESTPOOL1 autoexpand should be off but is " \
+ "$autoexp"
+ fi
+ typeset prev_size=$(get_pool_prop size $TESTPOOL1)
+ typeset zfs_prev_size=$(get_prop avail $TESTPOOL1)
+
+ # Increase the size of the file devices
+ for i in 1 2 3; do
+ log_must truncate -s $exp_size ${TEMPFILE}.$i
+ done
+
+ # Reopen the pool and check that the `expandsize` property is set
+ log_must zpool reopen $TESTPOOL1
+ typeset zpool_expandsize=$(get_pool_prop expandsize $TESTPOOL1)
+
+ if [[ $type == "mirror" ]]; then
+ typeset expected_zpool_expandsize=$(($exp_size-$org_size))
+ else
+ typeset expected_zpool_expandsize=$((3*($exp_size-$org_size)))
+ fi
+
+ if [[ "$zpool_expandsize" = "-" ]]; then
+ log_fail "pool $TESTPOOL1 did not detect any " \
+ "expandsize after reopen"
+ fi
+
+ if [[ $zpool_expandsize -ne $expected_zpool_expandsize ]]; then
+ log_fail "pool $TESTPOOL1 did not detect correct " \
+ "expandsize after reopen: found $zpool_expandsize," \
+ "expected $expected_zpool_expandsize"
+ fi
+
+ # Online the devices to add the new space to the pool. Add an
+ # artificial delay between online commands order to prevent them
+ # from being merged in to a single history entry. This makes
+ # is easier to verify each expansion for the striped pool case.
+ for i in 1 2 3; do
+ log_must zpool online -e $TESTPOOL1 ${TEMPFILE}.$i
+ sleep 3
+ done
+
+ typeset expand_size=$(get_pool_prop size $TESTPOOL1)
+ typeset zfs_expand_size=$(get_prop avail $TESTPOOL1)
+ log_note "$TESTPOOL1 $type has previous size: $prev_size and " \
+ "expanded size: $expand_size"
+
+ # compare available pool size from zfs
+ if [[ $zfs_expand_size -gt $zfs_prev_size ]]; then
+ # check for zpool history for the pool size expansion
+ if [[ $type == " " ]]; then
+ typeset expansion_size=$(($exp_size-$org_size))
+ typeset size_addition=$(zpool history -il $TESTPOOL1 \
+ | grep "pool '$TESTPOOL1' size:" | \
+ grep "vdev online" | \
+ grep "(+${expansion_size}" | wc -l)
+
+ if [[ $size_addition -ne $i ]]; then
+ log_fail "pool $TESTPOOL1 has not expanded " \
+ "after zpool online -e, " \
+ "$size_addition/3 vdevs expanded"
+ fi
+ elif [[ $type == "mirror" ]]; then
+ typeset expansion_size=$(($exp_size-$org_size))
+ zpool history -il $TESTPOOL1 | \
+ grep "pool '$TESTPOOL1' size:" | \
+ grep "vdev online" | \
+ grep "(+${expansion_size})" >/dev/null 2>&1
+
+ if [[ $? -ne 0 ]]; then
+ log_fail "pool $TESTPOOL1 has not expanded " \
+ "after zpool online -e"
+ fi
+ else
+ typeset expansion_size=$((3*($exp_size-$org_size)))
+ zpool history -il $TESTPOOL1 | \
+ grep "pool '$TESTPOOL1' size:" | \
+ grep "vdev online" | \
+ grep "(+${expansion_size})" >/dev/null 2>&1
+
+ if [[ $? -ne 0 ]] ; then
+ log_fail "pool $TESTPOOL1 has not expanded " \
+ "after zpool online -e"
+ fi
+ fi
+ else
+ log_fail "pool $TESTPOOL1 did not expand after vdev expansion " \
+ "and zpool online -e"
+ fi
+ log_must zpool destroy $TESTPOOL1
+done
+log_pass "zpool can expand after zpool online -e"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_003_neg.ksh
new file mode 100755
index 000000000000..323d0b907bd0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_003_neg.ksh
@@ -0,0 +1,138 @@
+#! /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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+# Copyright (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_expand/zpool_expand.cfg
+
+#
+# Description:
+# Once set zpool autoexpand=off, zpool can *NOT* autoexpand by
+# Dynamic VDEV Expansion
+#
+#
+# STRATEGY:
+# 1) Create three vdevs (loopback, scsi_debug, and file)
+# 2) Create pool by using the different devices and set autoexpand=off
+# 3) Expand each device as appropriate
+# 4) Check that the pool size is not expanded
+#
+# NOTE: Three different device types are used in this test to verify
+# expansion of non-partitioned block devices (loopback), partitioned
+# block devices (scsi_debug), and non-disk file vdevs. ZFS volumes
+# are not used in order to avoid a possible lock inversion when
+# layering pools on zvols.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+
+ if losetup -a | grep -q $DEV1; then
+ losetup -d $DEV1
+ fi
+
+ rm -f $FILE_LO $FILE_RAW
+
+ block_device_wait
+ unload_scsi_debug
+}
+
+log_onexit cleanup
+
+log_assert "zpool can not expand if set autoexpand=off after vdev expansion"
+
+for type in " " mirror raidz raidz2; do
+ log_note "Setting up loopback, scsi_debug, and file vdevs"
+ log_must truncate -s $org_size $FILE_LO
+ DEV1=$(losetup -f)
+ log_must losetup $DEV1 $FILE_LO
+
+ load_scsi_debug $org_size_mb 1 1 1 '512b'
+ block_device_wait
+ DEV2=$(get_debug_device)
+
+ log_must truncate -s $org_size $FILE_RAW
+ DEV3=$FILE_RAW
+
+ # The -f is required since we're mixing disk and file vdevs.
+ log_must zpool create -f $TESTPOOL1 $type $DEV1 $DEV2 $DEV3
+
+ typeset autoexp=$(get_pool_prop autoexpand $TESTPOOL1)
+ if [[ $autoexp != "off" ]]; then
+ log_fail "zpool $TESTPOOL1 autoexpand should be off but is " \
+ "$autoexp"
+ fi
+
+ typeset prev_size=$(get_pool_prop size $TESTPOOL1)
+
+
+ # Expand each device as appropriate being careful to add an artificial
+ # delay to ensure we get a single history entry for each. This makes
+ # is easier to verify each expansion for the striped pool case, since
+ # they will not be merged in to a single larger expansion.
+ log_note "Expanding loopback, scsi_debug, and file vdevs"
+ log_must truncate -s $exp_size $FILE_LO
+ log_must losetup -c $DEV1
+ sleep 3
+
+ echo "2" > /sys/bus/pseudo/drivers/scsi_debug/virtual_gb
+ echo "1" > /sys/class/block/$DEV2/device/rescan
+ block_device_wait
+ sleep 3
+
+ log_must truncate -s $exp_size $FILE_RAW
+
+ # This is far longer than we should need to wait, but let's be sure.
+ sleep 5
+
+ # check for zpool history for the pool size expansion
+ zpool history -il $TESTPOOL1 | grep "pool '$TESTPOOL1' size:" | \
+ grep "vdev online" >/dev/null 2>&1
+
+ if [[ $? -eq 0 ]]; then
+ log_fail "pool $TESTPOOL1 is not autoexpand after vdev " \
+ "expansion"
+ fi
+
+ typeset expand_size=$(get_pool_prop size $TESTPOOL1)
+
+ if [[ "$prev_size" != "$expand_size" ]]; then
+ log_fail "pool $TESTPOOL1 size changed after vdev expansion"
+ fi
+
+ cleanup
+done
+
+log_pass "zpool can not autoexpand if autoexpand=off after vdev expansion"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_004_pos.ksh
new file mode 100755
index 000000000000..8a4db824bc9c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_004_pos.ksh
@@ -0,0 +1,100 @@
+#! /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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2015 by Delphix. All rights reserved.
+# Copyright (c) 2017 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_expand/zpool_expand.cfg
+
+#
+# DESCRIPTION:
+# After vdev expansion, all 4 labels have the same set of uberblocks.
+#
+#
+# STRATEGY:
+# 1) Create 3 files
+# 2) Create a pool backed by the files
+# 3) Expand the files' size with truncate
+# 4) Use zpool online -e to expand the vdevs
+# 5) Check that for all the devices, all 4 labels have the same uberblocks
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+
+ for i in 1 2 3; do
+ [ -e ${TEMPFILE}.$i ] && log_must rm ${TEMPFILE}.$i
+ done
+}
+
+log_onexit cleanup
+
+log_assert "After vdev expansion, all 4 labels have the same set of uberblocks."
+
+for type in " " mirror raidz raidz2; do
+ for i in 1 2 3; do
+ log_must truncate -s $org_size ${TEMPFILE}.$i
+ done
+
+ log_must zpool create $TESTPOOL1 $type $TEMPFILE.1 \
+ $TEMPFILE.2 $TEMPFILE.3
+
+ sync_pool $TESTPOOL1
+
+ for i in 1 2 3; do
+ log_must truncate -s $exp_size ${TEMPFILE}.$i
+ done
+
+ for i in 1 2 3; do
+ log_must zpool online -e $TESTPOOL1 ${TEMPFILE}.$i
+ done
+
+ sync_pool $TESTPOOL1
+
+
+ for i in 1 2 3; do
+ non_uniform=$(zdb -lu ${TEMPFILE}.$i | \
+ grep 'labels = ' | \
+ grep -c -v 'labels = 0 1 2 3')
+
+ log_note "non-uniform label count: $non_uniform"
+
+ if [[ $non_uniform -ne 0 ]]; then
+ log_fail "After vdev expansion, all labels contents are not identical"
+ fi
+ done
+
+ log_must zpool destroy $TESTPOOL1
+done
+
+log_pass "After vdev expansion, all 4 labels have the same set of uberblocks."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_005_pos.ksh
new file mode 100755
index 000000000000..54ec73b67b26
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_expand/zpool_expand_005_pos.ksh
@@ -0,0 +1,99 @@
+#! /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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/blkdev.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_expand/zpool_expand.cfg
+
+#
+# DESCRIPTION:
+#
+# STRATEGY:
+# 1) Create a scsi_debug device and a pool based on it
+# 2) Expand the device and rescan the scsi bus
+# 3) Reopen the pool and check that it detects new available space
+# 4) Online the device and check that the pool has been expanded
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+ unload_scsi_debug
+}
+
+log_onexit cleanup
+
+log_assert "zpool based on scsi device can be expanded with zpool online -e"
+
+# run scsi_debug to create a device
+MINVDEVSIZE_MB=$((MINVDEVSIZE / 1048576))
+load_scsi_debug $MINVDEVSIZE_MB 1 1 1 '512b'
+block_device_wait
+SDISK=$(get_debug_device)
+log_must zpool create $TESTPOOL1 $SDISK
+
+typeset autoexp=$(get_pool_prop autoexpand $TESTPOOL1)
+if [[ $autoexp != "off" ]]; then
+ log_fail "zpool $TESTPOOL1 autoexpand should be off but is $autoexp"
+fi
+
+typeset prev_size=$(get_pool_prop size $TESTPOOL1)
+log_note "original pool size: $prev_size"
+
+# resize the scsi_debug device
+echo "5" > /sys/bus/pseudo/drivers/scsi_debug/virtual_gb
+# rescan the device to detect the new size
+echo "1" > /sys/class/block/$SDISK/device/rescan
+block_device_wait
+
+# reopen the pool so ZFS can see the new space
+log_must zpool reopen $TESTPOOL1
+
+typeset expandsize=$(get_pool_prop expandsize $TESTPOOL1)
+log_note "pool expandsize: $expandsize"
+if [[ "$zpool_expandsize" = "-" ]]; then
+ log_fail "pool $TESTPOOL1 did not detect any " \
+ "expandsize after reopen"
+fi
+
+# online the device so the zpool will use the new space
+log_must zpool online -e $TESTPOOL1 $SDISK
+
+typeset new_size=$(get_pool_prop size $TESTPOOL1)
+log_note "new pool size: $new_size"
+if [[ $new_size -le $prev_size ]]; then
+ log_fail "pool $TESTPOOL1 did not expand " \
+ "after vdev expansion and zpool online -e"
+fi
+
+log_pass "zpool based on scsi_debug can be expanded with reopen and online -e"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_export/Makefile.am
new file mode 100644
index 000000000000..86452e8acc6e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/Makefile.am
@@ -0,0 +1,11 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_export
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_export_001_pos.ksh \
+ zpool_export_002_pos.ksh \
+ zpool_export_003_neg.ksh \
+ zpool_export_004_pos.ksh
+
+dist_pkgdata_DATA = \
+ zpool_export.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_export/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_export/setup.ksh
new file mode 100755
index 000000000000..664fb2ddd8ca
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/setup.ksh
@@ -0,0 +1,37 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_export/zpool_export.cfg
+
+DISK=${DISKS%% *}
+
+if ! is_physical_device $DISK; then
+ log_unsupported "Only partitionable physical disks can be used"
+fi
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.cfg
new file mode 100644
index 000000000000..1501c0463015
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.cfg
@@ -0,0 +1,59 @@
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+export DISK_ARRAY_NUM=0
+export DISK_ARRAY_LIMIT=4
+export DISKSARRAY=""
+export VDEVS_NUM=32
+
+function set_disks
+{
+ typeset -a disk_array=($(find_disks $DISKS))
+
+ if (( ${#disk_array[*]} <= 1 )); then
+ export DISK=${DISKS%% *}
+ else
+ export DISK=""
+ typeset -i i=0
+ while (( i < ${#disk_array[*]} )); do
+ export DISK${i}="${disk_array[$i]}"
+ DISKSARRAY="$DISKSARRAY ${disk_array[$i]}"
+ (( i = i + 1 ))
+ (( i>$DISK_ARRAY_LIMIT )) && break
+ done
+ export DISK_ARRAY_NUM=$i
+ export DISKSARRAY
+ fi
+}
+
+set_disks
+set_device_dir
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_001_pos.ksh
new file mode 100755
index 000000000000..b6823553d727
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_001_pos.ksh
@@ -0,0 +1,71 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_export/zpool_export.cfg
+
+#
+# DESCRIPTION:
+# Exported pools should no longer be visible from 'zpool list'.
+# Therefore, we export an existing pool and verify it cannot
+# be accessed.
+#
+# STRATEGY:
+# 1. Unmount the test directory.
+# 2. Export the pool.
+# 3. Verify the pool is no longer present in the list output.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset dir=$(get_device_dir $DISKS)
+
+ datasetexists "$TESTPOOL/$TESTFS" || \
+ log_must zpool import -d $dir $TESTPOOL
+
+ ismounted "$TESTPOOL/$TESTFS"
+ (( $? != 0 )) && \
+ log_must zfs mount $TESTPOOL/$TESTFS
+}
+
+log_onexit cleanup
+
+log_assert "Verify a pool can be exported."
+
+log_must zfs umount $TESTDIR
+log_must zpool export $TESTPOOL
+
+poolexists $TESTPOOL && \
+ log_fail "$TESTPOOL unexpectedly found in 'zpool list' output."
+
+log_pass "Successfully exported a ZPOOL."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_002_pos.ksh
new file mode 100755
index 000000000000..81473d903aa4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_002_pos.ksh
@@ -0,0 +1,81 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# The 'zpool export' command must fail when a pool is
+# busy i.e. mounted.
+#
+# STRATEGY:
+# 1. Try and export the default pool when mounted and busy.
+# 2. Verify an error is returned.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset dir=$(get_device_dir $DISKS)
+ cd $olddir || \
+ log_fail "Couldn't cd back to $olddir"
+
+ datasetexists "$TESTPOOL/$TESTFS" || \
+ log_must zpool import -d $dir $TESTPOOL
+
+ ismounted "$TESTPOOL/$TESTFS"
+ (( $? != 0 )) && \
+ log_must zfs mount $TESTPOOL/$TESTFS
+
+ [[ -e $TESTDIR/$TESTFILE0 ]] && \
+ log_must rm -rf $TESTDIR/$TESTFILE0
+}
+
+olddir=$PWD
+
+log_onexit cleanup
+
+log_assert "Verify a busy ZPOOL cannot be exported."
+
+ismounted "$TESTPOOL/$TESTFS"
+(( $? != 0 )) && \
+ log_fail "$TESTDIR not mounted. Unable to continue."
+
+cd $TESTDIR || \
+ log_fail "Couldn't cd to $TESTDIR"
+
+log_mustnot zpool export $TESTPOOL
+
+poolexists $TESTPOOL || \
+ log_fail "$TESTPOOL not found in 'zpool list' output."
+
+log_pass "Unable to export a busy ZPOOL as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_003_neg.ksh
new file mode 100755
index 000000000000..b188f9c3304a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_003_neg.ksh
@@ -0,0 +1,69 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zpool export' should return an error with badly formed parameters,
+#
+# STRATEGY:
+# 1. Create an array of parameters
+# 2. For each parameter in the array, execute 'zpool export'
+# 3. Verify an error is returned.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset dir=$(get_device_dir $DISKS)
+ datasetexists "$TESTPOOL/$TESTFS" || \
+ log_must zpool import -d $dir $TESTPOOL
+
+ ismounted "$TESTPOOL/$TESTFS"
+ (( $? != 0 )) && \
+ log_must zfs mount $TESTPOOL/$TESTFS
+}
+
+log_onexit cleanup
+
+set -A args "" "-f" "-? $TESTPOOL" "-QWERTYUIO $TESTPOOL"
+
+log_assert "'zpool export' should return an error with badly-formed parameters."
+
+typeset -i i=0
+while (( $i < ${#args[*]} )); do
+ log_mustnot zpool export ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "'zpool export' badly formed parameters fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_004_pos.ksh
new file mode 100755
index 000000000000..0f1a7c624df7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_004_pos.ksh
@@ -0,0 +1,103 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify zpool export succeed or fail with spare.
+#
+# STRATEGY:
+# 1. Create two mirror pools with same spare.
+# 2. Verify zpool export one pool succeed.
+# 3. Import the pool.
+# 4. Replace one device with the spare and detach it in one pool.
+# 5. Verify zpool export the pool succeed.
+# 6. Import the pool.
+# 7. Replace one device with the spare in one pool.
+# 8. Verify zpool export the pool fail.
+# 9. Verify zpool export the pool with "-f" succeed.
+# 10. Import the pool.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ mntpnt=$TESTDIR0
+ datasetexists $TESTPOOL1 || log_must zpool import -d $mntpnt $TESTPOOL1
+ datasetexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+ datasetexists $TESTPOOL2 && destroy_pool $TESTPOOL2
+ typeset -i i=0
+ while ((i < 5)); do
+ if [[ -e $mntpnt/vdev$i ]]; then
+ log_must rm -f $mntpnt/vdev$i
+ fi
+ ((i += 1))
+ done
+ log_must rmdir $mntpnt
+}
+
+
+log_assert "Verify zpool export succeed or fail with spare."
+log_onexit cleanup
+
+mntpnt=$TESTDIR0
+log_must mkdir -p $mntpnt
+
+# mntpnt=$(get_prop mountpoint $TESTPOOL)
+
+typeset -i i=0
+while ((i < 5)); do
+ log_must truncate -s $MINVDEVSIZE $mntpnt/vdev$i
+ eval vdev$i=$mntpnt/vdev$i
+ ((i += 1))
+done
+
+log_must zpool create $TESTPOOL1 mirror $vdev0 $vdev1 spare $vdev4
+log_must zpool create $TESTPOOL2 mirror $vdev2 $vdev3 spare $vdev4
+
+log_must zpool export $TESTPOOL1
+log_must zpool import -d $mntpnt $TESTPOOL1
+
+log_must zpool replace $TESTPOOL1 $vdev0 $vdev4
+log_must zpool detach $TESTPOOL1 $vdev4
+log_must zpool export $TESTPOOL1
+log_must zpool import -d $mntpnt $TESTPOOL1
+
+log_must zpool replace $TESTPOOL1 $vdev0 $vdev4
+log_mustnot zpool export $TESTPOOL1
+
+log_must zpool export -f $TESTPOOL1
+log_must zpool import -d $mntpnt $TESTPOOL1
+
+log_pass "Verify zpool export succeed or fail with spare."
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_get/Makefile.am
new file mode 100644
index 000000000000..0c87c9b37763
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/Makefile.am
@@ -0,0 +1,12 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_get
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_get_001_pos.ksh \
+ zpool_get_002_pos.ksh \
+ zpool_get_003_pos.ksh \
+ zpool_get_004_neg.ksh \
+ zpool_get_005_pos.ksh
+
+dist_pkgdata_DATA = \
+ zpool_get.cfg zpool_get_parsable.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/cleanup.ksh
new file mode 100755
index 000000000000..6c992b5f02ae
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/cleanup.ksh
@@ -0,0 +1,36 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/setup.ksh
new file mode 100755
index 000000000000..063ad743b7a8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/setup.ksh
@@ -0,0 +1,37 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+verify_runnable "both"
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg
new file mode 100644
index 000000000000..8abef65de19f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg
@@ -0,0 +1,104 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2014 by Delphix. All rights reserved.
+# Copyright 2016 Nexenta Systems, Inc. All rights reserved.
+#
+
+# Set the expected properties of zpool
+typeset -a properties=(
+ "size"
+ "capacity"
+ "altroot"
+ "health"
+ "guid"
+ "load_guid"
+ "version"
+ "bootfs"
+ "delegation"
+ "autoreplace"
+ "cachefile"
+ "checkpoint"
+ "failmode"
+ "listsnapshots"
+ "autoexpand"
+ "dedupratio"
+ "free"
+ "allocated"
+ "readonly"
+ "comment"
+ "expandsize"
+ "freeing"
+ "fragmentation"
+ "leaked"
+ "multihost"
+ "autotrim"
+ "feature@async_destroy"
+ "feature@empty_bpobj"
+ "feature@lz4_compress"
+ "feature@multi_vdev_crash_dump"
+ "feature@spacemap_histogram"
+ "feature@enabled_txg"
+ "feature@hole_birth"
+ "feature@extensible_dataset"
+ "feature@embedded_data"
+ "feature@bookmarks"
+ "feature@filesystem_limits"
+ "feature@large_blocks"
+ "feature@sha512"
+ "feature@skein"
+ "feature@device_removal"
+ "feature@obsolete_counts"
+ "feature@zpool_checkpoint"
+ "feature@spacemap_v2"
+ "feature@redaction_bookmarks"
+ "feature@redacted_datasets"
+ "feature@bookmark_written"
+ "feature@log_spacemap"
+ "feature@device_rebuild"
+)
+
+if is_linux || is_freebsd; then
+ properties+=(
+ "ashift"
+ "feature@large_dnode"
+ "feature@userobj_accounting"
+ "feature@encryption"
+ "feature@project_quota"
+ "feature@allocation_classes"
+ "feature@resilver_defer"
+ "feature@bookmark_v2"
+ "feature@livelist"
+ "feature@zstd_compress"
+ )
+fi
+
+if ! is_freebsd; then
+ properties+=(
+ "feature@edonr"
+ )
+fi
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_001_pos.ksh
new file mode 100755
index 000000000000..d3b21d663f16
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_001_pos.ksh
@@ -0,0 +1,61 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# Zpool get usage message is displayed when called with no arguments
+#
+# STRATEGY:
+# 1. Run zpool get
+# 2. Check that exit status is set to 2
+# 3. Check usage message contains text "usage"
+#
+
+log_assert "Zpool get usage message is displayed when called with no arguments."
+
+zpool get > /dev/null 2>&1
+RET=$?
+if [ $RET != 2 ]
+then
+ log_fail "\"zpool get\" exit status $RET should be equal to 2."
+fi
+
+OUTPUT=$(zpool get 2>&1 | grep -i usage)
+RET=$?
+if [ $RET != 0 ]
+then
+ log_fail "Usage message for zpool get did not contain the word 'usage'."
+fi
+
+log_pass "Zpool get usage message is displayed when called with no arguments."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_002_pos.ksh
new file mode 100755
index 000000000000..ba83fadb06f1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_002_pos.ksh
@@ -0,0 +1,97 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_get/zpool_get.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool get all works as expected
+#
+# STRATEGY:
+#
+# 1. Using zpool get, retrieve all default values
+# 2. Verify that the header is printed
+# 3. Verify that we can see all the properties we expect to see
+# 4. Verify that the total output contains just those properties + header.
+#
+# Test for those properties are expected to check whether their
+# default values are sane, or whether they can be changed with zpool set.
+#
+
+function cleanup
+{
+ rm -f $values
+}
+log_onexit cleanup
+log_assert "Zpool get all works as expected"
+
+typeset -i i=0;
+typeset values=$TEST_BASE_DIR/values.$$
+
+if ! is_global_zone ; then
+ TESTPOOL=${TESTPOOL%%/*}
+fi
+
+log_must zpool get all $TESTPOOL
+zpool get all $TESTPOOL > $values
+
+log_note "Checking zpool get all output for a header."
+grep ^"NAME " $values > /dev/null 2>&1
+if [ $? -ne 0 ]
+then
+ log_fail "The header was not printed from zpool get all"
+fi
+
+
+while [ $i -lt "${#properties[@]}" ]
+do
+ log_note "Checking for ${properties[$i]} property"
+ grep "$TESTPOOL *${properties[$i]}" $values > /dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ log_fail "zpool property ${properties[$i]} was not found\
+ in pool output."
+ fi
+ i=$(( $i + 1 ))
+done
+
+# increment the counter to include the header line
+i=$(( $i + 1 ))
+
+COUNT=$(wc $values | awk '{print $1}')
+if [ $i -ne $COUNT ]
+then
+ log_fail "Found zpool features not in the zpool_get test config $i/$COUNT."
+fi
+
+log_pass "Zpool get all works as expected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_003_pos.ksh
new file mode 100755
index 000000000000..89fca9cbd485
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_003_pos.ksh
@@ -0,0 +1,77 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_get/zpool_get.cfg
+
+#
+# DESCRIPTION:
+#
+# Zpool get returns values for all known properties
+#
+# STRATEGY:
+# 1. For all properties, verify zpool get retrieves a value
+#
+
+function cleanup
+{
+ rm -f $values
+}
+
+log_assert "Zpool get returns values for all known properties"
+log_onexit cleanup
+
+if ! is_global_zone ; then
+ TESTPOOL=${TESTPOOL%%/*}
+fi
+
+typeset -i i=0;
+typeset values=$TEST_BASE_DIR/values.$$
+
+while [ $i -lt "${#properties[@]}" ]
+do
+ log_note "Checking for ${properties[$i]} property"
+ log_must eval "zpool get ${properties[$i]} $TESTPOOL > $values"
+ grep "${properties[$i]}" $values > /dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ log_fail "${properties[$i]} not seen in output"
+ fi
+ grep "^NAME " $values > /dev/null 2>&1
+ # only need to check this once.
+ if [ $i -eq 0 ] && [ $? -ne 0 ]
+ then
+ log_fail "Header not seen in zpool get output"
+ fi
+ i=$(( $i + 1 ))
+done
+
+log_pass "Zpool get returns values for all known properties"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_004_neg.ksh
new file mode 100755
index 000000000000..1edd2ba79af9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_004_neg.ksh
@@ -0,0 +1,61 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# Malformed zpool get commands are rejected
+#
+# STRATEGY:
+#
+# 1. Run several different "zpool get" commands that should fail.
+#
+
+log_assert "Malformed zpool get commands are rejected"
+
+if ! is_global_zone ; then
+ TESTPOOL=${TESTPOOL%%/*}
+fi
+
+set -A arguments "$TESTPOOL $TESTPOOL" "$TESTPOOL rubbish" "-v $TESTPOOL" \
+ "nosuchproperty $TESTPOOL" "--$TESTPOOL" "all all" \
+ "type $TESTPOOL" "usage: $TESTPOOL" "bootfs $TESTPOOL@" \
+ "bootfs,bootfs $TESTPOOL" "name $TESTPOOL" "t%d%s" \
+ "bootfs,delegation $TESTPOOL" "delegation $TESTPOOL@"
+
+for arg in $arguments
+do
+ log_mustnot zpool get $arg
+done
+
+log_pass "Malformed zpool get commands are rejected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_005_pos.ksh
new file mode 100755
index 000000000000..ad27d180fdb1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_005_pos.ksh
@@ -0,0 +1,78 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2014 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_get/zpool_get_parsable.cfg
+
+#
+# DESCRIPTION:
+#
+# Zpool get returns parsable values for all known parsable properties
+#
+# STRATEGY:
+# 1. For all parsable properties, verify zpool get -p returns a parsable value
+#
+
+if ! is_global_zone ; then
+ TESTPOOL=${TESTPOOL%%/*}
+fi
+
+typeset -i i=0
+
+while [[ $i -lt "${#properties[@]}" ]]; do
+ log_note "Checking for parsable ${properties[$i]} property"
+ log_must eval "zpool get -p ${properties[$i]} $TESTPOOL >/tmp/value.$$"
+ grep "${properties[$i]}" /tmp/value.$$ >/dev/null 2>&1
+ if [[ $? -ne 0 ]]; then
+ log_fail "${properties[$i]} not seen in output"
+ fi
+
+ typeset v=$(grep "${properties[$i]}" /tmp/value.$$ | awk '{print $3}')
+
+ log_note "${properties[$i]} has a value of $v"
+
+ # Determine if this value is a valid number, result in return code
+ log_must test -n "$v"
+ expr $v + 0 >/dev/null 2>&1
+
+ # All properties must be positive integers in order to be
+ # parsable (i.e. a return code of 0 or 1 from expr above).
+ # The only exception is "expandsize", which may be "-".
+ if [[ ! ($? -eq 0 || $? -eq 1 || \
+ ("${properties[$i]}" = "expandsize" && "$v" = "-")) ]]; then
+ log_fail "${properties[$i]} is not parsable"
+ fi
+
+ i=$(( $i + 1 ))
+done
+
+rm /tmp/value.$$
+log_pass "Zpool get returns parsable values for all known parsable properties"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_parsable.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_parsable.cfg
new file mode 100644
index 000000000000..e7b95a47223b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_parsable.cfg
@@ -0,0 +1,33 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2014 by Delphix. All rights reserved.
+#
+
+# Set the expected properties of zpool
+typeset -a properties=("allocated" "capacity" "expandsize" "free" "freeing"
+ "leaked" "size")
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_history/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_history/Makefile.am
new file mode 100644
index 000000000000..8755f8f6c8a9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_history/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_history
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_history_001_neg.ksh \
+ zpool_history_002_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_history/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_history/cleanup.ksh
new file mode 100755
index 000000000000..e4998138f701
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_history/cleanup.ksh
@@ -0,0 +1,34 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_history/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_history/setup.ksh
new file mode 100755
index 000000000000..b2a852a4c9b5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_history/setup.ksh
@@ -0,0 +1,35 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_container_volume_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_001_neg.ksh
new file mode 100755
index 000000000000..a2b73182bf4c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_001_neg.ksh
@@ -0,0 +1,69 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify 'zpool history' can deal with non-existent pools and garbage
+# to the command.
+#
+# STRATEGY:
+# 1. Create pool, volume & snap
+# 2. Verify 'zpool history' can cope with incorrect arguments.
+#
+
+verify_runnable "global"
+
+snap=$TESTPOOL/$TESTFS@snap
+clone=$TESTPOOL/clone
+
+set -A neg_opt "$TESTPOOL/$TESTCTR" "$TESTPOOL/$TESTVOL" "-t $TESTPOOL" \
+ "-v $TESTPOOL" "$snap" "$clone" "nonexist" "TESTPOOL"
+
+function cleanup
+{
+ datasetexists $clone && log_must zfs destroy $clone
+ datasetexists $snap && log_must zfs destroy $snap
+}
+
+log_assert "Verify 'zpool history' can deal with non-existent pools and " \
+ "garbage to the command."
+log_onexit cleanup
+
+log_must zfs snapshot $snap
+log_must zfs clone $snap $clone
+
+for opt in "${neg_opt[@]}"; do
+ log_mustnot eval "zpool history $opt > /dev/null"
+done
+
+log_pass "'zpool history' command line negation test passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_002_pos.ksh
new file mode 100755
index 000000000000..0146aa5bc1dd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_history/zpool_history_002_pos.ksh
@@ -0,0 +1,53 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify zpool history can handle options [-il] correctly.
+#
+# STRATEGY:
+# 1. Create varied combinations of option -i & -l.
+# 2. Verify 'zpool history' can cope with these combination correctly.
+#
+
+verify_runnable "global"
+
+log_assert "Verify zpool history can handle options [-il] correctly."
+
+options="-i -l -il -li -lil -ili -lli -iill -liil"
+
+for opt in $options; do
+ log_must eval "zpool history $opt $TESTPOOL > /dev/null 2>&1"
+done
+
+log_pass "Verify zpool history can handle options [-il] passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_import/Makefile.am
new file mode 100644
index 000000000000..ad0f9c46edc7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/Makefile.am
@@ -0,0 +1,48 @@
+SUBDIRS = blockfiles
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_import
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ import_cachefile_device_added.ksh \
+ import_cachefile_device_removed.ksh \
+ import_cachefile_device_replaced.ksh \
+ import_cachefile_mirror_attached.ksh \
+ import_cachefile_mirror_detached.ksh \
+ import_cachefile_shared_device.ksh \
+ import_devices_missing.ksh \
+ import_paths_changed.ksh \
+ import_rewind_config_changed.ksh \
+ import_rewind_device_replaced.ksh \
+ zpool_import_001_pos.ksh \
+ zpool_import_002_pos.ksh \
+ zpool_import_003_pos.ksh \
+ zpool_import_004_pos.ksh \
+ zpool_import_005_pos.ksh \
+ zpool_import_006_pos.ksh \
+ zpool_import_007_pos.ksh \
+ zpool_import_008_pos.ksh \
+ zpool_import_009_neg.ksh \
+ zpool_import_010_pos.ksh \
+ zpool_import_011_neg.ksh \
+ zpool_import_012_pos.ksh \
+ zpool_import_013_neg.ksh \
+ zpool_import_014_pos.ksh \
+ zpool_import_015_pos.ksh \
+ zpool_import_all_001_pos.ksh \
+ zpool_import_features_001_pos.ksh \
+ zpool_import_features_002_neg.ksh \
+ zpool_import_features_003_pos.ksh \
+ zpool_import_missing_001_pos.ksh \
+ zpool_import_missing_002_pos.ksh \
+ zpool_import_missing_003_pos.ksh \
+ zpool_import_rename_001_pos.ksh \
+ zpool_import_encrypted.ksh \
+ zpool_import_encrypted_load.ksh \
+ zpool_import_errata3.ksh \
+ zpool_import_errata4.ksh
+
+dist_pkgdata_DATA = \
+ zpool_import.cfg \
+ zpool_import.kshlib
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/Makefile.am
new file mode 100644
index 000000000000..dc3685e4b9cc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/Makefile.am
@@ -0,0 +1,5 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles
+dist_pkgdata_DATA = \
+ unclean_export.dat.bz2 \
+ cryptv0.dat.bz2 \
+ missing_ivset.dat.bz2
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/cryptv0.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/cryptv0.dat.bz2
new file mode 100644
index 000000000000..1c625c2c447b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/cryptv0.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/missing_ivset.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/missing_ivset.dat.bz2
new file mode 100644
index 000000000000..2b91d9003b85
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/missing_ivset.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/unclean_export.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/unclean_export.dat.bz2
new file mode 100644
index 000000000000..a7e042b523df
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/blockfiles/unclean_export.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/cleanup.ksh
new file mode 100755
index 000000000000..d5717ee1561e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/cleanup.ksh
@@ -0,0 +1,50 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+verify_runnable "global"
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+
+for pool in "$TESTPOOL" "$TESTPOOL1"; do
+ datasetexists $pool/$TESTFS && \
+ log_must zfs destroy -Rf $pool/$TESTFS
+ destroy_pool "$pool"
+done
+
+for dir in "$TESTDIR" "$TESTDIR1" "$DEVICE_DIR" ; do
+ [[ -d $dir ]] && \
+ log_must rm -rf $dir
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_added.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_added.ksh
new file mode 100755
index 000000000000..ab72042a219c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_added.ksh
@@ -0,0 +1,76 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# A pool should be importable using an outdated cachefile that is unaware
+# that one or two top-level vdevs were added.
+#
+# STRATEGY:
+# 1. Create a pool with some devices and an alternate cachefile.
+# 2. Backup the cachefile.
+# 3. Add a device/mirror/raid to the pool.
+# 4. Export the pool.
+# 5. Verify that we can import the pool using the backed-up cachefile.
+#
+
+verify_runnable "global"
+
+log_onexit cleanup
+
+function test_add_vdevs
+{
+ typeset poolcreate="$1"
+ typeset addvdevs="$2"
+ typeset poolcheck="$3"
+
+ log_note "$0: pool '$poolcreate', add $addvdevs."
+
+ log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $poolcreate
+
+ log_must cp $CPATH $CPATHBKP
+
+ log_must zpool add -f $TESTPOOL1 $addvdevs
+
+ log_must zpool export $TESTPOOL1
+
+ log_must zpool import -c $CPATHBKP $TESTPOOL1
+ log_must check_pool_config $TESTPOOL1 "$poolcheck"
+
+ # Cleanup
+ log_must zpool destroy $TESTPOOL1
+ log_must rm -f $CPATH $CPATHBKP
+
+ log_note ""
+}
+
+test_add_vdevs "$VDEV0" "$VDEV1" "$VDEV0 $VDEV1"
+test_add_vdevs "$VDEV0 $VDEV1" "$VDEV2" "$VDEV0 $VDEV1 $VDEV2"
+test_add_vdevs "$VDEV0" "$VDEV1 $VDEV2" "$VDEV0 $VDEV1 $VDEV2"
+test_add_vdevs "$VDEV0" "mirror $VDEV1 $VDEV2" \
+ "$VDEV0 mirror $VDEV1 $VDEV2"
+test_add_vdevs "mirror $VDEV0 $VDEV1" "mirror $VDEV2 $VDEV3" \
+ "mirror $VDEV0 $VDEV1 mirror $VDEV2 $VDEV3"
+test_add_vdevs "$VDEV0" "raidz $VDEV1 $VDEV2 $VDEV3" \
+ "$VDEV0 raidz $VDEV1 $VDEV2 $VDEV3"
+test_add_vdevs "$VDEV0" "log $VDEV1" "$VDEV0 log $VDEV1"
+test_add_vdevs "$VDEV0 log $VDEV1" "$VDEV2" "$VDEV0 $VDEV2 log $VDEV1"
+test_add_vdevs "$VDEV0" "$VDEV1 log $VDEV2" "$VDEV0 $VDEV1 log $VDEV2"
+
+log_pass "zpool import -c cachefile_unaware_of_add passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_removed.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_removed.ksh
new file mode 100755
index 000000000000..3fe3861236d6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_removed.ksh
@@ -0,0 +1,145 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# A pool should be importable using an outdated cachefile that is unaware
+# that one or more vdevs were removed.
+#
+# STRATEGY:
+# 1. Create a pool with some devices and an alternate cachefile.
+# 2. Backup the cachefile.
+# 3. Remove device(s) from the pool and remove them.
+# 4. (Optionally) Add device(s) to pool.
+# 5. Export the pool.
+# 6. Verify that we can import the pool using the backed-up cachefile.
+#
+
+verify_runnable "global"
+
+function custom_cleanup
+{
+ cleanup
+}
+
+log_onexit custom_cleanup
+
+function test_remove_vdev
+{
+ typeset poolcreate="$1"
+ typeset removevdev="$2"
+ typeset poolcheck="$3"
+
+ log_note "$0: pool '$poolcreate', remove $2."
+
+ log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $poolcreate
+
+ log_must cp $CPATH $CPATHBKP
+
+ log_must zpool remove $TESTPOOL1 $removevdev
+ log_must wait_for_pool_config $TESTPOOL1 "$poolcheck"
+ log_must rm $removevdev
+
+ log_must zpool export $TESTPOOL1
+
+ log_must zpool import -c $CPATHBKP $TESTPOOL1
+ log_must check_pool_config $TESTPOOL1 "$poolcheck"
+
+ # Cleanup
+ log_must zpool destroy $TESTPOOL1
+ log_must rm -f $CPATH $CPATHBKP
+ log_must mkfile $FILE_SIZE $removevdev
+
+ log_note ""
+}
+
+#
+# We have to remove top-level non-log vdevs one by one, else there is a high
+# chance pool will report busy and command will fail for the second vdev.
+#
+function test_remove_two_vdevs
+{
+ log_note "$0."
+ log_must zpool create -o cachefile=$CPATH $TESTPOOL1 \
+ $VDEV0 $VDEV1 $VDEV2 $VDEV3 $VDEV4
+
+ log_must cp $CPATH $CPATHBKP
+
+ log_must zpool remove $TESTPOOL1 $VDEV4
+ log_must wait_for_pool_config $TESTPOOL1 \
+ "$VDEV0 $VDEV1 $VDEV2 $VDEV3"
+ log_must zpool remove $TESTPOOL1 $VDEV3
+ log_must wait_for_pool_config $TESTPOOL1 "$VDEV0 $VDEV1 $VDEV2"
+ log_must rm $VDEV3 $VDEV4
+
+ log_must zpool export $TESTPOOL1
+
+ log_must zpool import -c $CPATHBKP $TESTPOOL1
+ log_must check_pool_config $TESTPOOL1 "$VDEV0 $VDEV1 $VDEV2"
+
+ # Cleanup
+ log_must zpool destroy $TESTPOOL1
+ log_must rm -f $CPATH $CPATHBKP
+ log_must mkfile $FILE_SIZE $VDEV3 $VDEV4
+
+ log_note ""
+}
+
+#
+# We want to test the case where a whole created by a log device is filled
+# by a regular device
+#
+function test_remove_log_then_add_vdev
+{
+ log_note "$0."
+ log_must zpool create -o cachefile=$CPATH $TESTPOOL1 \
+ $VDEV0 $VDEV1 $VDEV2 log $VDEV3
+
+ log_must cp $CPATH $CPATHBKP
+
+ log_must zpool remove $TESTPOOL1 $VDEV1
+ log_must wait_for_pool_config $TESTPOOL1 "$VDEV0 $VDEV2 log $VDEV3"
+ log_must zpool remove $TESTPOOL1 $VDEV3
+ log_must check_pool_config $TESTPOOL1 "$VDEV0 $VDEV2"
+ log_must rm $VDEV1 $VDEV3
+ log_must zpool add $TESTPOOL1 $VDEV4
+
+ log_must zpool export $TESTPOOL1
+
+ log_must zpool import -c $CPATHBKP $TESTPOOL1
+ log_must check_pool_config $TESTPOOL1 "$VDEV0 $VDEV2 $VDEV4"
+
+ # Cleanup
+ log_must zpool destroy $TESTPOOL1
+ log_must rm -f $CPATH $CPATHBKP
+ log_must mkfile $FILE_SIZE $VDEV1 $VDEV3
+
+ log_note ""
+}
+
+test_remove_vdev "$VDEV0 $VDEV1 $VDEV2" "$VDEV2" "$VDEV0 $VDEV1"
+test_remove_vdev "$VDEV0 $VDEV1 $VDEV2" "$VDEV1" "$VDEV0 $VDEV2"
+test_remove_vdev "$VDEV0 log $VDEV1" "$VDEV1" "$VDEV0"
+test_remove_vdev "$VDEV0 log $VDEV1 $VDEV2" "$VDEV1 $VDEV2" "$VDEV0"
+test_remove_vdev "$VDEV0 $VDEV1 $VDEV2 log $VDEV3" "$VDEV2" \
+ "$VDEV0 $VDEV1 log $VDEV3"
+test_remove_two_vdevs
+test_remove_log_then_add_vdev
+
+log_pass "zpool import -c cachefile_unaware_of_remove passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_replaced.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_replaced.ksh
new file mode 100755
index 000000000000..a42c6974762f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_replaced.ksh
@@ -0,0 +1,160 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# A pool should be importable using an outdated cachefile that is unaware
+# of a zpool replace operation at different stages in time.
+#
+# STRATEGY:
+# 1. Create a pool with some devices and an alternate cachefile.
+# 2. Backup the cachefile.
+# 3. Initiate device replacement, backup cachefile again and export pool.
+# Special care must be taken so that resilvering doesn't complete
+# before we exported the pool.
+# 4. Verify that we can import the pool using the first cachefile backup.
+# (Test 1. cachefile: pre-replace, pool: resilvering)
+# 5. Wait for the resilvering to finish and export the pool.
+# 6. Verify that we can import the pool using the first cachefile backup.
+# (Test 2. cachefile: pre-replace, pool: post-replace)
+# 7. Export the pool.
+# 8. Verify that we can import the pool using the second cachefile backup.
+# (Test 3. cachefile: resilvering, pool: post-replace)
+#
+# STRATEGY TO SLOW DOWN RESILVERING:
+# 1. Reduce zfs_txg_timeout, which controls how long can we resilver for
+# each sync.
+# 2. Add data to pool
+# 3. Re-import the pool so that data isn't cached
+# 4. Use zfs_scan_suspend_progress to ensure resilvers don't progress
+# 5. Trigger the resilvering
+# 6. Use spa freeze to stop writing to the pool.
+# 7. Re-enable scan progress
+# 8. Export the pool
+#
+
+verify_runnable "global"
+
+ZFS_TXG_TIMEOUT=""
+
+function custom_cleanup
+{
+ # Revert zfs_txg_timeout to defaults
+ [[ -n ZFS_TXG_TIMEOUT ]] &&
+ log_must set_zfs_txg_timeout $ZFS_TXG_TIMEOUT
+
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+ cleanup
+}
+
+log_onexit custom_cleanup
+
+function test_replacing_vdevs
+{
+ typeset poolcreate="$1"
+ typeset replacevdev="$2"
+ typeset replaceby="$3"
+ typeset poolfinalstate="$4"
+ typeset zinjectdevices="$5"
+ typeset earlyremove="$6"
+ typeset writedata="$7"
+
+ log_note "$0: pool '$poolcreate', replace $replacevdev by $replaceby."
+
+ log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $poolcreate
+
+ # Cachefile: pool in pre-replace state
+ log_must cp $CPATH $CPATHBKP
+
+ # Steps to insure resilvering happens very slowly.
+ log_must write_some_data $TESTPOOL1 $writedata
+ log_must zpool export $TESTPOOL1
+ log_must cp $CPATHBKP $CPATH
+ log_must zpool import -c $CPATH -o cachefile=$CPATH $TESTPOOL1
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+ log_must zpool replace $TESTPOOL1 $replacevdev $replaceby
+
+ # Cachefile: pool in resilvering state
+ log_must cp $CPATH $CPATHBKP2
+
+ # Confirm pool is still replacing
+ log_must pool_is_replacing $TESTPOOL1
+ log_must zpool export $TESTPOOL1
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+
+ ( $earlyremove ) && log_must rm $replacevdev
+
+ ############################################################
+ # Test 1. Cachefile: pre-replace, pool: resilvering
+ ############################################################
+ log_must cp $CPATHBKP $CPATH
+ log_must zpool import -c $CPATH $TESTPOOL1
+
+ # Wait for resilvering to finish
+ log_must wait_for_pool_config $TESTPOOL1 "$poolfinalstate"
+ log_must zpool export $TESTPOOL1
+
+ ( ! $earlyremove ) && log_must rm $replacevdev
+
+ ############################################################
+ # Test 2. Cachefile: pre-replace, pool: post-replace
+ ############################################################
+ log_must zpool import -c $CPATHBKP $TESTPOOL1
+ log_must check_pool_config $TESTPOOL1 "$poolfinalstate"
+ log_must zpool export $TESTPOOL1
+
+ ############################################################
+ # Test 3. Cachefile: resilvering, pool: post-replace
+ ############################################################
+ log_must zpool import -c $CPATHBKP2 $TESTPOOL1
+ log_must check_pool_config $TESTPOOL1 "$poolfinalstate"
+
+ # Cleanup
+ log_must zpool destroy $TESTPOOL1
+ log_must rm -f $CPATH $CPATHBKP $CPATHBKP2
+ log_must mkfile $FILE_SIZE $replacevdev
+
+ log_note ""
+}
+
+# We set zfs_txg_timeout to 1 to reduce resilvering time at each sync.
+ZFS_TXG_TIMEOUT=$(get_zfs_txg_timeout)
+set_zfs_txg_timeout 1
+
+test_replacing_vdevs "$VDEV0 $VDEV1" \
+ "$VDEV1" "$VDEV2" \
+ "$VDEV0 $VDEV2" \
+ "$VDEV0 $VDEV1" \
+ false 20
+
+test_replacing_vdevs "mirror $VDEV0 $VDEV1" \
+ "$VDEV1" "$VDEV2" \
+ "mirror $VDEV0 $VDEV2" \
+ "$VDEV0 $VDEV1" \
+ true 10
+
+test_replacing_vdevs "raidz $VDEV0 $VDEV1 $VDEV2" \
+ "$VDEV1" "$VDEV3" \
+ "raidz $VDEV0 $VDEV3 $VDEV2" \
+ "$VDEV0 $VDEV1 $VDEV2" \
+ true 20
+
+set_zfs_txg_timeout $ZFS_TXG_TIMEOUT
+
+log_pass "zpool import -c cachefile_unaware_of_replace passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_mirror_attached.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_mirror_attached.ksh
new file mode 100755
index 000000000000..b90e24c2cdc5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_mirror_attached.ksh
@@ -0,0 +1,72 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# A pool should be importable using an outdated cachefile that misses a
+# mirror that was attached.
+#
+# STRATEGY:
+# 1. Create a pool with some devices and an alternate cachefile.
+# 2. Backup the cachefile.
+# 3. Attach a mirror to one of the devices in the pool.
+# 4. Export the pool.
+# 5. Verify that we can import the pool using the backed-up cachefile.
+#
+
+verify_runnable "global"
+
+log_onexit cleanup
+
+function test_attach_vdev
+{
+ typeset poolcreate="$1"
+ typeset attachto="$2"
+ typeset attachvdev="$3"
+ typeset poolcheck="$4"
+
+ log_note "$0: pool '$poolcreate', attach $attachvdev to $attachto."
+
+ log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $poolcreate
+
+ log_must cp $CPATH $CPATHBKP
+
+ log_must zpool attach $TESTPOOL1 $attachto $attachvdev
+
+ log_must zpool export $TESTPOOL1
+
+ log_must zpool import -c $CPATHBKP $TESTPOOL1
+ log_must check_pool_config $TESTPOOL1 "$poolcheck"
+
+ # Cleanup
+ log_must zpool destroy $TESTPOOL1
+ log_must rm -f $CPATH $CPATHBKP
+
+ log_note ""
+}
+
+test_attach_vdev "$VDEV0" "$VDEV0" "$VDEV4" "mirror $VDEV0 $VDEV4"
+test_attach_vdev "$VDEV0 $VDEV1" "$VDEV1" "$VDEV4" \
+ "$VDEV0 mirror $VDEV1 $VDEV4"
+test_attach_vdev "mirror $VDEV0 $VDEV1" "$VDEV0" "$VDEV4" \
+ "mirror $VDEV0 $VDEV1 $VDEV4"
+test_attach_vdev "$VDEV0 log $VDEV1" "$VDEV1" "$VDEV4" \
+ "$VDEV0 log mirror $VDEV1 $VDEV4"
+
+log_pass "zpool import -c cachefile_unaware_of_attach passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_mirror_detached.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_mirror_detached.ksh
new file mode 100755
index 000000000000..ba695418f839
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_mirror_detached.ksh
@@ -0,0 +1,70 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# A pool should be importable using an outdated cachefile that is unaware
+# that a mirror was detached.
+#
+# STRATEGY:
+# 1. Create a pool with some devices mirrored and an alternate cachefile.
+# 2. Backup the cachefile.
+# 3. Detach a mirror from the pool.
+# 4. Export the pool.
+# 5. Verify that we can import the pool using the backed-up cachefile.
+#
+
+verify_runnable "global"
+
+log_onexit cleanup
+
+function test_detach_vdev
+{
+ typeset poolcreate="$1"
+ typeset poolcheck="$2"
+
+ log_note "$0: pool '$poolcreate', detach $VDEV4."
+
+ log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $poolcreate
+
+ log_must cp $CPATH $CPATHBKP
+
+ log_must zpool detach $TESTPOOL1 $VDEV4
+ log_must rm -f $VDEV4
+
+ log_must zpool export $TESTPOOL1
+
+ log_must zpool import -c $CPATHBKP $TESTPOOL1
+ log_must check_pool_config $TESTPOOL1 "$poolcheck"
+
+ # Cleanup
+ log_must zpool destroy $TESTPOOL1
+ log_must rm -f $CPATH $CPATHBKP
+ log_must mkfile $FILE_SIZE $VDEV4
+
+ log_note ""
+}
+
+test_detach_vdev "mirror $VDEV0 $VDEV4" "$VDEV0"
+test_detach_vdev "mirror $VDEV0 $VDEV4 mirror $VDEV1 $VDEV2" \
+ "$VDEV0 mirror $VDEV1 $VDEV2"
+test_detach_vdev "mirror $VDEV0 $VDEV1 $VDEV4" "mirror $VDEV0 $VDEV1"
+test_detach_vdev "$VDEV0 log mirror $VDEV1 $VDEV4" "$VDEV0 log $VDEV1"
+
+log_pass "zpool import -c cachefile_unaware_of_detach passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_shared_device.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_shared_device.ksh
new file mode 100755
index 000000000000..887993dfd1ec
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_shared_device.ksh
@@ -0,0 +1,113 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# A pool should not try to write to a device that doesn't belong to it
+# anymore, even if the device is in its cachefile.
+#
+# STRATEGY:
+# 1. Create pool1 with some devices and an alternate cachefile.
+# 2. Backup the cachefile.
+# 3. Export pool1.
+# 4. Create pool2 using a device that belongs to pool1.
+# 5. Export pool2.
+# 6. Compute checksum of the shared device.
+# 7. Import pool1 and write some data to it.
+# 8. Verify that the checksum of the shared device hasn't changed.
+#
+
+verify_runnable "global"
+
+function custom_cleanup
+{
+ destroy_pool $TESTPOOL2
+ cleanup
+}
+
+log_onexit custom_cleanup
+
+function dev_checksum
+{
+ typeset dev="$1"
+ typeset checksum
+
+ log_note "Compute checksum of '$dev'"
+
+ checksum=$(md5digest $dev)
+ if [[ $? -ne 0 ]]; then
+ log_fail "Failed to compute checksum of '$dev'"
+ return 1
+ fi
+
+ echo "$checksum"
+ return 0
+}
+
+function test_shared_device
+{
+ typeset pool1="$1"
+ typeset pool2="$2"
+ typeset sharedvdev="$3"
+ typeset importflags="${4:-}"
+
+ log_note "$0: pool1 '$pool1', pool2 '$pool2' takes $sharedvdev."
+
+ log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $pool1
+
+ log_must cp $CPATH $CPATHBKP
+
+ log_must zpool export $TESTPOOL1
+
+ log_must zpool create -f $TESTPOOL2 $pool2
+
+ log_must zpool export $TESTPOOL2
+
+ typeset checksum1=$(dev_checksum $sharedvdev)
+
+ log_must zpool import -c $CPATHBKP $importflags $TESTPOOL1
+
+ log_must write_some_data $TESTPOOL1 2
+
+ log_must zpool destroy $TESTPOOL1
+
+ typeset checksum2=$(dev_checksum $sharedvdev)
+
+ if [[ $checksum1 == $checksum2 ]]; then
+ log_pass "Device hasn't been modified by original pool"
+ else
+ log_fail "Device has been modified by original pool." \
+ "Checksum mismatch: $checksum1 != $checksum2."
+ fi
+
+ # Cleanup
+ log_must zpool import -d $DEVICE_DIR $TESTPOOL2
+ log_must zpool destroy $TESTPOOL2
+ log_must rm -f $CPATH $CPATHBKP
+
+ log_note ""
+}
+
+test_shared_device "mirror $VDEV0 $VDEV1" "mirror $VDEV1 $VDEV2" "$VDEV1"
+test_shared_device "mirror $VDEV0 $VDEV1 $VDEV2" "mirror $VDEV2 $VDEV3" \
+ "$VDEV2"
+test_shared_device "raidz $VDEV0 $VDEV1 $VDEV2" "$VDEV2" "$VDEV2"
+test_shared_device "$VDEV0 log $VDEV1" "$VDEV2 log $VDEV1" "$VDEV1" "-m"
+
+log_pass "Pool doesn't write to a device it doesn't own anymore."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_devices_missing.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_devices_missing.ksh
new file mode 100755
index 000000000000..53828c912ca3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_devices_missing.ksh
@@ -0,0 +1,122 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# A pool should be importable when up to 2 top-level devices are missing.
+#
+# STRATEGY:
+# 1. Create a pool.
+# 2. Write some data to the pool and checksum it.
+# 3. Add one or more devices.
+# 4. Write more data to the pool and checksum it.
+# 5. Export the pool.
+# 6. Move added devices out of the devices directory.
+# 7. Import the pool with missing devices.
+# 8. Verify that the first batch of data is intact.
+# 9. Verify that accessing the second batch of data doesn't suspend pool.
+# 10. Export the pool, move back missing devices, Re-import the pool.
+# 11. Verify that all the data is intact.
+#
+
+verify_runnable "global"
+
+function custom_cleanup
+{
+ log_must set_spa_load_verify_metadata 1
+ log_must set_spa_load_verify_data 1
+ log_must set_zfs_max_missing_tvds 0
+ log_must rm -rf $BACKUP_DEVICE_DIR
+ # Highly damaged pools may fail to be destroyed, so we export them.
+ poolexists $TESTPOOL1 && log_must zpool export $TESTPOOL1
+ cleanup
+}
+
+log_onexit custom_cleanup
+
+function test_devices_missing
+{
+ typeset poolcreate="$1"
+ typeset addvdevs="$2"
+ typeset missingvdevs="$3"
+ typeset -i missingtvds="$4"
+
+ log_note "$0: pool '$poolcreate', adding $addvdevs, then" \
+ "moving away $missingvdevs."
+
+ log_must zpool create $TESTPOOL1 $poolcreate
+
+ log_must generate_data $TESTPOOL1 $MD5FILE "first"
+
+ log_must zpool add $TESTPOOL1 $addvdevs
+
+ log_must generate_data $TESTPOOL1 $MD5FILE2 "second"
+
+ log_must zpool export $TESTPOOL1
+
+ log_must mv $missingvdevs $BACKUP_DEVICE_DIR
+
+ # Tell zfs that it is ok to import a pool with missing top-level vdevs
+ log_must set_zfs_max_missing_tvds $missingtvds
+ # Missing devices means that data or metadata may be corrupted.
+ (( missingtvds > 1 )) && log_must set_spa_load_verify_metadata 0
+ log_must set_spa_load_verify_data 0
+ log_must zpool import -o readonly=on -d $DEVICE_DIR $TESTPOOL1
+
+ log_must verify_data_md5sums $MD5FILE
+
+ log_note "Try reading second batch of data, make sure pool doesn't" \
+ "get suspended."
+ verify_data_md5sums $MD5FILE >/dev/null 2>&1
+
+ log_must zpool export $TESTPOOL1
+
+ typeset newpaths=$(echo "$missingvdevs" | \
+ sed "s:$DEVICE_DIR:$BACKUP_DEVICE_DIR:g")
+ log_must mv $newpaths $DEVICE_DIR
+ log_must set_spa_load_verify_metadata 1
+ log_must set_spa_load_verify_data 1
+ log_must set_zfs_max_missing_tvds 0
+ log_must zpool import -d $DEVICE_DIR $TESTPOOL1
+
+ log_must verify_data_md5sums $MD5FILE
+ log_must verify_data_md5sums $MD5FILE2
+
+ # Cleanup
+ log_must zpool destroy $TESTPOOL1
+
+ log_note ""
+}
+
+log_must mkdir -p $BACKUP_DEVICE_DIR
+
+test_devices_missing "$VDEV0" "$VDEV1" "$VDEV1" 1
+test_devices_missing "$VDEV0" "$VDEV1 $VDEV2" "$VDEV1" 1
+test_devices_missing "mirror $VDEV0 $VDEV1" "mirror $VDEV2 $VDEV3" \
+ "$VDEV2 $VDEV3" 1
+test_devices_missing "$VDEV0 log $VDEV1" "$VDEV2" "$VDEV2" 1
+
+#
+# Note that we are testing for 2 non-consecutive missing devices.
+# Missing consecutive devices results in missing metadata. Because of
+# Missing metadata can cause the root dataset to fail to mount.
+#
+test_devices_missing "$VDEV0" "$VDEV1 $VDEV2 $VDEV3" "$VDEV1 $VDEV3" 2
+
+log_pass "zpool import succeeded with missing devices."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_paths_changed.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_paths_changed.ksh
new file mode 100755
index 000000000000..7ee306e26d58
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_paths_changed.ksh
@@ -0,0 +1,98 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# A pool should be importable even if device paths have changed.
+#
+# STRATEGY:
+# 1. Create a pool.
+# 2. Export the pool.
+# 3. Change the paths of some of the devices.
+# 4. Verify that we can import the pool in a healthy state.
+#
+
+verify_runnable "global"
+
+log_onexit cleanup
+
+function test_new_paths
+{
+ typeset poolcreate="$1"
+ typeset pathstochange="$2"
+
+ log_note "$0: pool '$poolcreate', changing paths of $pathstochange."
+
+ log_must zpool create $TESTPOOL1 $poolcreate
+
+ log_must zpool export $TESTPOOL1
+
+ for dev in $pathstochange; do
+ log_must mv $dev "${dev}_new"
+ done
+
+ log_must zpool import -d $DEVICE_DIR $TESTPOOL1
+ log_must check_pool_healthy $TESTPOOL1
+
+ # Cleanup
+ log_must zpool destroy $TESTPOOL1
+ for dev in $pathstochange; do
+ log_must mv "${dev}_new" $dev
+ done
+
+ log_note ""
+}
+
+function test_swap_paths
+{
+ typeset poolcreate="$1"
+ typeset pathtoswap1="$2"
+ typeset pathtoswap2="$3"
+
+ log_note "$0: pool '$poolcreate', swapping paths of $pathtoswap1" \
+ "and $pathtoswap2."
+
+ log_must zpool create $TESTPOOL1 $poolcreate
+
+ log_must zpool export $TESTPOOL1
+
+ log_must mv $pathtoswap2 "$pathtoswap2.tmp"
+ log_must mv $pathtoswap1 "$pathtoswap2"
+ log_must mv "$pathtoswap2.tmp" $pathtoswap1
+
+ log_must zpool import -d $DEVICE_DIR $TESTPOOL1
+ log_must check_pool_healthy $TESTPOOL1
+
+ # Cleanup
+ log_must zpool destroy $TESTPOOL1
+
+ log_note ""
+}
+
+test_new_paths "$VDEV0 $VDEV1" "$VDEV0 $VDEV1"
+test_new_paths "mirror $VDEV0 $VDEV1" "$VDEV0 $VDEV1"
+test_new_paths "$VDEV0 log $VDEV1" "$VDEV1"
+test_new_paths "raidz $VDEV0 $VDEV1 $VDEV2" "$VDEV1"
+
+test_swap_paths "$VDEV0 $VDEV1" "$VDEV0" "$VDEV1"
+test_swap_paths "raidz $VDEV0 $VDEV1 $VDEV2" "$VDEV0" "$VDEV1"
+test_swap_paths "mirror $VDEV0 $VDEV1 mirror $VDEV2 $VDEV3" \
+ "$VDEV0" "$VDEV2"
+
+log_pass "zpool import succeeded after changing device paths."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_config_changed.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_config_changed.ksh
new file mode 100755
index 000000000000..74d75b6cdec0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_config_changed.ksh
@@ -0,0 +1,261 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# It should be possible to rewind a pool beyond a configuration change.
+#
+# STRATEGY:
+# 1. Create a pool.
+# 2. Generate files and remember their md5sum.
+# 3. Note last synced txg.
+# 4. Take a snapshot to make sure old blocks are not overwritten.
+# 5. Perform zpool add/attach/detach/remove operation.
+# 6. Change device paths if requested and re-import pool.
+# 7. Checkpoint the pool as one last attempt to preserve old blocks.
+# 8. Overwrite the files.
+# 9. Export the pool.
+# 10. Verify that we can rewind the pool to the noted txg.
+# 11. Verify that the files are readable and retain their old data.
+#
+# DISCLAIMER:
+# This test can fail since nothing guarantees that old MOS blocks aren't
+# overwritten. Snapshots protect datasets and data files but not the MOS.
+# sync_some_data_a_few_times interleaves file data and MOS data for a few
+# txgs, thus increasing the odds that some txgs will have their MOS data
+# left untouched.
+#
+
+verify_runnable "global"
+
+function custom_cleanup
+{
+ set_vdev_validate_skip 0
+ cleanup
+ log_must set_tunable64 VDEV_MIN_MS_COUNT 16
+}
+
+log_onexit custom_cleanup
+
+function test_common
+{
+ typeset poolcreate="$1"
+ typeset addvdevs="$2"
+ typeset attachargs="${3:-}"
+ typeset detachvdev="${4:-}"
+ typeset removevdev="${5:-}"
+ typeset finalpool="${6:-}"
+
+ typeset poolcheck="$poolcreate"
+
+ log_must zpool create $TESTPOOL1 $poolcreate
+
+ log_must generate_data $TESTPOOL1 $MD5FILE
+
+ # syncing a few times while writing new data increases the odds that MOS
+ # metadata for some of the txgs will survive
+ log_must sync_some_data_a_few_times $TESTPOOL1
+ typeset txg
+ txg=$(get_last_txg_synced $TESTPOOL1)
+ log_must zfs snapshot -r $TESTPOOL1@snap1
+
+ #
+ # Perform config change operations
+ #
+ if [[ -n $addvdevs ]]; then
+ log_must zpool add -f $TESTPOOL1 $addvdevs
+ fi
+ if [[ -n $attachargs ]]; then
+ log_must zpool attach $TESTPOOL1 $attachargs
+ fi
+ if [[ -n $detachvdev ]]; then
+ log_must zpool detach $TESTPOOL1 $detachvdev
+ fi
+ if [[ -n $removevdev ]]; then
+ [[ -z $finalpool ]] &&
+ log_fail "Must provide final pool status!"
+ log_must zpool remove $TESTPOOL1 $removevdev
+ log_must wait_for_pool_config $TESTPOOL1 "$finalpool"
+ fi
+ if [[ -n $pathstochange ]]; then
+ #
+ # Change device paths and re-import pool to update labels
+ #
+ zpool export $TESTPOOL1
+ for dev in $pathstochange; do
+ log_must mv $dev "${dev}_new"
+ poolcheck=$(echo "$poolcheck" | \
+ sed "s:$dev:${dev}_new:g")
+ done
+ zpool import -d $DEVICE_DIR $TESTPOOL1
+ fi
+
+ #
+ # In an attempt to leave MOS data untouched so extreme
+ # rewind is successful during import we checkpoint the
+ # pool and hope that these MOS data are part of the
+ # checkpoint (e.g they stay around). If this goes as
+ # expected, then extreme rewind should rewind back even
+ # further than the time that we took the checkpoint.
+ #
+ # Note that, ideally we would want to take a checkpoint
+ # right after we record the txg we plan to rewind to.
+ # But since we can't attach, detach or remove devices
+ # while having a checkpoint, we take it after the
+ # operation that changes the config.
+ #
+ log_must zpool checkpoint $TESTPOOL1
+
+ log_must overwrite_data $TESTPOOL1 ""
+
+ log_must zpool export $TESTPOOL1
+
+ log_must zpool import -d $DEVICE_DIR -T $txg $TESTPOOL1
+ log_must check_pool_config $TESTPOOL1 "$poolcheck"
+
+ log_must verify_data_md5sums $MD5FILE
+
+ # Cleanup
+ log_must zpool destroy $TESTPOOL1
+ if [[ -n $pathstochange ]]; then
+ for dev in $pathstochange; do
+ log_must mv "${dev}_new" $dev
+ done
+ fi
+ # Fast way to clear vdev labels
+ log_must zpool create -f $TESTPOOL2 $VDEV0 $VDEV1 $VDEV2 $VDEV3 $VDEV4
+ log_must zpool destroy $TESTPOOL2
+
+ log_note ""
+}
+
+function test_add_vdevs
+{
+ typeset poolcreate="$1"
+ typeset addvdevs="$2"
+
+ log_note "$0: pool '$poolcreate', add $addvdevs."
+
+ test_common "$poolcreate" "$addvdevs"
+}
+
+function test_attach_vdev
+{
+ typeset poolcreate="$1"
+ typeset attachto="$2"
+ typeset attachvdev="$3"
+
+ log_note "$0: pool '$poolcreate', attach $attachvdev to $attachto."
+
+ test_common "$poolcreate" "" "$attachto $attachvdev"
+}
+
+function test_detach_vdev
+{
+ typeset poolcreate="$1"
+ typeset detachvdev="$2"
+
+ log_note "$0: pool '$poolcreate', detach $detachvdev."
+
+ test_common "$poolcreate" "" "" "$detachvdev"
+}
+
+function test_attach_detach_vdev
+{
+ typeset poolcreate="$1"
+ typeset attachto="$2"
+ typeset attachvdev="$3"
+ typeset detachvdev="$4"
+
+ log_note "$0: pool '$poolcreate', attach $attachvdev to $attachto," \
+ "then detach $detachvdev."
+
+ test_common "$poolcreate" "" "$attachto $attachvdev" "$detachvdev"
+}
+
+function test_remove_vdev
+{
+ typeset poolcreate="$1"
+ typeset removevdev="$2"
+ typeset finalpool="$3"
+
+ log_note "$0: pool '$poolcreate', remove $removevdev."
+
+ test_common "$poolcreate" "" "" "" "$removevdev" "$finalpool"
+}
+
+# Record txg history
+is_linux && log_must set_tunable32 TXG_HISTORY 100
+
+# Make the devices bigger to reduce chances of overwriting MOS metadata.
+increase_device_sizes $(( FILE_SIZE * 4 ))
+
+# Increase the number of metaslabs for small pools temporarily to
+# reduce the chance of reusing a metaslab that holds old MOS metadata.
+log_must set_tunable64 VDEV_MIN_MS_COUNT 150
+
+# Part of the rewind test is to see how it reacts to path changes
+typeset pathstochange="$VDEV0 $VDEV1 $VDEV2 $VDEV3"
+
+log_note " == test rewind after device addition == "
+
+test_add_vdevs "$VDEV0" "$VDEV1"
+test_add_vdevs "$VDEV0 $VDEV1" "$VDEV2"
+test_add_vdevs "$VDEV0" "$VDEV1 $VDEV2"
+test_add_vdevs "mirror $VDEV0 $VDEV1" "mirror $VDEV2 $VDEV3"
+test_add_vdevs "$VDEV0" "raidz $VDEV1 $VDEV2 $VDEV3"
+test_add_vdevs "$VDEV0" "log $VDEV1"
+test_add_vdevs "$VDEV0 log $VDEV1" "$VDEV2"
+
+log_note " == test rewind after device attach == "
+
+test_attach_vdev "$VDEV0" "$VDEV0" "$VDEV1"
+test_attach_vdev "mirror $VDEV0 $VDEV1" "$VDEV0" "$VDEV2"
+test_attach_vdev "$VDEV0 $VDEV1" "$VDEV0" "$VDEV2"
+
+log_note " == test rewind after device removal == "
+
+# Once we remove a device it will be overlooked in the device scan, so we must
+# preserve its original path
+pathstochange="$VDEV0 $VDEV2"
+test_remove_vdev "$VDEV0 $VDEV1 $VDEV2" "$VDEV1" "$VDEV0 $VDEV2"
+
+#
+# Path change and detach are incompatible. Detach changes the guid of the vdev
+# so we have no direct way to link the new path to an existing vdev.
+#
+pathstochange=""
+
+log_note " == test rewind after device detach == "
+
+test_detach_vdev "mirror $VDEV0 $VDEV1" "$VDEV1"
+test_detach_vdev "mirror $VDEV0 $VDEV1 mirror $VDEV2 $VDEV3" "$VDEV1"
+test_detach_vdev "$VDEV0 log mirror $VDEV1 $VDEV2" "$VDEV2"
+
+log_note " == test rewind after device attach followed by device detach == "
+
+#
+# We need to disable vdev validation since once we detach VDEV1, VDEV0 will
+# inherit the mirror tvd's guid and lose its original guid.
+#
+set_vdev_validate_skip 1
+test_attach_detach_vdev "$VDEV0" "$VDEV0" "$VDEV1" "$VDEV1"
+set_vdev_validate_skip 0
+
+log_pass "zpool import rewind after configuration change passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_device_replaced.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_device_replaced.ksh
new file mode 100755
index 000000000000..94d1cb25d184
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_device_replaced.ksh
@@ -0,0 +1,181 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# It should be possible to rewind a pool beyond a device replacement.
+#
+# STRATEGY:
+# 1. Create a pool.
+# 2. Generate files and remember their md5sum.
+# 3. Sync a few times and note last synced txg.
+# 4. Take a snapshot to make sure old blocks are not overwritten.
+# 5. Initiate device replacement and export the pool. Special care must
+# be taken so that resilvering doesn't complete before the export.
+# 6. Test 1: Rewind pool to noted txg and then verify data checksums.
+# Import it read-only so that we do not overwrite blocks in later txgs.
+# 7. Re-import pool at latest txg and let the replacement finish.
+# 8. Export the pool an remove the new device - we shouldn't need it.
+# 9. Test 2: Rewind pool to noted txg and then verify data checksums.
+#
+# STRATEGY TO SLOW DOWN RESILVERING:
+# 1. Reduce zfs_txg_timeout, which controls how long can we resilver for
+# each sync.
+# 2. Add data to pool
+# 3. Re-import the pool so that data isn't cached
+# 4. Use zinject to slow down device I/O
+# 5. Trigger the resilvering
+# 6. Use spa freeze to stop writing to the pool.
+# 7. Clear zinject events (needed to export the pool)
+# 8. Export the pool
+#
+# DISCLAIMER:
+# This test can fail since nothing guarantees that old MOS blocks aren't
+# overwritten. Snapshots protect datasets and data files but not the MOS.
+# sync_some_data_a_few_times interleaves file data and MOS data for a few
+# txgs, thus increasing the odds that some txgs will have their MOS data
+# left untouched.
+#
+
+verify_runnable "global"
+
+ZFS_TXG_TIMEOUT=""
+
+function custom_cleanup
+{
+ # Revert zfs_txg_timeout to defaults
+ [[ -n $ZFS_TXG_TIMEOUT ]] &&
+ log_must set_zfs_txg_timeout $ZFS_TXG_TIMEOUT
+ log_must rm -rf $BACKUP_DEVICE_DIR
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+ cleanup
+}
+
+log_onexit custom_cleanup
+
+function test_replace_vdev
+{
+ typeset poolcreate="$1"
+ typeset replacevdev="$2"
+ typeset replaceby="$3"
+ typeset poolfinalstate="$4"
+ typeset zinjectdevices="$5"
+ typeset writedata="$6"
+
+ log_note "$0: pool '$poolcreate', replace $replacevdev by $replaceby."
+
+ log_must zpool create $TESTPOOL1 $poolcreate
+
+ # generate data and checksum it
+ log_must generate_data $TESTPOOL1 $MD5FILE
+
+ # add more data so that resilver takes longer
+ log_must write_some_data $TESTPOOL1 $writedata
+
+ # Syncing a few times while writing new data increases the odds that
+ # MOS metadata for some of the txgs will survive.
+ log_must sync_some_data_a_few_times $TESTPOOL1
+ typeset txg
+ txg=$(get_last_txg_synced $TESTPOOL1)
+ log_must zfs snapshot -r $TESTPOOL1@snap1
+
+ # This should not free original data.
+ log_must overwrite_data $TESTPOOL1 ""
+
+ log_must zpool export $TESTPOOL1
+ log_must zpool import -d $DEVICE_DIR $TESTPOOL1
+
+ # Ensure resilvering doesn't complete.
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+ log_must zpool replace $TESTPOOL1 $replacevdev $replaceby
+
+ # Confirm pool is still replacing
+ log_must pool_is_replacing $TESTPOOL1
+ log_must zpool export $TESTPOOL1
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+
+ ############################################################
+ # Test 1: rewind while device is resilvering.
+ # Import read only to avoid overwriting more recent blocks.
+ ############################################################
+ log_must zpool import -d $DEVICE_DIR -o readonly=on -T $txg $TESTPOOL1
+ log_must check_pool_config $TESTPOOL1 "$poolcreate"
+
+ log_must verify_data_md5sums $MD5FILE
+
+ log_must zpool export $TESTPOOL1
+
+ # Import pool at latest txg to finish the resilvering
+ log_must zpool import -d $DEVICE_DIR $TESTPOOL1
+ log_must overwrite_data $TESTPOOL1 ""
+ log_must wait_for_pool_config $TESTPOOL1 "$poolfinalstate"
+ log_must zpool export $TESTPOOL1
+
+ # Move out the new device
+ log_must mv $replaceby $BACKUP_DEVICE_DIR/
+
+ ############################################################
+ # Test 2: rewind after device has been replaced.
+ # Import read-write since we won't need the pool anymore.
+ ############################################################
+ log_must zpool import -d $DEVICE_DIR -T $txg $TESTPOOL1
+ log_must check_pool_config $TESTPOOL1 "$poolcreate"
+
+ log_must verify_data_md5sums $MD5FILE
+
+ # Cleanup
+ log_must zpool destroy $TESTPOOL1
+ # Restore the device we moved out
+ log_must mv "$BACKUP_DEVICE_DIR/$(basename $replaceby)" $DEVICE_DIR/
+ # Fast way to clear vdev labels
+ log_must zpool create -f $TESTPOOL2 $VDEV0 $VDEV1 $VDEV2 $VDEV3 $VDEV4
+ log_must zpool destroy $TESTPOOL2
+
+ log_note ""
+}
+
+# Record txg history
+is_linux && log_must set_tunable32 TXG_HISTORY 100
+
+log_must mkdir -p $BACKUP_DEVICE_DIR
+# Make the devices bigger to reduce chances of overwriting MOS metadata.
+increase_device_sizes $(( FILE_SIZE * 4 ))
+
+# We set zfs_txg_timeout to 1 to reduce resilvering time at each sync.
+ZFS_TXG_TIMEOUT=$(get_zfs_txg_timeout)
+set_zfs_txg_timeout 1
+
+test_replace_vdev "$VDEV0 $VDEV1" \
+ "$VDEV1" "$VDEV2" \
+ "$VDEV0 $VDEV2" \
+ "$VDEV0 $VDEV1" 15
+
+test_replace_vdev "mirror $VDEV0 $VDEV1" \
+ "$VDEV1" "$VDEV2" \
+ "mirror $VDEV0 $VDEV2" \
+ "$VDEV0 $VDEV1" 10
+
+test_replace_vdev "raidz $VDEV0 $VDEV1 $VDEV2" \
+ "$VDEV1" "$VDEV3" \
+ "raidz $VDEV0 $VDEV3 $VDEV2" \
+ "$VDEV0 $VDEV1 $VDEV2" 10
+
+set_zfs_txg_timeout $ZFS_TXG_TIMEOUT
+
+log_pass "zpool import rewind after device replacement passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/setup.ksh
new file mode 100755
index 000000000000..74324c84eac4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/setup.ksh
@@ -0,0 +1,56 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+verify_runnable "global"
+
+create_pool "$TESTPOOL" "$DISK"
+
+if [[ -d $TESTDIR ]]; then
+ rm -rf $TESTDIR || log_unresolved Could not remove $TESTDIR
+ mkdir -p $TESTDIR || log_unresolved Could not create $TESTDIR
+fi
+
+log_must zfs create $TESTPOOL/$TESTFS
+log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+
+[[ ! -d $DEVICE_DIR ]] && \
+ log_must mkdir -p $DEVICE_DIR
+
+i=0
+while (( i < $MAX_NUM )); do
+ log_must mkfile $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i
+ (( i = i + 1 ))
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.cfg
new file mode 100644
index 000000000000..6c1ab194e92c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.cfg
@@ -0,0 +1,64 @@
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+export DISK=${DISKS%% *}
+export FS_SIZE="$((($MINVDEVSIZE / (1024 * 1024)) * 32))m"
+export FILE_SIZE="$((MINVDEVSIZE))"
+export SLICE_SIZE="$((($MINVDEVSIZE / (1024 * 1024)) * 2))m"
+export MAX_NUM=5
+export DEVICE_DIR=$TEST_BASE_DIR/dev_import-test
+export BACKUP_DEVICE_DIR=$TEST_BASE_DIR/bakdev_import-test
+export DEVICE_FILE=disk
+export DEVICE_ARCHIVE=archive_import-test
+export MYTESTFILE=$STF_SUITE/include/libtest.shlib
+
+export CPATH=$TEST_BASE_DIR/cachefile.$$
+export CPATHBKP=$TEST_BASE_DIR/cachefile.$$.bkp
+export CPATHBKP2=$TEST_BASE_DIR/cachefile.$$.bkp2
+export MD5FILE=$TEST_BASE_DIR/md5sums.$$
+export MD5FILE2=$TEST_BASE_DIR/md5sums.$$.2
+
+export GROUP_NUM=3
+typeset -i num=0
+while (( num < $GROUP_NUM )); do
+ DEVICE_FILES="$DEVICE_FILES ${DEVICE_DIR}/${DEVICE_FILE}$num"
+ (( num = num + 1 ))
+done
+export DEVICE_FILES
+
+export VDEV0=$DEVICE_DIR/${DEVICE_FILE}0
+export VDEV1=$DEVICE_DIR/${DEVICE_FILE}1
+export VDEV2=$DEVICE_DIR/${DEVICE_FILE}2
+export VDEV3=$DEVICE_DIR/${DEVICE_FILE}3
+export VDEV4=$DEVICE_DIR/${DEVICE_FILE}4
+
+export ALTER_ROOT=/alter_import-test
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.kshlib b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.kshlib
new file mode 100644
index 000000000000..48794c982cf4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.kshlib
@@ -0,0 +1,356 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# Prototype cleanup function for zpool_import tests.
+#
+function cleanup
+{
+ # clear any remaining zinjections
+ log_must zinject -c all > /dev/null
+
+ destroy_pool $TESTPOOL1
+
+ log_must rm -f $CPATH $CPATHBKP $CPATHBKP2 $MD5FILE $MD5FILE2
+
+ log_must rm -rf $DEVICE_DIR/*
+ typeset i=0
+ while (( i < $MAX_NUM )); do
+ log_must mkfile $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i
+ ((i += 1))
+ done
+ is_linux && set_tunable32 TXG_HISTORY 0
+}
+
+#
+# Write a bit of data and sync several times.
+# This function is intended to be used by zpool rewind tests.
+#
+function sync_some_data_a_few_times
+{
+ typeset pool=$1
+ typeset -i a_few_times=${2:-10}
+
+ typeset file="/$pool/tmpfile"
+ for i in {0..$a_few_times}; do
+ dd if=/dev/urandom of=${file}_$i bs=128k count=10
+ sync_pool "$pool"
+ done
+
+ return 0
+}
+
+#
+# Just write a moderate amount of data to the pool.
+#
+function write_some_data
+{
+ typeset pool=$1
+ typeset files10mb=${2:-10}
+
+ typeset ds="$pool/fillerds"
+ zfs create $ds
+ [[ $? -ne 0 ]] && return 1
+
+ # Create 100 MB of data
+ typeset file="/$ds/fillerfile"
+ for i in {1..$files10mb}; do
+ dd if=/dev/urandom of=$file.$i bs=128k count=80
+ [[ $? -ne 0 ]] && return 1
+ done
+
+ return 0
+}
+
+#
+# Create/overwrite a few datasets with files.
+# Checksum all the files and store digests in a file.
+#
+# newdata: overwrite existing files if false.
+# md5file: file where to store md5 digests
+# datasetname: base name for datasets
+#
+function _generate_data_common
+{
+ typeset pool=$1
+ typeset newdata=$2
+ typeset md5file=$3
+ typeset datasetname=$4
+
+ typeset -i datasets=3
+ typeset -i files=5
+ typeset -i blocks=10
+
+ [[ -n $md5file ]] && rm -f $md5file
+ for i in {1..$datasets}; do
+ ( $newdata ) && log_must zfs create "$pool/$datasetname$i"
+ for j in {1..$files}; do
+ typeset file="/$pool/$datasetname$i/file$j"
+ dd if=/dev/urandom of=$file bs=128k count=$blocks > /dev/null
+ if [[ -n $md5file ]]; then
+ typeset cksum=$(md5digest $file)
+ echo $cksum $file >> $md5file
+ fi
+ done
+ ( $newdata ) && sync_pool "$pool"
+ done
+
+ return 0
+}
+
+function generate_data
+{
+ typeset pool=$1
+ typeset md5file="$2"
+ typeset datasetname=${3:-ds}
+
+ _generate_data_common $pool true "$md5file" $datasetname
+}
+
+function overwrite_data
+{
+ typeset pool=$1
+ typeset md5file="$2"
+ typeset datasetname=${3:-ds}
+
+ _generate_data_common $1 false "$md5file" $datasetname
+}
+
+#
+# Verify md5sums of every file in md5sum file $1.
+#
+function verify_data_md5sums
+{
+ typeset md5file=$1
+
+ if [[ ! -f $md5file ]]; then
+ log_note "md5 sums file '$md5file' doesn't exist"
+ return 1
+ fi
+
+ cat $md5file | \
+ while read digest file; do
+ typeset digest1=$(md5digest $file)
+ if [[ "$digest1" != "$digest" ]]; then
+ return 1
+ fi
+ done
+
+ return 0
+}
+
+#
+# Set devices size in DEVICE_DIR to $1.
+#
+function increase_device_sizes
+{
+ typeset newfilesize=$1
+
+ typeset -i i=0
+ while (( i < $MAX_NUM )); do
+ log_must mkfile $newfilesize ${DEVICE_DIR}/${DEVICE_FILE}$i
+ ((i += 1))
+ done
+}
+
+#
+# Translate vdev names returned by zpool status into more generic names.
+#
+# eg: mirror-2 --> mirror
+#
+function _translate_vdev
+{
+ typeset vdev=$1
+
+ typeset keywords="mirror replacing raidz1 raidz2 raidz3 indirect"
+ for word in $keywords; do
+ echo $vdev | egrep "^${word}-[0-9]+\$" > /dev/null
+ if [[ $? -eq 0 ]]; then
+ vdev=$word
+ break
+ fi
+ done
+
+ [[ $vdev == "logs" ]] && echo "log" && return 0
+ [[ $vdev == "raidz1" ]] && echo "raidz" && return 0
+
+ echo $vdev
+ return 0
+}
+
+#
+# Check that pool configuration returned by zpool status matches expected
+# configuration. Format for the check string is same as the vdev arguments for
+# creating a pool
+# Add -q for quiet mode.
+#
+# eg: check_pool_config pool1 "mirror c0t0d0s0 c0t1d0s0 log c1t1d0s0"
+#
+function check_pool_config
+{
+ typeset logfailure=true
+ if [[ $1 == '-q' ]]; then
+ logfailure=false
+ shift
+ fi
+
+ typeset poolname=$1
+ typeset expected=$2
+
+ typeset status
+ status=$(zpool status $poolname 2>&1)
+ if [[ $? -ne 0 ]]; then
+ if ( $logfailure ); then
+ log_note "zpool status $poolname failed: $status"
+ fi
+ return 1
+ fi
+
+ typeset actual=""
+ typeset began=false
+ printf "$status\n" | while read line; do
+ typeset vdev=$(echo "$line" | awk '{printf $1}')
+ if ( ! $began ) && [[ $vdev == NAME ]]; then
+ began=true
+ continue
+ fi
+ ( $began ) && [[ -z $vdev ]] && break;
+
+ if ( $began ); then
+ [[ -z $actual ]] && actual="$vdev" && continue
+ vdev=$(_translate_vdev $vdev)
+ actual="$actual $vdev"
+ fi
+ done
+
+ expected="$poolname $expected"
+
+ if [[ "$actual" != "$expected" ]]; then
+ if ( $logfailure ); then
+ log_note "expected pool vdevs:"
+ log_note "> '$expected'"
+ log_note "actual pool vdevs:"
+ log_note "> '$actual'"
+ fi
+ return 1
+ fi
+
+ return 0
+}
+
+#
+# Check that pool configuration returned by zpool status matches expected
+# configuration within a given timeout in seconds. See check_pool_config().
+#
+# eg: wait_for_pool_config pool1 "mirror c0t0d0s0 c0t1d0s0" 60
+#
+function wait_for_pool_config
+{
+ typeset poolname=$1
+ typeset expectedconfig="$2"
+ typeset -i timeout=${3:-60}
+
+ timeout=$(( $timeout + $(date +%s) ))
+
+ while (( $(date +%s) < $timeout )); do
+ check_pool_config -q $poolname "$expectedconfig"
+ [[ $? -eq 0 ]] && return 0
+ sleep 3
+ done
+
+ check_pool_config $poolname "$expectedconfig"
+ return $?
+}
+
+#
+# Check that pool status is ONLINE
+#
+function check_pool_healthy
+{
+ typeset pool=$1
+
+ typeset status
+ status=$(zpool status $pool 2>&1)
+ if [[ $? -ne 0 ]]; then
+ log_note "zpool status $pool failed: $status"
+ return 1
+ fi
+
+ status=$(echo "$status" | grep "$pool" | grep -v "pool:" | \
+ awk '{print $2}')
+
+ if [[ $status != "ONLINE" ]]; then
+ log_note "Invalid zpool status for '$pool': '$status'" \
+ "!= 'ONLINE'"
+ return 1
+ fi
+
+ return 0
+}
+
+#
+# Return 0 if a device is currently being replaced in the pool.
+#
+function pool_is_replacing
+{
+ typeset pool=$1
+
+ zpool status $pool | grep "replacing" | grep "ONLINE" > /dev/null
+
+ return $?
+}
+
+function set_vdev_validate_skip
+{
+ set_tunable32 VDEV_VALIDATE_SKIP "$1"
+}
+
+function get_zfs_txg_timeout
+{
+ get_tunable TXG_TIMEOUT
+}
+
+function set_zfs_txg_timeout
+{
+ set_tunable32 TXG_TIMEOUT "$1"
+}
+
+function set_spa_load_verify_metadata
+{
+ set_tunable32 SPA_LOAD_VERIFY_METADATA "$1"
+}
+
+function set_spa_load_verify_data
+{
+ set_tunable32 SPA_LOAD_VERIFY_DATA "$1"
+}
+
+function set_zfs_max_missing_tvds
+{
+ set_tunable32 MAX_MISSING_TVDS "$1"
+}
+
+#
+# Use zdb to find the last txg that was synced in an active pool.
+#
+function get_last_txg_synced
+{
+ typeset pool=$1
+
+ zdb -u $pool | awk '$1 == "txg" { print $3 }' | sort -n | tail -n 1
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_001_pos.ksh
new file mode 100755
index 000000000000..6369a297c17d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_001_pos.ksh
@@ -0,0 +1,138 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# Once a pool has been exported, it should be recreated after a
+# successful import. Verify that is true.
+#
+# STRATEGY:
+# 1. Populate the default test directory and unmount it.
+# 2. Export the default test pool.
+# 3. Import it using the various combinations.
+# - Regular import
+# - Alternate Root Specified
+# Try to import it by name or guid randomly.
+# 4. Verify it shows up under 'zpool list'.
+# 5. Verify it can be mounted again and contains a file.
+#
+
+verify_runnable "global"
+
+set -A pools "$TESTPOOL" "$TESTPOOL1"
+set -A devs " -s" "-d $DEVICE_DIR"
+set -A options "" "-R $ALTER_ROOT"
+set -A mtpts "$TESTDIR" "$TESTDIR1"
+
+
+function cleanup
+{
+ typeset -i i=0
+
+ while (( i < ${#pools[*]} )); do
+ poolexists ${pools[i]} && \
+ log_must zpool export ${pools[i]}
+
+ datasetexists "${pools[i]}/$TESTFS" || \
+ log_must zpool import ${devs[i]} ${pools[i]}
+
+ ismounted "${pools[i]}/$TESTFS" || \
+ log_must zfs mount ${pools[i]}/$TESTFS
+
+ [[ -e ${mtpts[i]}/$TESTFILE0 ]] && \
+ log_must rm -rf ${mtpts[i]}/$TESTFILE0
+
+ ((i = i + 1))
+ done
+
+ cleanup_filesystem $TESTPOOL1 $TESTFS
+
+ destroy_pool $TESTPOOL1
+
+ [[ -d $ALTER_ROOT ]] && \
+ log_must rm -rf $ALTER_ROOT
+}
+
+log_onexit cleanup
+
+log_assert "Verify that an exported pool can be imported."
+
+setup_filesystem "$DEVICE_FILES" $TESTPOOL1 $TESTFS $TESTDIR1
+
+checksum1=$(sum $MYTESTFILE | awk '{print $1}')
+
+typeset -i i=0
+typeset -i j=0
+typeset basedir
+
+while (( i < ${#pools[*]} )); do
+ guid=$(get_config ${pools[i]} pool_guid)
+ log_must cp $MYTESTFILE ${mtpts[i]}/$TESTFILE0
+
+ log_must zfs umount ${mtpts[i]}
+
+ j=0
+ while (( j < ${#options[*]} )); do
+ log_must zpool export ${pools[i]}
+
+ typeset target=${pools[i]}
+ if (( RANDOM % 2 == 0 )) ; then
+ target=$guid
+ log_note "Import by guid."
+ fi
+ log_must zpool import ${devs[i]} ${options[j]} $target
+
+ log_must poolexists ${pools[i]}
+
+ log_must ismounted ${pools[i]}/$TESTFS
+
+ basedir=${mtpts[i]}
+ [[ -n ${options[j]} ]] && \
+ basedir=$ALTER_ROOT/${mtpts[i]}
+
+ [[ ! -e $basedir/$TESTFILE0 ]] && \
+ log_fail "$basedir/$TESTFILE0 missing after import."
+
+ checksum2=$(sum $basedir/$TESTFILE0 | awk '{print $1}')
+ [[ "$checksum1" != "$checksum2" ]] && \
+ log_fail "Checksums differ ($checksum1 != $checksum2)"
+
+ ((j = j + 1))
+ done
+
+ ((i = i + 1))
+done
+
+log_pass "Successfully imported a ZPOOL"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_002_pos.ksh
new file mode 100755
index 000000000000..898f93cc9062
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_002_pos.ksh
@@ -0,0 +1,142 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# Verify that an exported pool cannot be imported
+# more than once.
+#
+# STRATEGY:
+# 1. Populate the default test directory and unmount it.
+# 2. Export the default test pool.
+# 3. Import it using the various combinations.
+# - Regular import
+# - Alternate Root Specified
+# 4. Verify it shows up under 'zpool list'.
+# 5. Verify it contains a file.
+# 6. Attempt to import it for a second time. Verify this fails.
+#
+
+verify_runnable "global"
+
+set -A pools "$TESTPOOL" "$TESTPOOL1"
+set -A devs "" "-d $DEVICE_DIR"
+set -A options "" "-R $ALTER_ROOT"
+set -A mtpts "$TESTDIR" "$TESTDIR1"
+
+
+function cleanup
+{
+ typeset -i i=0
+ while (( i < ${#pools[*]} )); do
+ poolexists ${pools[i]} && \
+ log_must zpool export ${pools[i]}
+
+ datasetexists "${pools[i]}/$TESTFS" || \
+ log_must zpool import ${devs[i]} ${pools[i]}
+
+ ismounted "${pools[i]}/$TESTFS" || \
+ log_must zfs mount ${pools[i]}/$TESTFS
+
+ [[ -e ${mtpts[i]}/$TESTFILE0 ]] && \
+ log_must rm -rf ${mtpts[i]}/$TESTFILE0
+
+ ((i = i + 1))
+ done
+
+ cleanup_filesystem $TESTPOOL1 $TESTFS
+
+ destroy_pool $TESTPOOL1
+
+ [[ -d $ALTER_ROOT ]] && \
+ log_must rm -rf $ALTER_ROOT
+}
+
+log_onexit cleanup
+
+log_assert "Verify that an exported pool cannot be imported more than once."
+
+setup_filesystem "$DEVICE_FILES" $TESTPOOL1 $TESTFS $TESTDIR1
+
+checksum1=$(sum $MYTESTFILE | awk '{print $1}')
+
+typeset -i i=0
+typeset -i j=0
+typeset basedir
+
+while (( i < ${#pools[*]} )); do
+ guid=$(get_config ${pools[i]} pool_guid)
+
+ log_must cp $MYTESTFILE ${mtpts[i]}/$TESTFILE0
+
+ log_must zfs umount ${mtpts[i]}
+
+ j=0
+ while (( j < ${#options[*]} )); do
+ log_must zpool export ${pools[i]}
+
+ typeset target=${pools[i]}
+ if (( RANDOM % 2 == 0 )) ; then
+ target=$guid
+ log_note "Import by guid."
+ fi
+
+ log_must zpool import ${devs[i]} ${options[j]} $target
+
+ log_must poolexists ${pools[i]}
+
+ log_must ismounted ${pools[i]}/$TESTFS
+
+ basedir=${mtpts[i]}
+ [[ -n ${options[j]} ]] && \
+ basedir=$ALTER_ROOT/${mtpts[i]}
+
+ [[ ! -e $basedir/$TESTFILE0 ]] && \
+ log_fail "$basedir/$TESTFILE0 missing after import."
+
+ checksum2=$(sum $basedir/$TESTFILE0 | awk '{print $1}')
+ [[ "$checksum1" != "$checksum2" ]] && \
+ log_fail "Checksums differ ($checksum1 != $checksum2)"
+
+ log_mustnot zpool import ${devs[i]} $target
+
+ ((j = j + 1))
+ done
+
+ ((i = i + 1))
+
+done
+
+log_pass "Unable to import the same pool twice as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_003_pos.ksh
new file mode 100755
index 000000000000..dfda989deab9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_003_pos.ksh
@@ -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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# Destroyed pools are not listed unless with -D option is specified.
+#
+# STRATEGY:
+# 1. Create test pool A.
+# 2. Destroy pool A.
+# 3. Verify only 'import -D' can list pool A.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL1
+
+ log_must rm $VDEV0 $VDEV1
+ log_must mkfile $FILE_SIZE $VDEV0 $VDEV1
+}
+
+log_assert "Destroyed pools are not listed unless with -D option is specified."
+log_onexit cleanup
+
+log_must zpool create $TESTPOOL1 $VDEV0 $VDEV1
+log_must zpool destroy $TESTPOOL1
+
+#
+# 'pool:' is the keywords of 'zpool import -D' output.
+#
+log_mustnot eval "zpool import -d $DEVICE_DIR | grep pool:"
+log_must eval "zpool import -d $DEVICE_DIR -D | grep pool:"
+
+log_pass "Destroyed pool only can be listed with -D option."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_004_pos.ksh
new file mode 100755
index 000000000000..657e28be2563
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_004_pos.ksh
@@ -0,0 +1,88 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# Destroyed pools devices was moved to another directory, it still can be
+# imported correctly.
+#
+# STRATEGY:
+# 1. Create test pool A with several devices.
+# 2. Destroy pool A.
+# 3. Move devices to another directory.
+# 4. Verify 'zpool import -D' succeed.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL1
+
+ log_must rm -rf $DEVICE_DIR/*
+ typeset i=0
+ while (( i < $MAX_NUM )); do
+ log_must mkfile $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i
+ ((i += 1))
+ done
+}
+
+log_assert "Destroyed pools devices was moved to another directory," \
+ "it still can be imported correctly."
+log_onexit cleanup
+
+log_must zpool create $TESTPOOL1 $VDEV0 $VDEV1 $VDEV2
+typeset guid=$(get_config $TESTPOOL1 pool_guid)
+typeset target=$TESTPOOL1
+if (( RANDOM % 2 == 0 )) ; then
+ target=$guid
+ log_note "Import by guid."
+fi
+log_must zpool destroy $TESTPOOL1
+
+log_note "Devices was moved to different directories."
+log_must mkdir $DEVICE_DIR/newdir1 $DEVICE_DIR/newdir2
+log_must mv $VDEV1 $DEVICE_DIR/newdir1
+log_must mv $VDEV2 $DEVICE_DIR/newdir2
+log_must zpool import -d $DEVICE_DIR/newdir1 -d $DEVICE_DIR/newdir2 \
+ -d $DEVICE_DIR -D -f $target
+log_must zpool destroy -f $TESTPOOL1
+
+log_note "Devices was moved to same directory."
+log_must mv $VDEV0 $DEVICE_DIR/newdir2
+log_must mv $DEVICE_DIR/newdir1/* $DEVICE_DIR/newdir2
+log_must zpool import -d $DEVICE_DIR/newdir2 -D -f $target
+log_must zpool destroy -f $TESTPOOL1
+
+log_pass "Destroyed pools devices was moved, 'zpool import -D' passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_005_pos.ksh
new file mode 100755
index 000000000000..79f026ede55f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_005_pos.ksh
@@ -0,0 +1,85 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# Destroyed pools devices was renamed, it still can be imported correctly.
+#
+# STRATEGY:
+# 1. Create test pool A with several devices.
+# 2. Destroy pool A and rename devices name.
+# 3. Verify 'zpool import -D' succeed.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL1
+
+ log_must rm -rf $DEVICE_DIR/*
+ typeset i=0
+ while (( i < $MAX_NUM )); do
+ log_must mkfile $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i
+ ((i += 1))
+ done
+}
+
+log_assert "Destroyed pools devices was renamed, it still can be imported " \
+ "correctly."
+log_onexit cleanup
+
+log_must zpool create $TESTPOOL1 $VDEV0 $VDEV1 $VDEV2
+typeset guid=$(get_config $TESTPOOL1 pool_guid)
+typeset target=$TESTPOOL1
+if (( RANDOM % 2 == 0 )) ; then
+ target=$guid
+ log_note "Import by guid."
+fi
+log_must zpool destroy $TESTPOOL1
+
+log_note "Part of devices was renamed in the same directory."
+log_must mv $VDEV0 $DEVICE_DIR/vdev0-new
+log_must zpool import -d $DEVICE_DIR -D -f $target
+log_must zpool destroy -f $TESTPOOL1
+
+log_note "All of devices was rename to different directories."
+log_must mkdir $DEVICE_DIR/newdir1 $DEVICE_DIR/newdir2
+log_must mv $VDEV1 $DEVICE_DIR/newdir1/vdev1-new
+log_must mv $VDEV2 $DEVICE_DIR/newdir2/vdev2-new
+log_must zpool import -d $DEVICE_DIR/newdir1 -d $DEVICE_DIR/newdir2 \
+ -d $DEVICE_DIR -D -f $target
+log_must zpool destroy -f $TESTPOOL1
+
+log_pass "Destroyed pools devices was renamed, 'zpool import -D' passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_006_pos.ksh
new file mode 100755
index 000000000000..2353bb07d040
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_006_pos.ksh
@@ -0,0 +1,83 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# For mirror, N-1 destroyed pools devices was removed or used by other
+# pool, it still can be imported correctly.
+#
+# STRATEGY:
+# 1. Create mirror with N disks.
+# 2. Destroy this mirror.
+# 3. Create another pool with N-1 disks which was used by this mirror.
+# 4. Verify import mirror can succeed.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL2
+ destroy_pool $TESTPOOL1
+
+ log_must rm -rf $DEVICE_DIR/*
+ typeset i=0
+ while (( i < $MAX_NUM )); do
+ log_must mkfile $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i
+ ((i += 1))
+ done
+}
+
+log_assert "For mirror, N-1 destroyed pools devices was removed or used " \
+ "by other pool, it still can be imported correctly."
+log_onexit cleanup
+
+log_must zpool create $TESTPOOL1 mirror $VDEV0 $VDEV1 $VDEV2
+typeset guid=$(get_config $TESTPOOL1 pool_guid)
+typeset target=$TESTPOOL1
+if (( RANDOM % 2 == 0 )) ; then
+ target=$guid
+ log_note "Import by guid."
+fi
+log_must zpool destroy $TESTPOOL1
+
+log_must zpool create $TESTPOOL2 $VDEV0 $VDEV2
+log_must zpool import -d $DEVICE_DIR -D -f $target
+log_must zpool destroy $TESTPOOL1
+
+log_must zpool destroy $TESTPOOL2
+log_must rm -rf $VDEV2
+log_must zpool import -d $DEVICE_DIR -D -f $target
+
+log_pass "zpool import -D mirror passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_007_pos.ksh
new file mode 100755
index 000000000000..6e93fd471171
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_007_pos.ksh
@@ -0,0 +1,90 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# For raidz, one destroyed pools devices was removed or used by other
+# pool, it still can be imported correctly.
+#
+# STRATEGY:
+# 1. Create a raidz pool A with N disks.
+# 2. Destroy this pool A.
+# 3. Create another pool B with 1 disk which was used by pool A.
+# 4. Verify import this raidz pool can succeed.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL2
+ destroy_pool $TESTPOOL1
+
+ log_must rm -rf $DEVICE_DIR/*
+ typeset i=0
+ while (( i < $MAX_NUM )); do
+ log_must mkfile $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i
+ ((i += 1))
+ done
+}
+
+log_assert "For raidz, one destroyed pools devices was removed or used by " \
+ "other pool, it still can be imported correctly."
+log_onexit cleanup
+
+log_must zpool create $TESTPOOL1 raidz $VDEV0 $VDEV1 $VDEV2 $VDIV3
+typeset guid=$(get_config $TESTPOOL1 pool_guid)
+typeset target=$TESTPOOL1
+if (( RANDOM % 2 == 0 )) ; then
+ target=$guid
+ log_note "Import by guid."
+fi
+log_must zpool destroy $TESTPOOL1
+
+log_must zpool create $TESTPOOL2 $VDEV0
+log_must zpool import -d $DEVICE_DIR -D -f $target
+log_must zpool destroy $TESTPOOL1
+
+log_must zpool destroy $TESTPOOL2
+log_must rm -rf $VDEV0
+log_must zpool import -d $DEVICE_DIR -D -f $target
+log_must zpool destroy $TESTPOOL1
+
+log_note "For raidz, two destroyed pool's devices were used, import failed."
+log_must mkfile $FILE_SIZE $VDEV0
+log_must zpool create $TESTPOOL2 $VDEV0 $VDEV1
+log_mustnot zpool import -d $DEVICE_DIR -D -f $target
+log_must zpool destroy $TESTPOOL2
+
+log_pass "zpool import -D raidz passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_008_pos.ksh
new file mode 100755
index 000000000000..096bbe8114ac
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_008_pos.ksh
@@ -0,0 +1,91 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# For raidz2, two destroyed pool's devices were removed or used by other
+# pool, it still can be imported correctly.
+#
+# STRATEGY:
+# 1. Create a raidz2 pool A with N disks.
+# 2. Destroy this pool A.
+# 3. Create another pool B with two disks which were used by pool A.
+# 4. Verify import this raidz2 pool can succeed.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL2
+ destroy_pool $TESTPOOL1
+
+ log_must rm -rf $DEVICE_DIR/*
+ typeset i=0
+ while (( i < $MAX_NUM )); do
+ log_must mkfile $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i
+ ((i += 1))
+ done
+}
+
+log_assert "For raidz2, two destroyed pools devices was removed or used by " \
+ "other pool, it still can be imported correctly."
+log_onexit cleanup
+
+log_must zpool create $TESTPOOL1 raidz2 $VDEV0 $VDEV1 $VDEV2 $VDIV3
+typeset guid=$(get_config $TESTPOOL1 pool_guid)
+typeset target=$TESTPOOL1
+if (( RANDOM % 2 == 0 )) ; then
+ target=$guid
+ log_note "Import by guid."
+fi
+log_must zpool destroy $TESTPOOL1
+
+log_must zpool create $TESTPOOL2 $VDEV0 $VDEV1
+log_must zpool import -d $DEVICE_DIR -D -f $target
+log_must zpool destroy $TESTPOOL1
+
+log_must zpool destroy $TESTPOOL2
+log_must rm -rf $VDEV0 $VDEV1
+log_must zpool import -d $DEVICE_DIR -D -f $target
+log_must zpool destroy $TESTPOOL1
+
+log_note "For raidz2, more than two destroyed pool's devices were used, " \
+ "import failed."
+log_must mkfile $FILE_SIZE $VDEV0 $VDEV1
+log_must zpool create $TESTPOOL2 $VDEV0 $VDEV1 $VDEV2
+log_mustnot zpool import -d $DEVICE_DIR -D -f $target
+log_must zpool destroy $TESTPOOL2
+
+log_pass "zpool import -D raidz2 passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_009_neg.ksh
new file mode 100755
index 000000000000..e7886ef3c859
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_009_neg.ksh
@@ -0,0 +1,103 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+# DESCRIPTION:
+# Try each 'zpool import' with inapplicable scenarios to make sure
+# it returns an error. include:
+# * A non-existent pool name is given
+# * '-d', but no device directory specified
+# * '-R', but no alter root directory specified
+# * '-a', but a pool name specified either
+# * more than 2 pool names is given
+# * The new pool name specified already exists
+# * Contain invalid characters not allowed in the ZFS namespace
+#
+# STRATEGY:
+# 1. Create an array of parameters
+# 2. For each parameter in the array, execute the sub-command
+# 3. Verify an error is returned.
+#
+
+verify_runnable "global"
+
+set -A args "blah" "-d" "-R" "-a $TESTPOOL" \
+ "$TESTPOOL ${TESTPOOL}-new ${TESTPOOL}-new" \
+ "$TESTPOOL $TESTPOOL1" \
+ "$TESTPOOL ${TESTPOOL1}*" "$TESTPOOL ${TESTPOOL1}?"
+
+set -A pools "$TESTPOOL" "$TESTPOOL1"
+set -A devs "" "-d $DEVICE_DIR"
+
+function cleanup
+{
+ typeset -i i=0
+ typeset -i j=0
+
+ while (( i < ${#pools[*]} )); do
+
+ poolexists ${pools[i]} && \
+ log_must zpool export ${pools[i]}
+
+ datasetexists "${pools[i]}/$TESTFS" || \
+ log_must zpool import ${devs[i]} ${pools[i]}
+
+ ismounted "${pools[i]}/$TESTFS" || \
+ log_must zfs mount ${pools[i]}/$TESTFS
+
+ ((i = i + 1))
+ done
+
+ cleanup_filesystem $TESTPOOL1 $TESTFS
+
+ destroy_pool $TESTPOOL1
+}
+
+log_onexit cleanup
+
+log_assert "Badly-formed 'zpool import' with inapplicable scenarios " \
+ "should return an error."
+
+setup_filesystem "$DEVICE_FILES" $TESTPOOL1 $TESTFS $TESTDIR1
+
+log_must zpool export $TESTPOOL
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_mustnot zpool import ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "Badly formed 'zpool import' with inapplicable scenarios " \
+ "fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_010_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_010_pos.ksh
new file mode 100755
index 000000000000..b337bd00f1e5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_010_pos.ksh
@@ -0,0 +1,92 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# 'zpool -D -a' can import all the specified directories destroyed pools.
+#
+# STRATEGY:
+# 1. Create a 5 ways mirror pool A with dev0/1/2/3/4, then destroy it.
+# 2. Create a stripe pool B with dev1. Then destroy it.
+# 3. Create a raidz2 pool C with dev2/3/4. Then destroy it.
+# 4. Create a raidz pool D with dev3/4. Then destroy it.
+# 5. Create a stripe pool E with dev4. Then destroy it.
+# 6. Verify 'zpool import -D -a' recover all the pools.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset dt
+ for dt in $poolE $poolD $poolC $poolB $poolA; do
+ destroy_pool $dt
+ done
+
+ log_must rm -rf $DEVICE_DIR/*
+ typeset i=0
+ while (( i < $MAX_NUM )); do
+ log_must mkfile $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i
+ ((i += 1))
+ done
+}
+
+log_assert "'zpool -D -a' can import all the specified directories " \
+ "destroyed pools."
+log_onexit cleanup
+
+poolA=poolA.$$; poolB=poolB.$$; poolC=poolC.$$; poolD=poolD.$$; poolE=poolE.$$
+
+log_must zpool create $poolA mirror $VDEV0 $VDEV1 $VDEV2 $VDEV3 $VDEV4
+log_must zpool destroy $poolA
+
+log_must zpool create $poolB $VDEV1
+log_must zpool destroy $poolB
+
+log_must zpool create $poolC raidz2 $VDEV2 $VDEV3 $VDEV4
+log_must zpool destroy $poolC
+
+log_must zpool create $poolD raidz $VDEV3 $VDEV4
+log_must zpool destroy $poolD
+
+log_must zpool create $poolE $VDEV4
+log_must zpool destroy $poolE
+
+log_must zpool import -d $DEVICE_DIR -D -f -a
+
+for dt in $poolA $poolB $poolC $poolD $poolE; do
+ log_must datasetexists $dt
+done
+
+log_pass "'zpool -D -a' test passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_011_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_011_neg.ksh
new file mode 100755
index 000000000000..b54168941722
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_011_neg.ksh
@@ -0,0 +1,81 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# For strip pool, any destroyed pool devices was demaged, zpool import -D
+# will failed.
+#
+# STRATEGY:
+# 1. Create strip pool A with three devices.
+# 2. Destroy this pool B.
+# 3. Create pool B with one of devices in step 1.
+# 4. Verify 'import -D' pool A will failed whenever pool B was destroyed
+# or not.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL1
+ destroy_pool $TESTPOOL2
+
+ #
+ # Recreate virtual devices to avoid destroyed pool information on files.
+ #
+ log_must rm -rf $VDEV0 $VDEV1 $VDEV2
+ log_must mkfile $FILE_SIZE $VDEV0 $VDEV1 $VDEV2
+}
+
+log_assert "For strip pool, any destroyed pool devices was demaged," \
+ "zpool import -D will failed."
+log_onexit cleanup
+
+log_must zpool create $TESTPOOL1 $VDEV0 $VDEV1 $VDEV2
+typeset guid=$(get_config $TESTPOOL1 pool_guid)
+typeset target=$TESTPOOL1
+if (( RANDOM % 2 == 0 )) ; then
+ target=$guid
+ log_note "Import by guid."
+fi
+log_must zpool destroy $TESTPOOL1
+log_must zpool create $TESTPOOL2 $VDEV2
+
+log_mustnot zpool import -d $DEVICE_DIR -D -f $target
+
+log_must zpool destroy $TESTPOOL2
+log_mustnot zpool import -d $DEVICE_DIR -D -f $target
+
+log_pass "Any strip pool devices damaged, pool can't be import passed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_012_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_012_pos.ksh
new file mode 100755
index 000000000000..a568948e37c4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_012_pos.ksh
@@ -0,0 +1,211 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# Once a pool has been exported, it should be recreated after a
+# successful import, all the sub-filesystems within it should all be restored,
+# include mount & share status. Verify that is true.
+#
+# STRATEGY:
+# 1. Create the test pool and hierarchical filesystems.
+# 2. Export the test pool, or destroy the test pool,
+# depend on testing import [-Df].
+# 3. Import it using the various combinations.
+# - Regular import
+# - Alternate Root Specified
+# 4. Verify the mount & share status is restored.
+#
+
+verify_runnable "global"
+
+set -A pools "$TESTPOOL" "$TESTPOOL1"
+set -A devs "" "-d $DEVICE_DIR"
+set -A options "" "-R $ALTER_ROOT"
+set -A mtpts "$TESTDIR" "$TESTDIR1"
+
+
+function cleanup
+{
+ typeset -i i=0
+
+ while ((i < ${#pools[*]})); do
+ if poolexists ${pools[i]}; then
+ log_must zpool export ${pools[i]}
+ log_note "Try to import ${devs[i]} ${pools[i]}"
+ zpool import ${devs[i]} ${pools[i]}
+ else
+ log_note "Try to import $option ${devs[i]} ${pools[i]}"
+ zpool import $option ${devs[i]} ${pools[i]}
+ fi
+
+ if poolexists ${pools[i]}; then
+ is_shared ${pools[i]} && \
+ log_must zfs set sharenfs=off ${pools[i]}
+
+ ismounted "${pools[i]}/$TESTFS" || \
+ log_must zfs mount ${pools[i]}/$TESTFS
+ fi
+
+ ((i = i + 1))
+ done
+
+ destroy_pool $TESTPOOL1
+
+ if datasetexists $TESTPOOL/$TESTFS; then
+ log_must zfs destroy -Rf $TESTPOOL/$TESTFS
+ fi
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+
+ [[ -d $ALTER_ROOT ]] && \
+ log_must rm -rf $ALTER_ROOT
+}
+
+log_onexit cleanup
+
+log_assert "Verify all mount & share status of sub-filesystems within a pool \
+ can be restored after import [-Df]."
+
+setup_filesystem "$DEVICE_FILES" $TESTPOOL1 $TESTFS $TESTDIR1
+# create a hierarchy of filesystem
+for pool in ${pools[@]} ; do
+ log_must zfs create $pool/$TESTFS/$TESTCTR
+ log_must zfs create $pool/$TESTFS/$TESTCTR/$TESTCTR1
+ log_must zfs set canmount=off $pool/$TESTFS/$TESTCTR
+ log_must zfs set canmount=off $pool/$TESTFS/$TESTCTR/$TESTCTR1
+ log_must zfs create $pool/$TESTFS/$TESTCTR/$TESTFS1
+ log_must zfs create $pool/$TESTFS/$TESTCTR/$TESTCTR1/$TESTFS1
+ log_must zfs create $pool/$TESTFS/$TESTFS1
+ log_must zfs snapshot $pool/$TESTFS/$TESTFS1@snap
+ log_must zfs clone $pool/$TESTFS/$TESTFS1@snap $pool/$TESTCLONE1
+done
+
+typeset mount_fs="$TESTFS $TESTFS/$TESTFS1 $TESTCLONE1 \
+ $TESTFS/$TESTCTR/$TESTFS1 $TESTFS/$TESTCTR/$TESTCTR1/$TESTFS1"
+typeset nomount_fs="$TESTFS/$TESTCTR $TESTFS/$TESTCTR/$TESTCTR1"
+
+typeset -i i=0
+typeset -i j=0
+typeset -i nfs_share_bit=0
+typeset -i guid_bit=0
+typeset basedir
+
+for option in "" "-Df"; do
+ i=0
+ while ((i < ${#pools[*]})); do
+ pool=${pools[i]}
+ guid=$(get_pool_prop guid $pool)
+ j=0
+ while ((j < ${#options[*]})); do
+ # set sharenfs property off/on
+ nfs_share_bit=0
+ while ((nfs_share_bit <= 1)); do
+ typeset f_share=""
+ typeset nfs_flag="sharenfs=off"
+ if ((nfs_share_bit == 1)); then
+ log_note "Set sharenfs=on $pool"
+ log_must zfs set sharenfs=on $pool
+ ! is_freebsd && log_must is_shared $pool
+ f_share="true"
+ nfs_flag="sharenfs=on"
+ fi
+ # for every off/on nfs bit import guid/pool_name
+ guid_bit=0
+ while ((guid_bit <= 1)); do
+ typeset guid_flag="pool name"
+ if [[ -z $option ]]; then
+ log_must_busy zpool export $pool
+ else
+ log_must_busy zpool destroy $pool
+ fi
+
+ typeset target=$pool
+ if ((guid_bit == 1)); then
+ log_note "Import by guid."
+ if [[ -z $guid ]]; then
+ log_fail "guid should "\
+ "not be empty!"
+ else
+ target=$guid
+ guid_flag="$guid"
+ fi
+ fi
+ log_note "Import with $nfs_flag and " \
+ "$guid_flag"
+ zpool import $option ${devs[i]} \
+ ${options[j]} $target
+ #import by GUID if import by pool name fails
+ if [[ $? != 0 ]]; then
+ log_note "Possible pool name" \
+ "duplicates. Try GUID import"
+ target=$guid
+ log_must zpool import $option \
+ ${devs[i]} ${options[j]} \
+ $target
+ fi
+ log_must poolexists $pool
+
+ for fs in $mount_fs; do
+ log_must ismounted $pool/$fs
+ [[ -n $f_share ]] && \
+ ! is_freebsd && \
+ log_must is_shared $pool/$fs
+ done
+
+ for fs in $nomount_fs; do
+ log_mustnot ismounted $pool/$fs
+ ! is_freebsd && \
+ log_mustnot is_shared $pool/$fs
+ done
+ ((guid_bit = guid_bit + 1))
+ done
+ # reset nfsshare=off
+ if [[ -n $f_share ]]; then
+ log_must zfs set sharenfs=off $pool
+ ! is_freebsd && log_mustnot is_shared $pool
+ fi
+ ((nfs_share_bit = nfs_share_bit + 1))
+ done
+
+ ((j = j + 1))
+ done
+
+ ((i = i + 1))
+ done
+done
+
+log_pass "All mount & share status of sub-filesystems within a pool \
+ can be restored after import [-Df]."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_013_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_013_neg.ksh
new file mode 100755
index 000000000000..7fef6254fa68
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_013_neg.ksh
@@ -0,0 +1,74 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# For pool may be in use from other system,
+# 'zpool import' will prompt the warning and fails.
+#
+# STRATEGY:
+# 1. Prepare rawfile that are created from other system.
+# 2. Verify 'zpool import' will fail.
+# 3. Verify 'zpool import -f' succeed.
+#
+
+verify_runnable "global"
+
+POOL_NAME=unclean_export
+POOL_FILE=unclean_export.dat
+
+function uncompress_pool
+{
+
+ log_note "Creating pool from $POOL_FILE"
+ log_must bzcat \
+ $STF_SUITE/tests/functional/cli_root/zpool_import/blockfiles/$POOL_FILE.bz2 \
+ > /$TESTPOOL/$POOL_FILE
+ return 0
+}
+
+function cleanup
+{
+ poolexists $POOL_NAME && destroy_pool $POOL_NAME
+ rm -f /$TESTPOOL/$POOL_FILE
+}
+
+log_assert "'zpool import' fails for pool that was not cleanly exported"
+log_onexit cleanup
+
+uncompress_pool
+log_mustnot zpool import -d /$TESTPOOL $POOL_NAME
+log_must zpool import -d /$TESTPOOL -f $POOL_NAME
+
+log_pass "'zpool import' fails for pool that was not cleanly exported"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_014_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_014_pos.ksh
new file mode 100755
index 000000000000..d70bced265f3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_014_pos.ksh
@@ -0,0 +1,91 @@
+#!/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 2016, loli10K. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# Temporary pool names should not be persisted on devices.
+#
+# STRATEGY:
+# 1. Create pool A, then export it.
+# 2. Re-import the pool with a temporary name B, then export it.
+# 3. Verify device labels still contain the expected pool name (A).
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset dt
+ for dt in $poolB $poolA; do
+ destroy_pool $dt
+ done
+
+ log_must rm -rf $DEVICE_DIR/*
+ typeset i=0
+ while (( i < $MAX_NUM )); do
+ log_must mkfile $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i
+ ((i += 1))
+ done
+}
+
+#
+# Verify name of (exported) pool from device $1 label is equal to $2
+# $1 device
+# $2 pool name
+#
+function verify_pool_name
+{
+ typeset device=$1
+ typeset poolname=$2
+ typeset labelname
+
+ zdb -e -l $device | grep " name:" | {
+ while read labelname ; do
+ if [[ "name: '$poolname'" != "$labelname" ]]; then
+ return 1
+ fi
+ done
+ }
+ return 0
+}
+
+log_assert "Temporary pool names should not be persisted on devices."
+log_onexit cleanup
+
+poolA=poolA.$$; poolB=poolB.$$;
+
+log_must zpool create $poolA $VDEV0
+log_must zpool export $poolA
+
+log_must zpool import -t $poolA $poolB -d $DEVICE_DIR
+log_must zpool export $poolB
+
+log_must eval "verify_pool_name $VDEV0 $poolA"
+
+log_pass "Temporary pool names are not persisted on devices."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_015_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_015_pos.ksh
new file mode 100755
index 000000000000..c984b9bf045a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_015_pos.ksh
@@ -0,0 +1,54 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Nutanix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# Make sure zpool import -d <device> works.
+#
+# STRATEGY:
+# 1. Create test pool A.
+# 2. Export pool A.
+# 3. Verify 'import -d <device>' works
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL1
+
+ log_must rm $VDEV0 $VDEV1
+ log_must truncate -s $FILE_SIZE $VDEV0 $VDEV1
+}
+
+log_assert "Pool can be imported with '-d <device>'"
+log_onexit cleanup
+
+log_must zpool create $TESTPOOL1 $VDEV0 $VDEV1
+log_must zpool export $TESTPOOL1
+
+log_must zpool import -d $VDEV0 -d $VDEV1 $TESTPOOL1
+log_must zpool export $TESTPOOL1
+
+# mix -d <dir> and -d <device>
+log_must mkdir $DEVICE_DIR/test_dir
+log_must ln -s $VDEV0 $DEVICE_DIR/test_dir/disk
+log_must zpool import -d $DEVICE_DIR/test_dir -d $VDEV1 $TESTPOOL1
+
+log_pass "Pool can be imported with '-d <device>'"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_all_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_all_001_pos.ksh
new file mode 100755
index 000000000000..b384ec9b1fce
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_all_001_pos.ksh
@@ -0,0 +1,168 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# Verify that 'zpool import -a' succeeds as root.
+#
+# STRATEGY:
+# 1. Create a group of pools with specified vdev.
+# 2. Create zfs filesystems within the given pools.
+# 3. Export the pools.
+# 4. Verify that import command succeed.
+#
+
+verify_runnable "global"
+
+set -A options "" "-R $ALTER_ROOT"
+
+typeset -A testpools
+typeset -i number=0
+typeset -i i=0
+typeset checksum1
+typeset poolname
+
+function setup_single_disk #disk #pool #fs #mtpt
+{
+ typeset disk=$1
+ typeset pool=$2
+ typeset fs=${3##/}
+ typeset mtpt=$4
+
+ setup_filesystem "$disk" "$pool" "$fs" "$mtpt"
+ log_must cp $MYTESTFILE $mtpt/$TESTFILE0
+ log_must zpool export $pool
+
+ [[ -d $mtpt ]] && \
+ rm -rf $mtpt
+}
+
+function cleanup_all
+{
+ typeset -i id=1
+
+ #
+ # Try import individually if 'import -a' failed.
+ #
+ for pool in `zpool import | grep "pool:" | awk '{print $2}'`; do
+ zpool import -f $pool
+ done
+
+ for pool in `zpool import -d $DEVICE_DIR | grep "pool:" | awk '{print $2}'`; do
+ log_must zpool import -d $DEVICE_DIR -f $pool
+ done
+
+ while (( id < number )); do
+ if poolexists ${TESTPOOL}-$id ; then
+ cleanup_filesystem "${TESTPOOL}-$id" $TESTFS
+ destroy_pool ${TESTPOOL}-$id
+ fi
+ (( id = id + 1 ))
+ done
+
+ [[ -d $ALTER_ROOT ]] && \
+ rm -rf $ALTER_ROOT
+}
+
+function checksum_all #alter_root
+{
+ typeset alter_root=$1
+ typeset -i id=1
+ typeset file
+ typeset checksum2
+
+ while (( id < number )); do
+ file=${alter_root}/$TESTDIR.$id/$TESTFILE0
+ [[ ! -e $file ]] && \
+ log_fail "$file missing after import."
+
+ checksum2=$(sum $file | awk '{print $1}')
+ [[ "$checksum1" != "$checksum2" ]] && \
+ log_fail "Checksums differ ($checksum1 != $checksum2)"
+
+ (( id = id + 1 ))
+ done
+
+ return 0
+}
+
+
+log_assert "Verify that 'zpool import -a' succeeds as root."
+log_onexit cleanup_all
+
+checksum1=$(sum $MYTESTFILE | awk '{print $1}')
+number=1
+
+#
+# setup exported pools on raw files
+#
+for disk in $DEVICE_FILES
+do
+ poolname="${TESTPOOL}-$number"
+ setup_single_disk "$disk" \
+ "$poolname" \
+ "$TESTFS" \
+ "$TESTDIR.$number"
+ testpools[$poolname]=$poolname
+ (( number = number + 1 ))
+done
+
+while (( i < ${#options[*]} )); do
+
+ log_must zpool import -d $DEVICE_DIR ${options[i]} -a -f
+
+ # export unintentionally imported pools
+ for poolname in $(get_all_pools); do
+ if [[ -z ${testpools[$poolname]} ]]; then
+ log_must_busy zpool export $poolname
+ fi
+ done
+
+ if [[ -n ${options[i]} ]]; then
+ checksum_all $ALTER_ROOT
+ else
+ checksum_all
+ fi
+
+ for poolname in ${testpools[@]}; do
+ if poolexists $poolname ; then
+ log_must_busy zpool export $poolname
+ fi
+ done
+
+ (( i = i + 1 ))
+done
+
+log_pass "'zpool import -a' succeeds as root."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_encrypted.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_encrypted.ksh
new file mode 100755
index 000000000000..4e9013afeb14
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_encrypted.ksh
@@ -0,0 +1,59 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool import' should import a pool with an encrypted dataset without
+# mounting it.
+#
+# STRATEGY:
+# 1. Create an encrypted pool
+# 2. Export the pool
+# 3. Attempt to import the pool
+# 4. Verify the pool exists and the key is not loaded
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL1
+ log_must rm $VDEV0
+ log_must mkfile $FILE_SIZE $VDEV0
+}
+log_onexit cleanup
+
+log_assert "'zpool import' should import a pool with an encrypted dataset" \
+ "without mounting it"
+
+log_must eval "echo $PASSPHRASE | zpool create -O encryption=on" \
+ "-O keyformat=passphrase -O keylocation=prompt $TESTPOOL1 $VDEV0"
+log_must zpool export $TESTPOOL1
+log_must zpool import -d $DEVICE_DIR $TESTPOOL1
+log_must poolexists $TESTPOOL1
+log_must key_unavailable $TESTPOOL1
+log_must unmounted $TESTPOOL1
+
+log_pass "'zpool import' imports a pool with an encrypted dataset without" \
+ "mounting it"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_encrypted_load.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_encrypted_load.ksh
new file mode 100755
index 000000000000..d060e8a798e2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_encrypted_load.ksh
@@ -0,0 +1,59 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool import -l' should import a pool with an encrypted dataset and load
+# its key.
+#
+# STRATEGY:
+# 1. Create an encrypted pool
+# 2. Export the pool
+# 3. Attempt to import the pool with the key
+# 4. Verify the pool exists and the key is loaded
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL1
+ log_must rm $VDEV0
+ log_must mkfile $FILE_SIZE $VDEV0
+}
+log_onexit cleanup
+
+log_assert "'zpool import -l' should import a pool with an encrypted dataset" \
+ "and load its key"
+
+log_must eval "echo $PASSPHRASE | zpool create -O encryption=on" \
+ "-O keyformat=passphrase -O keylocation=prompt $TESTPOOL1 $VDEV0"
+log_must zpool export $TESTPOOL1
+log_must eval "echo $PASSPHRASE | zpool import -l -d $DEVICE_DIR $TESTPOOL1"
+log_must poolexists $TESTPOOL1
+log_must key_available $TESTPOOL1
+log_must mounted $TESTPOOL1
+
+log_pass "'zpool import -l' imports a pool with an encrypted dataset and" \
+ "loads its key"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_errata3.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_errata3.ksh
new file mode 100755
index 000000000000..86baf1f6e35d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_errata3.ksh
@@ -0,0 +1,103 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zpool import' should import a pool with Errata #3 while preventing
+# the user from performing read write operations
+#
+# STRATEGY:
+# 1. Import a pre-packaged pool with Errata #3
+# 2. Attempt to write to the effected datasets
+# 3. Attempt to read from the effected datasets
+# 4. Attempt to perform a raw send of the effected datasets
+# 5. Perform a regular send of the datasets under a new encryption root
+# 6. Verify the new datasets can be read from and written to
+# 7. Destroy the old effected datasets
+# 8. Reimport the pool and verify that the errata is no longer present
+#
+
+verify_runnable "global"
+
+POOL_NAME=cryptv0
+POOL_FILE=cryptv0.dat
+
+function uncompress_pool
+{
+ log_note "Creating pool from $POOL_FILE"
+ log_must bzcat \
+ $STF_SUITE/tests/functional/cli_root/zpool_import/blockfiles/$POOL_FILE.bz2 \
+ > /$TESTPOOL/$POOL_FILE
+ return 0
+}
+
+function cleanup
+{
+ poolexists $POOL_NAME && log_must zpool destroy $POOL_NAME
+ [[ -e /$TESTPOOL/$POOL_FILE ]] && rm /$TESTPOOL/$POOL_FILE
+ return 0
+}
+log_onexit cleanup
+
+log_assert "Verify that Errata 3 is properly handled"
+
+uncompress_pool
+log_must zpool import -d /$TESTPOOL/ $POOL_NAME
+log_must eval "zpool status $POOL_NAME | grep -q Errata" # also detects 'Errata #4'
+log_must eval "zpool status $POOL_NAME | grep -q ZFS-8000-ER"
+log_must eval "echo 'password' | zfs load-key $POOL_NAME/testfs"
+log_must eval "echo 'password' | zfs load-key $POOL_NAME/testvol"
+
+log_mustnot zfs mount $POOL_NAME/testfs
+log_must zfs mount -o ro $POOL_NAME/testfs
+
+old_mntpnt=$(get_prop mountpoint $POOL_NAME/testfs)
+log_must eval "ls $old_mntpnt | grep -q testfile"
+block_device_wait
+log_mustnot dd if=/dev/zero of=/dev/zvol/$POOL_NAME/testvol bs=512 count=1
+log_must dd if=/dev/zvol/$POOL_NAME/testvol of=/dev/null bs=512 count=1
+
+log_must zpool set feature@bookmark_v2=enabled $POOL_NAME # necessary for Errata #4
+
+log_must eval "echo 'password' | zfs create \
+ -o encryption=on -o keyformat=passphrase -o keylocation=prompt \
+ $POOL_NAME/encroot"
+log_mustnot eval "zfs send -w $POOL_NAME/testfs@snap1 | \
+ zfs recv $POOL_NAME/encroot/testfs"
+log_mustnot eval "zfs send -w $POOL_NAME/testvol@snap1 | \
+ zfs recv $POOL_NAME/encroot/testvol"
+
+log_must eval "zfs send $POOL_NAME/testfs@snap1 | \
+ zfs recv $POOL_NAME/encroot/testfs"
+log_must eval "zfs send $POOL_NAME/testvol@snap1 | \
+ zfs recv $POOL_NAME/encroot/testvol"
+block_device_wait
+log_must dd if=/dev/zero of=/dev/zvol/$POOL_NAME/encroot/testvol bs=512 count=1
+new_mntpnt=$(get_prop mountpoint $POOL_NAME/encroot/testfs)
+log_must eval "ls $new_mntpnt | grep -q testfile"
+log_must zfs destroy -r $POOL_NAME/testfs
+log_must zfs destroy -r $POOL_NAME/testvol
+
+log_must zpool export $POOL_NAME
+log_must zpool import -d /$TESTPOOL/ $POOL_NAME
+log_mustnot eval "zpool status $POOL_NAME | grep -q 'Errata #3'"
+log_pass "Errata 3 is properly handled"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_errata4.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_errata4.ksh
new file mode 100755
index 000000000000..a0f063a8dc83
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_errata4.ksh
@@ -0,0 +1,143 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zpool import' should import a pool with Errata #4. Users should be
+# able to set the zfs_disable_ivset_guid_check to continue normal
+# operation and the errata should disappear when no more effected
+# datasets remain.
+#
+# STRATEGY:
+# 1. Import a pre-packaged pool with Errata #4 and verify its state
+# 2. Prepare pool to fix existing datasets
+# 3. Use raw sends to fix datasets
+# 4. Ensure fixed datasets match their initial counterparts
+# 5. Destroy the initial datasets and verify the errata is gone
+#
+
+verify_runnable "global"
+
+POOL_NAME=missing_ivset
+POOL_FILE=missing_ivset.dat
+
+function uncompress_pool
+{
+ log_note "Creating pool from $POOL_FILE"
+ log_must bzcat \
+ $STF_SUITE/tests/functional/cli_root/zpool_import/blockfiles/$POOL_FILE.bz2 \
+ > /$TESTPOOL/$POOL_FILE
+ return 0
+}
+
+function cleanup
+{
+ log_must set_tunable32 DISABLE_IVSET_GUID_CHECK 0
+ poolexists $POOL_NAME && log_must zpool destroy $POOL_NAME
+ [[ -e /$TESTPOOL/$POOL_FILE ]] && rm /$TESTPOOL/$POOL_FILE
+ return 0
+}
+log_onexit cleanup
+
+log_assert "Verify that Errata 4 is properly handled"
+
+function has_ivset_guid # dataset
+{
+ ds="$1"
+ ivset_guid=$(get_prop ivsetguid $ds)
+
+ if [ "$ivset_guid" == "-" ]; then
+ return 1
+ else
+ return 0
+ fi
+}
+
+# 1. Import a pre-packaged pool with Errata #4 and verify its state
+uncompress_pool
+log_must zpool import -d /$TESTPOOL/ $POOL_NAME
+log_must eval "zpool status $POOL_NAME | grep -q 'Errata #4'"
+log_must eval "zpool status $POOL_NAME | grep -q ZFS-8000-ER"
+bm2_value=$(zpool get -H -o value feature@bookmark_v2 $POOL_NAME)
+if [ "$bm2_value" != "disabled" ]; then
+ log_fail "initial pool's bookmark_v2 feature is not disabled"
+fi
+
+log_mustnot has_ivset_guid $POOL_NAME/testfs@snap1
+log_mustnot has_ivset_guid $POOL_NAME/testfs@snap2
+log_mustnot has_ivset_guid $POOL_NAME/testfs@snap3
+log_mustnot has_ivset_guid $POOL_NAME/testvol@snap1
+log_mustnot has_ivset_guid $POOL_NAME/testvol@snap2
+log_mustnot has_ivset_guid $POOL_NAME/testvol@snap3
+
+# 2. Prepare pool to fix existing datasets
+log_must zpool set feature@bookmark_v2=enabled $POOL_NAME
+log_must set_tunable32 DISABLE_IVSET_GUID_CHECK 1
+log_must zfs create $POOL_NAME/fixed
+
+# 3. Use raw sends to fix datasets
+log_must eval "zfs send -w $POOL_NAME/testfs@snap1 | \
+ zfs recv $POOL_NAME/fixed/testfs"
+log_must eval "zfs send -w -i @snap1 $POOL_NAME/testfs@snap2 | \
+ zfs recv $POOL_NAME/fixed/testfs"
+log_must eval \
+ "zfs send -w -i $POOL_NAME/testfs#snap2 $POOL_NAME/testfs@snap3 | \
+ zfs recv $POOL_NAME/fixed/testfs"
+
+log_must eval "zfs send -w $POOL_NAME/testvol@snap1 | \
+ zfs recv $POOL_NAME/fixed/testvol"
+log_must eval "zfs send -w -i @snap1 $POOL_NAME/testvol@snap2 | \
+ zfs recv $POOL_NAME/fixed/testvol"
+log_must eval \
+ "zfs send -w -i $POOL_NAME/testvol#snap2 $POOL_NAME/testvol@snap3 | \
+ zfs recv $POOL_NAME/fixed/testvol"
+
+# 4. Ensure fixed datasets match their initial counterparts
+log_must eval "echo 'password' | zfs load-key $POOL_NAME/testfs"
+log_must eval "echo 'password' | zfs load-key $POOL_NAME/testvol"
+log_must eval "echo 'password' | zfs load-key $POOL_NAME/fixed/testfs"
+log_must eval "echo 'password' | zfs load-key $POOL_NAME/fixed/testvol"
+log_must zfs mount $POOL_NAME/testfs
+log_must zfs mount $POOL_NAME/fixed/testfs
+block_device_wait
+
+old_mntpnt=$(get_prop mountpoint $POOL_NAME/testfs)
+new_mntpnt=$(get_prop mountpoint $POOL_NAME/fixed/testfs)
+log_must diff -r "$old_mntpnt" "$new_mntpnt"
+log_must diff /dev/zvol/$POOL_NAME/testvol /dev/zvol/$POOL_NAME/fixed/testvol
+
+log_must has_ivset_guid $POOL_NAME/fixed/testfs@snap1
+log_must has_ivset_guid $POOL_NAME/fixed/testfs@snap2
+log_must has_ivset_guid $POOL_NAME/fixed/testfs@snap3
+log_must has_ivset_guid $POOL_NAME/fixed/testvol@snap1
+log_must has_ivset_guid $POOL_NAME/fixed/testvol@snap2
+log_must has_ivset_guid $POOL_NAME/fixed/testvol@snap3
+
+# 5. Destroy the initial datasets and verify the errata is gone
+log_must zfs destroy -r $POOL_NAME/testfs
+log_must zfs destroy -r $POOL_NAME/testvol
+
+log_must zpool export $POOL_NAME
+log_must zpool import -d /$TESTPOOL/ $POOL_NAME
+log_mustnot eval "zpool status $POOL_NAME | grep -q 'Errata #4'"
+log_mustnot eval "zpool status $POOL_NAME | grep -q ZFS-8000-ER"
+log_pass "Errata 4 is properly handled"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_001_pos.ksh
new file mode 100755
index 000000000000..973efb7acf3c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_001_pos.ksh
@@ -0,0 +1,71 @@
+#!/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) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#################################################################################
+#
+# Pool can be imported with inactive unsupported features.
+#
+# 1. Create new pool.
+# 2. Export and inject unsuppored features with zhack.
+# 3. Import pool normally with no problems.
+# 4. Verify that unsupported@ properties exist for the unsupported features.
+#
+################################################################################
+
+verify_runnable "global"
+
+features="com.test:xxx_unsup0 com.test:xxx_unsup1 com.test:xxx_unsup2"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+
+ log_must rm $VDEV0
+ log_must mkfile $FILE_SIZE $VDEV0
+}
+
+log_assert "Pool with inactive unsupported features can be imported."
+log_onexit cleanup
+
+log_must zpool create $TESTPOOL1 $VDEV0
+log_must zpool export $TESTPOOL1
+
+for feature in $features; do
+ log_must zhack -d $DEVICE_DIR feature enable $TESTPOOL1 $feature
+done
+
+log_must zpool import -d $DEVICE_DIR $TESTPOOL1
+for feature in $features; do
+ state=$(zpool list -Ho unsupported@$feature $TESTPOOL1)
+ if [[ "$state" != "inactive" ]]; then
+ log_fail "unsupported@$feature is '$state'"
+ fi
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_002_neg.ksh
new file mode 100755
index 000000000000..d16ef217a444
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_002_neg.ksh
@@ -0,0 +1,87 @@
+#!/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) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#################################################################################
+#
+# Pool cannot be opened with active unsupported features. Error message should
+# list active unsupported features.
+#
+# 1. Create new pool.
+# 2. Export and inject unsuppored features with zhack, make some of them active.
+# 3. Try to import pool, error should only list active features. It should
+# not say anything about being able to import the pool in readonly mode.
+#
+################################################################################
+
+verify_runnable "global"
+
+enabled_features="com.test:xxx_unsup1 com.test:xxx_unsup3"
+active_features="com.test:xxx_unsup0 com.test:xxx_unsup2"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+
+ log_must rm $VDEV0
+ log_must mkfile $FILE_SIZE $VDEV0
+}
+
+log_assert "Pool with active unsupported features cannot be imported."
+log_onexit cleanup
+
+log_must zpool create $TESTPOOL1 $VDEV0
+log_must zpool export $TESTPOOL1
+
+for feature in $enabled_features $active_features; do
+ log_must zhack -d $DEVICE_DIR feature enable $TESTPOOL1 $feature
+done
+
+for feature in $active_features; do
+ log_must zhack -d $DEVICE_DIR feature ref $TESTPOOL1 $feature
+done
+
+log_mustnot zpool import -d $DEVICE_DIR $TESTPOOL1
+
+# error message should not mention "readonly"
+log_mustnot eval "zpool import -d $DEVICE_DIR $TESTPOOL1 | grep readonly"
+log_mustnot poolexists $TESTPOOL1
+
+for feature in $active_features; do
+ log_must eval "zpool import -d $DEVICE_DIR $TESTPOOL1 \
+ | grep $feature"
+ log_mustnot poolexists $TESTPOOL1
+done
+
+for feature in $enabled_features; do
+ log_mustnot eval "zpool import -d $DEVICE_DIR $TESTPOOL1 \
+ | grep $feature"
+ log_mustnot poolexists $TESTPOOL1
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_003_pos.ksh
new file mode 100755
index 000000000000..e92c95f54c52
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_features_003_pos.ksh
@@ -0,0 +1,106 @@
+#!/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) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#################################################################################
+#
+# Pool can be imported with active read-only compatible features. If a feature
+# is read-only compatible but also inactive its property status should be
+# "inactive" rather than "readonly".
+#
+# 1. Create new pool.
+# 2. Export and inject variety of unsupported features.
+# 3. Try to import read-write, this should fail. The error should only list
+# the active read-only compatible feature and mention "readonly=on".
+# 4. Import the pool in read-only mode.
+# 5. Verify values of unsupported@ properties.
+#
+################################################################################
+
+verify_runnable "global"
+
+enabled_features="com.test:xxx_unsup0 com.test:xxx_unsup2"
+active_features="com.test:xxx_unsup1 com.test:xxx_unsup3"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+
+ log_must rm $VDEV0
+ log_must mkfile $FILE_SIZE $VDEV0
+}
+
+log_assert "Pool with active read-only compatible features can be imported."
+log_onexit cleanup
+
+log_must zpool create $TESTPOOL1 $VDEV0
+log_must zpool export $TESTPOOL1
+
+for feature in $enabled_features $active_features; do
+ log_must zhack -d $DEVICE_DIR feature enable -r $TESTPOOL1 $feature
+done
+
+for feature in $active_features; do
+ log_must zhack -d $DEVICE_DIR feature ref $TESTPOOL1 $feature
+done
+
+log_mustnot zpool import -d $DEVICE_DIR $TESTPOOL1
+
+# error message should mention "readonly"
+log_must eval "zpool import -d $DEVICE_DIR $TESTPOOL1 | grep readonly"
+log_mustnot poolexists $TESTPOOL1
+
+for feature in $enabled_features; do
+ log_mustnot eval "zpool import -d $DEVICE_DIR $TESTPOOL1 \
+ | grep $feature"
+ log_mustnot poolexists $TESTPOOL1
+done
+
+for feature in $active_features; do
+ log_must eval "zpool import -d $DEVICE_DIR $TESTPOOL1 \
+ | grep $feature"
+ log_mustnot poolexists $TESTPOOL1
+done
+
+log_must zpool import -o readonly=on -d $DEVICE_DIR $TESTPOOL1
+
+for feature in $enabled_features; do
+ state=$(zpool list -Ho unsupported@$feature $TESTPOOL1)
+ if [[ "$state" != "inactive" ]]; then
+ log_fail "unsupported@$feature is '$state'"
+ fi
+done
+
+for feature in $active_features; do
+ state=$(zpool list -Ho unsupported@$feature $TESTPOOL1)
+ if [[ "$state" != "readonly" ]]; then
+ log_fail "unsupported@$feature is '$state'"
+ fi
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_001_pos.ksh
new file mode 100755
index 000000000000..78e9bbf689d0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_001_pos.ksh
@@ -0,0 +1,203 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# Once a pool has been exported, and one or more devices are
+# damaged or missing (d/m), import should handle this kind of situation
+# as described:
+# - Regular, report error while any number of devices failing.
+# - Mirror could withstand (N-1) devices failing
+# before data integrity is compromised
+# - Raidz could withstand one devices failing
+# before data integrity is compromised
+# Verify those are true.
+#
+# STRATEGY:
+# 1. Create test pool upon device files using the various combinations.
+# - Regular pool
+# - Mirror
+# - Raidz
+# 2. Create necessary filesystem and test files.
+# 3. Export the test pool.
+# 4. Remove one or more devices
+# 5. Verify 'zpool import' will handle d/m device successfully.
+# Using the various combinations.
+# - Regular import
+# - Alternate Root Specified
+# It should be succeed with single d/m device upon 'raidz' & 'mirror',
+# but failed against 'regular' or more d/m devices.
+# 6. If import succeed, verify following is true:
+# - The pool shows up under 'zpool list'.
+# - The pool's health should be DEGRADED.
+# - It contains the correct test file
+#
+
+verify_runnable "global"
+
+set -A vdevs "" "mirror" "raidz"
+set -A options "" "-R $ALTER_ROOT"
+
+function cleanup
+{
+ # recover the vdevs
+ recreate_files
+
+ [[ -d $ALTER_ROOT ]] && \
+ log_must rm -rf $ALTER_ROOT
+}
+
+function recreate_files
+{
+ if poolexists "$TESTPOOL1" ; then
+ cleanup_filesystem $TESTPOOL1 $TESTFS
+ destroy_pool $TESTPOOL1
+ fi
+
+ log_must rm -rf $DEVICE_DIR/*
+ typeset i=0
+ while (( i < $MAX_NUM )); do
+ log_must mkfile $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i
+ ((i += 1))
+ done
+}
+
+log_onexit cleanup
+
+log_assert "Verify that import could handle damaged or missing device."
+
+CWD=$PWD
+cd $DEVICE_DIR || log_fail "Unable change directory to $DEVICE_DIR"
+
+checksum1=$(sum $MYTESTFILE | awk '{print $1}')
+
+typeset -i i=0
+typeset -i j=0
+typeset -i count=0
+typeset basedir backup
+
+while (( i < ${#vdevs[*]} )); do
+
+ setup_filesystem "$DEVICE_FILES" \
+ $TESTPOOL1 $TESTFS $TESTDIR1 \
+ "" ${vdevs[i]}
+
+ backup=""
+
+ guid=$(get_config $TESTPOOL1 pool_guid)
+ log_must cp $MYTESTFILE $TESTDIR1/$TESTFILE0
+
+ log_must zfs umount $TESTDIR1
+
+ j=0
+ while (( j < ${#options[*]} )); do
+
+ count=0
+ action=log_must
+
+ #
+ # Restore all device files.
+ #
+ [[ -n $backup ]] && \
+ log_must tar xf $DEVICE_DIR/$DEVICE_ARCHIVE
+
+ for device in $DEVICE_FILES ; do
+ log_must rm -f $device
+
+ poolexists $TESTPOOL1 && \
+ log_must zpool export $TESTPOOL1
+
+ #
+ # Backup all device files while filesystem prepared.
+ #
+ if [[ -z $backup ]]; then
+ log_must tar cf $DEVICE_DIR/$DEVICE_ARCHIVE \
+ ${DEVICE_FILE}*
+ backup="true"
+ fi
+
+ (( count = count + 1 ))
+
+ case "${vdevs[i]}" in
+ 'mirror') (( count == $GROUP_NUM )) && \
+ action=log_mustnot
+ ;;
+ 'raidz') (( count > 1 )) && \
+ action=log_mustnot
+ ;;
+ '') action=log_mustnot
+ ;;
+ esac
+
+ typeset target=$TESTPOOL1
+ if (( RANDOM % 2 == 0 )) ; then
+ target=$guid
+ log_note "Import by guid."
+ fi
+ $action zpool import \
+ -d $DEVICE_DIR ${options[j]} $target
+
+ [[ $action == "log_mustnot" ]] && continue
+
+ log_must poolexists $TESTPOOL1
+
+ health=$(zpool list -H -o health $TESTPOOL1)
+
+ [[ $health == "DEGRADED" ]] || \
+ log_fail "$TESTPOOL1: Incorrect health($health)"
+ log_must ismounted $TESTPOOL1/$TESTFS
+
+ basedir=$TESTDIR1
+ [[ -n ${options[j]} ]] && \
+ basedir=$ALTER_ROOT/$TESTDIR1
+
+ [[ ! -e $basedir/$TESTFILE0 ]] && \
+ log_fail "$basedir/$TESTFILE0 missing after import."
+
+ checksum2=$(sum $basedir/$TESTFILE0 | awk '{print $1}')
+ [[ "$checksum1" != "$checksum2" ]] && \
+ log_fail "Checksums differ ($checksum1 != $checksum2)"
+
+ done
+
+ ((j = j + 1))
+ done
+
+ recreate_files
+
+ ((i = i + 1))
+done
+
+log_pass "Import could handle damaged or missing device."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_002_pos.ksh
new file mode 100755
index 000000000000..c6d2637074fe
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_002_pos.ksh
@@ -0,0 +1,197 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# Once a pool has been exported, and one or more devices are
+# move to other place, import should handle this kind of situation
+# as described:
+# - Regular, report error while any number of devices failing.
+# - Mirror could withstand (N-1) devices failing
+# before data integrity is compromised
+# - Raidz could withstand one devices failing
+# before data integrity is compromised
+# Verify that is true.
+#
+# STRATEGY:
+# 1. Create test pool upon device files using the various combinations.
+# - Regular pool
+# - Mirror
+# - Raidz
+# 2. Create necessary filesystem and test files.
+# 3. Export the test pool.
+# 4. Move one or more device files to other directory
+# 5. Verify 'zpool import -d' with the new directory
+# will handle moved files successfully.
+# Using the various combinations.
+# - Regular import
+# - Alternate Root Specified
+#
+
+verify_runnable "global"
+
+set -A vdevs "" "mirror" "raidz"
+set -A options "" "-R $ALTER_ROOT"
+
+function cleanup
+{
+ cd $DEVICE_DIR || log_fail "Unable change directory to $DEVICE_DIR"
+ [[ -e $DEVICE_DIR/$DEVICE_ARCHIVE ]] && \
+ log_must tar xf $DEVICE_DIR/$DEVICE_ARCHIVE
+
+ poolexists $TESTPOOL1 || \
+ log_must zpool import -d $DEVICE_DIR $TESTPOOL1
+
+ cleanup_filesystem $TESTPOOL1 $TESTFS
+
+ destroy_pool $TESTPOOL1
+}
+
+function cleanup_all
+{
+ cleanup
+
+ # recover dev files
+ typeset i=0
+ while (( i < $MAX_NUM )); do
+ typeset dev_file=${DEVICE_DIR}/${DEVICE_FILE}$i
+ if [[ ! -e ${dev_file} ]]; then
+ log_must mkfile $FILE_SIZE ${dev_file}
+ fi
+ ((i += 1))
+ done
+
+ log_must rm -f $DEVICE_DIR/$DEVICE_ARCHIVE
+ cd $CWD || log_fail "Unable change directory to $CWD"
+
+ [[ -d $ALTER_ROOT ]] && \
+ log_must rm -rf $ALTER_ROOT
+
+ [[ -d $BACKUP_DEVICE_DIR ]] && \
+ log_must rm -rf $BACKUP_DEVICE_DIR
+}
+
+log_onexit cleanup_all
+
+log_assert "Verify that import could handle moving device."
+
+CWD=$PWD
+
+[[ ! -d $BACKUP_DEVICE_DIR ]] &&
+ log_must mkdir -p $BACKUP_DEVICE_DIR
+
+cd $DEVICE_DIR || log_fail "Unable change directory to $DEVICE_DIR"
+
+typeset -i i=0
+typeset -i j=0
+typeset -i count=0
+typeset basedir backup
+typeset action
+
+while (( i < ${#vdevs[*]} )); do
+
+ (( i != 0 )) && \
+ log_must tar xf $DEVICE_DIR/$DEVICE_ARCHIVE
+
+ setup_filesystem "$DEVICE_FILES" \
+ $TESTPOOL1 $TESTFS $TESTDIR1 \
+ "" ${vdevs[i]}
+
+ guid=$(get_config $TESTPOOL1 pool_guid)
+ backup=""
+
+ log_must cp $MYTESTFILE $TESTDIR1/$TESTFILE0
+
+ log_must zfs umount $TESTDIR1
+
+ j=0
+ while (( j < ${#options[*]} )); do
+
+ count=0
+
+ #
+ # Restore all device files.
+ #
+ [[ -n $backup ]] && \
+ log_must tar xf $DEVICE_DIR/$DEVICE_ARCHIVE
+
+ log_must rm -f $BACKUP_DEVICE_DIR/*
+
+ for device in $DEVICE_FILES ; do
+
+ poolexists $TESTPOOL1 && \
+ log_must zpool export $TESTPOOL1
+
+ #
+ # Backup all device files while filesystem prepared.
+ #
+ if [[ -z $backup ]] ; then
+ log_must tar cf $DEVICE_DIR/$DEVICE_ARCHIVE ${DEVICE_FILE}*
+ backup="true"
+ fi
+
+ log_must mv $device $BACKUP_DEVICE_DIR
+
+ (( count = count + 1 ))
+
+ action=log_mustnot
+ case "${vdevs[i]}" in
+ 'mirror') (( count < $GROUP_NUM )) && \
+ action=log_must
+ ;;
+ 'raidz') (( count == 1 )) && \
+ action=log_must
+ ;;
+ esac
+
+ typeset target=$TESTPOOL1
+ if (( RANDOM % 2 == 0 )) ; then
+ target=$guid
+ log_note "Import by guid."
+ fi
+ $action zpool import \
+ -d $DEVICE_DIR ${options[j]} $target
+
+ done
+
+ ((j = j + 1))
+ done
+
+ cleanup
+
+ ((i = i + 1))
+done
+
+log_pass "Import could handle moving device."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_003_pos.ksh
new file mode 100755
index 000000000000..6fa55250a77d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_missing_003_pos.ksh
@@ -0,0 +1,237 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# Once a pool has been exported, but one or more devices are
+# overlapped with other exported pool, import should handle
+# this kind of situation properly.
+#
+# STRATEGY:
+# 1. Repeat 1-3, create two test pools upon device files separately.
+# These two pools should have one or more devices are overlapped.
+# using the various combinations.
+# - Regular pool
+# - Mirror
+# - Raidz
+# 2. Create necessary filesystem and test files.
+# 3. Export the test pool.
+# 4. Verify 'zpool import -d' with these two pools will have results
+# as described:
+# - Regular, report error while any number of devices failing.
+# - Mirror could withstand (N-1) devices failing
+# before data integrity is compromised
+# - Raidz could withstand one devices failing
+# before data integrity is compromised
+#
+
+verify_runnable "global"
+
+# See issue: https://github.com/openzfs/zfs/issues/6839
+if ! is_illumos; then
+ log_unsupported "Test case may be slow"
+fi
+
+set -A vdevs "" "mirror" "raidz"
+
+function verify
+{
+ typeset pool=$1
+ typeset fs=$2
+ typeset mtpt=$3
+ typeset health=$4
+ typeset file=$5
+ typeset checksum1=$6
+
+ typeset myhealth
+ typeset mymtpt
+ typeset checksum2
+
+ log_must poolexists $pool
+
+ myhealth=$(zpool list -H -o health $pool)
+
+ [[ $myhealth == $health ]] || \
+ log_fail "$pool: Incorrect health ($myhealth), " \
+ "expected ($health)."
+
+ log_must ismounted $pool/$fs
+
+ mymtpt=$(get_prop mountpoint $pool/$fs)
+ [[ $mymtpt == $mtpt ]] || \
+ log_fail "$pool/$fs: Incorrect mountpoint ($mymtpt), " \
+ "expected ($mtpt)."
+
+ [[ ! -e $mtpt/$file ]] && \
+ log_fail "$mtpt/$file missing after import."
+
+ checksum2=$(sum $mymtpt/$file | awk '{print $1}')
+ [[ "$checksum1" != "$checksum2" ]] && \
+ log_fail "Checksums differ ($checksum1 != $checksum2)"
+
+ return 0
+
+}
+
+function cleanup
+{
+ cd $DEVICE_DIR || log_fail "Unable change directory to $DEVICE_DIR"
+
+ for pool in $TESTPOOL1 $TESTPOOL2; do
+ if poolexists "$pool" ; then
+ cleanup_filesystem $pool $TESTFS
+ destroy_pool $pool
+ fi
+ done
+
+ [[ -e $DEVICE_DIR/$DEVICE_ARCHIVE ]] && \
+ log_must tar xf $DEVICE_DIR/$DEVICE_ARCHIVE
+}
+
+function cleanup_all
+{
+ cleanup
+
+ # recover dev files
+ typeset i=0
+ while (( i < $MAX_NUM )); do
+ typeset file=${DEVICE_DIR}/${DEVICE_FILE}$i
+ if [[ -e $file ]]; then
+ log_must rm $file
+ fi
+ log_must mkfile $FILE_SIZE $file
+ ((i += 1))
+ done
+
+ log_must rm -f $DEVICE_DIR/$DEVICE_ARCHIVE
+ cd $CWD || log_fail "Unable change directory to $CWD"
+
+}
+
+log_onexit cleanup_all
+
+log_assert "Verify that import could handle device overlapped."
+
+CWD=$PWD
+
+cd $DEVICE_DIR || log_fail "Unable change directory to $DEVICE_DIR"
+log_must tar cf $DEVICE_DIR/$DEVICE_ARCHIVE ${DEVICE_FILE}*
+
+checksum1=$(sum $MYTESTFILE | awk '{print $1}')
+
+typeset -i i=0
+typeset -i j=0
+typeset -i count=0
+typeset -i num=0
+typeset vdev1=""
+typeset vdev2=""
+typeset action
+
+while (( num < $GROUP_NUM )); do
+ vdev1="$vdev1 ${DEVICE_DIR}/${DEVICE_FILE}$num"
+ (( num = num + 1 ))
+done
+
+while (( i < ${#vdevs[*]} )); do
+ j=0
+ while (( j < ${#vdevs[*]} )); do
+
+ (( j != 0 )) && \
+ log_must tar xf $DEVICE_DIR/$DEVICE_ARCHIVE
+
+ typeset -i overlap=1
+ typeset -i begin
+ typeset -i end
+
+ while (( overlap <= $GROUP_NUM )); do
+ vdev2=""
+ (( begin = $GROUP_NUM - overlap ))
+ (( end = 2 * $GROUP_NUM - overlap - 1 ))
+ (( num = begin ))
+ while (( num <= end )); do
+ vdev2="$vdev2 ${DEVICE_DIR}/${DEVICE_FILE}$num"
+ (( num = num + 1 ))
+ done
+
+ setup_filesystem "$vdev1" $TESTPOOL1 $TESTFS $TESTDIR1 \
+ "" ${vdevs[i]}
+ log_must cp $MYTESTFILE $TESTDIR1/$TESTFILE0
+ log_must zfs umount $TESTDIR1
+ poolexists $TESTPOOL1 && \
+ log_must zpool export $TESTPOOL1
+
+ setup_filesystem "$vdev2" $TESTPOOL2 $TESTFS $TESTDIR2 \
+ "" ${vdevs[j]}
+ log_must cp $MYTESTFILE $TESTDIR2/$TESTFILE0
+ log_must zfs umount $TESTDIR2
+ poolexists $TESTPOOL2 && \
+ log_must zpool export $TESTPOOL2
+
+ action=log_must
+ case "${vdevs[i]}" in
+ 'mirror') (( overlap == $GROUP_NUM )) && \
+ action=log_mustnot
+ ;;
+ 'raidz') (( overlap > 1 )) && \
+ action=log_mustnot
+ ;;
+ '') action=log_mustnot
+ ;;
+ esac
+
+ $action zpool import -d $DEVICE_DIR $TESTPOOL1
+ log_must zpool import -d $DEVICE_DIR $TESTPOOL2
+
+ if [[ $action == log_must ]]; then
+ verify "$TESTPOOL1" "$TESTFS" "$TESTDIR1" \
+ "DEGRADED" "$TESTFILE0" "$checksum1"
+ fi
+
+ verify "$TESTPOOL2" "$TESTFS" "$TESTDIR2" \
+ "ONLINE" "$TESTFILE0" "$checksum1"
+
+ cleanup
+
+ (( overlap = overlap + 1 ))
+
+ done
+
+ ((j = j + 1))
+ done
+
+ ((i = i + 1))
+done
+
+log_pass "Import could handle device overlapped."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_rename_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_rename_001_pos.ksh
new file mode 100755
index 000000000000..bb6bf86d7881
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_rename_001_pos.ksh
@@ -0,0 +1,174 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
+
+#
+# DESCRIPTION:
+# An exported pool can be imported under a different name. Hence
+# we test that a previously exported pool can be renamed.
+#
+# STRATEGY:
+# 1. Copy a file into the default test directory.
+# 2. Umount the default directory.
+# 3. Export the pool.
+# 4. Import the pool using the name ${TESTPOOL}-new,
+# and using the various combinations.
+# - Regular import
+# - Alternate Root Specified
+# 5. Verify it exists in the 'zpool list' output.
+# 6. Verify the default file system is mounted and that the file
+# from step (1) is present.
+#
+
+verify_runnable "global"
+
+set -A pools "$TESTPOOL" "$TESTPOOL1"
+set -A devs "" "-d $DEVICE_DIR"
+set -A options "" "-R $ALTER_ROOT"
+set -A mtpts "$TESTDIR" "$TESTDIR1"
+
+
+function cleanup
+{
+ typeset -i i=0
+ while (( i < ${#pools[*]} )); do
+ if poolexists "${pools[i]}-new" ; then
+ log_must zpool export "${pools[i]}-new"
+
+ [[ -d /${pools[i]}-new ]] && \
+ log_must rm -rf /${pools[i]}-new
+
+ log_must zpool import ${devs[i]} \
+ "${pools[i]}-new" ${pools[i]}
+ fi
+
+ datasetexists "${pools[i]}" || \
+ log_must zpool import ${devs[i]} ${pools[i]}
+
+ ismounted "${pools[i]}/$TESTFS" || \
+ log_must zfs mount ${pools[i]}/$TESTFS
+
+ [[ -e ${mtpts[i]}/$TESTFILE0 ]] && \
+ log_must rm -rf ${mtpts[i]}/$TESTFILE0
+
+ ((i = i + 1))
+
+ done
+
+ cleanup_filesystem $TESTPOOL1 $TESTFS $TESTDIR1
+
+ destroy_pool $TESTPOOL1
+
+ [[ -d $ALTER_ROOT ]] && \
+ log_must rm -rf $ALTER_ROOT
+ [[ -e $VDEV_FILE ]] && \
+ log_must rm $VDEV_FILE
+}
+
+log_onexit cleanup
+
+log_assert "Verify that an imported pool can be renamed."
+
+setup_filesystem "$DEVICE_FILES" $TESTPOOL1 $TESTFS $TESTDIR1
+checksum1=$(sum $MYTESTFILE | awk '{print $1}')
+
+typeset -i i=0
+typeset -i j=0
+typeset basedir
+
+while (( i < ${#pools[*]} )); do
+ guid=$(get_config ${pools[i]} pool_guid)
+ log_must cp $MYTESTFILE ${mtpts[i]}/$TESTFILE0
+
+ log_must zfs umount ${mtpts[i]}
+
+ j=0
+ while (( j < ${#options[*]} )); do
+ log_must zpool export ${pools[i]}
+
+ [[ -d /${pools[i]} ]] && \
+ log_must rm -rf /${pools[i]}
+
+ typeset target=${pools[i]}
+ if (( RANDOM % 2 == 0 )) ; then
+ target=$guid
+ log_note "Import by guid."
+ fi
+
+ log_must zpool import ${devs[i]} ${options[j]} \
+ $target ${pools[i]}-new
+
+ log_must poolexists "${pools[i]}-new"
+
+ log_must ismounted ${pools[i]}-new/$TESTFS
+
+ basedir=${mtpts[i]}
+ [[ -n ${options[j]} ]] && \
+ basedir=$ALTER_ROOT/${mtpts[i]}
+
+ [[ ! -e $basedir/$TESTFILE0 ]] && \
+ log_fail "$basedir/$TESTFILE0 missing after import."
+
+ checksum2=$(sum $basedir/$TESTFILE0 | awk '{print $1}')
+ [[ "$checksum1" != "$checksum2" ]] && \
+ log_fail "Checksums differ ($checksum1 != $checksum2)"
+
+ log_must zpool export "${pools[i]}-new"
+
+ [[ -d /${pools[i]}-new ]] && \
+ log_must rm -rf /${pools[i]}-new
+
+ target=${pools[i]}-new
+ if (( RANDOM % 2 == 0 )) ; then
+ target=$guid
+ fi
+ log_must zpool import ${devs[i]} $target ${pools[i]}
+
+ ((j = j + 1))
+ done
+
+ ((i = i + 1))
+done
+
+VDEV_FILE=$(mktemp $TEST_BASE_DIR/tmp.XXXXXX)
+
+log_must mkfile -n 128M $VDEV_FILE
+log_must zpool create overflow $VDEV_FILE
+log_must zfs create overflow/testfs
+ID=$(zpool get -Ho value guid overflow)
+log_must zpool export overflow
+log_mustnot zpool import -d $TEST_BASE_DIR $(echo id) \
+ $(printf "%*s\n" 250 "" | tr ' ' 'c')
+
+log_pass "Successfully imported and renamed a ZPOOL"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/Makefile.am
new file mode 100644
index 000000000000..2ebc376d9cb9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/Makefile.am
@@ -0,0 +1,17 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_initialize
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ zpool_initialize_attach_detach_add_remove.ksh \
+ zpool_initialize_import_export.ksh \
+ zpool_initialize_offline_export_import_online.ksh \
+ zpool_initialize_online_offline.ksh \
+ zpool_initialize_split.ksh \
+ zpool_initialize_start_and_cancel_neg.ksh \
+ zpool_initialize_start_and_cancel_pos.ksh \
+ zpool_initialize_suspend_resume.ksh \
+ zpool_initialize_unsupported_vdevs.ksh \
+ zpool_initialize_verify_checksums.ksh \
+ zpool_initialize_verify_initialized.ksh
+
+dist_pkgdata_DATA = \
+ zpool_initialize.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/cleanup.ksh
new file mode 100755
index 000000000000..3c7dbd31705d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/cleanup.ksh
@@ -0,0 +1,31 @@
+#!/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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
new file mode 100644
index 000000000000..8b0727483cfb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
@@ -0,0 +1,43 @@
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+function initialize_prog_line # pool disk
+{
+ typeset pool="$1"
+ typeset disk="$2"
+ zpool status -i "$pool" | grep "$disk" | grep "[[:digit:]]* initialized"
+}
+
+function initialize_progress # pool disk
+{
+ initialize_prog_line "$1" "$2" | \
+ sed 's/.*(\([0-9]\{1,\}\)% initialized.*/\1/g'
+}
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ log_must zpool destroy -f $TESTPOOL
+ fi
+
+ if poolexists $TESTPOOL1; then
+ log_must zpool destroy -f $TESTPOOL1
+ fi
+}
+log_onexit cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_attach_detach_add_remove.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_attach_detach_add_remove.ksh
new file mode 100755
index 000000000000..2a695025d214
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_attach_detach_add_remove.ksh
@@ -0,0 +1,68 @@
+#!/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) 2016 by Delphix. All rights reserved.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+
+#
+# DESCRIPTION:
+# Detaching/attaching, adding/removing data devices works with initializing.
+#
+# STRATEGY:
+# 1. Create a single-disk pool.
+# 2. Start initializing.
+# 3. Attach a second disk, ensure initializing continues.
+# 4. Detach the second disk, ensure initializing continues.
+# 5. Add a second disk, ensure initializing continues.
+# 6. Remove the first disk, ensure initializing stops.
+#
+
+DISK1="$(echo $DISKS | cut -d' ' -f1)"
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+
+log_must zpool create -f $TESTPOOL $DISK1
+
+log_must zpool initialize $TESTPOOL $DISK1
+progress="$(initialize_progress $TESTPOOL $DISK1)"
+[[ -z "$progress" ]] && log_fail "Initializing did not start"
+
+log_must zpool attach $TESTPOOL $DISK1 $DISK2
+new_progress="$(initialize_progress $TESTPOOL $DISK1)"
+[[ "$progress" -le "$new_progress" ]] || \
+ log_fail "Lost initializing progress on demotion to child vdev"
+progress="$new_progress"
+
+log_must zpool detach $TESTPOOL $DISK2
+new_progress="$(initialize_progress $TESTPOOL $DISK1)"
+[[ "$progress" -le "$new_progress" ]] || \
+ log_fail "Lost initializing progress on promotion to top vdev"
+progress="$new_progress"
+
+log_must zpool add $TESTPOOL $DISK2
+log_must zpool remove $TESTPOOL $DISK1
+[[ -z "$(initialize_prog_line $TESTPOOL $DISK1)" ]] || \
+ log_fail "Initializing continued after initiating removal"
+
+log_pass "Initializing worked as expected across attach/detach and add/remove"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_import_export.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_import_export.ksh
new file mode 100755
index 000000000000..386d2a5dc237
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_import_export.ksh
@@ -0,0 +1,78 @@
+#!/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) 2016 by Delphix. All rights reserved.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+
+#
+# DESCRIPTION:
+# Initializing automatically resumes across import/export.
+#
+# STRATEGY:
+# 1. Create a one-disk pool.
+# 2. Start initializing and verify that initializing is active.
+# 3. Export the pool.
+# 4. Import the pool.
+# 5. Verify that initializing resumes and progress does not regress.
+# 6. Suspend initializing.
+# 7. Repeat steps 3-4.
+# 8. Verify that progress does not regress but initializing is still suspended.
+#
+
+DISK1=${DISKS%% *}
+
+log_must zpool create -f $TESTPOOL $DISK1
+log_must zpool initialize $TESTPOOL
+
+sleep 2
+
+progress="$(initialize_progress $TESTPOOL $DISK1)"
+[[ -z "$progress" ]] && log_fail "Initializing did not start"
+
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+
+new_progress="$(initialize_progress $TESTPOOL $DISK1)"
+[[ -z "$new_progress" ]] && log_fail "Initializing did not restart after import"
+[[ "$progress" -le "$new_progress" ]] || \
+ log_fail "Initializing lost progress after import"
+log_mustnot eval "initialize_prog_line $TESTPOOL $DISK1 | grep suspended"
+
+log_must zpool initialize -s $TESTPOOL $DISK1
+action_date="$(initialize_prog_line $TESTPOOL $DISK1 | \
+ sed 's/.*ed at \(.*\)).*/\1/g')"
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+new_action_date=$(initialize_prog_line $TESTPOOL $DISK1 | \
+ sed 's/.*ed at \(.*\)).*/\1/g')
+[[ "$action_date" != "$new_action_date" ]] && \
+ log_fail "Initializing action date did not persist across export/import"
+
+[[ "$new_progress" -le "$(initialize_progress $TESTPOOL $DISK1)" ]] || \
+ log_fail "Initializing lost progress after import"
+
+log_must eval "initialize_prog_line $TESTPOOL $DISK1 | grep suspended"
+
+log_pass "Initializing retains state as expected across export/import"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_offline_export_import_online.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_offline_export_import_online.ksh
new file mode 100755
index 000000000000..dedd466e4e6e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_offline_export_import_online.ksh
@@ -0,0 +1,66 @@
+#!/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) 2016 by Delphix. All rights reserved.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+
+#
+# DESCRIPTION:
+# Miscellaneous complex sequences of operations function as expected.
+#
+# STRATEGY:
+# 1. Create a pool with a two-way mirror.
+# 2. Start initializing, offline, export, import, online and verify that
+# initializing state is preserved / initializing behaves as expected
+# at each step.
+#
+
+DISK1="$(echo $DISKS | cut -d' ' -f1)"
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+
+log_must zpool create -f $TESTPOOL mirror $DISK1 $DISK2
+
+log_must zpool initialize $TESTPOOL $DISK1
+log_must zpool offline $TESTPOOL $DISK1
+progress="$(initialize_progress $TESTPOOL $DISK1)"
+[[ -z "$progress" ]] && log_fail "Initializing did not start"
+log_mustnot eval "initialize_prog_line $TESTPOOL $DISK1 | grep suspended"
+
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+
+new_progress="$(initialize_progress $TESTPOOL $DISK1)"
+[[ -z "$new_progress" ]] && log_fail "Initializing did not start after import"
+[[ "$new_progress" -ge "$progress" ]] || \
+ log_fail "Initializing lost progress after import"
+log_mustnot eval "initialize_prog_line $TESTPOOL $DISK1 | grep suspended"
+
+log_must zpool online $TESTPOOL $DISK1
+new_progress="$(initialize_progress $TESTPOOL $DISK1)"
+[[ "$new_progress" -ge "$progress" ]] || \
+ log_fail "Initializing lost progress after online"
+
+log_pass "Initializing behaves as expected at each step of:" \
+ "initialize + offline + export + import + online"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_online_offline.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_online_offline.ksh
new file mode 100755
index 000000000000..55bd3188c966
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_online_offline.ksh
@@ -0,0 +1,74 @@
+#!/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) 2016 by Delphix. All rights reserved.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+
+#
+# DESCRIPTION:
+# Initializing automatically resumes across offline/online.
+#
+# STRATEGY:
+# 1. Create a pool with a two-way mirror.
+# 2. Start initializing one of the disks and verify that initializing is active.
+# 3. Offline the disk.
+# 4. Online the disk.
+# 5. Verify that initializing resumes and progress does not regress.
+# 6. Suspend initializing.
+# 7. Repeat steps 3-4 and verify that initializing does not resume.
+#
+
+DISK1=${DISKS%% *}
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+
+log_must zpool create -f $TESTPOOL mirror $DISK1 $DISK2
+log_must zpool initialize $TESTPOOL $DISK1
+
+log_must zpool offline $TESTPOOL $DISK1
+
+progress="$(initialize_progress $TESTPOOL $DISK1)"
+[[ -z "$progress" ]] && log_fail "Initializing did not start"
+
+log_must zpool online $TESTPOOL $DISK1
+
+new_progress="$(initialize_progress $TESTPOOL $DISK1)"
+[[ -z "$new_progress" ]] && \
+ log_fail "Initializing did not restart after onlining"
+[[ "$progress" -le "$new_progress" ]] || \
+ log_fail "Initializing lost progress after onlining"
+log_mustnot eval "initialize_prog_line $TESTPOOL $DISK1 | grep suspended"
+
+log_must zpool initialize -s $TESTPOOL $DISK1
+action_date="$(initialize_prog_line $TESTPOOL $DISK1 | \
+ sed 's/.*ed at \(.*\)).*/\1/g')"
+log_must zpool offline $TESTPOOL $DISK1
+log_must zpool online $TESTPOOL $DISK1
+new_action_date=$(initialize_prog_line $TESTPOOL $DISK1 | \
+ sed 's/.*ed at \(.*\)).*/\1/g')
+[[ "$action_date" != "$new_action_date" ]] && \
+ log_fail "Initializing action date did not persist across offline/online"
+log_must eval "initialize_prog_line $TESTPOOL $DISK1 | grep suspended"
+
+log_pass "Initializing performs as expected across offline/online"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_split.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_split.ksh
new file mode 100755
index 000000000000..69b27c26c9bc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_split.ksh
@@ -0,0 +1,64 @@
+#!/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) 2016 by Delphix. All rights reserved.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+
+#
+# DESCRIPTION:
+# Initializing state is preserved across zpool split.
+#
+# STRATEGY:
+# 1. Create a pool with a two-way mirror.
+# 2. Start initializing both devices.
+# 3. Split the pool. Ensure initializing continues on the original.
+# 4. Import the new pool. Ensure initializing resumes on it.
+#
+
+DISK1="$(echo $DISKS | cut -d' ' -f1)"
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+POOL2="${TESTPOOL}_split"
+
+log_must zpool create -f $TESTPOOL mirror $DISK1 $DISK2
+
+log_must zpool initialize $TESTPOOL $DISK1 $DISK2
+orig_prog1="$(initialize_progress $TESTPOOL $DISK1)"
+orig_prog2="$(initialize_progress $TESTPOOL $DISK2)"
+[[ -z "$orig_prog1" ]] && log_fail "Initializing did not start"
+
+log_must zpool split $TESTPOOL $TESTPOOL1 $DISK2
+
+# Ensure initializing continued as expected on the original pool.
+[[ "$(initialize_progress $TESTPOOL $DISK1)" -ge "$orig_prog1" ]] || \
+ log_fail "Initializing lost progress on original pool"
+log_mustnot eval "initialize_prog_line $TESTPOOL $DISK1 | grep suspended"
+
+log_must zpool import $TESTPOOL1
+
+[[ "$(initialize_progress $TESTPOOL1 $DISK2)" -ge "$orig_prog2" ]] || \
+ log_fail "Initializing lost progress on split pool"
+log_mustnot eval "initialize_prog_line $TESTPOOL1 $DISK1 | grep suspended"
+
+log_pass "Initializing behaves as expected on zpool split"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_neg.ksh
new file mode 100755
index 000000000000..59b266d321c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_neg.ksh
@@ -0,0 +1,60 @@
+#!/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) 2016 by Delphix. All rights reserved.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+
+#
+# DESCRIPTION:
+# Cancelling and suspending initialize doesn't work if not all specified vdevs
+# are being initialized.
+#
+# STRATEGY:
+# 1. Create a three-disk pool.
+# 2. Start initializing and verify that initializing is active.
+# 3. Try to cancel and suspend initializing on the non-initializing disks.
+# 4. Try to re-initialize the currently initializing disk.
+#
+
+DISK1=${DISKS%% *}
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+DISK3="$(echo $DISKS | cut -d' ' -f3)"
+
+log_must zpool list -v
+log_must zpool create -f $TESTPOOL $DISK1 $DISK2 $DISK3
+log_must zpool initialize $TESTPOOL $DISK1
+
+[[ -z "$(initialize_progress $TESTPOOL $DISK1)" ]] && \
+ log_fail "Initialize did not start"
+
+log_mustnot zpool initialize -c $TESTPOOL $DISK2
+log_mustnot zpool initialize -c $TESTPOOL $DISK2 $DISK3
+
+log_mustnot zpool initialize -s $TESTPOOL $DISK2
+log_mustnot zpool initialize -s $TESTPOOL $DISK2 $DISK3
+
+log_mustnot zpool initialize $TESTPOOL $DISK1
+
+log_pass "Nonsensical initialize operations fail"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_pos.ksh
new file mode 100755
index 000000000000..5003b5f10bdb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_start_and_cancel_pos.ksh
@@ -0,0 +1,52 @@
+#!/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) 2016 by Delphix. All rights reserved.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+
+#
+# DESCRIPTION:
+# Starting and stopping an initialize works.
+#
+# STRATEGY:
+# 1. Create a one-disk pool.
+# 2. Start initializing and verify that initializing is active.
+# 3. Cancel initializing and verify that initializing is not active.
+#
+
+DISK1=${DISKS%% *}
+
+log_must zpool create -f $TESTPOOL $DISK1
+log_must zpool initialize $TESTPOOL
+
+[[ -z "$(initialize_progress $TESTPOOL $DISK1)" ]] && \
+ log_fail "Initialize did not start"
+
+log_must zpool initialize -c $TESTPOOL
+
+[[ -z "$(initialize_progress $TESTPOOL $DISK1)" ]] || \
+ log_fail "Initialize did not stop"
+
+log_pass "Initialize start + cancel works"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_suspend_resume.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_suspend_resume.ksh
new file mode 100755
index 000000000000..bce3da5267cd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_suspend_resume.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) 2016 by Delphix. All rights reserved.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+
+#
+# DESCRIPTION:
+# Suspending and resuming initializing works.
+#
+# STRATEGY:
+# 1. Create a one-disk pool.
+# 2. Start initializing and verify that initializing is active.
+# 3. Wait 3 seconds, then suspend initializing and verify that the progress
+# reporting says so.
+# 4. Wait 5 seconds and ensure initializing progress doesn't advance.
+# 5. Restart initializing and verify that the progress doesn't regress.
+#
+
+DISK1=${DISKS%% *}
+
+log_must zpool create -f $TESTPOOL $DISK1
+log_must zpool initialize $TESTPOOL
+
+[[ -z "$(initialize_progress $TESTPOOL $DISK1)" ]] && \
+ log_fail "Initializing did not start"
+
+sleep 5
+log_must zpool initialize -s $TESTPOOL
+log_must eval "initialize_prog_line $TESTPOOL $DISK1 | grep suspended"
+progress="$(initialize_progress $TESTPOOL $DISK1)"
+
+sleep 3
+[[ "$progress" -eq "$(initialize_progress $TESTPOOL $DISK1)" ]] || \
+ log_fail "Initializing progress advanced while suspended"
+
+log_must zpool initialize $TESTPOOL $DISK1
+[[ "$progress" -le "$(initialize_progress $TESTPOOL $DISK1)" ]] ||
+ log_fail "Initializing progress regressed after resuming"
+
+log_pass "Suspend + resume initializing works as expected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_unsupported_vdevs.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_unsupported_vdevs.ksh
new file mode 100755
index 000000000000..bd4ca069c49b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_unsupported_vdevs.ksh
@@ -0,0 +1,74 @@
+#!/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) 2016 by Delphix. All rights reserved.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+
+#
+# DESCRIPTION:
+# Attempting to initialize unsupported vdevs should fail.
+#
+# STRATEGY:
+# 1. Create a pool with the following configuration:
+# root
+# mirror
+# vdev0
+# vdev1 (offline)
+# cache
+# vdev2
+# spare
+# vdev3
+# 2. Try to initialize vdev1, vdev2, and vdev3. Ensure that all 3 fail.
+#
+function cleanup
+{
+ if datasetexists $TESTPOOL; then
+ log_must zpool destroy -f $TESTPOOL
+ fi
+ if [[ -d $TESTDIR ]]; then
+ log_must rm -rf $TESTDIR
+ fi
+}
+log_onexit cleanup
+
+log_must mkdir $TESTDIR
+set -A FDISKS
+for n in {0..2}; do
+ log_must mkfile $MINVDEVSIZE $TESTDIR/vdev$n
+ FDISKS+=("$TESTDIR/vdev$n")
+done
+FDISKS+=("${DISKS%% *}")
+
+log_must zpool create $TESTPOOL mirror ${FDISKS[0]} ${FDISKS[1]} \
+ spare ${FDISKS[2]} cache ${FDISKS[3]}
+
+log_must zpool offline $TESTPOOL ${FDISKS[1]}
+
+log_mustnot zpool initialize $TESTPOOL mirror-0
+for n in {1..3}; do
+ log_mustnot zpool initialize $TESTPOOL ${FDISKS[$n]}
+done
+
+log_pass "Attempting to initialize failed on unsupported devices"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_checksums.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_checksums.ksh
new file mode 100755
index 000000000000..9be752ff83f2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_checksums.ksh
@@ -0,0 +1,59 @@
+#!/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) 2016 by Delphix. All rights reserved.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+
+#
+# DESCRIPTION:
+# Initializing does not cause file corruption.
+#
+# STRATEGY:
+# 1. Create a one-disk pool.
+# 2. Write data to the pool.
+# 3. Start initializing and verify that initializing is active.
+# 4. Write more data to the pool.
+# 5. Run zdb to validate checksums.
+#
+
+DISK1=${DISKS%% *}
+
+log_must zpool create -f $TESTPOOL $DISK1
+log_must dd if=/dev/urandom of=/$TESTPOOL/file1 bs=1M count=30
+log_must sync
+
+log_must zpool initialize $TESTPOOL
+
+log_must zdb -cc $TESTPOOL
+
+[[ -z "$(initialize_progress $TESTPOOL $DISK1)" ]] && \
+ log_fail "Initializing did not start"
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/file2 bs=1M count=30
+log_must sync
+
+log_must zdb -cc $TESTPOOL
+
+log_pass "Initializing does not corrupt existing or new data"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_initialized.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_initialized.ksh
new file mode 100755
index 000000000000..6a8f7d49f2b2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_verify_initialized.ksh
@@ -0,0 +1,89 @@
+#!/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) 2016 by Delphix. All rights reserved.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+
+#
+# DESCRIPTION:
+# After initializing, the disk is actually initialized.
+#
+# STRATEGY:
+# 1. Create a one-disk pool.
+# 2. Initialize the disk to completion.
+# 3. Load all metaslabs that don't have a spacemap, and make sure the entire
+# metaslab has been filled with the initializing pattern (deadbeef).
+#
+
+function cleanup
+{
+ set_tunable64 INITIALIZE_VALUE $ORIG_PATTERN
+ zpool import -d $TESTDIR $TESTPOOL
+
+ if datasetexists $TESTPOOL ; then
+ zpool destroy -f $TESTPOOL
+ fi
+ if [[ -d "$TESTDIR" ]]; then
+ rm -rf "$TESTDIR"
+ fi
+}
+log_onexit cleanup
+
+PATTERN="deadbeefdeadbeef"
+SMALLFILE="$TESTDIR/smallfile"
+
+ORIG_PATTERN=$(get_tunable INITIALIZE_VALUE)
+log_must set_tunable64 INITIALIZE_VALUE $(printf %llu 0x$PATTERN)
+
+log_must mkdir "$TESTDIR"
+log_must mkfile $MINVDEVSIZE "$SMALLFILE"
+log_must zpool create $TESTPOOL "$SMALLFILE"
+log_must zpool initialize $TESTPOOL
+
+while [[ "$(initialize_progress $TESTPOOL $SMALLFILE)" -lt "100" ]]; do
+ sleep 0.5
+done
+
+log_must zpool export $TESTPOOL
+
+spacemaps=0
+bs=512
+while read -r sm; do
+ typeset offset="$(echo $sm | cut -d ' ' -f1)"
+ typeset size="$(echo $sm | cut -d ' ' -f2)"
+
+ spacemaps=$((spacemaps + 1))
+ offset=$(((4 * 1024 * 1024) + 16#$offset))
+ out=$(dd if=$SMALLFILE skip=$(($offset / $bs)) \
+ count=$(($size / $bs)) bs=$bs 2>/dev/null | od -t x8 -Ad)
+ echo "$out" | log_must egrep "$PATTERN|\*|$size"
+done <<< "$(zdb -p $TESTDIR -Pme $TESTPOOL | egrep 'spacemap[ ]+0 ' | \
+ awk '{print $4, $8}')"
+
+if [[ $spacemaps -eq 0 ]];then
+ log_fail "Did not find any empty space maps to check"
+else
+ log_pass "Initializing wrote appropriate amount to disk"
+fi
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/Makefile.am
new file mode 100644
index 000000000000..c258f0c929d4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/Makefile.am
@@ -0,0 +1,9 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_labelclear
+dist_pkgdata_SCRIPTS = \
+ zpool_labelclear_active.ksh \
+ zpool_labelclear_exported.ksh \
+ zpool_labelclear_removed.ksh \
+ zpool_labelclear_valid.ksh
+
+dist_pkgdata_DATA = \
+ labelclear.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/labelclear.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/labelclear.cfg
new file mode 100644
index 000000000000..b2a10aa28a46
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/labelclear.cfg
@@ -0,0 +1,28 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2016 Nexenta Systems, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+typeset disks=(${DISKS[*]})
+
+if is_freebsd; then
+ typeset disk1=/dev/${disks[0]}
+ typeset disk2=/dev/${disks[1]}
+ typeset disk3=/dev/${disks[2]}
+else
+ typeset disk1=${disks[0]}
+ typeset disk2=${disks[1]}
+ typeset disk3=${disks[2]}
+fi
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_active.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_active.ksh
new file mode 100755
index 000000000000..b63d55d7ad64
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_active.ksh
@@ -0,0 +1,68 @@
+#!/bin/ksh -p
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2016 Nexenta Systems, Inc.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_labelclear/labelclear.cfg
+
+# DESCRIPTION:
+# Check that zpool labelclear will refuse to clear the label
+# (with or without -f) on any vdevs of the imported pool.
+#
+# STRATEGY:
+# 1. Create the pool with log device.
+# 2. Try clearing the label on data and log devices.
+# 3. Add auxiliary (cache/spare) vdevs.
+# 4. Try clearing the label on auxiliary vdevs.
+# 5. Check that zpool labelclear will return non-zero and
+# labels are intact.
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+log_assert "zpool labelclear will fail on all vdevs of imported pool"
+
+# Create simple pool, skip any mounts
+log_must zpool create -O mountpoint=none -f $TESTPOOL $disk1 log $disk2
+
+# Check that labelclear [-f] will fail on ACTIVE pool vdevs
+log_mustnot zpool labelclear $disk1
+log_must zdb -lq $disk1
+log_mustnot zpool labelclear -f $disk1
+log_must zdb -lq $disk1
+log_mustnot zpool labelclear $disk2
+log_must zdb -lq $disk2
+log_mustnot zpool labelclear -f $disk2
+log_must zdb -lq $disk2
+
+# Add a cache/spare to the pool, check that labelclear [-f] will fail
+# on the vdev and will succeed once it's removed from pool config
+for vdevtype in "cache" "spare"; do
+ log_must zpool add $TESTPOOL $vdevtype $disk3
+ log_mustnot zpool labelclear $disk3
+ log_must zdb -lq $disk3
+ log_mustnot zpool labelclear -f $disk3
+ log_must zdb -lq $disk3
+ log_must zpool remove $TESTPOOL $disk3
+ log_must zpool labelclear $disk3
+ log_mustnot zdb -lq $disk3
+done
+
+log_pass "zpool labelclear will fail on all vdevs of imported pool"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_exported.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_exported.ksh
new file mode 100755
index 000000000000..72a555bebe07
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_exported.ksh
@@ -0,0 +1,74 @@
+#!/bin/ksh -p
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2016 Nexenta Systems, Inc.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_labelclear/labelclear.cfg
+
+# DESCRIPTION:
+# Check that zpool labelclear will refuse to clear the label
+# on ACTIVE vdevs of exported pool without -f, and will succeeded with -f.
+#
+# STRATEGY:
+# 1. Create a pool with log device.
+# 2. Export the pool.
+# 3. Check that zpool labelclear returns non-zero when trying to
+# clear the label on ACTIVE vdevs, and succeeds with -f.
+# 4. Add auxiliary vdevs (cache/spare).
+# 5. Check that zpool labelclear succeeds on auxiliary vdevs of
+# exported pool.
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+log_assert "zpool labelclear will fail on ACTIVE vdevs of exported pool and" \
+ "succeed with -f"
+
+for vdevtype in "" "cache" "spare"; do
+ # Create simple pool, skip any mounts
+ log_must zpool create -O mountpoint=none -f $TESTPOOL $disk1 log $disk2
+ # Add auxiliary vdevs (cache/spare)
+ if [[ -n $vdevtype ]]; then
+ log_must zpool add $TESTPOOL $vdevtype $disk3
+ fi
+ # Export the pool
+ log_must zpool export $TESTPOOL
+
+ # Check that labelclear will fail without -f
+ log_mustnot zpool labelclear $disk1
+ log_must zdb -lq $disk1
+ log_mustnot zpool labelclear $disk2
+ log_must zdb -lq $disk2
+
+ # Check that labelclear will succeed with -f
+ log_must zpool labelclear -f $disk1
+ log_mustnot zdb -lq $disk1
+ log_must zpool labelclear -f $disk2
+ log_mustnot zdb -lq $disk2
+
+ # Check that labelclear on auxiliary vdevs will succeed
+ if [[ -n $vdevtype ]]; then
+ log_must zpool labelclear $disk3
+ log_mustnot zdb -lq $disk3
+ fi
+done
+
+log_pass "zpool labelclear will fail on ACTIVE vdevs of exported pool and" \
+ "succeed with -f"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_removed.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_removed.ksh
new file mode 100755
index 000000000000..f93de6e22445
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_removed.ksh
@@ -0,0 +1,62 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2016 Nexenta Systems, Inc.
+# Copyright (c) 2019 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_labelclear/labelclear.cfg
+
+# DESCRIPTION:
+# Check that `zpool labelclear` can clear labels on removed devices.
+#
+# STRATEGY:
+# 1. Create a pool with primary, log, spare and cache devices.
+# 2. Remove a top-level vdev, log, spare, and cache device.
+# 3. Run `zpool labelclear` on the removed device.
+# 4. Verify the label has been removed.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -f $DEVICE1 $DEVICE2 $DEVICE3 $DEVICE4 $DEVICE5
+}
+
+log_onexit cleanup
+log_assert "zpool labelclear works for removed devices"
+
+DEVICE1="$TEST_BASE_DIR/device-1"
+DEVICE2="$TEST_BASE_DIR/device-2"
+DEVICE3="$TEST_BASE_DIR/device-3"
+DEVICE4="$TEST_BASE_DIR/device-4"
+DEVICE5="$TEST_BASE_DIR/device-5"
+
+log_must truncate -s $((SPA_MINDEVSIZE * 8)) $DEVICE1
+log_must truncate -s $SPA_MINDEVSIZE $DEVICE2 $DEVICE3 $DEVICE4 $DEVICE5
+
+log_must zpool create -f $TESTPOOL $DEVICE1 $DEVICE2 \
+ log $DEVICE3 cache $DEVICE4 spare $DEVICE5
+log_must zpool sync
+
+# Remove each type of vdev and verify the label can be cleared.
+for dev in $DEVICE5 $DEVICE4 $DEVICE3 $DEVICE2; do
+ log_must zpool remove $TESTPOOL $dev
+ log_must zpool sync $TESTPOOL
+ log_must zpool labelclear $dev
+ log_mustnot zdb -lq $dev
+done
+
+log_pass "zpool labelclear works for removed devices"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_valid.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_valid.ksh
new file mode 100755
index 000000000000..31af9fd3f807
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_labelclear/zpool_labelclear_valid.ksh
@@ -0,0 +1,94 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2016 Nexenta Systems, Inc.
+# Copyright (c) 2019 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_labelclear/labelclear.cfg
+
+# DESCRIPTION:
+# Check that `zpool labelclear` only clears valid labels. Expected
+# label offsets which do not contain intact labels are left untouched.
+#
+# STRATEGY:
+# 1. Create a pool with primary, log, spare and cache devices.
+# 2. Export the pool.
+# 3. Write a known pattern over the first two device labels.
+# 4. Verify with zdb that only the last two device labels are intact.
+# 5. Verify the pool could be imported using those labels.
+# 6. Run `zpool labelclear` to destroy those last two labels.
+# 7. Verify the pool can no longer be found; let alone imported.
+# 8. Verify the pattern is intact to confirm `zpool labelclear` did
+# not write to first two label offsets.
+# 9. Verify that no valid label remain.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -f $PATTERN_FILE $DISK_PATTERN_FILE \
+ $DEVICE1 $DEVICE2 $DEVICE3 $DEVICE4
+}
+
+log_onexit cleanup
+log_assert "zpool labelclear will only clear valid labels"
+
+PATTERN_FILE=$TEST_BASE_DIR/pattern
+DISK_PATTERN_FILE=$TEST_BASE_DIR/disk-pattern
+
+DEVICE1="$TEST_BASE_DIR/device-1"
+DEVICE2="$TEST_BASE_DIR/device-2"
+DEVICE3="$TEST_BASE_DIR/device-3"
+DEVICE4="$TEST_BASE_DIR/device-4"
+
+log_must dd if=/dev/urandom of=$PATTERN_FILE bs=1048576 count=4
+
+log_must truncate -s $SPA_MINDEVSIZE $DEVICE1 $DEVICE2 $DEVICE3 $DEVICE4
+
+log_must zpool create -O mountpoint=none -f $TESTPOOL $DEVICE1 \
+ log $DEVICE2 cache $DEVICE3 spare $DEVICE4
+log_must zpool export $TESTPOOL
+
+# Overwrite the first 4M of each device and verify the expected labels.
+for dev in $DEVICE1 $DEVICE2 $DEVICE3 $DEVICE4; do
+ dd if=$PATTERN_FILE of=$dev bs=1048576 conv=notrunc
+ log_must eval "zdb -l $dev | grep 'labels = 2 3'"
+done
+
+# Verify the pool could be imported using those labels.
+log_must eval "zpool import -d $TEST_BASE_DIR | grep $TESTPOOL"
+
+# Verify the last two labels on each vdev can be cleared.
+for dev in $DEVICE1 $DEVICE2 $DEVICE3 $DEVICE4; do
+ log_must zpool labelclear -f $dev
+done
+
+# Verify there is no longer a pool which can be imported.
+log_mustnot eval "zpool import -d $TEST_BASE_DIR | grep $TESTPOOL"
+
+# Verify the original pattern over the first two labels is intact
+for dev in $DEVICE1 $DEVICE2 $DEVICE3 $DEVICE4; do
+ log_must dd if=$dev of=$DISK_PATTERN_FILE bs=1048576 count=4
+ log_must cmp $DISK_PATTERN_FILE $PATTERN_FILE
+ log_mustnot zdb -lq $dev
+done
+
+# Verify an error is reported when there are no labels to clear.
+for dev in $DEVICE1 $DEVICE2 $DEVICE3 $DEVICE4; do
+ log_mustnot zpool labelclear -f $dev
+done
+
+log_pass "zpool labelclear will only clear valid labels"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/Makefile.am
new file mode 100644
index 000000000000..33fbb18d66f3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/Makefile.am
@@ -0,0 +1,7 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_offline
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_offline_001_pos.ksh \
+ zpool_offline_002_neg.ksh \
+ zpool_offline_003_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/cleanup.ksh
new file mode 100755
index 000000000000..89c146249e71
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/cleanup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/setup.ksh
new file mode 100755
index 000000000000..2229f87e6208
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/setup.ksh
@@ -0,0 +1,35 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+DISK=${DISKS%% *}
+
+default_mirror_setup $DISKS
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_001_pos.ksh
new file mode 100755
index 000000000000..6f4c2e3182d1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_001_pos.ksh
@@ -0,0 +1,124 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Executing 'zpool offline' with valid parameters succeeds.
+#
+# STRATEGY:
+# 1. Create an array of correctly formed 'zpool offline' options
+# 2. Execute each element of the array.
+# 3. Verify use of each option is successful.
+
+verify_runnable "global"
+
+DISKLIST=$(get_disklist $TESTPOOL)
+set -A disks $DISKLIST
+typeset -i num=${#disks[*]}
+
+set -A args "" "-t"
+
+function cleanup
+{
+ #
+ # Ensure we don't leave disks in the offline state
+ #
+ for disk in $DISKLIST; do
+ log_must zpool online $TESTPOOL $disk
+ check_state $TESTPOOL $disk "online"
+ if [[ $? != 0 ]]; then
+ log_fail "Unable to online $disk"
+ fi
+
+ done
+}
+
+log_assert "Executing 'zpool offline' with correct options succeeds"
+
+log_onexit cleanup
+
+if [[ -z $DISKLIST ]]; then
+ log_fail "DISKLIST is empty."
+fi
+
+typeset -i i=0
+typeset -i j=1
+
+for disk in $DISKLIST; do
+ i=0
+ while [[ $i -lt ${#args[*]} ]]; do
+ if (( j < num )) ; then
+ log_must zpool offline ${args[$i]} $TESTPOOL $disk
+ check_state $TESTPOOL $disk "offline"
+ if [[ $? != 0 ]]; then
+ log_fail "$disk of $TESTPOOL did not match offline state"
+ fi
+ else
+ log_mustnot zpool offline ${args[$i]} $TESTPOOL $disk
+ check_state $TESTPOOL $disk "online"
+ if [[ $? != 0 ]]; then
+ log_fail "$disk of $TESTPOOL did not match online state"
+ fi
+ fi
+
+ (( i = i + 1 ))
+ done
+ (( j = j + 1 ))
+done
+
+log_note "Issuing repeated 'zpool offline' commands succeeds."
+
+typeset -i iters=20
+typeset -i index=0
+
+for disk in $DISKLIST; do
+ i=0
+ while [[ $i -lt $iters ]]; do
+ index=`expr $RANDOM % ${#args[*]}`
+ log_must zpool offline ${args[$index]} $TESTPOOL $disk
+ check_state $TESTPOOL $disk "offline"
+ if [[ $? != 0 ]]; then
+ log_fail "$disk of $TESTPOOL is not offline."
+ fi
+
+ (( i = i + 1 ))
+ done
+
+ log_must zpool online $TESTPOOL $disk
+ check_state $TESTPOOL $disk "online"
+ if [[ $? != 0 ]]; then
+ log_fail "$disk of $TESTPOOL did not match online state"
+ fi
+done
+
+log_pass "'zpool offline -f' succeeded"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_002_neg.ksh
new file mode 100755
index 000000000000..14e0ab3fa75b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_002_neg.ksh
@@ -0,0 +1,96 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Executing 'zpool offline' command with bad options fails.
+#
+# STRATEGY:
+# 1. Create an array of badly formed 'zpool offline' options.
+# 2. Execute each element of the array.
+# 3. Verify an error code is returned.
+#
+
+verify_runnable "global"
+
+DISKLIST=$(get_disklist $TESTPOOL)
+
+set -A args "" "-?" "-t fakepool" "-f fakepool" "-ev fakepool" "fakepool" \
+ "-t $TESTPOOL" "-t $TESTPOOL/$TESTFS" "-t $TESTPOOL/$TESTFS $DISKLIST" \
+ "-t $TESTPOOL/$TESTCTR" "-t $TESTPOOL/$TESTCTR/$TESTFS1" \
+ "-t $TESTPOOL/$TESTCTR $DISKLIST" "-t $TESTPOOL/$TESTVOL" \
+ "-t $TESTPOOL/$TESTCTR/$TESTFS1 $DISKLIST" \
+ "-t $TESTPOOL/$TESTVOL $DISKLIST" \
+ "-t $DISKLIST" \
+ "-f $TESTPOOL" "-f $TESTPOOL/$TESTFS" "-f $TESTPOOL/$TESTFS $DISKLIST" \
+ "-f $TESTPOOL/$TESTCTR" "-f $TESTPOOL/$TESTCTR/$TESTFS1" \
+ "-f $TESTPOOL/$TESTCTR $DISKLIST" "-f $TESTPOOL/$TESTVOL" \
+ "-f $TESTPOOL/$TESTCTR/$TESTFS1 $DISKLIST" \
+ "-f $TESTPOOL/$TESTVOL $DISKLIST" \
+ "-f $DISKLIST" \
+ "-ft $TESTPOOL" "-ft $TESTPOOL/$TESTFS" \
+ "-ft $TESTPOOL/$TESTFS $DISKLIST" \
+ "-ft $TESTPOOL/$TESTCTR" "-ft $TESTPOOL/$TESTCTR/$TESTFS1" \
+ "-ft $TESTPOOL/$TESTCTR $DISKLIST" "-ft $TESTPOOL/$TESTVOL" \
+ "-ft $TESTPOOL/$TESTCTR/$TESTFS1 $DISKLIST" \
+ "-ft $TESTPOOL/$TESTVOL $DISKLIST" \
+ "-ft $DISKLIST" \
+ "-tf $TESTPOOL" "-tf $TESTPOOL/$TESTFS" \
+ "-tf $TESTPOOL/$TESTFS $DISKLIST" \
+ "-tf $TESTPOOL/$TESTCTR" "-tf $TESTPOOL/$TESTCTR/$TESTFS1" \
+ "-tf $TESTPOOL/$TESTCTR $DISKLIST" "-tf $TESTPOOL/$TESTVOL" \
+ "-tf $TESTPOOL/$TESTCTR/$TESTFS1 $DISKLIST" \
+ "-tf $TESTPOOL/$TESTVOL $DISKLIST" \
+ "-tf $DISKLIST" \
+ "$TESTPOOL" "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTFS $DISKLIST" \
+ "$TESTPOOL/$TESTCTR" "$TESTPOOL/$TESTCTR/$TESTFS1" \
+ "$TESTPOOL/$TESTCTR $DISKLIST" "$TESTPOOL/$TESTVOL" \
+ "$TESTPOOL/$TESTCTR/$TESTFS1 $DISKLIST" "$TESTPOOL/$TESTVOL $DISKLIST" \
+ "$DISKLIST"
+
+log_assert "Executing 'zpool offline' with bad options fails"
+
+if [[ -z $DISKLIST ]]; then
+ log_fail "DISKLIST is empty."
+fi
+
+typeset -i i=0
+
+while [[ $i -lt ${#args[*]} ]]; do
+
+ log_mustnot zpool offline ${args[$i]}
+
+ (( i = i + 1 ))
+done
+
+log_pass "'zpool offline' command with bad options failed as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_003_pos.ksh
new file mode 100755
index 000000000000..7b5d21cba208
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_offline/zpool_offline_003_pos.ksh
@@ -0,0 +1,111 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Test force faulting a VDEV with 'zpool offline -f'
+#
+# STRATEGY:
+# For both temporary and persistent faults, do the following:
+# 1. Force fault a vdev, and clear the fault.
+# 2. Offline a vdev, force fault it, clear the fault, and online it.
+# 3. Force fault a vdev, export it, then import it.
+
+verify_runnable "global"
+
+DISKLIST=$(get_disklist $TESTPOOL)
+set -A disks $DISKLIST
+typeset -i num=${#disks[*]}
+
+set -A args "" "-t"
+
+function cleanup
+{
+ # Ensure we don't leave disks in the offline state
+ for disk in $DISKLIST; do
+ log_must zpool online $TESTPOOL $disk
+ check_state $TESTPOOL $disk "online"
+ if [[ $? != 0 ]]; then
+ log_fail "Unable to online $disk"
+ fi
+ done
+}
+
+log_assert "Executing 'zpool offline -f' with correct options succeeds"
+
+log_onexit cleanup
+
+if [[ -z $DISKLIST ]]; then
+ log_fail "DISKLIST is empty."
+fi
+
+typeset -i i=0
+typeset -i j=1
+
+# Get name of the first disk in the pool
+disk=${DISKLIST%% *}
+
+# Test temporary and persistent faults
+for arg in f tf ; do
+ # Force fault disk, and clear the fault
+ log_must zpool offline -$arg $TESTPOOL $disk
+ check_state $TESTPOOL $disk "faulted"
+ log_must zpool clear $TESTPOOL $disk
+ check_state $TESTPOOL $disk "online"
+
+ # Offline a disk, force fault it, clear the fault, and online it
+ log_must zpool offline $TESTPOOL $disk
+ check_state $TESTPOOL $disk "offline"
+ log_must zpool offline -$arg $TESTPOOL $disk
+ check_state $TESTPOOL $disk "faulted"
+ log_must zpool clear $TESTPOOL $disk
+ check_state $TESTPOOL $disk "offline"
+ log_must zpool online $TESTPOOL $disk
+ check_state $TESTPOOL $disk "online"
+
+ # Test faults across imports
+ log_must zpool offline -tf $TESTPOOL $disk
+ check_state $TESTPOOL $disk "faulted"
+ log_must zpool export $TESTPOOL
+ log_must zpool import $TESTPOOL
+ log_note "-$arg now imported"
+ if [[ "$arg" = "f" ]] ; then
+ # Persistent fault
+ check_state $TESTPOOL $disk "faulted"
+ log_must zpool clear $TESTPOOL $disk
+ else
+ # Temporary faults get cleared by imports
+ check_state $TESTPOOL $disk "online"
+ fi
+done
+log_pass "'zpool offline -f' with correct options succeeded"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_online/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_online/Makefile.am
new file mode 100644
index 000000000000..12681e3c4141
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_online/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_online
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_online_001_pos.ksh \
+ zpool_online_002_neg.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_online/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_online/cleanup.ksh
new file mode 100755
index 000000000000..89c146249e71
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_online/cleanup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_online/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_online/setup.ksh
new file mode 100755
index 000000000000..2229f87e6208
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_online/setup.ksh
@@ -0,0 +1,35 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+DISK=${DISKS%% *}
+
+default_mirror_setup $DISKS
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_001_pos.ksh
new file mode 100755
index 000000000000..7ba301e2b56b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_001_pos.ksh
@@ -0,0 +1,124 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Executing 'zpool online' with valid parameters succeeds.
+#
+# STRATEGY:
+# 1. Create an array of correctly formed 'zpool online' options
+# 2. Execute each element of the array.
+# 3. Verify use of each option is successful.
+#
+
+verify_runnable "global"
+
+DISKLIST=$(get_disklist $TESTPOOL)
+
+set -A args ""
+
+function cleanup
+{
+ #
+ # Ensure we don't leave disks in temporary online state (-t)
+ #
+ for disk in $DISKLIST; do
+ log_must zpool online $TESTPOOL $disk
+ check_state $TESTPOOL $disk "online"
+ if [[ $? != 0 ]]; then
+ log_fail "Unable to online $disk"
+ fi
+
+ done
+}
+
+log_assert "Executing 'zpool online' with correct options succeeds"
+
+log_onexit cleanup
+
+if [[ -z $DISKLIST ]]; then
+ log_fail "DISKLIST is empty."
+fi
+
+typeset -i i=0
+typeset -i j=0
+
+for disk in $DISKLIST; do
+ i=0
+ while [[ $i -lt ${#args[*]} ]]; do
+
+ log_must sync_pool $TESTPOOL
+ log_must zpool offline $TESTPOOL $disk
+ check_state $TESTPOOL $disk "offline"
+ if [[ $? != 0 ]]; then
+ log_fail "$disk of $TESTPOOL did not match offline state"
+ fi
+
+ log_must zpool online ${args[$i]} $TESTPOOL $disk
+ check_state $TESTPOOL $disk "online"
+ if [[ $? != 0 ]]; then
+ log_fail "$disk of $TESTPOOL did not match online state"
+ fi
+
+ while [[ $j -lt 20 ]]; do
+ is_pool_resilvered $TESTPOOL && break
+ sleep 0.5
+ (( j = j + 1 ))
+ done
+ is_pool_resilvered $TESTPOOL || \
+ log_file "Pool didn't resilver after online"
+
+ (( i = i + 1 ))
+ done
+done
+
+log_note "Issuing repeated 'zpool online' commands succeeds."
+
+typeset -i iters=20
+typeset -i index=0
+
+for disk in $DISKLIST; do
+ i=0
+ while [[ $i -lt $iters ]]; do
+ index=`expr $RANDOM % ${#args[*]}`
+ log_must zpool online ${args[$index]} $TESTPOOL $disk
+ check_state $TESTPOOL $disk "online"
+ if [[ $? != 0 ]]; then
+ log_fail "$disk of $TESTPOOL did not match online state"
+ fi
+
+ (( i = i + 1 ))
+ done
+done
+
+log_pass "'zpool online' with correct options succeeded"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_002_neg.ksh
new file mode 100755
index 000000000000..79855e64a809
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_online/zpool_online_002_neg.ksh
@@ -0,0 +1,75 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Executing 'zpool online' command with bad options fails.
+#
+# STRATEGY:
+# 1. Create an array of badly formed 'zpool online' options.
+# 2. Execute each element of the array.
+# 3. Verify an error code is returned.
+#
+verify_runnable "global"
+
+DISKLIST=$(get_disklist $TESTPOOL)
+
+set -A args "" "-?" "-e fakepool" "-v fakepool" "-ev fakepool" "-ve fakepool" \
+ "-t $TESTPOOL" "-t $TESTPOOL/$TESTFS" "-t $TESTPOOL/$TESTFS $DISKLIST" \
+ "-t $TESTPOOL/$TESTCTR" "-t $TESTPOOL/$TESTCTR/$TESTFS1" \
+ "-t $TESTPOOL/$TESTCTR $DISKLIST" "-t $TESTPOOL/$TESTVOL" \
+ "-t $TESTPOOL/$TESTCTR/$TESTFS1 $DISKLIST" \
+ "-t $TESTPOOL/$TESTVOL $DISKLIST" \
+ "-t $DISKLIST" \
+ "$TESTPOOL" "$TESTPOOL/$TESTFS" "$TESTPOOL/$TESTFS $DISKLIST" \
+ "$TESTPOOL/$TESTCTR" "$TESTPOOL/$TESTCTR/$TESTFS1" \
+ "$TESTPOOL/$TESTCTR $DISKLIST" "$TESTPOOL/$TESTVOL" \
+ "$TESTPOOL/$TESTCTR/$TESTFS1 $DISKLIST" "$TESTPOOL/$TESTVOL $DISKLIST" \
+ "$DISKLIST"
+
+log_assert "Executing 'zpool online' with bad options fails"
+
+if [[ -z $DISKLIST ]]; then
+ log_fail "DISKLIST is empty."
+fi
+
+typeset -i i=0
+
+while [[ $i -lt ${#args[*]} ]]; do
+
+ log_mustnot zpool online ${args[$i]}
+
+ (( i = i + 1 ))
+done
+
+log_pass "'zpool online' command with bad options failed as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/Makefile.am
new file mode 100644
index 000000000000..e30e3f60c2d6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/Makefile.am
@@ -0,0 +1,10 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_remove
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_remove_001_neg.ksh \
+ zpool_remove_002_pos.ksh \
+ zpool_remove_003_pos.ksh
+
+dist_pkgdata_DATA = \
+ zpool_remove.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/cleanup.ksh
new file mode 100755
index 000000000000..307fae7196d2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/cleanup.ksh
@@ -0,0 +1,38 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_remove/zpool_remove.cfg
+
+DISK=${DISKS%% *}
+if is_mpath_device $DISK; then
+ delete_partitions
+fi
+
+cleanup_devices $DISKS
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/setup.ksh
new file mode 100755
index 000000000000..8ce094bcc701
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/setup.ksh
@@ -0,0 +1,37 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_remove/zpool_remove.cfg
+
+verify_runnable "global"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove.cfg
new file mode 100644
index 000000000000..1b8312e99372
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove.cfg
@@ -0,0 +1,31 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+echo $DISKS | read DISK0 DISK1 DISK2
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_001_neg.ksh
new file mode 100755
index 000000000000..0c098a61e238
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_001_neg.ksh
@@ -0,0 +1,95 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_remove/zpool_remove.cfg
+
+#
+# DESCRIPTION:
+# Verify that 'zpool can not remove device except inactive hot spares from pool'
+#
+# STRATEGY:
+# 1. Create all kinds of pool (strip, mirror, raidz, hotspare)
+# 2. Try to remove device from the pool
+# 3. Verify that the remove failed.
+#
+
+typeset vdev_devs="${DISK0}"
+typeset mirror_devs="${DISK0} ${DISK1}"
+typeset raidz_devs=${mirror_devs}
+typeset raidz1_devs=${mirror_devs}
+typeset raidz2_devs="${mirror_devs} ${DISK2}"
+typeset spare_devs1="${DISK0}"
+typeset spare_devs2="${DISK1}"
+
+function check_remove
+{
+ typeset pool=$1
+ typeset devs="$2"
+ typeset dev
+
+ for dev in $devs; do
+ log_mustnot zpool remove $dev
+ done
+
+ destroy_pool $pool
+
+}
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+}
+
+set -A create_args "$vdev_devs" "mirror $mirror_devs" \
+ "raidz $raidz_devs" "raidz $raidz1_devs" \
+ "raidz2 $raidz2_devs" \
+ "$spare_devs1 spare $spare_devs2"
+
+set -A verify_disks "$vdev_devs" "$mirror_devs" "$raidz_devs" \
+ "$raidz1_devs" "$raidz2_devs" "$spare_devs1"
+
+
+log_assert "Check zpool remove <pool> <device> can not remove " \
+ "active device from pool"
+
+log_onexit cleanup
+
+typeset -i i=0
+while [[ $i -lt ${#create_args[*]} ]]; do
+ log_must zpool create $TESTPOOL ${create_args[i]}
+ check_remove $TESTPOOL "${verify_disks[i]}"
+ (( i = i + 1))
+done
+
+log_pass "'zpool remove <pool> <device> fail as expected .'"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_002_pos.ksh
new file mode 100755
index 000000000000..4ab7ac659b83
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_002_pos.ksh
@@ -0,0 +1,68 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_remove/zpool_remove.cfg
+
+#
+# DESCRIPTION:
+# Verify that 'zpool can only remove inactive hot spare devices from pool'
+#
+# STRATEGY:
+# 1. Create a hotspare pool
+# 2. Try to remove the inactive hotspare device from the pool
+# 3. Verify that the remove succeed.
+#
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+}
+
+log_onexit cleanup
+
+typeset spare_devs1="${DISK0}"
+typeset spare_devs2="${DISK1}"
+
+log_assert "zpool remove can only remove inactive hotspare device from pool"
+
+log_note "check hotspare device which is created by zpool create"
+log_must zpool create $TESTPOOL $spare_devs1 spare $spare_devs2
+log_must zpool remove $TESTPOOL $spare_devs2
+
+log_note "check hotspare device which is created by zpool add"
+log_must zpool add $TESTPOOL spare $spare_devs2
+log_must zpool remove $TESTPOOL $spare_devs2
+log_must zpool destroy $TESTPOOL
+
+log_pass "zpool remove can only remove inactive hotspare device from pool"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_003_pos.ksh
new file mode 100755
index 000000000000..4e132d9d00b5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_remove/zpool_remove_003_pos.ksh
@@ -0,0 +1,71 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_remove/zpool_remove.cfg
+
+#
+# DESCRIPTION:
+# Verify that 'zpool can remove hotspare devices from pool when it state
+# switch from active to inactive'
+#
+# STRATEGY:
+# 1. Create a hotspare pool
+# 2. Try to replace the inactive hotspare device to active device in the pool
+# 3. Try to detach active (spare) device to make it inactive
+# 3. Verify that the zpool remove succeed.
+#
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+}
+
+log_onexit cleanup
+typeset disk=${DISK}
+
+typeset spare_devs1="${DISK0}"
+typeset spare_devs2="${DISK1}"
+typeset spare_devs3="${DISK2}"
+
+log_assert "zpool remove can remove hotspare device which state go though" \
+ " active to inactive in pool"
+
+log_note "Check spare device which state go through active to inactive"
+log_must zpool create $TESTPOOL $spare_devs1 $spare_devs2 spare $spare_devs3
+log_must zpool replace $TESTPOOL $spare_devs2 $spare_devs3
+log_mustnot zpool remove $TESTPOOL $spare_devs3
+log_must zpool detach $TESTPOOL $spare_devs3
+log_must zpool remove $TESTPOOL $spare_devs3
+
+log_pass "'zpool remove device passed as expected.'"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/Makefile.am
new file mode 100644
index 000000000000..01ad68c817f2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/Makefile.am
@@ -0,0 +1,15 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_reopen
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_reopen_001_pos.ksh \
+ zpool_reopen_002_pos.ksh \
+ zpool_reopen_003_pos.ksh \
+ zpool_reopen_004_pos.ksh \
+ zpool_reopen_005_pos.ksh \
+ zpool_reopen_006_neg.ksh \
+ zpool_reopen_007_pos.ksh
+
+dist_pkgdata_DATA = \
+ zpool_reopen.cfg \
+ zpool_reopen.shlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/cleanup.ksh
new file mode 100755
index 000000000000..25fced1ec17b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/cleanup.ksh
@@ -0,0 +1,37 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016, 2017 by Intel Corporation. All rights reserved.
+# Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_reopen/zpool_reopen.shlib
+
+verify_runnable "global"
+
+if ! is_linux; then
+ log_unsupported "scsi debug module unsupported"
+fi
+
+cleanup_devices $DISKS
+
+# Unplug the disk and remove scsi_debug module
+if is_linux; then
+ for SDDEVICE in $(get_debug_device); do
+ remove_disk $SDDEVICE
+ done
+ unload_scsi_debug
+fi
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/setup.ksh
new file mode 100755
index 000000000000..59b8764ced84
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/setup.ksh
@@ -0,0 +1,30 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016, 2017 by Intel Corporation. All rights reserved.
+# Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_reopen/zpool_reopen.cfg
+
+verify_runnable "global"
+
+# Create scsi_debug devices for the reopen tests
+if is_linux; then
+ load_scsi_debug $SDSIZE $SDHOSTS $SDTGTS $SDLUNS '512b'
+else
+ log_unsupported "scsi debug module unsupported"
+fi
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen.cfg
new file mode 100644
index 000000000000..7451ffd8c53f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen.cfg
@@ -0,0 +1,43 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016, 2017 by Intel Corporation. All rights reserved.
+# Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+export DISK_ARRAY_NUM=$(echo ${DISKS} | nawk '{print NF}')
+export DISKSARRAY=$DISKS
+export SMALL_FILE_SIZE=10
+export LARGE_FILE_SIZE=80
+export MAXTIMEOUT=40
+
+export SDSIZE=256
+export SDHOSTS=1
+export SDTGTS=1
+export SDLUNS=1
+
+export DISK1=$(echo $DISKS | nawk '{print $1}')
+export DISK2=$(echo $DISKS | nawk '{print $2}')
+export DISK3=$(echo $DISKS | nawk '{print $3}')
+
+if is_linux; then
+ set_slice_prefix
+ set_device_dir
+ devs_id[0]=$(get_persistent_disk_name $DISK1)
+ devs_id[1]=$(get_persistent_disk_name $DISK2)
+ devs_id[2]=$(get_persistent_disk_name $DISK3)
+ export devs_id
+fi
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen.shlib b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen.shlib
new file mode 100644
index 000000000000..075ad85e9f96
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen.shlib
@@ -0,0 +1,124 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+#
+# Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_reopen/zpool_reopen.cfg
+
+#
+# Clear labels on the given disks
+#
+function clear_labels #disks
+{
+ for disk in $@; do
+ if ( is_loop_device $disk ) || ( is_mpath_device $disk ); then
+ zpool labelclear -f /dev/$disk
+ else
+ zpool labelclear -f /dev/${disk}1
+ fi
+ done
+}
+
+#
+# Set the REMOVED_DISK and REMOVED_DISK_ID constants for device
+# used for re-plugging. When the disk is loop device use the
+# scsi_debug emulated drive. Otherwise use the real drive.
+#
+function set_removed_disk
+{
+ if is_loop_device $DISK1; then
+ export REMOVED_DISK=$(get_debug_device)
+ export REMOVED_DISK_ID=$(get_persistent_disk_name $REMOVED_DISK)
+ elif ( is_real_device $DISK1 ) || ( is_mpath_device $DISK1 ); then
+ export REMOVED_DISK="$DISK1"
+ export REMOVED_DISK_ID=${devs_id[0]}
+ else
+ log_fail "No drives that supports removal"
+ fi
+}
+
+#
+# Generate random file of the given size in MiB
+#
+function generate_random_file #path size_mb
+{
+ typeset path=$1
+ typeset -i size_mb=$2
+ file_write -o create -f $path -b 1048576 -s0 -c $size_mb -d R
+}
+
+#
+# Wait until specific event or timeout occur.
+#
+# The passed function is executed with pool name as argument
+# with an interval of 1 second until it succeeds or until the
+# timeout occurs.
+# It returns 1 on timeout or 0 otherwise.
+#
+function wait_for_action #pool timeout function
+{
+ typeset pool=$1
+ typeset -i timeout=$2
+ typeset func=$3
+
+ while [ $timeout -gt 0 ]; do
+ (( --timeout ))
+ if ( $func $pool ); then
+ return 0
+ fi
+ sleep 1
+ done
+
+ return 1
+}
+
+#
+# Helpers for wait_for_action function:
+# wait_for_resilver_start - wait until resilver is started
+# wait_for_resilver_end - wait until resilver is finished
+# wait_for_scrub_end - wait until scrub is finished
+#
+function wait_for_resilver_start #pool timeout
+{
+ wait_for_action $1 $2 is_pool_resilvering
+ return $?
+}
+
+function wait_for_resilver_end #pool timeout
+{
+ wait_for_action $1 $2 is_pool_resilvered
+ return $?
+}
+
+function wait_for_scrub_end #pool timeout
+{
+ wait_for_action $1 $2 is_pool_scrubbed
+ return $?
+}
+
+#
+# Check if scan action has been restarted on the given pool
+#
+
+function is_scan_restarted #pool
+{
+ typeset pool=$1
+ zpool history -i $pool | grep -q "scan aborted, restarting"
+ return $?
+}
+
+function is_deferred_scan_started #pool
+{
+ typeset pool=$1
+ zpool history -i $pool | grep -q "starting deferred resilver"
+ return $?
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_001_pos.ksh
new file mode 100755
index 000000000000..68ebf669c9f5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_001_pos.ksh
@@ -0,0 +1,70 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_reopen/zpool_reopen.shlib
+
+#
+# DESCRIPTION:
+# Test if zpool reopen with no arguments works correctly.
+#
+# STRATEGY:
+# 1. Create a pool.
+# 2. Remove a disk.
+# 3. Reopen a pool and verify if removed disk is marked as unavailable.
+# 4. "Plug back" disk.
+# 5. Reopen a pool and verify if removed disk is marked online again.
+# 6. Check if reopen caused resilver start.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ # bring back removed disk online for further tests
+ insert_disk $REMOVED_DISK $scsi_host
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ clear_labels $REMOVED_DISK $DISK2
+}
+
+log_assert "Testing zpool reopen with no arguments"
+log_onexit cleanup
+
+set_removed_disk
+scsi_host=$(get_scsi_host $REMOVED_DISK)
+
+# 1. Create a pool.
+default_mirror_setup_noexit $REMOVED_DISK_ID $DISK2
+# 2. Remove a disk.
+remove_disk $REMOVED_DISK
+# 3. Reopen a pool and verify if removed disk is marked as unavailable.
+log_must zpool reopen
+log_must check_state $TESTPOOL "$REMOVED_DISK_ID" "unavail"
+# Write some data to the pool
+log_must generate_random_file /$TESTPOOL/data $SMALL_FILE_SIZE
+# 4. "Plug back" disk.
+insert_disk $REMOVED_DISK $scsi_host
+# 5. Reopen a pool and verify if removed disk is marked online again.
+log_must zpool reopen
+log_must check_state $TESTPOOL "$REMOVED_DISK_ID" "online"
+# 6. Check if reopen caused resilver start.
+log_must wait_for_resilver_end $TESTPOOL $MAXTIMEOUT
+
+# clean up
+log_must zpool destroy $TESTPOOL
+clear_labels $REMOVED_DISK $DISK2
+
+log_pass "Zpool reopen with no arguments test passed"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_002_pos.ksh
new file mode 100755
index 000000000000..444c8a68523f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_002_pos.ksh
@@ -0,0 +1,70 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_reopen/zpool_reopen.shlib
+
+#
+# DESCRIPTION:
+# Test if zpool reopen with pool name as argument works correctly.
+#
+# STRATEGY:
+# 1. Create a pool.
+# 2. Remove a disk.
+# 3. Reopen a pool and verify if removed disk is marked as unavailable.
+# 4. "Plug back" disk.
+# 5. Reopen a pool and verify if removed disk is marked online again.
+# 6. Check if reopen caused resilver start.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ # bring back removed disk online for further tests
+ insert_disk $REMOVED_DISK $scsi_host
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ clear_labels $REMOVED_DISK $DISK2
+}
+
+log_assert "Testing zpool reopen with no arguments"
+log_onexit cleanup
+
+set_removed_disk
+scsi_host=$(get_scsi_host $REMOVED_DISK)
+
+# 1. Create a pool.
+default_mirror_setup_noexit $REMOVED_DISK_ID $DISK2
+# 2. Remove a disk.
+remove_disk $REMOVED_DISK
+# 3. Reopen a pool and verify if removed disk is marked as unavailable.
+log_must zpool reopen $TESTPOOL
+log_must check_state $TESTPOOL "$REMOVED_DISK_ID" "unavail"
+# Write some data to the pool
+log_must generate_random_file /$TESTPOOL/data $SMALL_FILE_SIZE
+# 4. "Plug back" disk.
+insert_disk $REMOVED_DISK $scsi_host
+# 5. Reopen a pool and verify if removed disk is marked online again.
+log_must zpool reopen $TESTPOOL
+log_must check_state $TESTPOOL "$REMOVED_DISK_ID" "online"
+# 6. Check if reopen caused resilver start.
+log_must wait_for_resilver_end $TESTPOOL $MAXTIMEOUT
+
+# clean up
+log_must zpool destroy $TESTPOOL
+clear_labels $REMOVED_DISK $DISK2
+
+log_pass "Zpool reopen with no arguments test passed"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_003_pos.ksh
new file mode 100755
index 000000000000..097dd3c71d1c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_003_pos.ksh
@@ -0,0 +1,100 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_reopen/zpool_reopen.shlib
+
+#
+# DESCRIPTION:
+# Test zpool reopen while scrub is running.
+# Checks if re-plugged device is fully resilvered.
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Remove a disk.
+# 3. Write a test file to the pool and calculate its checksum.
+# 4. Execute scrub.
+# 5. "Plug back" disk.
+# 6. Reopen a pool.
+# 7. Check if scrub scan is replaced by resilver.
+# 8. Put another device offline and check if the test file checksum is correct.
+#
+# NOTES:
+# A 250ms delay is added to make sure that the scrub is running while
+# the reopen kicks the resilver.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must zinject -c all
+ # bring back removed disk online for further tests
+ insert_disk $REMOVED_DISK $scsi_host
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_assert "Testing zpool reopen with pool name as argument"
+log_onexit cleanup
+
+set_removed_disk
+scsi_host=$(get_scsi_host $REMOVED_DISK)
+
+# 1. Create a pool
+default_mirror_setup_noexit $REMOVED_DISK_ID $DISK2
+# 2. Remove a disk.
+remove_disk $REMOVED_DISK
+
+log_must zpool reopen $TESTPOOL
+log_must check_state $TESTPOOL "$REMOVED_DISK_ID" "unavail"
+
+# 3. Write a test file to the pool and calculate its checksum.
+TESTFILE=/$TESTPOOL/data
+log_must generate_random_file /$TESTPOOL/data $LARGE_FILE_SIZE
+TESTFILE_MD5=$(md5digest $TESTFILE)
+
+# 4. Execute scrub.
+# add delay to I/O requests for remaining disk in pool
+log_must zinject -d $DISK2 -D250:1 $TESTPOOL
+log_must zpool scrub $TESTPOOL
+
+# 5. "Plug back" disk.
+insert_disk $REMOVED_DISK $scsi_host
+# 6. Reopen a pool.
+log_must zpool reopen $TESTPOOL
+log_must check_state $TESTPOOL "$REMOVED_DISK_ID" "online"
+# 7. Check if scrub scan is replaced by resilver.
+# the scrub operation has to be running while reopen is executed
+log_must is_pool_scrubbing $TESTPOOL true
+# remove delay from disk
+log_must zinject -c all
+# the scrub will be replaced by resilver, wait until it ends
+log_must wait_for_resilver_end $TESTPOOL $MAXTIMEOUT
+# check if the scrub scan has been interrupted by resilver
+log_must is_scan_restarted $TESTPOOL
+
+# 8. Put another device offline and check if the test file checksum is correct.
+log_must zpool offline $TESTPOOL $DISK2
+CHECK_MD5=$(md5digest $TESTFILE)
+[[ $CHECK_MD5 == $TESTFILE_MD5 ]] || \
+ log_fail "Checksums differ ($CHECK_MD5 != $TESTFILE_MD5)"
+log_must zpool online $TESTPOOL $DISK2
+sleep 1
+
+# clean up
+log_must zpool destroy $TESTPOOL
+
+log_pass "Zpool reopen test successful"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_004_pos.ksh
new file mode 100755
index 000000000000..956ceebafbc6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_004_pos.ksh
@@ -0,0 +1,88 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_reopen/zpool_reopen.shlib
+
+#
+# DESCRIPTION:
+# Test zpool reopen -n while scrub is running.
+# Checks if re-plugged device is NOT resilvered.
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Remove a disk.
+# 3. Write test file to pool.
+# 4. Execute scrub.
+# 5. "Plug back" disk.
+# 6. Reopen a pool with an -n flag.
+# 7. Check if resilver was deferred.
+# 8. Check if trying to put device to offline fails because of no valid
+# replicas.
+#
+# NOTES:
+# A 125ms delay is added to make sure that the scrub is running while
+# the reopen is invoked.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must zinject -c all
+ # bring back removed disk online for further tests
+ insert_disk $REMOVED_DISK $scsi_host
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_assert "Testing zpool reopen with pool name as argument"
+log_onexit cleanup
+
+set_removed_disk
+scsi_host=$(get_scsi_host $REMOVED_DISK)
+
+# 1. Create a pool
+default_mirror_setup_noexit $REMOVED_DISK_ID $DISK2
+# 2. Remove a disk.
+remove_disk $REMOVED_DISK
+log_must zpool reopen -n $TESTPOOL
+log_must check_state $TESTPOOL "$REMOVED_DISK_ID" "unavail"
+# 3. Write test file to pool.
+log_must generate_random_file /$TESTPOOL/data $LARGE_FILE_SIZE
+# 4. Execute scrub.
+# add delay to I/O requests for remaining disk in pool
+log_must zinject -d $DISK2 -D125:1 $TESTPOOL
+log_must zpool scrub $TESTPOOL
+# 5. "Plug back" disk.
+insert_disk $REMOVED_DISK $scsi_host
+# 6. Reopen a pool with an -n flag.
+log_must zpool reopen -n $TESTPOOL
+log_must check_state $TESTPOOL "$REMOVED_DISK_ID" "online"
+# remove delay from disk
+log_must zinject -c all
+# 7. Check if scrub scan is NOT replaced by resilver.
+log_must wait_for_scrub_end $TESTPOOL $MAXTIMEOUT
+log_must is_deferred_scan_started $TESTPOOL
+
+# 8. Check if trying to put device to offline fails because of no valid
+# replicas.
+log_must wait_for_resilver_end $TESTPOOL $MAXTIMEOUT
+log_must zpool offline $TESTPOOL $DISK2
+
+# clean up
+log_must zpool destroy $TESTPOOL
+
+log_pass "Zpool reopen test successful"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_005_pos.ksh
new file mode 100755
index 000000000000..fc298d01061e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_005_pos.ksh
@@ -0,0 +1,86 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_reopen/zpool_reopen.shlib
+
+#
+# DESCRIPTION:
+# Test zpool reopen -n while resilver is running.
+# Checks if the resilver is restarted.
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Remove a disk.
+# 3. Write test file to pool.
+# 4. "Plug back" disk.
+# 5. Reopen a pool and wait until resilvering is started.
+# 6. Reopen a pool again with -n flag.
+# 7. Wait until resilvering is finished and check if it was restarted.
+#
+# NOTES:
+# A 25ms delay is added to make sure that the resilver is running while
+# the reopen is invoked.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must zinject -c all
+ insert_disk $REMOVED_DISK $scsi_host
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_assert "Testing zpool reopen with pool name as argument"
+log_onexit cleanup
+
+set_removed_disk
+scsi_host=$(get_scsi_host $REMOVED_DISK)
+
+# 1. Create a pool
+default_mirror_setup_noexit $REMOVED_DISK_ID $DISK2
+# 2. Remove a disk.
+remove_disk $REMOVED_DISK
+
+log_must zpool reopen $TESTPOOL
+log_must check_state $TESTPOOL "$REMOVED_DISK_ID" "unavail"
+# 3. Write test file to pool.
+log_must generate_random_file /$TESTPOOL/data $LARGE_FILE_SIZE
+# 4. "Plug back" disk.
+insert_disk $REMOVED_DISK $scsi_host
+
+# 5. Reopen a pool and wait until resilvering is started.
+log_must zpool reopen $TESTPOOL
+log_must check_state $TESTPOOL "$REMOVED_DISK_ID" "online"
+# add delay to I/O requests for the reopened disk
+log_must zinject -d $REMOVED_DISK_ID -D25:1 $TESTPOOL
+# wait until resilver starts
+log_must wait_for_resilver_start $TESTPOOL $MAXTIMEOUT
+
+# 6. Reopen a pool again with -n flag.
+log_must zpool reopen -n $TESTPOOL
+
+# 7. Wait until resilvering is finished and check if it was restarted.
+log_must wait_for_resilver_end $TESTPOOL $MAXTIMEOUT
+# remove delay from disk
+log_must zinject -c all
+log_mustnot is_scan_restarted $TESTPOOL
+
+# clean up
+log_must zpool destroy $TESTPOOL
+
+log_pass "Zpool reopen test successful"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_006_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_006_neg.ksh
new file mode 100755
index 000000000000..6533bde68fbe
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_006_neg.ksh
@@ -0,0 +1,43 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Wrong arguments passed to zpool reopen should cause an error.
+#
+# STRATEGY:
+# 1. Create an array with bad 'zpool reopen' arguments.
+# 2. For each argument execute the 'zpool reopen' command and verify
+# if it returns an error.
+#
+
+verify_runnable "global"
+
+# 1. Create an array with bad 'zpool reopen' arguments.
+typeset -a args=("!" "1" "-s" "--n" "-1" "-" "-c" "-f" "-d 2" "-abc" "-na")
+
+log_assert "Test 'zpool reopen' with invalid arguments."
+
+# 2. For each argument execute the 'zpool reopen' command and verify
+# if it returns an error.
+for arg in ${args[@]}; do
+ log_mustnot zpool reopen $arg
+done
+
+log_pass "Passing invalid arguments to 'zpool reopen' failed as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_007_pos.ksh
new file mode 100755
index 000000000000..4ba56af85d32
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_reopen/zpool_reopen_007_pos.ksh
@@ -0,0 +1,67 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_reopen/zpool_reopen.shlib
+
+#
+# DESCRIPTION:
+# Test zpool reopen while performing IO to the pool.
+# Verify that no IO errors of any kind of reported.
+#
+# STRATEGY:
+# 1. Create a non-redundant pool.
+# 2. Repeat:
+# a. Write files to the pool.
+# b. Execute 'zpool reopen'.
+# 3. Verify that no errors are reported by 'zpool status'.
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_assert "Testing zpool reopen with concurrent user IO"
+log_onexit cleanup
+
+set_removed_disk
+scsi_host=$(get_scsi_host $REMOVED_DISK)
+
+# 1. Create a non-redundant pool.
+log_must zpool create $TESTPOOL $DISK1 $DISK2 $DISK3
+
+for i in $(seq 10); do
+ # 3a. Write files in the background to the pool.
+ mkfile 64m /$TESTPOOL/data.$i &
+
+ # 3b. Execute 'zpool reopen'.
+ log_must zpool reopen $TESTPOOL
+
+ for disk in $DISK1 $DISK2 $DISK3; do
+ zpool status -P -v $TESTPOOL | grep $disk | \
+ read -r name state rd wr cksum
+ log_must [ $state = "ONLINE" ]
+ log_must [ $rd -eq 0 ]
+ log_must [ $wr -eq 0 ]
+ log_must [ $cksum -eq 0 ]
+ done
+done
+
+wait
+
+log_pass "Zpool reopen with concurrent user IO successful"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/Makefile.am
new file mode 100644
index 000000000000..2e3ea69f2ca9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/Makefile.am
@@ -0,0 +1,7 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_replace
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_replace_001_neg.ksh \
+ replace-o_ashift.ksh \
+ replace_prop_ashift.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/cleanup.ksh
new file mode 100755
index 000000000000..89c146249e71
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/cleanup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace-o_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace-o_ashift.ksh
new file mode 100755
index 000000000000..0fc2c69ba143
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace-o_ashift.ksh
@@ -0,0 +1,101 @@
+#!/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 2017, loli10K. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# 'zpool replace -o ashift=<n> ...' should work with different ashift
+# values.
+#
+# STRATEGY:
+# 1. Create various pools with different ashift values.
+# 2. Verify 'replace -o ashift=<n>' works only with allowed values.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+ rm -f $disk1 $disk2
+}
+
+log_assert "zpool replace -o ashift=<n>' works with different ashift values"
+log_onexit cleanup
+
+disk1=$TEST_BASE_DIR/disk1
+disk2=$TEST_BASE_DIR/disk2
+log_must truncate -s $SIZE $disk1
+log_must truncate -s $SIZE $disk2
+
+typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16")
+for ashift in ${ashifts[@]}
+do
+ for cmdval in ${ashifts[@]}
+ do
+ log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
+ verify_ashift $disk1 $ashift
+ if [[ $? -ne 0 ]]
+ then
+ log_fail "Pool was created without setting ashift " \
+ "value to $ashift"
+ fi
+ # ashift_of(replacing_disk) <= ashift_of(existing_vdev)
+ if [[ $cmdval -le $ashift ]]
+ then
+ log_must zpool replace -o ashift=$cmdval $TESTPOOL1 \
+ $disk1 $disk2
+ verify_ashift $disk2 $ashift
+ if [[ $? -ne 0 ]]
+ then
+ log_fail "Device was replaced without " \
+ "setting ashift value to $ashift"
+ fi
+ wait_replacing $TESTPOOL1
+ else
+ log_mustnot zpool replace -o ashift=$cmdval $TESTPOOL1 \
+ $disk1 $disk2
+ fi
+ # clean things for the next run
+ log_must zpool destroy $TESTPOOL1
+ log_must zpool labelclear $disk1
+ log_must zpool labelclear $disk2
+ done
+done
+
+typeset badvals=("off" "on" "1" "8" "17" "1b" "ff" "-")
+for badval in ${badvals[@]}
+do
+ log_must zpool create $TESTPOOL1 $disk1
+ log_mustnot zpool replace -o ashift=$badval $TESTPOOL1 $disk1 $disk2
+ log_must zpool destroy $TESTPOOL1
+ log_must zpool labelclear $disk1
+ log_mustnot zpool labelclear $disk2
+done
+
+log_pass "zpool replace -o ashift=<n>' works with different ashift values"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace_prop_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace_prop_ashift.ksh
new file mode 100755
index 000000000000..fbdd44ceb581
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/replace_prop_ashift.ksh
@@ -0,0 +1,97 @@
+#!/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 2017, loli10K. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# 'zpool replace' should use the ashift pool property value as default.
+#
+# STRATEGY:
+# 1. Create a pool with default values.
+# 2. Verify 'zpool replace' uses the ashift pool property value when
+# replacing an existing device.
+# 3. Verify the default ashift value can still be overridden by manually
+# specifying '-o ashift=<n>' from the command line.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+ rm -f $disk1 $disk2
+}
+
+log_assert "'zpool replace' uses the ashift pool property value as default."
+log_onexit cleanup
+
+disk1=$TEST_BASE_DIR/disk1
+disk2=$TEST_BASE_DIR/disk2
+log_must truncate -s $SIZE $disk1
+log_must truncate -s $SIZE $disk2
+
+typeset ashifts=("9" "10" "11" "12" "13" "14" "15" "16")
+for ashift in ${ashifts[@]}
+do
+ for pprop in ${ashifts[@]}
+ do
+ log_must zpool create -o ashift=$ashift $TESTPOOL1 $disk1
+ log_must zpool set ashift=$pprop $TESTPOOL1
+ # ashift_of(replacing_disk) <= ashift_of(existing_vdev)
+ if [[ $pprop -le $ashift ]]
+ then
+ log_must zpool replace $TESTPOOL1 $disk1 $disk2
+ wait_replacing $TESTPOOL1
+ verify_ashift $disk2 $ashift
+ if [[ $? -ne 0 ]]
+ then
+ log_fail "Device was replaced without " \
+ "setting ashift value to $ashift"
+ fi
+ else
+ # cannot replace if pool prop ashift > vdev ashift
+ log_mustnot zpool replace $TESTPOOL1 $disk1 $disk2
+ # verify we can override the pool prop value manually
+ log_must zpool replace -o ashift=$ashift $TESTPOOL1 \
+ $disk1 $disk2
+ wait_replacing $TESTPOOL1
+ verify_ashift $disk2 $ashift
+ if [[ $? -ne 0 ]]
+ then
+ log_fail "Device was replaced without " \
+ "setting ashift value to $ashift"
+ fi
+ fi
+ # clean things for the next run
+ log_must zpool destroy $TESTPOOL1
+ log_must zpool labelclear $disk1
+ log_must zpool labelclear $disk2
+ done
+done
+
+log_pass "'zpool replace' uses the ashift pool property value."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/setup.ksh
new file mode 100755
index 000000000000..2229f87e6208
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/setup.ksh
@@ -0,0 +1,35 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+DISK=${DISKS%% *}
+
+default_mirror_setup $DISKS
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_replace/zpool_replace_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/zpool_replace_001_neg.ksh
new file mode 100755
index 000000000000..725e495ebb89
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_replace/zpool_replace_001_neg.ksh
@@ -0,0 +1,83 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Executing 'zpool replace' command with bad options fails.
+#
+# STRATEGY:
+# 1. Create an array of badly formed 'zpool replace' options.
+# 2. Execute each element of the array.
+# 3. Verify an error code is returned.
+#
+
+verify_runnable "global"
+
+DISKLIST=$(get_disklist $TESTPOOL)
+
+set -A args "" "-f" "-?" "-z fakepool" "-f fakepool" "-ev fakepool" "fakepool" \
+ "$TESTPOOL" "-t $TESTPOOL/$TESTFS" "-t $TESTPOOL/$TESTFS $DISKLIST" \
+ "$TESTPOOL/$TESTCTR" "-t $TESTPOOL/$TESTCTR/$TESTFS1" \
+ "$TESTPOOL/$TESTCTR $DISKLIST" "-t $TESTPOOL/$TESTVOL" \
+ "$TESTPOOL/$TESTCTR/$TESTFS1 $DISKLIST" \
+ "$TESTPOOL/$TESTVOL $DISKLIST" \
+ "$DISKLIST" \
+ "fakepool fakedevice" "fakepool fakedevice fakenewdevice" \
+ "$TESTPOOL fakedevice" "$TESTPOOL $DISKLIST" \
+ "$TESTPOOL fakedevice fakenewdevice fakenewdevice" \
+ "-f $TESTPOOL" "-f $TESTPOOL/$TESTFS" "-f $TESTPOOL/$TESTFS $DISKLIST" \
+ "-f $TESTPOOL/$TESTCTR" "-f $TESTPOOL/$TESTCTR/$TESTFS1" \
+ "-f $TESTPOOL/$TESTCTR $DISKLIST" "-f $TESTPOOL/$TESTVOL" \
+ "-f $TESTPOOL/$TESTCTR/$TESTFS1 $DISKLIST" \
+ "-f $TESTPOOL/$TESTVOL $DISKLIST" \
+ "-f $DISKLIST" \
+ "-f fakepool fakedevice" "-f fakepool fakedevice fakenewdevice" \
+ "-f $TESTPOOL fakedevice fakenewdevice fakenewdevice" \
+ "-f $TESTPOOL fakedevice" "-f $TESTPOOL $DISKLIST"
+
+log_assert "Executing 'zpool replace' with bad options fails"
+
+if [[ -z $DISKLIST ]]; then
+ log_fail "DISKLIST is empty."
+fi
+
+typeset -i i=0
+
+while [[ $i -lt ${#args[*]} ]]; do
+
+ log_mustnot zpool replace ${args[$i]}
+
+ (( i = i + 1 ))
+done
+
+log_pass "'zpool replace' command with bad options failed as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/Makefile.am
new file mode 100644
index 000000000000..2cec5335fbae
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/Makefile.am
@@ -0,0 +1,9 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_resilver
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_resilver_bad_args.ksh \
+ zpool_resilver_restart.ksh
+
+dist_pkgdata_DATA = \
+ zpool_resilver.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/cleanup.ksh
new file mode 100755
index 000000000000..c74e23919cd1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/cleanup.ksh
@@ -0,0 +1,33 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+
+verify_runnable "global"
+
+destroy_mirrors
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/setup.ksh
new file mode 100755
index 000000000000..48ceecdf9eb7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/setup.ksh
@@ -0,0 +1,39 @@
+#!/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) 2018 by Datto. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_resilver/zpool_resilver.cfg
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 3
+
+default_mirror_setup_noexit $DISK1 $DISK2 $DISK3
+
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+
+# Create 256M of data
+log_must file_write -b 1048576 -c 256 -o create -d 0 -f $mntpnt/bigfile
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver.cfg
new file mode 100644
index 000000000000..2a942d69f6d0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver.cfg
@@ -0,0 +1,30 @@
+#
+# 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) 2018 by Datto. All rights reserved.
+#
+
+export DISK1=$(echo $DISKS | nawk '{print $1}')
+export DISK2=$(echo $DISKS | nawk '{print $2}')
+export DISK3=$(echo $DISKS | nawk '{print $3}')
+
+export MAXTIMEOUT=300
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_bad_args.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_bad_args.ksh
new file mode 100755
index 000000000000..abd514086630
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_bad_args.ksh
@@ -0,0 +1,71 @@
+#!/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) 2018 by Datto. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# A badly formed parameter passed to 'zpool resilver' should
+# return an error.
+#
+# STRATEGY:
+# 1. Create an array containing bad 'zpool reilver' parameters.
+# 2. For each element, execute the sub-command.
+# 3. Verify it returns an error.
+# 4. Confirm the sub-command returns an error if the resilver_defer
+# feature isn't active.
+#
+
+verify_runnable "global"
+
+set -A args "" "-?" "blah blah" "-%" "--?" "-*" "-=" \
+ "-a" "-b" "-c" "-d" "-e" "-f" "-g" "-h" "-i" "-j" "-k" "-l" \
+ "-m" "-n" "-o" "-p" "-q" "-r" "-s" "-t" "-u" "-v" "-w" "-x" "-y" "-z" \
+ "-A" "-B" "-C" "-D" "-E" "-F" "-G" "-H" "-I" "-J" "-K" "-L" \
+ "-M" "-N" "-O" "-P" "-Q" "-R" "-S" "-T" "-U" "-V" "-W" "-X" "-W" "-Z"
+
+function cleanup
+{
+ log_must destroy_pool $TESTPOOL2
+ log_must rm -f $TEST_BASE_DIR/zpool_resilver.dat
+}
+
+log_onexit cleanup
+
+log_assert "Execute 'zpool resilver' using invalid parameters."
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zpool resilver ${args[i]}
+
+ ((i = i + 1))
+done
+
+log_must mkfile $MINVDEVSIZE $TEST_BASE_DIR/zpool_resilver.dat
+log_must zpool create -d $TESTPOOL2 $TEST_BASE_DIR/zpool_resilver.dat
+log_mustnot zpool resilver $TESTPOOL2
+
+log_pass "Badly formed 'zpool resilver' parameters fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_restart.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_restart.ksh
new file mode 100755
index 000000000000..80fc169126d2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_restart.ksh
@@ -0,0 +1,86 @@
+#!/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) 2018 Datto Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_reopen/zpool_reopen.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_resilver/zpool_resilver.cfg
+
+#
+# DESCRIPTION:
+# "Verify 'zpool resilver' restarts in-progress resilvers"
+#
+# STRATEGY:
+# 1. Write some data and detach the first drive so it has resilver
+# work to do
+# 2. Repeat the process with a second disk
+# 3. Reattach the drives, causing the second drive's resilver to be
+# deferred
+# 4. Manually restart the resilver with all drives
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+ log_must rm -f $mntpnt/biggerfile1
+ log_must rm -f $mntpnt/biggerfile2
+}
+
+log_onexit cleanup
+
+log_assert "Verify 'zpool resilver' restarts in-progress resilvers"
+
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+
+# 1. Write some data and detach the first drive so it has resilver work to do
+log_must file_write -b 524288 -c 1024 -o create -d 0 -f $mntpnt/biggerfile1
+log_must sync
+log_must zpool detach $TESTPOOL $DISK2
+
+# 2. Repeat the process with a second disk
+log_must file_write -b 524288 -c 1024 -o create -d 0 -f $mntpnt/biggerfile2
+log_must sync
+log_must zpool detach $TESTPOOL $DISK3
+
+# 3. Reattach the drives, causing the second drive's resilver to be deferred
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+
+log_must zpool attach $TESTPOOL $DISK1 $DISK2
+log_must is_pool_resilvering $TESTPOOL true
+
+log_must zpool attach $TESTPOOL $DISK1 $DISK3
+log_must is_pool_resilvering $TESTPOOL true
+
+# 4. Manually restart the resilver with all drives
+log_must zpool resilver $TESTPOOL
+log_must is_deferred_scan_started $TESTPOOL
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+log_must wait_for_resilver_end $TESTPOOL $MAXTIMEOUT
+log_must check_state $TESTPOOL "$DISK2" "online"
+log_must check_state $TESTPOOL "$DISK3" "online"
+
+log_pass "Verified 'zpool resilver' restarts in-progress resilvers"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/Makefile.am
new file mode 100644
index 000000000000..e2dfd9d64c40
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/Makefile.am
@@ -0,0 +1,16 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_scrub
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_scrub_001_neg.ksh \
+ zpool_scrub_002_pos.ksh \
+ zpool_scrub_003_pos.ksh \
+ zpool_scrub_004_pos.ksh \
+ zpool_scrub_005_pos.ksh \
+ zpool_scrub_encrypted_unloaded.ksh \
+ zpool_scrub_offline_device.ksh \
+ zpool_scrub_print_repairing.ksh \
+ zpool_scrub_multiple_copies.ksh
+
+dist_pkgdata_DATA = \
+ zpool_scrub.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/cleanup.ksh
new file mode 100755
index 000000000000..03eb9901cb3e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/cleanup.ksh
@@ -0,0 +1,34 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+
+verify_runnable "global"
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+destroy_mirrors
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/setup.ksh
new file mode 100755
index 000000000000..936fd798e9dd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/setup.ksh
@@ -0,0 +1,44 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+default_mirror_setup_noexit $DISK1 $DISK2
+
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+
+# Create 256M of data
+log_must file_write -b 1048576 -c 256 -o create -d 0 -f $mntpnt/bigfile
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
new file mode 100644
index 000000000000..fdf2f428477f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
@@ -0,0 +1,35 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+export DISK1=${DISKS%% *}
+export DISK2=$(echo $DISKS | awk '{print $2}')
+
+export ZFS_SCAN_VDEV_LIMIT_SLOW=$((128*1024))
+export ZFS_SCAN_VDEV_LIMIT_DEFAULT=$((4*1024*1024))
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_001_neg.ksh
new file mode 100755
index 000000000000..96bc185dd40c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_001_neg.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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# A badly formed parameter passed to 'zpool scrub' should
+# return an error.
+#
+# STRATEGY:
+# 1. Create an array containing bad 'zpool scrub' parameters.
+# 2. For each element, execute the sub-command.
+# 3. Verify it returns an error.
+#
+
+verify_runnable "global"
+
+set -A args "" "-?" "blah blah" "-%" "--?" "-*" "-=" \
+ "-a" "-b" "-c" "-d" "-e" "-f" "-g" "-h" "-i" "-j" "-k" "-l" \
+ "-m" "-n" "-o" "-p" "-q" "-r" "-s" "-t" "-u" "-v" "-w" "-x" "-y" "-z" \
+ "-A" "-B" "-C" "-D" "-E" "-F" "-G" "-H" "-I" "-J" "-K" "-L" \
+ "-M" "-N" "-O" "-P" "-Q" "-R" "-S" "-T" "-U" "-V" "-W" "-X" "-W" "-Z"
+
+
+log_assert "Execute 'zpool scrub' using invalid parameters."
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zpool scrub ${args[i]}
+
+ ((i = i + 1))
+done
+
+log_pass "Badly formed 'zpool scrub' parameters fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_002_pos.ksh
new file mode 100755
index 000000000000..449bb9a82277
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_002_pos.ksh
@@ -0,0 +1,78 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+# Copyright (c) 2017 Datto Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+
+#
+# DESCRIPTION:
+# Verify scrub, scrub -p, and scrub -s show the right status.
+#
+# STRATEGY:
+# 1. Create pool and create a 100MB file in it.
+# 2. zpool scrub the pool and verify it's doing a scrub.
+# 3. Pause scrub and verify it's paused.
+# 4. Try to pause a paused scrub and make sure that fails.
+# 5. Resume the paused scrub and verify scrub is again being performed.
+# 6. Verify zpool scrub -s succeed when the system is scrubbing.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+ log_must rm -f $mntpnt/biggerfile
+}
+
+log_onexit cleanup
+
+log_assert "Verify scrub, scrub -p, and scrub -s show the right status."
+
+# Create 1G of additional data
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+log_must file_write -b 1048576 -c 1024 -o create -d 0 -f $mntpnt/biggerfile
+log_must sync
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+log_must zpool scrub $TESTPOOL
+log_must is_pool_scrubbing $TESTPOOL true
+log_must zpool scrub -p $TESTPOOL
+log_must is_pool_scrub_paused $TESTPOOL true
+log_mustnot zpool scrub -p $TESTPOOL
+log_must is_pool_scrub_paused $TESTPOOL true
+log_must zpool scrub $TESTPOOL
+log_must is_pool_scrubbing $TESTPOOL true
+log_must zpool scrub -s $TESTPOOL
+log_must is_pool_scrub_stopped $TESTPOOL true
+
+log_pass "Verified scrub, -s, and -p show expected status."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_003_pos.ksh
new file mode 100755
index 000000000000..12dc044e9e08
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_003_pos.ksh
@@ -0,0 +1,65 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+# Copyright (c) 2017 by Datto Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+
+#
+# DESCRIPTION:
+# scrub command fails when there is an existing scrub in progress
+#
+# STRATEGY:
+# 1. Setup a pool and fill it with data
+# 2. Kick off a scrub
+# 2. Kick off a second scrub and verify it fails
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+}
+
+log_onexit cleanup
+
+log_assert "Scrub command fails when there is already a scrub in progress"
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+log_must zpool scrub $TESTPOOL
+log_must is_pool_scrubbing $TESTPOOL true
+log_mustnot zpool scrub $TESTPOOL
+log_must is_pool_scrubbing $TESTPOOL true
+log_must zpool scrub -s $TESTPOOL
+log_must is_pool_scrub_stopped $TESTPOOL true
+
+log_pass "Issuing a scrub command failed when scrub was already in progress"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_004_pos.ksh
new file mode 100755
index 000000000000..a7ae7f16b1af
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_004_pos.ksh
@@ -0,0 +1,78 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+
+#
+# DESCRIPTION:
+# Resilver prevent scrub from starting until the resilver completes
+#
+# STRATEGY:
+# 1. Setup a mirror pool and filled with data.
+# 2. Detach one of devices
+# 3. Create a file for the resilver to work on so it takes some time
+# 4. Export/import the pool to ensure the cache is dropped
+# 5. Verify scrub failed until the resilver completed
+#
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+ rm -f $mntpnt/extra
+}
+
+verify_runnable "global"
+
+log_onexit cleanup
+
+log_assert "Resilver prevent scrub from starting until the resilver completes"
+
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+
+# Temporarily prevent scan progress so our test doesn't race
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+
+while ! is_pool_resilvering $TESTPOOL; do
+ log_must zpool detach $TESTPOOL $DISK2
+ log_must file_write -b 1048576 -c 128 -o create -d 0 -f $mntpnt/extra
+ log_must zpool export $TESTPOOL
+ log_must zpool import $TESTPOOL
+ log_must zpool attach $TESTPOOL $DISK1 $DISK2
+done
+
+log_must is_pool_resilvering $TESTPOOL
+log_mustnot zpool scrub $TESTPOOL
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+log_must zpool wait -t resilver $TESTPOOL
+
+log_pass "Resilver prevent scrub from starting until the resilver completes"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_005_pos.ksh
new file mode 100755
index 000000000000..69a33983d379
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_005_pos.ksh
@@ -0,0 +1,57 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+
+#
+# DESCRIPTION:
+# When scrubbing, detach device should not break system.
+#
+# STRATEGY:
+# 1. Setup filesys with data.
+# 2. Detaching and attaching the device when scrubbing.
+# 3. Try it twice, verify both of them work fine.
+#
+
+verify_runnable "global"
+
+log_assert "When scrubbing, detach device should not break system."
+
+log_must zpool scrub $TESTPOOL
+log_must zpool detach $TESTPOOL $DISK2
+log_must zpool attach -w $TESTPOOL $DISK1 $DISK2
+
+log_must zpool scrub $TESTPOOL
+log_must zpool detach $TESTPOOL $DISK1
+log_must zpool attach -w $TESTPOOL $DISK2 $DISK1
+
+log_pass "When scrubbing, detach device should not break system."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_encrypted_unloaded.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_encrypted_unloaded.ksh
new file mode 100755
index 000000000000..a8c15424db27
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_encrypted_unloaded.ksh
@@ -0,0 +1,67 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2017 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Scrubs must work on an encrypted dataset with an unloaded key.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset
+# 2. Generate data on the dataset
+# 3. Unmount the encrypted dataset and unload its key
+# 4. Start a scrub
+# 5. Wait for the scrub to complete
+# 6. Verify the scrub had no errors
+# 7. Load the dataset key and mount it
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS2 && \
+ log_must zfs destroy $TESTPOOL/$TESTFS2
+}
+log_onexit cleanup
+
+log_assert "Scrubs must work on an encrypted dataset with an unloaded key"
+
+log_must eval "echo 'password' | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS2"
+
+typeset mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS2)
+log_must mkfile 10m $mntpnt/file1
+
+for i in 2..10; do
+ log_must mkfile 512b $mntpnt/file$i
+done
+
+log_must zfs unmount $TESTPOOL/$TESTFS2
+log_must zfs unload-key $TESTPOOL/$TESTFS2
+
+log_must zpool scrub -w $TESTPOOL
+
+log_must check_pool_status $TESTPOOL "scan" "with 0 errors"
+
+log_must eval "echo 'password' | zfs mount -l $TESTPOOL/$TESTFS2"
+
+log_pass "Scrubs work on an encrypted dataset with an unloaded key"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_multiple_copies.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_multiple_copies.ksh
new file mode 100755
index 000000000000..2dd33c99c554
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_multiple_copies.ksh
@@ -0,0 +1,77 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Scrubs and self-healing should be able to repair data from additional
+# copies that may be stored.
+#
+#
+# STRATEGY:
+# 1. Create a dataset with copies=3
+# 2. Write a file to the dataset
+# 3. zinject errors into the first and second DVAs of that file
+# 4. Scrub and verify the scrub repaired all errors
+# 7. Read the file normally to check that self healing also works
+# 8. Remove the zinject handler
+# 9. Scrub again and confirm 0 bytes were scrubbed
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_dataset $TESTPOOL/$TESTFS2
+ log_must zinject -c all
+}
+log_onexit cleanup
+
+log_assert "Scrubs and self healing must work with additional copies"
+
+log_must zfs create -o copies=3 $TESTPOOL/$TESTFS2
+typeset mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS2)
+log_must mkfile 10m $mntpnt/file
+log_must zpool sync $TESTPOOL
+
+log_must zinject -a -t data -C 0,1 -e io $mntpnt/file
+
+log_must zpool scrub $TESTPOOL
+log_must wait_scrubbed $TESTPOOL
+
+log_must check_pool_status $TESTPOOL "scan" "with 0 errors"
+log_must check_pool_status $TESTPOOL "errors" "No known data errors"
+
+log_must dd if=$mntpnt/file of=/dev/null bs=1M iflag=fullblock
+log_must check_pool_status $TESTPOOL "errors" "No known data errors"
+
+log_must zinject -c all
+
+log_must zpool scrub $TESTPOOL
+log_must wait_scrubbed $TESTPOOL
+
+zpool status
+
+log_must check_pool_status $TESTPOOL "errors" "No known data errors"
+log_must check_pool_status $TESTPOOL "scan" "with 0 errors"
+log_must check_pool_status $TESTPOOL "scan" "repaired 0B"
+
+log_pass "Scrubs and self healing work with additional copies"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_offline_device.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_offline_device.ksh
new file mode 100755
index 000000000000..7a07e643343d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_offline_device.ksh
@@ -0,0 +1,133 @@
+#!/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 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_reopen/zpool_reopen.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+
+#
+# DESCRIPTION:
+# Scrubbing a pool with offline devices correctly preserves DTL entries
+#
+# STRATEGY:
+# 1. Create the pool
+# 2. Offline the first device
+# 3. Write to the pool
+# 4. Scrub the pool
+# 5. Online the first device and offline the second device
+# 6. Scrub the pool again
+# 7. Verify data integrity
+#
+# NOTE:
+# Ported from script used to reproduce issue #5806
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL2 && destroy_pool $TESTPOOL2
+ log_must rm -f $DISK1 $DISK2 $DISK3 $DISK4
+}
+
+#
+# Update to [online|offline] $device status on $pool synchronously
+#
+function zpool_do_sync # <status> <pool> <device>
+{
+ status="$1"
+ pool="$2"
+ device="$3"
+
+ if [[ $status != "online" && $status != "offline" ]]; then
+ log_fail "zpool_do_sync: invalid status $status"
+ fi
+
+ log_must zpool $status $pool $device
+ for i in {1..10}; do
+ check_state $pool $device $status && return 0
+ done
+ log_fail "Failed to $status device $device"
+}
+
+#
+# Start a scrub on $pool and wait for its completion
+#
+function zpool_scrub_sync # <pool>
+{
+ pool="$1"
+
+ log_must zpool scrub $pool
+ while ! is_pool_scrubbed $pool; do
+ sleep 1
+ done
+}
+
+log_assert "Scrubbing a pool with offline devices correctly preserves DTLs"
+log_onexit cleanup
+
+DEVSIZE='128m'
+FILESIZE='100m'
+TESTDIR="$TEST_BASE_DIR/zpool_scrub_offline_device"
+DISK1="$TEST_BASE_DIR/zpool_disk1.dat"
+DISK2="$TEST_BASE_DIR/zpool_disk2.dat"
+DISK3="$TEST_BASE_DIR/zpool_disk3.dat"
+DISK4="$TEST_BASE_DIR/zpool_disk4.dat"
+RESILVER_TIMEOUT=40
+
+# 1. Create the pool
+log_must truncate -s $DEVSIZE $DISK1
+log_must truncate -s $DEVSIZE $DISK2
+log_must truncate -s $DEVSIZE $DISK3
+log_must truncate -s $DEVSIZE $DISK4
+poolexists $TESTPOOL2 && destroy_pool $TESTPOOL2
+log_must zpool create -O mountpoint=$TESTDIR $TESTPOOL2 \
+ raidz2 $DISK1 $DISK2 $DISK3 $DISK4
+
+# 2. Offline the first device
+zpool_do_sync 'offline' $TESTPOOL2 $DISK1
+
+# 3. Write to the pool
+log_must mkfile $FILESIZE "$TESTDIR/data.bin"
+
+# 4. Scrub the pool
+zpool_scrub_sync $TESTPOOL2
+
+# 5. Online the first device and offline the second device
+zpool_do_sync 'online' $TESTPOOL2 $DISK1
+zpool_do_sync 'offline' $TESTPOOL2 $DISK2
+log_must wait_for_resilver_end $TESTPOOL2 $RESILVER_TIMEOUT
+
+# 6. Scrub the pool again
+zpool_scrub_sync $TESTPOOL2
+
+# 7. Verify data integrity
+cksum=$(zpool status $TESTPOOL2 | awk 'L{print $NF;L=0} /CKSUM$/{L=1}')
+if [[ $cksum != 0 ]]; then
+ log_fail "Unexpected CKSUM errors found on $TESTPOOL2 ($cksum)"
+fi
+
+log_pass "Scrubbing a pool with offline devices correctly preserves DTLs"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_print_repairing.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_print_repairing.ksh
new file mode 100755
index 000000000000..4b51cd9625ec
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_print_repairing.ksh
@@ -0,0 +1,74 @@
+#!/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) 2018 Lawrence Livermore National Security, LLC.
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+
+#
+# DESCRIPTION:
+# zpool status should print "(repairing)" on drives with errors found
+# while scrubbing.
+#
+# STRATEGY:
+# 1. Create a file (already done in setup.ksh)
+# 2. Inject read errors on one vdev
+# 3. Run a scrub
+# 4. Verify we see "(repairing)" on the bad vdev
+#
+
+verify_runnable "global"
+
+log_assert "Verify we see '(repairing)' while scrubbing a bad vdev."
+
+function cleanup
+{
+ log_must zinject -c all
+ log_must set_tunable64 SCAN_VDEV_LIMIT $ZFS_SCAN_VDEV_LIMIT_DEFAULT
+ zpool scrub -s $TESTPOOL || true
+}
+
+log_onexit cleanup
+
+# A file is already created in setup.ksh. Inject read errors on the first disk.
+log_must zinject -d $DISK1 -e io -T read -f 100 $TESTPOOL
+
+# Make the scrub slow
+log_must zinject -d $DISK1 -D10:1 $TESTPOOL
+log_must set_tunable64 SCAN_VDEV_LIMIT $ZFS_SCAN_VDEV_LIMIT_SLOW
+
+log_must zpool scrub $TESTPOOL
+
+# Wait for the scrub to show '(repairing)'. Timeout after 10 sec if it doesn't
+# show it.
+for i in {0..100} ; do
+ if ! is_pool_scrubbing $TESTPOOL ; then
+ break
+ fi
+
+ if zpool status | grep "$DISK1" | grep -q '(repairing)' ; then
+ log_pass "Correctly saw '(repairing)' while scrubbing"
+ fi
+
+ sleep 0.1
+done
+log_fail "Never saw '(repairing)' while scrubbing"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_set/Makefile.am
new file mode 100644
index 000000000000..916e8bb8d20e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/Makefile.am
@@ -0,0 +1,9 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_set
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_set_001_pos.ksh \
+ zpool_set_002_neg.ksh \
+ zpool_set_003_neg.ksh \
+ zpool_set_ashift.ksh \
+ zpool_set_features.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_001_pos.ksh
new file mode 100755
index 000000000000..f08fdfab7fd6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_001_pos.ksh
@@ -0,0 +1,60 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+#
+# DESCRIPTION:
+#
+# Zpool set usage message is displayed when called with no arguments
+#
+# STRATEGY:
+# 1. Run zpool set
+# 2. Check that exit status is set to 2
+# 3. Check usage message contains text "usage"
+#
+#
+
+log_assert "zpool set usage message is displayed when called with no arguments"
+
+zpool set > /dev/null 2>&1
+RET=$?
+if [ $RET != 2 ]
+then
+ log_fail "\"zpool set\" exit status $RET should be equal to 2."
+fi
+
+OUTPUT=$(zpool set 2>&1 | grep -i usage)
+if [ $? != 0 ]
+then
+ log_fail "Usage message for zpool set did not contain the word 'usage'."
+fi
+
+log_pass "zpool set usage message is displayed when called with no arguments"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_002_neg.ksh
new file mode 100755
index 000000000000..34d7fd821464
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_002_neg.ksh
@@ -0,0 +1,124 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# Malformed zpool set commands are rejected
+#
+# STRATEGY:
+# 1. Create an array of many different malformed zfs set arguments
+# 2. Run zpool set for each arg checking each will exit with status code 1
+#
+#
+
+verify_runnable "global"
+
+# note to self - need to make sure there isn't a pool called bootfs
+# before running this test...
+function cleanup {
+
+ zpool destroy bootfs
+ rm $FILEVDEV
+}
+
+log_assert "Malformed zpool set commands are rejected"
+
+if poolexists bootfs
+then
+ log_unsupported "Unable to run test on a machine with a pool called \
+ bootfs"
+fi
+
+log_onexit cleanup
+
+# build up an array of bad arguments.
+set -A arguments "rubbish " \
+ "foo@bar= " \
+ "@@@= +pool " \
+ "zpool bootfs " \
+ "bootfs " \
+ "bootfs +" \
+ "bootfs=bootfs/123 " \
+ "bootfs=bootfs@val " \
+ "Bootfs=bootfs " \
+ "- " \
+ "== " \
+ "set " \
+ "@@ " \
+ "12345 " \
+ "€にほんご " \
+ "/ " \
+ "bootfs=bootfs /" \
+ "bootfs=a%d%s "
+
+
+# here, we build up a large string.
+# a word to the ksh-wary, ${#array[@]} gives you the
+# total number of entries in an array, so array[${#array[@]}]
+# will index the last entry+1, ksh arrays start at index 0.
+COUNT=0
+while [ $COUNT -le 1025 ]
+do
+ bigname="${bigname}o"
+ COUNT=$(( $COUNT + 1 ))
+done
+
+# add an argument of maximum length property name
+arguments[${#arguments[@]}]="$bigname=value"
+
+# add an argument of maximum length property value
+arguments[${#arguments[@]}]="bootfs=$bigname"
+
+# Create a pool called bootfs (so-called, so as to trip any clashes between
+# property name, and pool name)
+# Also create a filesystem in this pool
+FILEVDEV="$TEST_BASE_DIR/zpool_set_002.$$.dat"
+log_must mkfile $MINVDEVSIZE $FILEVDEV
+log_must zpool create bootfs $FILEVDEV
+log_must zfs create bootfs/root
+
+typeset -i i=0;
+while [ $i -lt "${#arguments[@]}" ]
+do
+ log_mustnot eval "zpool set ${arguments[$i]} > /dev/null 2>&1"
+
+ # now also try with a valid pool in the argument list
+ log_mustnot eval "zpool set ${arguments[$i]}bootfs > /dev/null 2>&1"
+
+ # now also try with two valid pools in the argument list
+ log_mustnot eval "zpool set ${arguments[$i]}bootfs bootfs > /dev/null"
+ i=$(( $i + 1))
+done
+
+log_pass "Malformed zpool set commands are rejected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_003_neg.ksh
new file mode 100755
index 000000000000..1d637b77af00
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_003_neg.ksh
@@ -0,0 +1,73 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# zpool set cannot set a readonly property
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Verify that we can't set readonly properties on that pool
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ zpool destroy $TESTPOOL1
+ rm $FILEVDEV
+}
+
+set -A props "available" "capacity" "guid" "health" "size" "used"
+set -A vals "100" "10" "12345" "HEALTHY" "10" "10"
+
+log_onexit cleanup
+
+log_assert "zpool set cannot set a readonly property"
+
+FILEVDEV="$TEST_BASE_DIR/zpool_set_003.$$.dat"
+log_must mkfile $MINVDEVSIZE $FILEVDEV
+log_must zpool create $TESTPOOL1 $FILEVDEV
+
+typeset -i i=0;
+while [ $i -lt "${#props[@]}" ]
+do
+ # try to set each property in the prop list with it's corresponding val
+ log_mustnot eval "zpool set ${props[$i]}=${vals[$i]} $TESTPOOL1 \
+ > /dev/null 2>&1"
+ i=$(( $i + 1))
+done
+
+log_pass "zpool set cannot set a readonly property"
+
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_ashift.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_ashift.ksh
new file mode 100755
index 000000000000..86e692fadafc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_ashift.ksh
@@ -0,0 +1,78 @@
+#!/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 2017, loli10K. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+#
+# zpool set can modify 'ashift' property
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Verify that we can set 'ashift' only to allowed values on that pool
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL1
+ rm -f $disk
+}
+
+typeset goodvals=("0" "9" "10" "11" "12" "13" "14" "15" "16")
+typeset badvals=("off" "on" "1" "8" "17" "1b" "ff" "-")
+
+log_onexit cleanup
+
+log_assert "zpool set can modify 'ashift' property"
+
+disk=$TEST_BASE_DIR/disk
+log_must mkfile $SIZE $disk
+log_must zpool create $TESTPOOL1 $disk
+
+for ashift in ${goodvals[@]}
+do
+ log_must zpool set ashift=$ashift $TESTPOOL1
+ typeset value=$(get_pool_prop ashift $TESTPOOL1)
+ if [[ "$ashift" != "$value" ]]; then
+ log_fail "'zpool set' did not update ashift value to $ashift "\
+ "(current = $value)"
+ fi
+done
+
+for ashift in ${badvals[@]}
+do
+ log_mustnot zpool set ashift=$ashift $TESTPOOL1
+ typeset value=$(get_pool_prop ashift $TESTPOOL1)
+ if [[ "$ashift" == "$value" ]]; then
+ log_fail "'zpool set' incorrectly set ashift value to $value"
+ fi
+done
+
+log_pass "zpool set can modify 'ashift' property"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_features.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_features.ksh
new file mode 100755
index 000000000000..f496a0e429d8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/zpool_set_features.ksh
@@ -0,0 +1,75 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zpool set' should be able to enable features on pools
+#
+# STRATEGY:
+# 1. Create a pool with all features disabled
+# 2. Verify 'zpool set' is able to enable a single feature
+# 3. Create a pool with all features enabled
+# 4. Verify 'zpool set' is *not* able to disable a single feature
+# 5. Rinse and repeat for known features
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL1
+ rm -f $FILEVDEV
+}
+
+log_assert "'zpool set' should be able to enable features on pools"
+log_onexit cleanup
+
+typeset -a features=(
+ "async_destroy"
+ "large_blocks"
+ "hole_birth"
+ "large_dnode"
+ "userobj_accounting"
+ "encryption"
+)
+FILEVDEV="$TEST_BASE_DIR/zpool_set_features.$$.dat"
+
+# Verify 'zpool set' is able to enable a single feature
+for feature in "${features[@]}"
+do
+ propname="feature@$feature"
+ truncate -s $SPA_MINDEVSIZE $FILEVDEV
+ log_must zpool create -d -f $TESTPOOL1 $FILEVDEV
+ log_must zpool set "$propname=enabled" $TESTPOOL1
+ propval="$(get_pool_prop $propname $TESTPOOL1)"
+ log_must test "$propval" == 'enabled' -o "$propval" == 'active'
+ cleanup
+done
+# Verify 'zpool set' is *not* able to disable a single feature
+for feature in "${features[@]}"
+do
+ propname="feature@$feature"
+ truncate -s $SPA_MINDEVSIZE $FILEVDEV
+ log_must zpool create -f $TESTPOOL1 $FILEVDEV
+ log_mustnot zpool set "$propname=disabled" $TESTPOOL1
+ propval="$(get_pool_prop $propname $TESTPOOL1)"
+ log_must test "$propval" == 'enabled' -o "$propval" == 'active'
+ cleanup
+done
+
+log_pass "'zpool set' can enable features on pools"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_split/Makefile.am
new file mode 100644
index 000000000000..1ca05a4e8e8d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/Makefile.am
@@ -0,0 +1,18 @@
+include $(top_srcdir)/config/Rules.am
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_split
+
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ zpool_split_cliargs.ksh \
+ zpool_split_devices.ksh \
+ zpool_split_encryption.ksh \
+ zpool_split_props.ksh \
+ zpool_split_vdevs.ksh \
+ zpool_split_resilver.ksh \
+ zpool_split_wholedisk.ksh \
+ zpool_split_indirect.ksh
+
+dist_pkgdata_DATA = \
+ zpool_split.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/cleanup.ksh
new file mode 100755
index 000000000000..e78deacd5bba
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/cleanup.ksh
@@ -0,0 +1,19 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/setup.ksh
new file mode 100755
index 000000000000..4497dbd7463a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/setup.ksh
@@ -0,0 +1,17 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split.cfg
new file mode 100644
index 000000000000..5833a420c87c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split.cfg
@@ -0,0 +1,18 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+export DISKSARRAY=$DISKS
+export DISK_ARRAY_NUM=$(echo ${DISKS} | nawk '{print NF}')
+set_device_dir
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_cliargs.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_cliargs.ksh
new file mode 100755
index 000000000000..ae9ad1354b0a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_cliargs.ksh
@@ -0,0 +1,80 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_split/zpool_split.cfg
+
+#
+# DESCRIPTION:
+# 'zpool split' should only work with supported options and parameters.
+#
+# STRATEGY:
+# 1. Verify every supported option is accepted
+# 2. Verify other unsupported options raise an error
+# 3. Verify we cannot split a pool if the destination already exists
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL
+ destroy_pool $TESTPOOL2
+ rm -f $DEVICE1 $DEVICE2 $DEVICE3
+}
+
+function setup_mirror
+{
+ truncate -s $SPA_MINDEVSIZE $DEVICE1
+ truncate -s $SPA_MINDEVSIZE $DEVICE2
+ log_must zpool create -f $TESTPOOL mirror $DEVICE1 $DEVICE2
+}
+
+log_assert "'zpool split' should only work with supported options and parameters."
+log_onexit cleanup
+
+typeset goodopts=(
+ "" "-g" "-L" "-n" "-P" "-o comment=ok" "-o ro -R /mnt" "-l -R /mnt" "-gLnP")
+typeset badopts=(
+ "-f" "-h" "-x" "-Pp" "-l" "-G" "-o" "-o ro" "-o comment" "-R" "-R dir" "=")
+
+DEVICE1="$TEST_BASE_DIR/device-1"
+DEVICE2="$TEST_BASE_DIR/device-2"
+DEVICE3="$TEST_BASE_DIR/device-3"
+
+# 1. Verify every supported option and/or parameter is accepted
+for opt in "${goodopts[@]}"
+do
+ setup_mirror
+ log_must zpool split $opt $TESTPOOL $TESTPOOL2
+ cleanup
+done
+
+# 2. Verify other unsupported options and/or parameters raise an error
+setup_mirror
+for opt in "${badopts[@]}"
+do
+ log_mustnot zpool split $opt $TESTPOOL $TESTPOOL2
+done
+cleanup
+
+# 3. Verify we cannot split a pool if the destination already exists
+setup_mirror
+truncate -s $SPA_MINDEVSIZE $DEVICE3
+log_must zpool create $TESTPOOL2 $DEVICE3
+log_mustnot zpool split $TESTPOOL $TESTPOOL2
+
+log_pass "'zpool split' only works with supported options and parameters."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_devices.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_devices.ksh
new file mode 100755
index 000000000000..d64c30d5c561
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_devices.ksh
@@ -0,0 +1,101 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_split/zpool_split.cfg
+
+#
+# DESCRIPTION:
+# 'zpool split' should use the provided devices to split the pool
+#
+# STRATEGY:
+# 1. Create various (mirror-only) pools
+# 2. Verify 'zpool split' can provide a list of devices to be included in the
+# new pool. At most one disk from each mirror can be specified.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL
+ destroy_pool $TESTPOOL2
+ rm -f $FILEDEV_PREFIX*
+}
+
+function setup_mirror # <conf>
+{
+ for filedev in "${fd[@]}"; do
+ truncate -s $SPA_MINDEVSIZE "$filedev"
+ done
+ log_must zpool create -f $TESTPOOL $conf
+}
+
+log_assert "'zpool split' should use the provided devices to split the pool"
+log_onexit cleanup
+
+typeset altroot="$TESTDIR/altroot-$TESTPOOL2"
+typeset FILEDEV_PREFIX="$TEST_BASE_DIR/filedev"
+typeset -A fd
+fd[01]="$FILEDEV_PREFIX-01"
+fd[02]="$FILEDEV_PREFIX-02"
+fd[03]="$FILEDEV_PREFIX-03"
+fd[11]="$FILEDEV_PREFIX-11"
+fd[12]="$FILEDEV_PREFIX-12"
+fd[13]="$FILEDEV_PREFIX-13"
+
+# Base pool configurations
+typeset poolconfs=("mirror ${fd[01]} ${fd[02]}"
+ "mirror ${fd[01]} ${fd[02]} ${fd[03]}"
+ "mirror ${fd[01]} ${fd[02]} mirror ${fd[11]} ${fd[12]}"
+ "mirror ${fd[01]} ${fd[02]} ${fd[03]} mirror ${fd[11]} ${fd[12]}"
+ "mirror ${fd[01]} ${fd[02]} mirror ${fd[11]} ${fd[12]} ${fd[13]}"
+ "mirror ${fd[01]} ${fd[02]} ${fd[03]} mirror ${fd[11]} ${fd[12]} ${fd[13]}"
+)
+# "good" device specifications
+typeset gooddevs=("${fd[01]}"
+ "${fd[02]}"
+ "${fd[02]} ${fd[11]}"
+ "${fd[12]}"
+ "${fd[02]}"
+ "${fd[03]} ${fd[12]}"
+)
+# "bad" device specifications
+typeset baddevs=("${fd[01]} ${fd[02]}"
+ "${fd[02]} ${fd[03]}"
+ "${fd[02]} baddev"
+ "baddev ${fd[11]}"
+ "${fd[11]} ${fd[12]} ${fd[13]}"
+ "${fd[01]} ${fd[02]} ${fd[13]}"
+)
+
+typeset -i i=0;
+while [ $i -lt "${#poolconfs[@]}" ]
+do
+ typeset conf=${poolconfs[$i]}
+ setup_mirror $conf
+ log_mustnot zpool split $TESTPOOL $TESTPOOL2 ${baddevs[$i]}
+ log_must zpool split -R $altroot $TESTPOOL $TESTPOOL2 ${gooddevs[$i]}
+ # Verify "good" devices ended up in the new pool
+ log_must poolexists $TESTPOOL2
+ for filedev in ${gooddevs[$i]}; do
+ log_must check_vdev_state $TESTPOOL2 $filedev "ONLINE"
+ done
+ cleanup
+ ((i = i + 1))
+done
+
+log_pass "'zpool split' can use the provided devices to split the pool"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_encryption.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_encryption.ksh
new file mode 100755
index 000000000000..768466983423
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_encryption.ksh
@@ -0,0 +1,59 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_split/zpool_split.cfg
+
+#
+# DESCRIPTION:
+# 'zpool split' should be able to split encrypted pools
+#
+# STRATEGY:
+# 1. Create an encrypted pool
+# 2. Split and re-import the pool, verify altroot is mounted.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL
+ destroy_pool $TESTPOOL2
+ rm -f $DEVICE1 $DEVICE2
+}
+
+log_assert "'zpool split' should be able to split encrypted pools"
+log_onexit cleanup
+
+DEVICE1="$TEST_BASE_DIR/device-1"
+DEVICE2="$TEST_BASE_DIR/device-2"
+passphrase="password"
+altroot="$TESTDIR/zpool-split-$RANDOM"
+
+# 1. Create an encrypted pool
+truncate -s $SPA_MINDEVSIZE $DEVICE1
+truncate -s $SPA_MINDEVSIZE $DEVICE2
+log_must eval "echo "$passphrase" | zpool create -O encryption=aes-256-ccm " \
+ "-O keyformat=passphrase $TESTPOOL mirror $DEVICE1 $DEVICE2"
+
+# 2. Split and re-import the pool, verify altroot is mounted.
+log_must eval "echo "$passphrase" | zpool split -l -R $altroot " \
+ "$TESTPOOL $TESTPOOL2"
+log_must test "$(get_prop 'encryption' $TESTPOOL2)" == "aes-256-ccm"
+log_must test "$(get_pool_prop 'altroot' $TESTPOOL2)" == "$altroot"
+log_must mounted $altroot/$TESTPOOL2
+
+log_pass "'zpool split' can split encrypted pools"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_indirect.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_indirect.ksh
new file mode 100755
index 000000000000..13f0d08b7f20
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_indirect.ksh
@@ -0,0 +1,69 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2020, George Amanakis. All rights reserved.
+# Copyright (c) 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool split' should succeed on pools with indirect vdevs.
+#
+# STRATEGY:
+# Create a mirrored pool, add a single device, remove it. `zpool split`
+# should succeed.
+#
+
+verify_runnable "global"
+
+log_assert "'zpool split' works on pools with indirect VDEVs."
+
+function cleanup
+{
+ if poolexists $TESTPOOL ; then
+ destroy_pool $TESTPOOL
+ fi
+ if poolexists $TESTPOOL2 ; then
+ destroy_pool $TESTPOOL2
+ fi
+ rm -f $VDEV_TEMP $VDEV_M1 $VDEV_M2
+}
+log_onexit cleanup
+
+typeset vdev_m12_mb=400
+typeset vdev_temp_mb=$(( floor($vdev_m12_mb / 2) ))
+typeset VDEV_TEMP="$TEST_BASE_DIR/vdev_temp"
+typeset VDEV_M1="$TEST_BASE_DIR/vdev_m1"
+typeset VDEV_M2="$TEST_BASE_DIR/vdev_m2"
+typeset altroot="$TESTDIR/altroot-$TESTPOOL2"
+
+log_must truncate -s ${vdev_temp_mb}M $VDEV_TEMP
+log_must truncate -s ${vdev_m12_mb}M $VDEV_M1
+log_must truncate -s ${vdev_m12_mb}M $VDEV_M2
+
+log_must zpool create -f $TESTPOOL $VDEV_TEMP
+log_must zpool add -f $TESTPOOL mirror $VDEV_M1 $VDEV_M2
+log_must zpool remove $TESTPOOL $VDEV_TEMP
+log_must wait_for_removal $TESTPOOL
+log_must zpool split -R $altroot $TESTPOOL $TESTPOOL2
+log_must poolexists $TESTPOOL2
+log_must test "$(get_pool_prop 'altroot' $TESTPOOL2)" == "$altroot"
+
+log_pass "'zpool split' works on pools with indirect VDEVs."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_props.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_props.ksh
new file mode 100755
index 000000000000..1aff8d31d91c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_props.ksh
@@ -0,0 +1,95 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_split/zpool_split.cfg
+. $STF_SUITE/tests/functional/mmp/mmp.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool split' can set new property values on the new pool
+#
+# STRATEGY:
+# 1. Create a mirror pool
+# 2. Verify 'zpool split' can set property values on the new pool, but only if
+# they are valid.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL
+ destroy_pool $TESTPOOL2
+ rm -f $DEVICE1 $DEVICE2
+ ! is_freebsd && log_must mmp_clear_hostid
+}
+
+function setup_mirror
+{
+ truncate -s $SPA_MINDEVSIZE $DEVICE1
+ truncate -s $SPA_MINDEVSIZE $DEVICE2
+ log_must zpool create -f $TESTPOOL mirror $DEVICE1 $DEVICE2
+}
+
+log_assert "'zpool split' can set new property values on the new pool"
+log_onexit cleanup
+
+DEVICE1="$TEST_BASE_DIR/device-1"
+DEVICE2="$TEST_BASE_DIR/device-2"
+
+typeset good_props=('comment=text' 'ashift=12' 'multihost=on'
+ 'listsnapshots=on' 'autoexpand=on' 'autoreplace=on'
+ 'delegation=off' 'failmode=continue')
+typeset bad_props=("bootfs=$TESTPOOL2/bootfs" 'version=28' 'ashift=4'
+ 'allocated=1234' 'capacity=5678' 'multihost=none'
+ 'feature@async_destroy=disabled' 'feature@xxx_fake_xxx=enabled'
+ 'propname=propval' 'readonly=on')
+if ! is_freebsd; then
+ good_props+=('multihost=on')
+ bad_props+=('multihost=none')
+ if [ -e $HOSTID_FILE ]; then
+ log_unsupported "System has existing $HOSTID_FILE file"
+ fi
+ # Needed to set multihost=on
+ log_must mmp_set_hostid $HOSTID1
+fi
+
+# Verify we can set a combination of valid property values on the new pool
+for prop in "${good_props[@]}"
+do
+ propname="$(awk -F= '{print $1}' <<< $prop)"
+ propval="$(awk -F= '{print $2}' <<< $prop)"
+ setup_mirror
+ log_must zpool split -o $prop $TESTPOOL $TESTPOOL2
+ log_must zpool import -N -d $TEST_BASE_DIR $TESTPOOL2
+ log_must test "$(get_pool_prop $propname $TESTPOOL2)" == "$propval"
+
+ destroy_pool $TESTPOOL
+ destroy_pool $TESTPOOL2
+ rm -f $DEVICE1 $DEVICE2
+done
+
+# Verify we cannot set invalid property values
+setup_mirror
+zfs create $TESTPOOL/bootfs
+for prop in "${bad_props[@]}"
+do
+ log_mustnot zpool split -o $prop $TESTPOOL $TESTPOOL2
+ log_mustnot zpool import -N -d $TEST_BASE_DIR $TESTPOOL2
+done
+
+log_pass "'zpool split' can set new property values on the new pool"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_resilver.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_resilver.ksh
new file mode 100755
index 000000000000..99a40ecf2b74
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_resilver.ksh
@@ -0,0 +1,105 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018, Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_split/zpool_split.cfg
+
+#
+# DESCRIPTION:
+# 'zpool split' should fail if resilver in progress for a disk
+#
+# STRATEGY:
+# The first scenario:
+# 1. Create a mirror pool
+# 2. Offline the first VDEV
+# 3. Put some data
+# 4. Online the first VDEV
+# 5. Verify 'zpool split' must fail
+#
+# The second scenario:
+# 1. Create a mirror pool
+# 2. Offline the second VDEV
+# 3. Put some data
+# 4. Online the second VDEV
+# 5. Verify 'zpool split' must fail
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+ destroy_pool $TESTPOOL
+ destroy_pool $TESTPOOL2
+ rm -f $DEVICE1 $DEVICE2
+}
+
+function setup_mirror
+{
+ truncate -s $DEVSIZE $DEVICE1
+ truncate -s $DEVSIZE $DEVICE2
+ log_must zpool create -f $TESTPOOL mirror $DEVICE1 $DEVICE2
+}
+
+function zpool_split #disk_to_be_offline/online
+{
+ typeset disk=$1
+
+ setup_mirror
+
+ # offline a disk, so it will not be fully sync before split
+ log_must zpool offline $TESTPOOL $disk
+
+ # Create 2G of additional data
+ mntpnt=$(get_prop mountpoint $TESTPOOL)
+ log_must file_write -b 2097152 -c 1024 -o create -d 0 -f $mntpnt/biggerfile
+ log_must sync
+
+ # temporarily prevent resilvering progress, so it will not finish too early
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+
+ log_must zpool online $TESTPOOL $disk
+
+ typeset i=0
+ while ! is_pool_resilvering $TESTPOOL; do
+ if (( i > 10 )); then
+ log_fail "resilvering is not started"
+ fi
+ ((i += 1))
+ sleep 1
+ done
+
+ log_mustnot zpool split $TESTPOOL $TESTPOOL2
+
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+}
+
+log_assert "Verify 'zpool split' will fail if resilver in progress for a disk"
+log_onexit cleanup
+
+DEVSIZE='3g'
+DEVICE1="$TEST_BASE_DIR/device-1"
+DEVICE2="$TEST_BASE_DIR/device-2"
+
+log_note "Verify ZFS prevents main pool corruption during 'split'"
+zpool_split $DEVICE1
+
+cleanup
+
+log_note "Verify ZFS prevents new pool corruption during 'split'"
+zpool_split $DEVICE2
+
+log_pass "'zpool split' failed as expected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_vdevs.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_vdevs.ksh
new file mode 100755
index 000000000000..9866cf7a5a58
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_vdevs.ksh
@@ -0,0 +1,150 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_split/zpool_split.cfg
+. $STF_SUITE/include/math.shlib
+
+#
+# DESCRIPTION:
+# 'zpool split' should only work on mirrors. Every other VDEV layout is not
+# supported.
+#
+# STRATEGY:
+# Create pools with various VDEV layouts and verify only mirrors can be split
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL
+ destroy_pool $TESTPOOL2
+ rm -f $FILEDEV_PREFIX*
+}
+
+#
+# Given a vdev type generate a pool configuration which can be immediately
+# used as "zpool create $poolname $config" or "zpool add $poolname $config".
+# Supported vdev types are:
+# "d" - single disk
+# "t" - stripe
+# "m" - mirror
+# "m3" - 3-way mirror
+# "z1" - raidz1
+# "z2" - raidz2
+# "z3" - raidz3
+# "s" - spare
+# "l" - log
+# "ll" - mirrored log
+# "c" - cache
+# "sc" - special class
+#
+function pool_config # <vdev-type>
+{
+ typeset config=""
+ typeset -A disks
+ disks[d]="d1"
+ disks[t]="t1 t2"
+ disks[m]="m1 m2"
+ disks[m3]="m1 m2 m3"
+ disks[z1]="z1 z2"
+ disks[z2]="z1 z2 z3"
+ disks[z3]="z1 z2 z3 z4"
+ disks[s]="s1"
+ disks[l]="l1"
+ disks[ll]="l1 l2"
+ disks[c]="c1"
+ disks[sc]="sc1 sc2"
+ case $1 in
+ d|t) # single disk or stripe
+ vdev='' ;;
+ m|m3) # 2-way or 3-way mirror
+ vdev='mirror';;
+ z1) # raidz1
+ vdev='raidz1';;
+ z2) # raidz2
+ vdev='raidz2';;
+ z3) # raidz3
+ vdev='raidz3';;
+ s) # spare
+ vdev='spare';;
+ l) # log
+ vdev='log';;
+ ll) # mirrored log
+ vdev='log mirror';;
+ c) # cache
+ vdev='cache';;
+ sc) # mirrored special class
+ vdev='special mirror';;
+ *)
+ log_fail "setup_pool: unsupported vdev type '$1'"
+ esac
+ config="$vdev"
+ for tok in ${disks[$1]}; do
+ filedev="$FILEDEV_PREFIX-$tok"
+ # if $filedev exists we are requesting the same vdev type twice
+ # in a row (eg. pool of striped mirrors): add a random suffix.
+ while [[ -f $filedev ]]; do
+ filedev="$filedev.$RANDOM"
+ done
+ truncate -s $SPA_MINDEVSIZE "$filedev"
+ config="$config $filedev"
+ done
+ echo "$config"
+}
+
+log_assert "'zpool split' should work only on mirror VDEVs"
+log_onexit cleanup
+
+# "good" and "bad" pool layouts
+# first token is always used with "zpool create"
+# second to last tokens, if any, are used with "zpool add"
+typeset -a goodconfs=("m" "m l" "m s" "m c" "m m" "m3" "m3 m3" "m m3 l s c" "m m sc")
+typeset -a badconfs=("d" "z1" "z2" "z3" "m d" "m3 d" "m z1" "m z2" "m z3")
+typeset FILEDEV_PREFIX="$TEST_BASE_DIR/filedev"
+typeset altroot="$TESTDIR/altroot-$TESTPOOL2"
+
+# Create pools with various VDEV layouts and verify only mirrors can be split
+for config in "${goodconfs[@]}"
+do
+ create_config="${config%% *}"
+ add_config="$(awk '{$1= "";print $0}' <<< $config)"
+ log_must zpool create $TESTPOOL $(pool_config $create_config)
+ for vdev in $add_config; do
+ log_must zpool add -f $TESTPOOL $(pool_config $vdev)
+ done
+ log_must zpool split -R $altroot $TESTPOOL $TESTPOOL2
+ log_must poolexists $TESTPOOL2
+ log_must test "$(get_pool_prop 'altroot' $TESTPOOL2)" == "$altroot"
+ cleanup
+done
+
+# Every other pool layout should *not* be splittable
+for config in "${badconfs[@]}"
+do
+ create_config="${config%% *}"
+ add_config="$(awk '{$1= "";print $0}' <<< $config)"
+ log_must zpool create $TESTPOOL $(pool_config $create_config)
+ for vdev in $add_config; do
+ log_must zpool add -f $TESTPOOL $(pool_config $vdev)
+ done
+ log_mustnot zpool split -R $altroot $TESTPOOL $TESTPOOL2
+ log_mustnot poolexists $TESTPOOL2
+ cleanup
+done
+
+log_pass "'zpool split' works only on mirror VDEVs"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_wholedisk.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_wholedisk.ksh
new file mode 100755
index 000000000000..085856c428ad
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_split/zpool_split_wholedisk.ksh
@@ -0,0 +1,84 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_split/zpool_split.cfg
+
+#
+# DESCRIPTION:
+# 'zpool split' should work with whole-disk devices.
+#
+# STRATEGY:
+# 1. Create a mirror with a whole-disk device
+# 2. Verify 'zpool split' works and successfully split the mirror
+# 3. Cleanup and create the same mirror
+# 4. Verify 'zpool split' using the other device
+#
+
+verify_runnable "both"
+
+if is_linux; then
+ # Add one 512b spare device (4Kn would generate IO errors on replace)
+ # NOTE: must be larger than other "file" vdevs and minimum SPA devsize:
+ # add 32m of fudge
+ load_scsi_debug $(($SPA_MINDEVSIZE/1024/1024+32)) 1 1 1 '512b'
+else
+ log_unsupported "scsi debug module unsupported"
+fi
+
+function cleanup
+{
+ destroy_pool $TESTPOOL
+ destroy_pool $TESTPOOL2
+ unload_scsi_debug
+ rm -f "$FILE_DEVICE"
+}
+
+function setup_mirror
+{
+ # NOTE: "-f" is required to create a mixed (file and disk device) mirror
+ log_must truncate -s $SPA_MINDEVSIZE $FILE_DEVICE
+ log_must zpool create -f $TESTPOOL mirror $FILE_DEVICE $DISK_DEVICE
+ # NOTE: verify disk is actually a "whole-disk" device
+ log_must test "$(zdb -PC $TESTPOOL | grep -c 'whole_disk: 1')" == 1
+}
+
+log_assert "'zpool split' should work with whole-disk devices"
+log_onexit cleanup
+
+FILE_DEVICE="$TEST_BASE_DIR/file-device"
+DISK_DEVICE="$(get_debug_device)"
+ALTROOT="$TEST_BASE_DIR/altroot-$TESTPOOL2"
+
+# 1. Create a mirror with a whole-disk device
+setup_mirror
+
+# 2. Verify 'zpool split' works and successfully split the mirror
+log_must zpool split -R "$ALTROOT" $TESTPOOL $TESTPOOL2 $DISK_DEVICE
+log_must check_vdev_state $TESTPOOL $FILE_DEVICE "ONLINE"
+log_must check_vdev_state $TESTPOOL2 $DISK_DEVICE "ONLINE"
+
+# 3. Cleanup and create the same mirror
+destroy_pool $TESTPOOL
+destroy_pool $TESTPOOL2
+setup_mirror
+
+# 4. Verify 'zpool split' using the other device
+log_must zpool split -R "$ALTROOT" $TESTPOOL $TESTPOOL2 $FILE_DEVICE
+log_must check_vdev_state $TESTPOOL $DISK_DEVICE "ONLINE"
+log_must check_vdev_state $TESTPOOL2 $FILE_DEVICE "ONLINE"
+
+log_pass "'zpool split' works with whole-disk devices"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_status/Makefile.am
new file mode 100644
index 000000000000..beb59e3d066b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_status
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_status_001_pos.ksh \
+ zpool_status_002_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_status/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_status/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/setup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_001_pos.ksh
new file mode 100755
index 000000000000..88c0601032a5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_001_pos.ksh
@@ -0,0 +1,62 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Executing 'zpool status' command with bad options fails.
+#
+# STRATEGY:
+# 1. Create an array of badly formed 'zpool status' options
+# 2. Execute each element of the array.
+# 3. Verify an error code is returned.
+#
+
+verify_runnable "both"
+
+
+set -A args "" "-?" "-x fakepool" "-v fakepool" "-xv fakepool" "-vx fakepool" \
+ "-x $TESTPOOL/$TESTFS" "-v $TESTPOOL/$TESTFS" "-xv $TESTPOOL/$TESTFS" \
+ "-vx $TESTPOOL/$TESTFS"
+
+log_assert "Executing 'zpool status' with bad options fails"
+
+typeset -i i=1
+
+while [[ $i -lt ${#args[*]} ]]; do
+
+ log_mustnot zpool status ${args[$i]}
+
+ (( i = i + 1 ))
+done
+
+log_pass "'zpool status' command with bad options failed as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_002_pos.ksh
new file mode 100755
index 000000000000..e2751b112597
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_status/zpool_status_002_pos.ksh
@@ -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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Executing 'zpool status' with correct options succeeds
+#
+# STRATEGY:
+# 1. Create an array of correctly formed 'zpool status' options
+# 2. Execute each element of the array.
+# 3. Verify use of each option is successful.
+#
+
+verify_runnable "both"
+
+typeset testpool
+if is_global_zone; then
+ testpool=$TESTPOOL
+else
+ testpool=${TESTPOOL%%/*}
+fi
+
+set -A args "" "-x" "-v" "-x $testpool" "-v $testpool" "-xv $testpool" \
+ "-vx $testpool"
+
+log_assert "Executing 'zpool status' with correct options succeeds"
+
+typeset -i i=0
+
+while [[ $i -lt ${#args[*]} ]]; do
+
+ log_must zpool status ${args[$i]}
+
+ (( i = i + 1 ))
+done
+
+log_pass "'zpool status' with correct options succeeded"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_sync/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_sync/Makefile.am
new file mode 100644
index 000000000000..7f5f67d1f343
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_sync/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_sync
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ zpool_sync_001_pos.ksh \
+ zpool_sync_002_neg.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_sync/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_sync/cleanup.ksh
new file mode 100755
index 000000000000..89c146249e71
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_sync/cleanup.ksh
@@ -0,0 +1,32 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_sync/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_sync/setup.ksh
new file mode 100755
index 000000000000..181e62b113c1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_sync/setup.ksh
@@ -0,0 +1,34 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_sync/zpool_sync_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_sync/zpool_sync_001_pos.ksh
new file mode 100755
index 000000000000..e72ca2157f10
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_sync/zpool_sync_001_pos.ksh
@@ -0,0 +1,88 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2017 Datto Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify 'zpool sync' can sync txgs to the pool(s) main vdevs.
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Use zdb to obtain current txg
+# 3. Create a file in the pool if we're not using force sync
+# 4. Use zpool sync to sync pool
+# 5. Verify the new txg is now bigger than the saved one
+#
+
+verify_runnable "global"
+
+function get_txg {
+ typeset -i txg=$(zdb -u $1 | sed -n 's/^[ ][ ]*txg = \(.*\)$/\1/p')
+ echo $txg
+}
+
+set -A args "sync $TESTPOOL" "sync -f $TESTPOOL" "sync" "sync -f"
+
+log_assert "Verify 'zpool sync' can sync a pool"
+
+typeset -i i=0
+typeset -i orig_txg=0
+typeset -i new_txg=0
+while [[ $i -lt ${#args[*]} ]]; do
+ orig_txg=$(get_txg $TESTPOOL)
+ if ! [[ "${args[i]}" =~ "-f" ]]; then
+ log_must touch /$TESTPOOL/$i
+ fi
+ log_must zpool ${args[i]}
+ new_txg=$(get_txg $TESTPOOL)
+ if [[ $orig_txg -ge $new_txg ]]; then
+ log_fail "'zpool ${args[i]}' failed: txg $orig_txg >= $new_txg"
+ fi
+ ((i = i + 1))
+done
+
+# sync_pool is implemented using 'zpool sync' so let's test it as well
+
+# make sure we can use sync_pool with force sync explicitly not used
+orig_txg=$(get_txg $TESTPOOL)
+log_must touch /$TESTPOOL/$i
+log_must sync_pool $TESTPOOL false
+new_txg=$(get_txg $TESTPOOL)
+if [[ $orig_txg -ge $new_txg ]]; then
+ log_fail "'sync_pool $TESTPOOL false' failed: txg $orig_txg >= $new_txg"
+fi
+
+# make sure we can use sync_pool with force sync explicitly enabled
+orig_txg=$(get_txg $TESTPOOL)
+log_must sync_pool $TESTPOOL true
+new_txg=$(get_txg $TESTPOOL)
+if [[ $orig_txg -ge $new_txg ]]; then
+ log_fail "'sync_pool $TESTPOOL true' failed: txg $orig_txg >= $new_txg"
+fi
+
+# make sure we can use sync_pool with force sync implicitly not used
+orig_txg=$(get_txg $TESTPOOL)
+log_must touch /$TESTPOOL/$i
+log_must sync_pool $TESTPOOL
+new_txg=$(get_txg $TESTPOOL)
+if [[ $orig_txg -ge $new_txg ]]; then
+ log_fail "'sync_pool $TESTPOOL' failed: txg $orig_txg >= $new_txg"
+fi
+
+log_pass "'zpool sync' syncs pool as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_sync/zpool_sync_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_sync/zpool_sync_002_neg.ksh
new file mode 100755
index 000000000000..e35a29130ccc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_sync/zpool_sync_002_neg.ksh
@@ -0,0 +1,44 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2017 Datto Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# A badly formed parameter passed to 'zpool sync' should
+# return an error.
+#
+# STRATEGY:
+# 1. Create an array containing bad 'zpool sync' parameters.
+# 2. For each element, execute the sub-command.
+# 3. Verify it returns an error.
+#
+
+verify_runnable "global"
+
+set -A args "1" "-a" "-?" "--%" "-123456" "0.5" "-o" "-b" "-b no" "-z 2"
+
+log_assert "Execute 'zpool sync' using invalid parameters."
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zpool sync ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "Invalid parameters to 'zpool sync' fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/Makefile.am
new file mode 100644
index 000000000000..d2d3b4ae88bb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/Makefile.am
@@ -0,0 +1,24 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_trim
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_trim_attach_detach_add_remove.ksh \
+ zpool_trim_import_export.ksh \
+ zpool_trim_multiple.ksh \
+ zpool_trim_neg.ksh \
+ zpool_trim_offline_export_import_online.ksh \
+ zpool_trim_online_offline.ksh \
+ zpool_trim_partial.ksh \
+ zpool_trim_rate.ksh \
+ zpool_trim_rate_neg.ksh \
+ zpool_trim_secure.ksh \
+ zpool_trim_split.ksh \
+ zpool_trim_start_and_cancel_neg.ksh \
+ zpool_trim_start_and_cancel_pos.ksh \
+ zpool_trim_suspend_resume.ksh \
+ zpool_trim_unsupported_vdevs.ksh \
+ zpool_trim_verify_checksums.ksh \
+ zpool_trim_verify_trimmed.ksh
+
+dist_pkgdata_DATA = \
+ zpool_trim.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/cleanup.ksh
new file mode 100755
index 000000000000..8ba8166333eb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/cleanup.ksh
@@ -0,0 +1,34 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+fi
+
+if poolexists $TESTPOOL1; then
+ destroy_pool $TESTPOOL1
+fi
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/setup.ksh
new file mode 100755
index 000000000000..09489600b3dc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/setup.ksh
@@ -0,0 +1,43 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+if is_freebsd; then
+ log_unsupported "FreeBSD has no hole punching mechanism for the time being."
+ diskinfo -v $DISKS | grep -qE 'No.*# TRIM/UNMAP support' &&
+ log_unsupported "DISKS do not support discard (TRIM/UNMAP)"
+else
+ DISK1=${DISKS%% *}
+
+ typeset -i max_discard=0
+ if is_disk_device $DEV_RDSKDIR/$DISK1; then
+ max_discard=$(lsblk -Dbn $DEV_RDSKDIR/$DISK1 | awk '{ print $4; exit }')
+ fi
+
+ if test $max_discard -eq 0; then
+ log_unsupported "DISKS do not support discard (TRIM/UNMAP)"
+ fi
+fi
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
new file mode 100644
index 000000000000..1c54c66c129c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
@@ -0,0 +1,43 @@
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+# Copyright (c) 2019 by Lawrence Livermore National Security, LLC.
+#
+
+function trim_prog_line # pool disk
+{
+ typeset pool="$1"
+ typeset disk="$2"
+ zpool status -t "$pool" | grep "$disk" | grep "[[:digit:]]* trimmed"
+}
+
+function trim_progress # pool disk
+{
+ trim_prog_line "$1" "$2" | sed 's/.*(\([0-9]\{1,\}\)% trimmed.*/\1/g'
+}
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+
+ if poolexists $TESTPOOL1; then
+ destroy_pool $TESTPOOL1
+ fi
+}
+log_onexit cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_attach_detach_add_remove.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_attach_detach_add_remove.ksh
new file mode 100755
index 000000000000..e715de9644b1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_attach_detach_add_remove.ksh
@@ -0,0 +1,64 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# Detaching/attaching, adding/removing data devices works with trimming.
+#
+# STRATEGY:
+# 1. Create a single-disk pool.
+# 2. Start trimming.
+# 3. Attach a second disk, ensure trimming continues.
+# 4. Detach the second disk, ensure trimming continues.
+# 5. Add a second disk, ensure trimming continues.
+# 6. Remove the first disk, ensure trimming stops.
+#
+
+DISK1="$(echo $DISKS | cut -d' ' -f1)"
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+
+log_must zpool create -f $TESTPOOL $DISK1
+
+log_must zpool trim -r 128M $TESTPOOL $DISK1
+progress="$(trim_progress $TESTPOOL $DISK1)"
+[[ -z "$progress" ]] && log_fail "Trim did not start"
+
+log_must zpool attach $TESTPOOL $DISK1 $DISK2
+new_progress="$(trim_progress $TESTPOOL $DISK1)"
+[[ "$progress" -le "$new_progress" ]] || \
+ log_fail "Lost trimming progress on demotion to child vdev"
+progress="$new_progress"
+
+log_must zpool detach $TESTPOOL $DISK2
+new_progress="$(trim_progress $TESTPOOL $DISK1)"
+[[ "$progress" -le "$new_progress" ]] || \
+ log_fail "Lost trimming progress on promotion to top vdev"
+progress="$new_progress"
+
+log_must zpool add $TESTPOOL $DISK2
+log_must zpool remove $TESTPOOL $DISK1
+[[ -z "$(trim_prog_line $TESTPOOL $DISK1)" ]] || \
+ log_fail "Trimming continued after initiating removal"
+
+log_pass "Trimming worked as expected across attach/detach and add/remove"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_import_export.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_import_export.ksh
new file mode 100755
index 000000000000..a624d368c3c1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_import_export.ksh
@@ -0,0 +1,88 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# Trimming automatically resumes across import/export.
+#
+# STRATEGY:
+# 1. Create a one-disk pool.
+# 2. Start trimming and verify that trimming is active.
+# 3. Export the pool.
+# 4. Import the pool.
+# 5. Verify that trimming resumes and progress does not regress.
+# 6. Suspend trimming.
+# 7. Repeat steps 3-4.
+# 8. Verify that progress does not regress but trimming is still suspended.
+#
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+
+ if [[ -d "$TESTDIR" ]]; then
+ rm -rf "$TESTDIR"
+ fi
+}
+
+LARGEFILE="$TESTDIR/largefile"
+
+log_must mkdir "$TESTDIR"
+log_must truncate -s 10G "$LARGEFILE"
+log_must zpool create -f $TESTPOOL $LARGEFILE
+
+log_must zpool trim -r 256M $TESTPOOL
+sleep 2
+
+progress="$(trim_progress $TESTPOOL $LARGEFILE)"
+[[ -z "$progress" ]] && log_fail "Trimming did not start"
+
+log_must zpool export $TESTPOOL
+log_must zpool import -d $TESTDIR $TESTPOOL
+
+new_progress="$(trim_progress $TESTPOOL $LARGEFILE)"
+[[ -z "$new_progress" ]] && log_fail "Trimming did not restart after import"
+
+[[ "$progress" -le "$new_progress" ]] || \
+ log_fail "Trimming lost progress after import"
+log_mustnot eval "trim_prog_line $TESTPOOL $LARGEFILE | grep suspended"
+
+log_must zpool trim -s $TESTPOOL $LARGEFILE
+action_date="$(trim_prog_line $TESTPOOL $LARGEFILE | \
+ sed 's/.*ed at \(.*\)).*/\1/g')"
+log_must zpool export $TESTPOOL
+log_must zpool import -d $TESTDIR $TESTPOOL
+new_action_date=$(trim_prog_line $TESTPOOL $LARGEFILE | \
+ sed 's/.*ed at \(.*\)).*/\1/g')
+[[ "$action_date" != "$new_action_date" ]] && \
+ log_fail "Trimming action date did not persist across export/import"
+
+[[ "$new_progress" -le "$(trim_progress $TESTPOOL $LARGEFILE)" ]] || \
+ log_fail "Trimming lost progress after import"
+
+log_must eval "trim_prog_line $TESTPOOL $LARGEFILE | grep suspended"
+
+log_pass "Trimming retains state as expected across export/import"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_multiple.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_multiple.ksh
new file mode 100755
index 000000000000..e8236ff83134
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_multiple.ksh
@@ -0,0 +1,65 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# Trimming can be performed multiple times
+#
+# STRATEGY:
+# 1. Create a pool with a single disk.
+# 2. Trim the entire pool.
+# 3. Verify trimming is reset (status, offset, and action date).
+# 4. Repeat steps 2 and 3 with the existing pool.
+#
+
+DISK1=${DISKS%% *}
+
+log_must zpool create -f $TESTPOOL $DISK1
+
+typeset action_date="none"
+for n in {1..3}; do
+ log_must zpool trim -r 2G $TESTPOOL
+ log_mustnot eval "trim_prog_line $TESTPOOL $DISK1 | grep complete"
+
+ [[ "$(trim_progress $TESTPOOL $DISK1)" -lt "100" ]] ||
+ log_fail "Trimming progress wasn't reset"
+
+ new_action_date="$(trim_prog_line $TESTPOOL $DISK1 | \
+ sed 's/.*ed at \(.*\)).*/\1/g')"
+ [[ "$action_date" != "$new_action_date" ]] ||
+ log_fail "Trimming action date wasn't reset"
+ action_date=$new_action_date
+
+ while [[ "$(trim_progress $TESTPOOL $DISK1)" -lt "100" ]]; do
+ progress="$(trim_progress $TESTPOOL $DISK1)"
+ sleep 0.5
+ [[ "$progress" -le "$(trim_progress $TESTPOOL $DISK1)" ]] ||
+ log_fail "Trimming progress regressed"
+ done
+
+ log_must eval "trim_prog_line $TESTPOOL $DISK1 | grep complete"
+ sleep 1
+done
+
+log_pass "Trimming multiple times performs as expected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_neg.ksh
new file mode 100755
index 000000000000..4ab2eb1a71b4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_neg.ksh
@@ -0,0 +1,53 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# A badly formed parameter passed to 'zpool trim' should
+# return an error.
+#
+# STRATEGY:
+# 1. Create an array containing bad 'zpool trim' parameters.
+# 2. For each element, execute the sub-command.
+# 3. Verify it returns an error.
+#
+
+DISK1=${DISKS%% *}
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+
+verify_runnable "global"
+
+set -A args "1" "-a" "-?" "--%" "-123456" "0.5" "-o" "-b" "-b no" "-z 2"
+
+log_assert "Execute 'zpool trim' using invalid parameters."
+
+log_must zpool create -f $TESTPOOL mirror $DISK1 $DISK2
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zpool trim ${args[i]} $TESTPOOL
+ ((i = i + 1))
+done
+
+log_pass "Invalid parameters to 'zpool trim' fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_offline_export_import_online.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_offline_export_import_online.ksh
new file mode 100755
index 000000000000..4f904d11ddda
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_offline_export_import_online.ksh
@@ -0,0 +1,62 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# Miscellaneous complex sequences of operations function as expected.
+#
+# STRATEGY:
+# 1. Create a pool with a two-way mirror.
+# 2. Start trimming, offline, export, import, online and verify that
+# trimming state is preserved / trimming behaves as expected
+# at each step.
+#
+
+DISK1="$(echo $DISKS | cut -d' ' -f1)"
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+
+log_must zpool create -f $TESTPOOL mirror $DISK1 $DISK2
+
+log_must zpool trim -r 128M $TESTPOOL $DISK1
+log_must zpool offline $TESTPOOL $DISK1
+progress="$(trim_progress $TESTPOOL $DISK1)"
+[[ -z "$progress" ]] && log_fail "Trimming did not start"
+log_mustnot eval "trim_prog_line $TESTPOOL $DISK1 | grep suspended"
+
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+
+new_progress="$(trim_progress $TESTPOOL $DISK1)"
+[[ -z "$new_progress" ]] && log_fail "Trimming did not start after import"
+[[ "$new_progress" -ge "$progress" ]] || \
+ log_fail "Trimming lost progress after import"
+log_mustnot eval "trim_prog_line $TESTPOOL $DISK1 | grep suspended"
+
+log_must zpool online $TESTPOOL $DISK1
+new_progress="$(trim_progress $TESTPOOL $DISK1)"
+[[ "$new_progress" -ge "$progress" ]] || \
+ log_fail "Trimming lost progress after online"
+
+log_pass "Trimming behaves as expected at each step of:" \
+ "trim + offline + export + import + online"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_online_offline.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_online_offline.ksh
new file mode 100755
index 000000000000..681cd12f71c5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_online_offline.ksh
@@ -0,0 +1,70 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# Trimming automatically resumes across offline/online.
+#
+# STRATEGY:
+# 1. Create a pool with a two-way mirror.
+# 2. Start trimming one of the disks and verify that trimming is active.
+# 3. Offline the disk.
+# 4. Online the disk.
+# 5. Verify that trimming resumes and progress does not regress.
+# 6. Suspend trimming.
+# 7. Repeat steps 3-4 and verify that trimming does not resume.
+#
+
+DISK1=${DISKS%% *}
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+
+log_must zpool create -f $TESTPOOL mirror $DISK1 $DISK2
+log_must zpool trim -r 128M $TESTPOOL $DISK1
+
+log_must zpool offline $TESTPOOL $DISK1
+
+progress="$(trim_progress $TESTPOOL $DISK1)"
+[[ -z "$progress" ]] && log_fail "Trimming did not start"
+
+log_must zpool online $TESTPOOL $DISK1
+
+new_progress="$(trim_progress $TESTPOOL $DISK1)"
+[[ -z "$new_progress" ]] && \
+ log_fail "Trimming did not restart after onlining"
+[[ "$progress" -le "$new_progress" ]] || \
+ log_fail "Trimming lost progress after onlining"
+log_mustnot eval "trim_prog_line $TESTPOOL $DISK1 | grep suspended"
+
+log_must zpool trim -s $TESTPOOL $DISK1
+action_date="$(trim_prog_line $TESTPOOL $DISK1 | \
+ sed 's/.*ed at \(.*\)).*/\1/g')"
+log_must zpool offline $TESTPOOL $DISK1
+log_must zpool online $TESTPOOL $DISK1
+new_action_date=$(trim_prog_line $TESTPOOL $DISK1 | \
+ sed 's/.*ed at \(.*\)).*/\1/g')
+[[ "$action_date" != "$new_action_date" ]] && \
+ log_fail "Trimming action date did not persist across offline/online"
+log_must eval "trim_prog_line $TESTPOOL $DISK1 | grep suspended"
+
+log_pass "Trimming performs as expected across offline/online"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_partial.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_partial.ksh
new file mode 100755
index 000000000000..5d14b74ecc15
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_partial.ksh
@@ -0,0 +1,114 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# Verify 'zpool trim' partial trim.
+#
+# STRATEGY:
+# 1. Create a pool on a single disk and mostly fill it.
+# 2. Expand the pool to create new unallocated metaslabs.
+# 3. Run 'zpool trim' to only TRIM allocated space maps.
+# 4. Verify the disk is least 90% of its original size.
+# 5. Run 'zpool trim' to perform a full TRIM.
+# 6. Verify the disk is less than 10% of its original size.
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+
+ if [[ -d "$TESTDIR" ]]; then
+ rm -rf "$TESTDIR"
+ fi
+
+ log_must set_tunable64 TRIM_METASLAB_SKIP 0
+ log_must set_tunable64 TRIM_EXTENT_BYTES_MIN $trim_extent_bytes_min
+ log_must set_tunable64 VDEV_MIN_MS_COUNT $vdev_min_ms_count
+}
+log_onexit cleanup
+
+LARGESIZE=$((MINVDEVSIZE * 4))
+LARGEFILE="$TESTDIR/largefile"
+
+# The minimum number of metaslabs is increased in order to simulate the
+# behavior of partial trimming on a more typically sized 1TB disk.
+typeset vdev_min_ms_count=$(get_tunable VDEV_MIN_MS_COUNT)
+log_must set_tunable64 VDEV_MIN_MS_COUNT 64
+
+# Minimum trim size is decreased to verify all trim sizes.
+typeset trim_extent_bytes_min=$(get_tunable TRIM_EXTENT_BYTES_MIN)
+log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 4096
+
+log_must mkdir "$TESTDIR"
+log_must truncate -s $LARGESIZE "$LARGEFILE"
+log_must zpool create $TESTPOOL "$LARGEFILE"
+log_must mkfile $(( floor(LARGESIZE * 0.80) )) /$TESTPOOL/file
+log_must zpool sync
+
+new_size=$(du -B1 "$LARGEFILE" | cut -f1)
+log_must test $new_size -le $LARGESIZE
+log_must test $new_size -gt $(( floor(LARGESIZE * 0.70) ))
+
+# Expand the pool to create new unallocated metaslabs.
+log_must zpool export $TESTPOOL
+log_must dd if=/dev/urandom of=$LARGEFILE conv=notrunc,nocreat \
+ seek=$((LARGESIZE / (1024 * 1024))) bs=$((1024 * 1024)) \
+ count=$((3 * LARGESIZE / (1024 * 1024)))
+log_must zpool import -d $TESTDIR $TESTPOOL
+log_must zpool online -e $TESTPOOL "$LARGEFILE"
+
+new_size=$(du -B1 "$LARGEFILE" | cut -f1)
+log_must test $new_size -gt $((4 * floor(LARGESIZE * 0.70) ))
+
+# Perform a partial trim, we expect it to skip most of the new metaslabs
+# which have never been used and therefore do not need be trimmed.
+log_must set_tunable64 TRIM_METASLAB_SKIP 1
+log_must zpool trim $TESTPOOL
+log_must set_tunable64 TRIM_METASLAB_SKIP 0
+
+log_must zpool sync
+while [[ "$(trim_progress $TESTPOOL $LARGEFILE)" -lt "100" ]]; do
+ sleep 0.5
+done
+
+new_size=$(du -B1 "$LARGEFILE" | cut -f1)
+log_must test $new_size -gt $LARGESIZE
+
+# Perform a full trim, all metaslabs will be trimmed the pool vdev
+# size will be reduced but not down to its original size due to the
+# space usage of the new metaslabs.
+log_must zpool trim $TESTPOOL
+
+log_must zpool sync
+while [[ "$(trim_progress $TESTPOOL $LARGEFILE)" -lt "100" ]]; do
+ sleep 0.5
+done
+
+new_size=$(du -B1 "$LARGEFILE" | cut -f1)
+log_must test $new_size -le $(( 2 * LARGESIZE))
+log_must test $new_size -gt $(( floor(LARGESIZE * 0.70) ))
+
+log_pass "Manual 'zpool trim' successfully partially trimmed pool"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_rate.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_rate.ksh
new file mode 100755
index 000000000000..6b83a1eede8e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_rate.ksh
@@ -0,0 +1,90 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# Verify 'zpool trim -r <rate>' rate limiting.
+#
+# STRATEGY:
+# 1. Create a pool on a single disk.
+# 2. Manually TRIM the pool with rate limiting.
+# 3. Verify the TRIM can be suspended.
+# 4. Restart the TRIM and verify the rate is preserved.
+#
+# NOTE: The tolerances and delays used in the test below are intentionally
+# set be to fairly large since we are capping the maximum trim rate. The
+# actual trim rate can be lower. The critical thing is that the trim rate
+# is limited, the rate is preserved when resuming, and it can be changed.
+#
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+
+ if [[ -d "$TESTDIR" ]]; then
+ rm -rf "$TESTDIR"
+ fi
+}
+log_onexit cleanup
+
+LARGEFILE="$TESTDIR/largefile"
+
+log_must mkdir "$TESTDIR"
+log_must truncate -s 10G "$LARGEFILE"
+log_must zpool create -f $TESTPOOL "$LARGEFILE"
+
+# Start trimming at 200M/s for 5 seconds (approximately 10% of the pool)
+log_must zpool trim -r 200M $TESTPOOL
+log_must sleep 4
+progress=$(trim_progress $TESTPOOL $LARGEFILE)
+log_must zpool trim -s $TESTPOOL
+log_must eval "trim_prog_line $TESTPOOL $LARGEFILE | grep suspended"
+log_must within_tolerance 10 $progress 5
+
+# Resuming trimming at 200M/s for 5 seconds (approximately 20% of the pool)
+log_must zpool trim $TESTPOOL
+log_must sleep 4
+progress=$(trim_progress $TESTPOOL $LARGEFILE)
+log_must zpool trim -s $TESTPOOL
+log_must eval "trim_prog_line $TESTPOOL $LARGEFILE | grep suspended"
+log_must within_tolerance 20 $progress 10
+
+# Increase trimming to 600M/s for 5 seconds (approximately 50% of the pool)
+log_must zpool trim -r 600M $TESTPOOL
+log_must sleep 4
+progress=$(trim_progress $TESTPOOL $LARGEFILE)
+log_must zpool trim -s $TESTPOOL
+log_must eval "trim_prog_line $TESTPOOL $LARGEFILE | grep suspended"
+log_must within_tolerance 50 $progress 15
+
+# Set maximum trim rate for 5 seconds (100% of the pool)
+log_must zpool trim -r 1T $TESTPOOL
+log_must sleep 4
+progress=$(trim_progress $TESTPOOL $LARGEFILE)
+log_must eval "trim_prog_line $TESTPOOL $LARGEFILE | grep complete"
+log_must within_tolerance 100 $progress 0
+
+log_pass "Manual TRIM rate throttles as expected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_rate_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_rate_neg.ksh
new file mode 100755
index 000000000000..11bd43076279
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_rate_neg.ksh
@@ -0,0 +1,53 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# A badly formed parameter passed to 'zpool trim -r' should
+# return an error.
+#
+# STRATEGY:
+# 1. Create an array containing bad 'zpool trim -r' parameters.
+# 2. For each element, execute the sub-command.
+# 3. Verify it returns an error.
+#
+
+DISK1=${DISKS%% *}
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+
+verify_runnable "global"
+
+set -A args "a" "--%" "10X" "yes" "-?" "z 99"
+
+log_assert "Execute 'zpool trim -r' using invalid parameters."
+
+log_must zpool create -f $TESTPOOL mirror $DISK1 $DISK2
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zpool trim -r ${args[i]} $TESTPOOL
+ ((i = i + 1))
+done
+
+log_pass "Invalid parameters to 'zpool trim -r' fail as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_secure.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_secure.ksh
new file mode 100755
index 000000000000..e97d09f515bc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_secure.ksh
@@ -0,0 +1,59 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# Verify 'zpool trim -d' secure trim.
+#
+# STRATEGY:
+# 1. Create a pool on a single file vdev.
+# 2. Run 'zpool trim -d' to securely TRIM allocated space maps.
+# 3. Verify it fails when using a file vdev.
+#
+# NOTE: Currently secure discard cannot be verified using file vdevs,
+# loopback, or scsi_debug devices. None of which support the feature.
+# It can only be tested using real SSDs which provide support.
+#
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+
+ if [[ -d "$TESTDIR" ]]; then
+ rm -rf "$TESTDIR"
+ fi
+}
+log_onexit cleanup
+
+LARGESIZE=$((MINVDEVSIZE * 4))
+LARGEFILE="$TESTDIR/largefile"
+
+log_must mkdir "$TESTDIR"
+log_must truncate -s $LARGESIZE "$LARGEFILE"
+log_must zpool create $TESTPOOL "$LARGEFILE"
+log_mustnot zpool trim -d $TESTPOOL
+
+log_pass "Manual 'zpool trim -d' failed as expected for file vdevs"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_split.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_split.ksh
new file mode 100755
index 000000000000..450dc6fd80f4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_split.ksh
@@ -0,0 +1,60 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# Trimming state is preserved across zpool split.
+#
+# STRATEGY:
+# 1. Create a pool with a two-way mirror.
+# 2. Start trimming both devices.
+# 3. Split the pool. Ensure trimming continues on the original.
+# 4. Import the new pool. Ensure trimming resumes on it.
+#
+
+DISK1="$(echo $DISKS | cut -d' ' -f1)"
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+POOL2="${TESTPOOL}_split"
+
+log_must zpool create -f $TESTPOOL mirror $DISK1 $DISK2
+
+log_must zpool trim $TESTPOOL $DISK1 $DISK2
+orig_prog1="$(trim_progress $TESTPOOL $DISK1)"
+orig_prog2="$(trim_progress $TESTPOOL $DISK2)"
+[[ -z "$orig_prog1" ]] && log_fail "Trimming did not start"
+
+log_must zpool split $TESTPOOL $TESTPOOL1 $DISK2
+
+# Ensure trimming continued as expected on the original pool.
+[[ "$(trim_progress $TESTPOOL $DISK1)" -ge "$orig_prog1" ]] || \
+ log_fail "Trimming lost progress on original pool"
+log_mustnot eval "trim_prog_line $TESTPOOL $DISK1 | grep suspended"
+
+log_must zpool import $TESTPOOL1
+
+[[ "$(trim_progress $TESTPOOL1 $DISK2)" -ge "$orig_prog2" ]] || \
+ log_fail "Trimming lost progress on split pool"
+log_mustnot eval "trim_prog_line $TESTPOOL1 $DISK1 | grep suspended"
+
+log_pass "Trimming behaves as expected on zpool split"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_start_and_cancel_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_start_and_cancel_neg.ksh
new file mode 100755
index 000000000000..faf134fbbd8d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_start_and_cancel_neg.ksh
@@ -0,0 +1,56 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# Cancelling and suspending trim doesn't work if not all specified vdevs
+# are being trimmed.
+#
+# STRATEGY:
+# 1. Create a three-disk pool.
+# 2. Start trimming and verify that trimming is active.
+# 3. Try to cancel and suspend trimming on the non-trimming disks.
+# 4. Try to re-trim the currently trimming disk.
+#
+
+DISK1=${DISKS%% *}
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+DISK3="$(echo $DISKS | cut -d' ' -f3)"
+
+log_must zpool list -v
+log_must zpool create -f $TESTPOOL $DISK1 $DISK2 $DISK3
+log_must zpool trim -r 128M $TESTPOOL $DISK1
+
+[[ -z "$(trim_progress $TESTPOOL $DISK1)" ]] && \
+ log_fail "Trim did not start"
+
+log_mustnot zpool trim -c $TESTPOOL $DISK2
+log_mustnot zpool trim -c $TESTPOOL $DISK2 $DISK3
+
+log_mustnot zpool trim -s $TESTPOOL $DISK2
+log_mustnot zpool trim -s $TESTPOOL $DISK2 $DISK3
+
+log_mustnot zpool trim $TESTPOOL $DISK1
+
+log_pass "Nonsensical trim operations fail"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_start_and_cancel_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_start_and_cancel_pos.ksh
new file mode 100755
index 000000000000..eaa4d90444b6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_start_and_cancel_pos.ksh
@@ -0,0 +1,48 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+
+#
+# DESCRIPTION:
+# Starting and stopping an initialize works.
+#
+# STRATEGY:
+# 1. Create a one-disk pool.
+# 2. Start initializing and verify that initializing is active.
+# 3. Cancel initializing and verify that initializing is not active.
+#
+
+DISK1=${DISKS%% *}
+
+log_must zpool create -f $TESTPOOL $DISK1
+log_must zpool initialize $TESTPOOL
+
+[[ -z "$(initialize_progress $TESTPOOL $DISK1)" ]] && \
+ log_fail "Initialize did not start"
+
+log_must zpool initialize -c $TESTPOOL
+
+[[ -z "$(initialize_progress $TESTPOOL $DISK1)" ]] || \
+ log_fail "Initialize did not stop"
+
+log_pass "Initialize start + cancel works"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_suspend_resume.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_suspend_resume.ksh
new file mode 100755
index 000000000000..553d911e124c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_suspend_resume.ksh
@@ -0,0 +1,74 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# Suspending and resuming trimming works.
+#
+# STRATEGY:
+# 1. Create a one-disk pool.
+# 2. Start trimming and verify that trimming is active.
+# 3. Wait 3 seconds, then suspend trimming and verify that the progress
+# reporting says so.
+# 4. Wait 3 seconds and ensure trimming progress doesn't advance.
+# 5. Restart trimming and verify that the progress doesn't regress.
+#
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+
+ if [[ -d "$TESTDIR" ]]; then
+ rm -rf "$TESTDIR"
+ fi
+}
+
+LARGEFILE="$TESTDIR/largefile"
+
+log_must mkdir "$TESTDIR"
+log_must truncate -s 10G "$LARGEFILE"
+log_must zpool create -f $TESTPOOL $LARGEFILE
+
+log_must zpool trim -r 256M $TESTPOOL
+sleep 2
+
+[[ -z "$(trim_progress $TESTPOOL $LARGEFILE)" ]] && \
+ log_fail "Trimming did not start"
+
+sleep 3
+log_must zpool trim -s $TESTPOOL
+log_must eval "trim_prog_line $TESTPOOL $LARGEFILE | grep suspended"
+progress="$(trim_progress $TESTPOOL $LARGEFILE)"
+
+sleep 3
+[[ "$progress" -eq "$(trim_progress $TESTPOOL $LARGEFILE)" ]] || \
+ log_fail "Trimming progress advanced while suspended"
+
+log_must zpool trim $TESTPOOL $LARGEFILE
+[[ "$progress" -le "$(trim_progress $TESTPOOL $LARGEFILE)" ]] ||
+ log_fail "Trimming progress regressed after resuming"
+
+log_pass "Suspend + resume trimming works as expected"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_unsupported_vdevs.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_unsupported_vdevs.ksh
new file mode 100755
index 000000000000..988745e30e97
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_unsupported_vdevs.ksh
@@ -0,0 +1,70 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# Attempting to trim unsupported vdevs should fail.
+#
+# STRATEGY:
+# 1. Create a pool with the following configuration:
+# root
+# mirror
+# vdev0
+# vdev1 (offline)
+# cache
+# vdev2
+# spare
+# vdev3
+# 2. Try to trim vdev1, vdev2, and vdev3. Ensure that all 3 fail.
+#
+function cleanup
+{
+ if datasetexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+ if [[ -d $TESTDIR ]]; then
+ log_must rm -rf $TESTDIR
+ fi
+}
+log_onexit cleanup
+
+log_must mkdir $TESTDIR
+set -A FDISKS
+for n in {0..2}; do
+ log_must mkfile $MINVDEVSIZE $TESTDIR/vdev$n
+ FDISKS+=("$TESTDIR/vdev$n")
+done
+FDISKS+=("${DISKS%% *}")
+
+log_must zpool create $TESTPOOL mirror ${FDISKS[0]} ${FDISKS[1]} \
+ spare ${FDISKS[2]} cache ${FDISKS[3]}
+
+log_must zpool offline $TESTPOOL ${FDISKS[1]}
+
+log_mustnot zpool trim $TESTPOOL mirror-0
+for n in {1..3}; do
+ log_mustnot zpool trim $TESTPOOL ${FDISKS[$n]}
+done
+
+log_pass "Attempting to trim failed on unsupported devices"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_checksums.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_checksums.ksh
new file mode 100755
index 000000000000..093dc3fb9e76
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_checksums.ksh
@@ -0,0 +1,69 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# Trimming does not cause file corruption.
+#
+# STRATEGY:
+# 1. Create a one-disk pool.
+# 2. Write data to the pool.
+# 3. Start trimming and verify that trimming is active.
+# 4. Write more data to the pool.
+# 5. Export the pool and use zdb to validate checksums.
+#
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+
+ if [[ -d "$TESTDIR" ]]; then
+ rm -rf "$TESTDIR"
+ fi
+}
+log_onexit cleanup
+
+LARGESIZE=$((MINVDEVSIZE * 4))
+LARGEFILE="$TESTDIR/largefile"
+
+log_must mkdir "$TESTDIR"
+log_must truncate -s $LARGESIZE "$LARGEFILE"
+log_must zpool create $TESTPOOL "$LARGEFILE"
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/file1 bs=1048576 count=64
+log_must zpool sync
+log_must zpool trim $TESTPOOL
+
+[[ -z "$(trim_progress $TESTPOOL $DISK1)" ]] && \
+ log_fail "Trimming did not start"
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/file2 bs=1048576 count=64
+log_must zpool sync
+
+log_must zpool export $TESTPOOL
+log_must zdb -e -p "$TESTDIR" -cc $TESTPOOL
+
+log_pass "Trimming does not corrupt existing or new data"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_trimmed.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_trimmed.ksh
new file mode 100755
index 000000000000..d5aaf49aebc5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_trimmed.ksh
@@ -0,0 +1,81 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# After trimming, the disk is actually trimmed.
+#
+# STRATEGY:
+# 1. Create a one-disk pool using a sparse file.
+# 2. Initialize the pool and verify the file vdev is no longer sparse.
+# 3. Trim the pool and verify the file vdev is again sparse.
+#
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+
+ if [[ -d "$TESTDIR" ]]; then
+ rm -rf "$TESTDIR"
+ fi
+
+ log_must set_tunable64 TRIM_EXTENT_BYTES_MIN $trim_extent_bytes_min
+}
+log_onexit cleanup
+
+LARGESIZE=$((MINVDEVSIZE * 4))
+LARGEFILE="$TESTDIR/largefile"
+
+# Reduce trim size to allow for tighter tolerance below when checking.
+typeset trim_extent_bytes_min=$(get_tunable TRIM_EXTENT_BYTES_MIN)
+log_must set_tunable64 TRIM_EXTENT_BYTES_MIN 4096
+
+log_must mkdir "$TESTDIR"
+log_must truncate -s $LARGESIZE "$LARGEFILE"
+log_must zpool create $TESTPOOL "$LARGEFILE"
+
+original_size=$(du -B1 "$LARGEFILE" | cut -f1)
+
+log_must zpool initialize $TESTPOOL
+
+while [[ "$(initialize_progress $TESTPOOL $LARGEFILE)" -lt "100" ]]; do
+ sleep 0.5
+done
+
+new_size=$(du -B1 "$LARGEFILE" | cut -f1)
+log_must within_tolerance $new_size $LARGESIZE $((128 * 1024 * 1024))
+
+log_must zpool trim $TESTPOOL
+
+while [[ "$(trim_progress $TESTPOOL $LARGEFILE)" -lt "100" ]]; do
+ sleep 0.5
+done
+
+new_size=$(du -B1 "$LARGEFILE" | cut -f1)
+log_must within_tolerance $new_size $original_size $((128 * 1024 * 1024))
+
+log_pass "Trimmed appropriate amount of disk space"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/Makefile.am
new file mode 100644
index 000000000000..18311ed2ca25
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/Makefile.am
@@ -0,0 +1,19 @@
+SUBDIRS = blockfiles
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_upgrade
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_upgrade_001_pos.ksh \
+ zpool_upgrade_002_pos.ksh \
+ zpool_upgrade_003_pos.ksh \
+ zpool_upgrade_004_pos.ksh \
+ zpool_upgrade_005_neg.ksh \
+ zpool_upgrade_006_neg.ksh \
+ zpool_upgrade_007_pos.ksh \
+ zpool_upgrade_008_pos.ksh \
+ zpool_upgrade_009_neg.ksh
+
+dist_pkgdata_DATA = \
+ zpool_upgrade.cfg \
+ zpool_upgrade.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/Makefile.am
new file mode 100644
index 000000000000..ce8da278e9f0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/Makefile.am
@@ -0,0 +1,54 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles
+dist_pkgdata_DATA = \
+ zfs-broken-mirror1.dat.bz2 \
+ zfs-broken-mirror2.dat.bz2 \
+ zfs-pool-v1.dat.bz2 \
+ zfs-pool-v10.dat.bz2 \
+ zfs-pool-v11.dat.bz2 \
+ zfs-pool-v12.dat.bz2 \
+ zfs-pool-v13.dat.bz2 \
+ zfs-pool-v14.dat.bz2 \
+ zfs-pool-v15.dat.bz2 \
+ zfs-pool-v1mirror1.dat.bz2 \
+ zfs-pool-v1mirror2.dat.bz2 \
+ zfs-pool-v1mirror3.dat.bz2 \
+ zfs-pool-v1raidz1.dat.bz2 \
+ zfs-pool-v1raidz2.dat.bz2 \
+ zfs-pool-v1raidz3.dat.bz2 \
+ zfs-pool-v1stripe1.dat.bz2 \
+ zfs-pool-v1stripe2.dat.bz2 \
+ zfs-pool-v1stripe3.dat.bz2 \
+ zfs-pool-v2.dat.bz2 \
+ zfs-pool-v2mirror1.dat.bz2 \
+ zfs-pool-v2mirror2.dat.bz2 \
+ zfs-pool-v2mirror3.dat.bz2 \
+ zfs-pool-v2raidz1.dat.bz2 \
+ zfs-pool-v2raidz2.dat.bz2 \
+ zfs-pool-v2raidz3.dat.bz2 \
+ zfs-pool-v2stripe1.dat.bz2 \
+ zfs-pool-v2stripe2.dat.bz2 \
+ zfs-pool-v2stripe3.dat.bz2 \
+ zfs-pool-v3.dat.bz2 \
+ zfs-pool-v3hotspare1.dat.bz2 \
+ zfs-pool-v3hotspare2.dat.bz2 \
+ zfs-pool-v3hotspare3.dat.bz2 \
+ zfs-pool-v3mirror1.dat.bz2 \
+ zfs-pool-v3mirror2.dat.bz2 \
+ zfs-pool-v3mirror3.dat.bz2 \
+ zfs-pool-v3raidz1.dat.bz2 \
+ zfs-pool-v3raidz2.dat.bz2 \
+ zfs-pool-v3raidz21.dat.bz2 \
+ zfs-pool-v3raidz22.dat.bz2 \
+ zfs-pool-v3raidz23.dat.bz2 \
+ zfs-pool-v3raidz3.dat.bz2 \
+ zfs-pool-v3stripe1.dat.bz2 \
+ zfs-pool-v3stripe2.dat.bz2 \
+ zfs-pool-v3stripe3.dat.bz2 \
+ zfs-pool-v4.dat.bz2 \
+ zfs-pool-v5.dat.bz2 \
+ zfs-pool-v6.dat.bz2 \
+ zfs-pool-v7.dat.bz2 \
+ zfs-pool-v8.dat.bz2 \
+ zfs-pool-v9.dat.bz2 \
+ zfs-pool-v999.dat.bz2 \
+ zfs-pool-vBROKEN.dat.bz2
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-broken-mirror1.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-broken-mirror1.dat.bz2
new file mode 100644
index 000000000000..7ec82b755b4c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-broken-mirror1.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-broken-mirror2.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-broken-mirror2.dat.bz2
new file mode 100644
index 000000000000..00ef2bc36ff3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-broken-mirror2.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1.dat.bz2
new file mode 100644
index 000000000000..9c8a157eebd6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v10.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v10.dat.bz2
new file mode 100644
index 000000000000..5caf41c42009
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v10.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v11.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v11.dat.bz2
new file mode 100644
index 000000000000..4af228e73f11
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v11.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v12.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v12.dat.bz2
new file mode 100644
index 000000000000..a116e9db6b52
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v12.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v13.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v13.dat.bz2
new file mode 100644
index 000000000000..3fab2262b7df
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v13.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v14.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v14.dat.bz2
new file mode 100644
index 000000000000..e8443c375c51
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v14.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v15.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v15.dat.bz2
new file mode 100644
index 000000000000..0887ae814a12
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v15.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1mirror1.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1mirror1.dat.bz2
new file mode 100644
index 000000000000..ed42283eb1db
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1mirror1.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1mirror2.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1mirror2.dat.bz2
new file mode 100644
index 000000000000..4e72f1acfba6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1mirror2.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1mirror3.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1mirror3.dat.bz2
new file mode 100644
index 000000000000..006c96df7073
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1mirror3.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1raidz1.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1raidz1.dat.bz2
new file mode 100644
index 000000000000..3c3531c70fc0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1raidz1.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1raidz2.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1raidz2.dat.bz2
new file mode 100644
index 000000000000..99a0768b01ec
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1raidz2.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1raidz3.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1raidz3.dat.bz2
new file mode 100644
index 000000000000..0fd057ecbaa9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1raidz3.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1stripe1.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1stripe1.dat.bz2
new file mode 100644
index 000000000000..41f63f668d2f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1stripe1.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1stripe2.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1stripe2.dat.bz2
new file mode 100644
index 000000000000..cc9eab160bed
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1stripe2.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1stripe3.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1stripe3.dat.bz2
new file mode 100644
index 000000000000..866bd96c93e1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1stripe3.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2.dat.bz2
new file mode 100644
index 000000000000..184e3c3788aa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2mirror1.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2mirror1.dat.bz2
new file mode 100644
index 000000000000..7466e7e25feb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2mirror1.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2mirror2.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2mirror2.dat.bz2
new file mode 100644
index 000000000000..de66b539b8e4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2mirror2.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2mirror3.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2mirror3.dat.bz2
new file mode 100644
index 000000000000..4c3504b84925
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2mirror3.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2raidz1.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2raidz1.dat.bz2
new file mode 100644
index 000000000000..e008ae099c4e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2raidz1.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2raidz2.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2raidz2.dat.bz2
new file mode 100644
index 000000000000..bf7f6b119976
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2raidz2.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2raidz3.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2raidz3.dat.bz2
new file mode 100644
index 000000000000..f7b7012690c5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2raidz3.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2stripe1.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2stripe1.dat.bz2
new file mode 100644
index 000000000000..16a7bb89d58e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2stripe1.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2stripe2.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2stripe2.dat.bz2
new file mode 100644
index 000000000000..8f7287ee7639
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2stripe2.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2stripe3.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2stripe3.dat.bz2
new file mode 100644
index 000000000000..9fccd05c506f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v2stripe3.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3.dat.bz2
new file mode 100644
index 000000000000..fc122d8b8f32
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3hotspare1.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3hotspare1.dat.bz2
new file mode 100644
index 000000000000..d5c7e3c8b776
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3hotspare1.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3hotspare2.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3hotspare2.dat.bz2
new file mode 100644
index 000000000000..47b4d6a2e98b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3hotspare2.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3hotspare3.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3hotspare3.dat.bz2
new file mode 100644
index 000000000000..cb253c308a18
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3hotspare3.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3mirror1.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3mirror1.dat.bz2
new file mode 100644
index 000000000000..e8ab50c45b65
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3mirror1.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3mirror2.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3mirror2.dat.bz2
new file mode 100644
index 000000000000..769e0f81abd6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3mirror2.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3mirror3.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3mirror3.dat.bz2
new file mode 100644
index 000000000000..e7e5a8958755
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3mirror3.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz1.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz1.dat.bz2
new file mode 100644
index 000000000000..6d43f74ba3c8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz1.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz2.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz2.dat.bz2
new file mode 100644
index 000000000000..6ab1059d0b91
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz2.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz21.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz21.dat.bz2
new file mode 100644
index 000000000000..dcc537f15d4e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz21.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz22.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz22.dat.bz2
new file mode 100644
index 000000000000..3cd92b173041
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz22.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz23.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz23.dat.bz2
new file mode 100644
index 000000000000..e3c5f41f9a03
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz23.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz3.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz3.dat.bz2
new file mode 100644
index 000000000000..2109fda7196a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3raidz3.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3stripe1.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3stripe1.dat.bz2
new file mode 100644
index 000000000000..4e6afe22b5c5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3stripe1.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3stripe2.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3stripe2.dat.bz2
new file mode 100644
index 000000000000..6e755dd83b75
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3stripe2.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3stripe3.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3stripe3.dat.bz2
new file mode 100644
index 000000000000..9cf396a3c558
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v3stripe3.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v4.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v4.dat.bz2
new file mode 100644
index 000000000000..b1c00e16892a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v4.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v5.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v5.dat.bz2
new file mode 100644
index 000000000000..9c6cb0c73648
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v5.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v6.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v6.dat.bz2
new file mode 100644
index 000000000000..1eb1fea9d442
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v6.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v7.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v7.dat.bz2
new file mode 100644
index 000000000000..04c6cac75c9a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v7.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v8.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v8.dat.bz2
new file mode 100644
index 000000000000..8f1e66303b5d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v8.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v9.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v9.dat.bz2
new file mode 100644
index 000000000000..94528d373b7b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v9.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v999.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v999.dat.bz2
new file mode 100644
index 000000000000..7ca57a24977a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v999.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-vBROKEN.dat.bz2 b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-vBROKEN.dat.bz2
new file mode 100644
index 000000000000..6595f4a5d28a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-vBROKEN.dat.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/cleanup.ksh
new file mode 100755
index 000000000000..1fab5305adc0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/cleanup.ksh
@@ -0,0 +1,39 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
+
+for config in $CONFIGS; do
+ destroy_upgraded_pool $config
+done
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/setup.ksh
new file mode 100755
index 000000000000..860ba0f061a6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/setup.ksh
@@ -0,0 +1,38 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+# give us a pool to play in
+default_setup "$DISKS"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.cfg
new file mode 100644
index 000000000000..993fafc0324d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.cfg
@@ -0,0 +1,161 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+# The following variable names describe files, stored as gzip compressed files
+# in the test directory which can be used to construct a pool of a given
+# version. The variable names are important, in that the construction
+# ZPOOL_VERSION_$var_FILES describes the files the pool is made from, and
+# ZPOOL_VERSION_$var_NAME describes the pool name.
+
+# v1 pools
+ZPOOL_VERSION_1_FILES="zfs-pool-v1.dat"
+ZPOOL_VERSION_1_NAME="v1-pool"
+# v1 stripe
+ZPOOL_VERSION_1stripe_FILES="zfs-pool-v1stripe1.dat \
+zfs-pool-v1stripe2.dat zfs-pool-v1stripe3.dat"
+ZPOOL_VERSION_1stripe_NAME="pool-v1stripe"
+# v1 raidz
+ZPOOL_VERSION_1raidz_FILES="zfs-pool-v1raidz1.dat zfs-pool-v1raidz2.dat \
+zfs-pool-v1raidz3.dat"
+ZPOOL_VERSION_1raidz_NAME="pool-v1raidz"
+# v1 mirror
+ZPOOL_VERSION_1mirror_FILES="zfs-pool-v1mirror1.dat zfs-pool-v1mirror2.dat \
+zfs-pool-v1mirror3.dat"
+ZPOOL_VERSION_1mirror_NAME="pool-v1mirror"
+
+# v2 pools
+ZPOOL_VERSION_2_FILES="zfs-pool-v2.dat"
+ZPOOL_VERSION_2_NAME="v2-pool"
+# v2 stripe
+ZPOOL_VERSION_2stripe_FILES="zfs-pool-v2stripe1.dat zfs-pool-v2stripe2.dat \
+zfs-pool-v2stripe3.dat"
+ZPOOL_VERSION_2stripe_NAME="pool-v2stripe"
+# v2 raidz
+ZPOOL_VERSION_2raidz_FILES="zfs-pool-v2raidz1.dat zfs-pool-v2raidz2.dat \
+zfs-pool-v2raidz3.dat"
+ZPOOL_VERSION_2raidz_NAME="pool-v2raidz"
+# v2 mirror
+ZPOOL_VERSION_2mirror_FILES="zfs-pool-v2mirror1.dat zfs-pool-v2mirror2.dat \
+zfs-pool-v2mirror3.dat"
+ZPOOL_VERSION_2mirror_NAME="pool-v2mirror"
+
+# v3 pools
+ZPOOL_VERSION_3_FILES="zfs-pool-v3.dat"
+ZPOOL_VERSION_3_NAME="v3-pool"
+# v3 stripe
+ZPOOL_VERSION_3stripe_FILES="zfs-pool-v3stripe1.dat zfs-pool-v3stripe2.dat \
+zfs-pool-v3stripe3.dat"
+ZPOOL_VERSION_3stripe_NAME="pool-v3stripe"
+# v3 raidz
+ZPOOL_VERSION_3raidz_FILES="zfs-pool-v3raidz1.dat zfs-pool-v3raidz2.dat \
+zfs-pool-v3raidz3.dat"
+ZPOOL_VERSION_3raidz_NAME="pool-v3raidz"
+# v3 mirror
+ZPOOL_VERSION_3mirror_FILES="zfs-pool-v3mirror1.dat zfs-pool-v3mirror2.dat \
+zfs-pool-v3mirror3.dat"
+ZPOOL_VERSION_3mirror_NAME="pool-v3mirror"
+# v3 raidz2
+ZPOOL_VERSION_3dblraidz_FILES="zfs-pool-v3raidz21.dat zfs-pool-v3raidz22.dat \
+zfs-pool-v3raidz23.dat"
+ZPOOL_VERSION_3dblraidz_NAME="pool-v3raidz2"
+# v3 hotspares
+ZPOOL_VERSION_3hotspare_FILES="zfs-pool-v3hotspare1.dat \
+zfs-pool-v3hotspare2.dat zfs-pool-v3hotspare3.dat"
+ZPOOL_VERSION_3hotspare_NAME="pool-v3hotspare"
+
+# v4 pool
+ZPOOL_VERSION_4_FILES="zfs-pool-v4.dat"
+ZPOOL_VERSION_4_NAME="v4-pool"
+
+# v5 pool
+ZPOOL_VERSION_5_FILES="zfs-pool-v5.dat"
+ZPOOL_VERSION_5_NAME="v5-pool"
+
+# v6 pool
+ZPOOL_VERSION_6_FILES="zfs-pool-v6.dat"
+ZPOOL_VERSION_6_NAME="v6-pool"
+
+# v7 pool
+ZPOOL_VERSION_7_FILES="zfs-pool-v7.dat"
+ZPOOL_VERSION_7_NAME="v7-pool"
+
+# v8 pool
+ZPOOL_VERSION_8_FILES="zfs-pool-v8.dat"
+ZPOOL_VERSION_8_NAME="v8-pool"
+
+# v9 pool
+ZPOOL_VERSION_9_FILES="zfs-pool-v9.dat"
+ZPOOL_VERSION_9_NAME="v9-pool"
+
+# v10 pool
+ZPOOL_VERSION_10_FILES="zfs-pool-v10.dat"
+ZPOOL_VERSION_10_NAME="v10-pool"
+
+# v11 pool
+ZPOOL_VERSION_11_FILES="zfs-pool-v11.dat"
+ZPOOL_VERSION_11_NAME="v11-pool"
+
+# v12 pool
+ZPOOL_VERSION_12_FILES="zfs-pool-v12.dat"
+ZPOOL_VERSION_12_NAME="v12-pool"
+
+# v13 pool
+ZPOOL_VERSION_13_FILES="zfs-pool-v13.dat"
+ZPOOL_VERSION_13_NAME="v13-pool"
+
+# v14 pool
+ZPOOL_VERSION_14_FILES="zfs-pool-v14.dat"
+ZPOOL_VERSION_14_NAME="v14-pool"
+
+# v15 pool
+ZPOOL_VERSION_15_FILES="zfs-pool-v15.dat"
+ZPOOL_VERSION_15_NAME="v15-pool"
+
+# v2 pool, with device problems on one side of the mirror
+# so that the pool appears as DEGRADED
+ZPOOL_VERSION_2brokenmirror_FILES="zfs-broken-mirror1.dat \
+zfs-broken-mirror2.dat"
+ZPOOL_VERSION_2brokenmirror_NAME="zfs-broken-mirror"
+
+# v999 pool (an unknown version) which can be used to check whether upgrade,
+# import or other tests that should fail against unknown pool version.
+# It should not be listed in the CONFIGS variable below, as these are pool
+# versions that can be imported and upgraded.
+ZPOOL_VERSION_9999_FILES="zfs-pool-v999.dat"
+ZPOOL_VERSION_9999_NAME="v999-pool"
+
+# This is a list of pool configurations we should be able to upgrade from,
+# each entry should have corresponding ZPOOL_VERSION_*_FILES and
+# ZPOOL_VERSION_*_NAME variables defined above.
+CONFIGS="1 1stripe 1raidz 1mirror \
+2 2stripe 2raidz 2mirror 2brokenmirror \
+3 3stripe 3raidz 3mirror 3dblraidz 3hotspare \
+4 5 6 7 8 9 10 11 12 13 14 15"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
new file mode 100644
index 000000000000..783ae54e717b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
@@ -0,0 +1,140 @@
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2017 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.cfg
+
+# This part of the test suite relies on variables being setup in the
+# zpool_upgrade.cfg script. Those variables give us details about which
+# files make up the pool, and what the pool name is.
+
+
+# A function to import a pool from files we have stored in the test suite
+# We import the pool, and create some random data in the pool.
+# $1 a version number we can use to get information about the pool
+function create_old_pool
+{
+ typeset vers=$1
+ typeset -n pool_files=ZPOOL_VERSION_${vers}_FILES
+ typeset -n pool_name=ZPOOL_VERSION_${vers}_NAME
+
+ log_note "Creating $pool_name from $pool_files"
+ for pool_file in $pool_files; do
+ log_must bzcat \
+ $STF_SUITE/tests/functional/cli_root/zpool_upgrade/blockfiles/$pool_file.bz2 \
+ >$TEST_BASE_DIR/$pool_file
+ done
+ log_must zpool import -d $TEST_BASE_DIR $pool_name
+
+ # Put some random contents into the pool
+ for i in {1..1024} ; do
+ dd if=/dev/urandom of=/$pool_name/random.$i \
+ count=1 bs=1024 > /dev/null 2>&1
+ done
+}
+
+
+# A function to check the contents of a pool, upgrade it to the current version
+# and then verify that the data is consistent after upgrading. Note that we're
+# not using "zpool status -x" to see if the pool is healthy, as it's possible
+# to also upgrade faulted, or degraded pools.
+# $1 a version number we can use to get information about the pool
+function check_upgrade
+{
+ typeset vers=$1
+ typeset -n pool_files=ZPOOL_VERSION_${vers}_FILES
+ typeset -n pool_name=ZPOOL_VERSION_${vers}_NAME
+ typeset pre_upgrade_checksum
+ typeset post_upgrade_checksum
+
+ log_note "Checking if we can upgrade from ZFS version $vers"
+ pre_upgrade_checksum=$(check_pool $pool_name pre)
+ log_must zpool upgrade $pool_name
+ post_upgrade_checksum=$(check_pool $pool_name post)
+
+ log_note "Checking that there are no differences between checksum output"
+ log_must diff $pre_upgrade_checksum $post_upgrade_checksum
+ rm $pre_upgrade_checksum $post_upgrade_checksum
+}
+
+# A function to destroy an upgraded pool, plus the files it was based on.
+# $1 a version number we can use to get information about the pool
+function destroy_upgraded_pool
+{
+ typeset vers=$1
+ typeset -n pool_files=ZPOOL_VERSION_${vers}_FILES
+ typeset -n pool_name=ZPOOL_VERSION_${vers}_NAME
+
+ destroy_pool $pool_name
+
+ for file in $pool_files; do
+ rm -f $TEST_BASE_DIR/$file
+ done
+}
+
+# This function does a basic sanity check on the pool by computing the
+# checksums of all files in the pool, echoing the name of the file containing
+# the checksum results.
+# $1 the name of the pool
+# $2 a flag we can use to determine when this check is being performed
+# (ie. pre or post pool-upgrade)
+function check_pool
+{
+ typeset pool=$1
+ typeset flag=$2
+ find /$pool -type f -exec cksum {} + > \
+ $TEST_BASE_DIR/pool-checksums.$pool.$flag
+ echo $TEST_BASE_DIR/pool-checksums.$pool.$flag
+}
+
+# This function simply checks that a pool has a particular version number
+# as reported by zdb and zpool upgrade -v
+# $1 the name of the pool
+# $2 the version of the pool we expect to see
+function check_poolversion
+{
+ typeset pool=$1
+ typeset vers=$2
+ typeset actual
+
+ # check version using zdb
+ actual=$(zdb -C $pool | sed -n 's/^.*version: \(.*\)$/\1/p')
+ if [[ $actual != $vers ]] ; then
+ log_fail "$pool: zdb reported version $actual, expected $vers"
+ fi
+
+ # check version using zpool upgrade
+ actual=$(zpool upgrade | grep $pool$ | \
+ awk '{print $1}' | sed -e 's/ //g')
+ if [[ $actual != $vers ]] ; then
+ log_fail "$pool: zpool reported version $actual, expected $vers"
+ fi
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_001_pos.ksh
new file mode 100755
index 000000000000..b49c19c5551c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_001_pos.ksh
@@ -0,0 +1,78 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# Executing 'zpool upgrade -v' command succeeds, prints a description of legacy
+# versions, and mentions feature flags.
+#
+# STRATEGY:
+# 1. Execute the command
+# 2. Verify a 0 exit status
+# 3. Grep for version descriptions and 'feature flags'
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ rm -f $versions
+}
+
+log_assert "Executing 'zpool upgrade -v' command succeeds"
+log_onexit cleanup
+
+typeset versions=$TEST_BASE_DIR/zpool-versions.$$
+
+log_must zpool upgrade -v
+
+# We also check that the usage message contains a description of legacy
+# versions and a note about feature flags.
+
+log_must eval "zpool upgrade -v | head -1 | grep 'feature flags'"
+
+zpool upgrade -v > $versions
+
+#
+# Current output for 'zpool upgrade -v' has different indent space
+# for single and double digit version number. For example,
+# 9 refquota and refreservation properties
+# 10 Cache devices
+#
+for version in {1..28}; do
+ log_note "Checking for a description of pool version $version"
+ log_must eval "awk '/^ $version / { print $1 }' $versions | grep $version"
+done
+
+log_pass "Executing 'zpool upgrade -v' command succeeds"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_002_pos.ksh
new file mode 100755
index 000000000000..16ab14907055
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_002_pos.ksh
@@ -0,0 +1,59 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# import pools of all versions - zpool upgrade on each pools works
+#
+# STRATEGY:
+# 1. Execute the command with several invalid options
+# 2. Verify a 0 exit status for each
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_upgraded_pool $config
+}
+
+log_assert "Import pools of all versions - zpool upgrade on each pool works"
+log_onexit cleanup
+
+for config in $CONFIGS; do
+ create_old_pool $config
+ check_upgrade $config
+ destroy_upgraded_pool $config
+done
+
+log_pass "Import pools of all versions - zpool upgrade on each pool works"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_003_pos.ksh
new file mode 100755
index 000000000000..0ac3470dedfe
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_003_pos.ksh
@@ -0,0 +1,59 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# Upgrading a pool that has already been upgraded succeeds.
+#
+# STRATEGY:
+# 1. Upgrade a pool, then try to upgrade it again
+# 2. Verify a 0 exit status
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_upgraded_pool 1
+}
+
+log_assert "Upgrading a pool that has already been upgraded succeeds"
+log_onexit cleanup
+
+# Create a version 1 pool
+create_old_pool 1
+check_upgrade 1
+check_upgrade 1
+destroy_upgraded_pool 1
+
+log_pass "Upgrading a pool that has already been upgraded succeeds"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_004_pos.ksh
new file mode 100755
index 000000000000..0e278c81ccb4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_004_pos.ksh
@@ -0,0 +1,83 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# zpool upgrade -a works
+#
+# STRATEGY:
+# 1. Create all upgradable pools for this system, then upgrade -a
+# 2. Verify a 0 exit status
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ for config in $CONFIGS; do
+ destroy_upgraded_pool $config
+ done
+}
+
+log_assert "zpool upgrade -a works"
+log_onexit cleanup
+
+TEST_POOLS=
+# Now build all of our pools
+for config in $CONFIGS; do
+ typeset -n pool_name=ZPOOL_VERSION_${config}_NAME
+
+ TEST_POOLS="$TEST_POOLS $pool_name"
+ create_old_pool $config
+ check_pool $pool_name pre > /dev/null
+done
+
+# upgrade them all at once
+export __ZFS_POOL_RESTRICT="$TEST_POOLS"
+log_must zpool upgrade -a
+unset __ZFS_POOL_RESTRICT
+
+# verify their contents then destroy them
+for config in $CONFIGS ; do
+ typeset -n pool_name=ZPOOL_VERSION_${config}_NAME
+
+ check_pool $pool_name post > /dev/null
+ log_must diff $TEST_BASE_DIR/pool-checksums.$pool_name.pre \
+ $TEST_BASE_DIR/pool-checksums.$pool_name.post
+ rm $TEST_BASE_DIR/pool-checksums.$pool_name.pre \
+ $TEST_BASE_DIR/pool-checksums.$pool_name.post
+ destroy_upgraded_pool $config
+done
+
+log_pass "zpool upgrade -a works"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_005_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_005_neg.ksh
new file mode 100755
index 000000000000..b294af06cf46
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_005_neg.ksh
@@ -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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# Variations of upgrade -v print usage message, return with non-zero status
+#
+# STRATEGY:
+# 1. Execute the command with several invalid options
+# 2. Verify a 0 exit status for each
+#
+
+verify_runnable "global"
+
+log_assert "Variations of upgrade -v print usage message," \
+ "return with non-zero status"
+
+for arg in "/tmp" "-?" "-va" "-v fakepool" "-a fakepool" ; do
+ log_mustnot zpool upgrade $arg
+done
+
+log_pass "Variations of upgrade -v print usage message," \
+ "return with non-zero status"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_006_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_006_neg.ksh
new file mode 100755
index 000000000000..4c16f81082ca
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_006_neg.ksh
@@ -0,0 +1,57 @@
+#!/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# Attempting to upgrade a non-existent pool will return an error
+#
+# STRATEGY:
+# 1. Compose non-existent pool name, try to upgrade it
+# 2. Verify non-zero exit status
+#
+
+log_assert "Attempting to upgrade a non-existent pool will return an error"
+
+NO_POOL=notapool
+
+while true ; do
+ if poolexists $NO_POOL ; then
+ NO_POOL="${NO_POOL}x"
+ else
+ log_mustnot zpool upgrade $NO_POOL
+ break
+ fi
+done
+
+log_pass "Attempting to upgrade a non-existent pool will return an error"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_007_pos.ksh
new file mode 100755
index 000000000000..696c8c66cc1c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_007_pos.ksh
@@ -0,0 +1,70 @@
+#!/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_upgrade/zfs_upgrade.kshlib
+
+#
+# DESCRIPTION:
+# import pools of all versions - verify the following operation not break.
+# * zfs create -o version=<vers> <filesystem>
+# * zfs upgrade [-V vers] <filesystem>
+# * zfs set version=<vers> <filesystem>
+#
+# STRATEGY:
+# 1. Import pools of all versions
+# 2. Setup a test environment over the old pools.
+# 3. Verify the commands related to 'zfs upgrade' succeed as expected.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_upgraded_pool $config
+}
+
+POOL_CONFIGS="1raidz 1mirror 2raidz 2mirror 3raidz 3mirror"
+
+log_assert "Import pools of all versions - 'zfs upgrade' on each pool works"
+log_onexit cleanup
+
+# $CONFIGS gets set in the .cfg script
+for config in $POOL_CONFIGS; do
+ typeset -n pool_name=ZPOOL_VERSION_${config}_NAME
+
+ create_old_pool $config
+ default_check_zfs_upgrade $pool_name
+ destroy_upgraded_pool $config
+done
+
+log_pass "Import pools of all versions - 'zfs upgrade' on each pool works"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_008_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_008_pos.ksh
new file mode 100755
index 000000000000..d930919652bf
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_008_pos.ksh
@@ -0,0 +1,80 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
+
+#
+# DESCRIPTION:
+#
+# zpool upgrade should be able to upgrade pools to a given version using -V
+#
+# STRATEGY:
+# 1. For all versions pools that can be upgraded on a given OS version
+# (latest pool version - 1)
+# 2. Pick a version that's a random number, greater than the version
+# we're running.
+# 3. Attempt to upgrade that pool to the given version
+# 4. Check the pool was upgraded correctly.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_upgraded_pool $ver_old
+}
+
+log_assert "zpool upgrade should be able to upgrade pools to a given version" \
+ "using -V"
+
+log_onexit cleanup
+
+# We're just using the single disk version of the pool, which should be
+# enough to determine if upgrade works correctly. Also set a MAX_VER
+# variable, which specifies the highest version that we should expect
+# a zpool upgrade operation to succeed from.
+VERSIONS="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
+MAX_VER=15
+
+for ver_old in $VERSIONS; do
+ typeset -n pool_name=ZPOOL_VERSION_${ver_old}_NAME
+ typeset -i ver_new=$(random_int_between $ver_old $MAX_VER)
+
+ create_old_pool $ver_old
+ log_must zpool upgrade -V $ver_new $pool_name > /dev/null
+ check_poolversion $pool_name $ver_new
+ destroy_upgraded_pool $ver_old
+done
+
+log_pass "zpool upgrade should be able to upgrade pools to a given version" \
+ "using -V"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_009_neg.ksh
new file mode 100755
index 000000000000..22ffda2114a5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/zpool_upgrade_009_neg.ksh
@@ -0,0 +1,66 @@
+#!/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
+
+#
+# DESCRIPTION:
+#
+# zpool upgrade -V shouldn't be able to upgrade a pool to an unknown version
+#
+# STRATEGY:
+# 1. Take an existing pool
+# 2. Attempt to upgrade it to an unknown version
+# 3. Verify that the upgrade failed, and the pool version was still the original
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_upgraded_pool $config
+}
+
+log_assert "zpool upgrade -V shouldn't be able to upgrade a pool to" \
+ "unknown version"
+
+typeset -i config=2
+typeset -n pool_name=ZPOOL_VERSION_${config}_NAME
+
+create_old_pool $config
+log_mustnot zpool upgrade -V 999 $pool_name
+log_mustnot zpool upgrade -V 999
+check_poolversion $pool_name $config
+destroy_upgraded_pool $config
+
+log_pass "zpool upgrade -V shouldn't be able to upgrade a pool to" \
+ "unknown version"
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/Makefile.am
new file mode 100644
index 000000000000..45ab8e3d4f18
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/Makefile.am
@@ -0,0 +1,22 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_wait
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_wait_discard.ksh \
+ zpool_wait_freeing.ksh \
+ zpool_wait_initialize_basic.ksh \
+ zpool_wait_initialize_cancel.ksh \
+ zpool_wait_initialize_flag.ksh \
+ zpool_wait_multiple.ksh \
+ zpool_wait_no_activity.ksh \
+ zpool_wait_remove.ksh \
+ zpool_wait_remove_cancel.ksh \
+ zpool_wait_trim_basic.ksh \
+ zpool_wait_trim_cancel.ksh \
+ zpool_wait_trim_flag.ksh \
+ zpool_wait_usage.ksh
+
+dist_pkgdata_DATA = \
+ zpool_wait.kshlib
+
+SUBDIRS = scan
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/cleanup.ksh
new file mode 100755
index 000000000000..456d2d0c2ddb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/cleanup.ksh
@@ -0,0 +1,20 @@
+#!/bin/ksh -p
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/Makefile.am
new file mode 100644
index 000000000000..451d83a79aa6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/Makefile.am
@@ -0,0 +1,11 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zpool_wait/scan
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_wait_replace.ksh \
+ zpool_wait_replace_cancel.ksh \
+ zpool_wait_rebuild.ksh \
+ zpool_wait_resilver.ksh \
+ zpool_wait_scrub_basic.ksh \
+ zpool_wait_scrub_cancel.ksh \
+ zpool_wait_scrub_flag.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/cleanup.ksh
new file mode 100755
index 000000000000..456d2d0c2ddb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/cleanup.ksh
@@ -0,0 +1,20 @@
+#!/bin/ksh -p
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/setup.ksh
new file mode 100755
index 000000000000..8a6a1a25b1e6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/setup.ksh
@@ -0,0 +1,32 @@
+#!/bin/ksh -p
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+verify_runnable "global"
+verify_disk_count $DISKS 3
+
+#
+# Set up a pool for use in the tests that do scrubbing and resilvering. Each
+# test leaves the pool in the same state as when it started, so it is safe to
+# share the same setup.
+#
+log_must zpool create -f $TESTPOOL $DISK1
+log_must dd if=/dev/urandom of="/$TESTPOOL/testfile" bs=1k count=256k
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_rebuild.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_rebuild.ksh
new file mode 100755
index 000000000000..8cd5864597af
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_rebuild.ksh
@@ -0,0 +1,64 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' works when waiting for sequential resilvering to complete.
+#
+# STRATEGY:
+# 1. Attach a device to the pool so that sequential resilvering starts.
+# 2. Start 'zpool wait'.
+# 3. Monitor the waiting process to make sure it returns neither too soon nor
+# too late.
+# 4. Repeat 1-3, except using the '-w' flag with 'zpool attach' instead of using
+# 'zpool wait'.
+#
+
+function cleanup
+{
+ remove_io_delay
+ kill_if_running $pid
+ get_disklist $TESTPOOL | grep $DISK2 >/dev/null && \
+ log_must zpool detach $TESTPOOL $DISK2
+}
+
+typeset -r IN_PROGRESS_CHECK="is_pool_resilvering $TESTPOOL"
+typeset pid
+
+log_onexit cleanup
+
+add_io_delay $TESTPOOL
+
+# Test 'zpool wait -t resilver'
+log_must zpool attach -s $TESTPOOL $DISK1 $DISK2
+log_bkgrnd zpool wait -t resilver $TESTPOOL
+pid=$!
+check_while_waiting $pid "$IN_PROGRESS_CHECK"
+
+log_must zpool detach $TESTPOOL $DISK2
+
+# Test 'zpool attach -w'
+log_bkgrnd zpool attach -sw $TESTPOOL $DISK1 $DISK2
+pid=$!
+while ! is_pool_resilvering $TESTPOOL && proc_exists $pid; do
+ log_must sleep .5
+done
+check_while_waiting $pid "$IN_PROGRESS_CHECK"
+
+log_pass "'zpool wait -t resilver' and 'zpool attach -w' work."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_replace.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_replace.ksh
new file mode 100755
index 000000000000..06df7b51cff9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_replace.ksh
@@ -0,0 +1,71 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' works when a replacing disks.
+#
+# STRATEGY:
+# 1. Attach a disk to pool to form two-way mirror.
+# 2. Start a replacement of the new disk.
+# 3. Start 'zpool wait'.
+# 4. Monitor the waiting process to make sure it returns neither too soon nor
+# too late.
+# 5. Repeat 2-4, except using the '-w' flag with 'zpool replace' instead of
+# using 'zpool wait'.
+#
+
+function cleanup
+{
+ remove_io_delay
+ kill_if_running $pid
+ get_disklist $TESTPOOL | grep $DISK2 >/dev/null && \
+ log_must zpool detach $TESTPOOL $DISK2
+ get_disklist $TESTPOOL | grep $DISK3 >/dev/null && \
+ log_must zpool detach $TESTPOOL $DISK3
+}
+
+function in_progress
+{
+ zpool status $TESTPOOL | grep 'replacing-' >/dev/null
+}
+
+typeset pid
+
+log_onexit cleanup
+
+log_must zpool attach -w $TESTPOOL $DISK1 $DISK2
+
+add_io_delay $TESTPOOL
+
+# Test 'zpool wait -t replace'
+log_must zpool replace $TESTPOOL $DISK2 $DISK3
+log_bkgrnd zpool wait -t replace $TESTPOOL
+pid=$!
+check_while_waiting $pid in_progress
+
+# Test 'zpool replace -w'
+log_bkgrnd zpool replace -w $TESTPOOL $DISK3 $DISK2
+pid=$!
+while ! is_pool_resilvering $TESTPOOL && proc_exists $pid; do
+ log_must sleep .5
+done
+check_while_waiting $pid in_progress
+
+log_pass "'zpool wait -t replace' and 'zpool replace -w' work."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_replace_cancel.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_replace_cancel.ksh
new file mode 100755
index 000000000000..f135de4bc774
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_replace_cancel.ksh
@@ -0,0 +1,64 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' works when a replacing disk is detached before the replacement
+# completes.
+#
+# STRATEGY:
+# 1. Attach a disk to pool to form two-way mirror.
+# 2. Modify tunable so that resilver won't complete while test is running.
+# 3. Start a replacement of the new disk.
+# 4. Start a process that waits for the replace.
+# 5. Wait a few seconds and then check that the wait process is actually
+# waiting.
+# 6. Cancel the replacement by detaching the replacing disk.
+# 7. Check that the wait process returns reasonably promptly.
+#
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+ kill_if_running $pid
+ get_disklist $TESTPOOL | grep $DISK2 >/dev/null && \
+ log_must zpool detach $TESTPOOL $DISK2
+ get_disklist $TESTPOOL | grep $DISK3 >/dev/null && \
+ log_must zpool detach $TESTPOOL $DISK3
+}
+
+typeset pid
+
+log_onexit cleanup
+
+log_must zpool attach -w $TESTPOOL $DISK1 $DISK2
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+
+log_must zpool replace $TESTPOOL $DISK2 $DISK3
+log_bkgrnd zpool wait -t replace $TESTPOOL
+pid=$!
+
+log_must sleep 3
+proc_must_exist $pid
+
+log_must zpool detach $TESTPOOL $DISK3
+bkgrnd_proc_succeeded $pid
+
+log_pass "'zpool wait -t replace' returns when replacing disk is detached."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_resilver.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_resilver.ksh
new file mode 100755
index 000000000000..a938901f7621
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_resilver.ksh
@@ -0,0 +1,64 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' works when waiting for resilvering to complete.
+#
+# STRATEGY:
+# 1. Attach a device to the pool so that resilvering starts.
+# 2. Start 'zpool wait'.
+# 3. Monitor the waiting process to make sure it returns neither too soon nor
+# too late.
+# 4. Repeat 1-3, except using the '-w' flag with 'zpool attach' instead of using
+# 'zpool wait'.
+#
+
+function cleanup
+{
+ remove_io_delay
+ kill_if_running $pid
+ get_disklist $TESTPOOL | grep $DISK2 >/dev/null && \
+ log_must zpool detach $TESTPOOL $DISK2
+}
+
+typeset -r IN_PROGRESS_CHECK="is_pool_resilvering $TESTPOOL"
+typeset pid
+
+log_onexit cleanup
+
+add_io_delay $TESTPOOL
+
+# Test 'zpool wait -t resilver'
+log_must zpool attach $TESTPOOL $DISK1 $DISK2
+log_bkgrnd zpool wait -t resilver $TESTPOOL
+pid=$!
+check_while_waiting $pid "$IN_PROGRESS_CHECK"
+
+log_must zpool detach $TESTPOOL $DISK2
+
+# Test 'zpool attach -w'
+log_bkgrnd zpool attach -w $TESTPOOL $DISK1 $DISK2
+pid=$!
+while ! is_pool_resilvering $TESTPOOL && proc_exists $pid; do
+ log_must sleep .5
+done
+check_while_waiting $pid "$IN_PROGRESS_CHECK"
+
+log_pass "'zpool wait -t resilver' and 'zpool attach -w' work."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_scrub_basic.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_scrub_basic.ksh
new file mode 100755
index 000000000000..d4bb17081700
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_scrub_basic.ksh
@@ -0,0 +1,49 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' works when waiting for a scrub to complete.
+#
+# STRATEGY:
+# 1. Start a scrub.
+# 2. Start 'zpool wait -t scrub'.
+# 3. Monitor the waiting process to make sure it returns neither too soon nor
+# too late.
+#
+
+function cleanup
+{
+ remove_io_delay
+ kill_if_running $pid
+}
+
+typeset pid
+
+log_onexit cleanup
+
+# Slow down scrub so that we actually have something to wait for.
+add_io_delay $TESTPOOL
+
+log_must zpool scrub $TESTPOOL
+log_bkgrnd zpool wait -t scrub $TESTPOOL
+pid=$!
+check_while_waiting $pid "is_pool_scrubbing $TESTPOOL"
+
+log_pass "'zpool wait -t scrub' works."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_scrub_cancel.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_scrub_cancel.ksh
new file mode 100755
index 000000000000..7adb3b2b82fa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_scrub_cancel.ksh
@@ -0,0 +1,66 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' works when a scrub is paused or canceled.
+#
+# STRATEGY:
+# 1. Modify tunable so that scrubs won't complete while test is running.
+# 2. Start a scrub.
+# 3. Start a process that waits for the scrub.
+# 4. Wait a few seconds and then check that the wait process is actually
+# waiting.
+# 5. Pause the scrub.
+# 6. Check that the wait process returns reasonably promptly.
+# 7. Repeat 2-6, except stop the scrub instead of pausing it.
+#
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+ kill_if_running $pid
+ is_pool_scrubbing $TESTPOOL && log_must zpool scrub -s $TESTPOOL
+}
+
+function do_test
+{
+ typeset stop_cmd=$1
+
+ log_must zpool scrub $TESTPOOL
+ log_bkgrnd zpool wait -t scrub $TESTPOOL
+ pid=$!
+
+ log_must sleep 3
+ proc_must_exist $pid
+
+ log_must eval "$stop_cmd"
+ bkgrnd_proc_succeeded $pid
+}
+
+typeset pid
+
+log_onexit cleanup
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+
+do_test "zpool scrub -p $TESTPOOL"
+do_test "zpool scrub -s $TESTPOOL"
+
+log_pass "'zpool wait -t scrub' works when scrub is canceled."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_scrub_flag.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_scrub_flag.ksh
new file mode 100755
index 000000000000..aac62cf460db
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/scan/zpool_wait_scrub_flag.ksh
@@ -0,0 +1,52 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool scrub -w' waits while scrub is in progress.
+#
+# STRATEGY:
+# 1. Start a scrub with the -w flag.
+# 2. Wait a few seconds and then check that the wait process is actually
+# waiting.
+# 3. Stop the scrub, make sure that the command returns reasonably promptly.
+#
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+ kill_if_running $pid
+}
+
+typeset pid
+
+log_onexit cleanup
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+
+log_bkgrnd zpool scrub -w $TESTPOOL
+pid=$!
+
+log_must sleep 3
+proc_must_exist $pid
+
+log_must zpool scrub -s $TESTPOOL
+bkgrnd_proc_succeeded $pid
+
+log_pass "'zpool scrub -w' works."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/setup.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/setup.ksh
new file mode 100755
index 000000000000..5a9af18464a6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/setup.ksh
@@ -0,0 +1,23 @@
+#!/bin/ksh -p
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+verify_runnable "global"
+
+verify_disk_count $DISKS 3
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
new file mode 100644
index 000000000000..b413f6e9f98d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
@@ -0,0 +1,124 @@
+#!/bin/ksh
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+typeset -a disk_array=($(find_disks $DISKS))
+
+typeset -r DISK1=${disk_array[0]}
+typeset -r DISK2=${disk_array[1]}
+typeset -r DISK3=${disk_array[2]}
+
+#
+# When the condition it is waiting for becomes true, 'zpool wait' should return
+# promptly. We want to enforce this, but any check will be racey because it will
+# take some small but indeterminate amount of time for the waiting thread to be
+# woken up and for the process to exit.
+#
+# To deal with this, we provide a grace period after the condition becomes true
+# during which 'zpool wait' can exit. If it hasn't exited by the time the grace
+# period expires we assume something is wrong and fail the test. While there is
+# no value that can really be correct, the idea is we choose something large
+# enough that it shouldn't cause issues in practice.
+#
+typeset -r WAIT_EXIT_GRACE=2.0
+
+function add_io_delay # pool
+{
+ for disk in $(get_disklist $1); do
+ log_must zinject -d $disk -D20:1 $1
+ done
+}
+
+function remove_io_delay
+{
+ log_must zinject -c all
+}
+
+function proc_exists # pid
+{
+ ps -p $1 >/dev/null
+}
+
+function proc_must_exist # pid
+{
+ proc_exists $1 || log_fail "zpool process exited too soon"
+}
+
+function proc_must_not_exist # pid
+{
+ proc_exists $1 && log_fail "zpool process took too long to exit"
+}
+
+function get_time
+{
+ date +'%H:%M:%S'
+}
+
+function kill_if_running
+{
+ typeset pid=$1
+ [[ $pid ]] && proc_exists $pid && log_must kill -s TERM $pid
+}
+
+# Log a command and then start it running in the background
+function log_bkgrnd
+{
+ log_note "$(get_time) Starting cmd in background '$@'"
+ "$@" &
+}
+
+# Check that a background process has completed and exited with a status of 0
+function bkgrnd_proc_succeeded
+{
+ typeset pid=$1
+
+ log_must sleep $WAIT_EXIT_GRACE
+
+ proc_must_not_exist $pid
+ wait $pid || log_fail "zpool process exited with status $?"
+ log_note "$(get_time) wait completed successfully"
+}
+
+#
+# Check that 'zpool wait' returns reasonably promptly after the condition
+# waited for becomes true, and not before.
+#
+function check_while_waiting
+{
+ # The pid of the waiting process
+ typeset wait_proc_pid=$1
+ # A check that should be true while the activity is in progress
+ typeset activity_check=$2
+
+ log_note "$(get_time) waiting for process $wait_proc_pid using" \
+ "activity check '$activity_check'"
+ while proc_exists $wait_proc_pid && eval "$activity_check"; do
+ log_must sleep .5
+ done
+
+ #
+ # If the activity being waited on is still in progress, then zpool wait
+ # exited too soon.
+ #
+ log_mustnot eval "$activity_check"
+
+ bkgrnd_proc_succeeded $wait_proc_pid
+}
+
+# Whether any vdev in the given pool is initializing
+function is_vdev_initializing # pool
+{
+ zpool status -i "$1" | grep 'initialized, started' >/dev/null
+}
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_discard.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_discard.ksh
new file mode 100755
index 000000000000..8d5747e09047
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_discard.ksh
@@ -0,0 +1,87 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' works when waiting for checkpoint discard to complete.
+#
+# STRATEGY:
+# 1. Create a pool.
+# 2. Add some data to the pool.
+# 3. Checkpoint the pool and delete the data so that the space is unique to the
+# checkpoint.
+# 4. Discard the checkpoint using the '-w' flag.
+# 5. Monitor the waiting process to make sure it returns neither too soon nor
+# too late.
+# 6. Repeat 2-5, but using 'zpool wait' instead of the '-w' flag.
+#
+
+function cleanup
+{
+ log_must zinject -c all
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ kill_if_running $pid
+
+ [[ $default_mem_limit ]] && log_must set_tunable64 \
+ SPA_DISCARD_MEMORY_LIMIT $default_mem_limit
+}
+
+function do_test
+{
+ typeset use_wait_flag=$1
+
+ log_must dd if=/dev/urandom of="$TESTFILE" bs=128k count=1k
+ log_must zpool checkpoint $TESTPOOL
+
+ # Make sure bulk of space is unique to checkpoint
+ log_must rm "$TESTFILE"
+
+ log_must zinject -d $DISK1 -D20:1 $TESTPOOL
+
+ if $use_wait_flag; then
+ log_bkgrnd zpool checkpoint -dw $TESTPOOL
+ pid=$!
+
+ while ! is_pool_discarding $TESTPOOL && proc_exists $pid; do
+ log_must sleep .5
+ done
+ else
+ log_must zpool checkpoint -d $TESTPOOL
+ log_bkgrnd zpool wait -t discard $TESTPOOL
+ pid=$!
+ fi
+
+ check_while_waiting $pid "is_pool_discarding $TESTPOOL"
+ log_must zinject -c all
+}
+
+typeset -r TESTFILE="/$TESTPOOL/testfile"
+typeset pid default_mem_limit
+
+log_onexit cleanup
+
+default_mem_limit=$(get_tunable SPA_DISCARD_MEMORY_LIMIT)
+log_must set_tunable64 SPA_DISCARD_MEMORY_LIMIT 32
+
+log_must zpool create $TESTPOOL $DISK1
+
+do_test true
+do_test false
+
+log_pass "'zpool wait -t discard' and 'zpool checkpoint -dw' work."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_freeing.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_freeing.ksh
new file mode 100755
index 000000000000..7f5a9e6a8d6c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_freeing.ksh
@@ -0,0 +1,112 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' works when waiting for background freeing to complete.
+#
+# STRATEGY:
+# 1. Create a pool.
+# 2. Modify tunables to make sure freeing is slow enough to observe.
+# 3. Create a file system with some data.
+# 4. Destroy the file system and call 'zpool wait'.
+# 5. Monitor the waiting process to make sure it returns neither too soon nor
+# too late.
+# 6. Repeat 3-5, except destroy a snapshot instead of a filesystem.
+# 7. Repeat 3-5, except destroy a clone.
+#
+
+function cleanup
+{
+ log_must set_tunable64 ASYNC_BLOCK_MAX_BLOCKS $default_async_block_max_blocks
+ log_must set_tunable64 LIVELIST_MAX_ENTRIES $default_max_livelist_entries
+ log_must set_tunable64 LIVELIST_MIN_PERCENT_SHARED $default_min_pct_shared
+
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ kill_if_running $pid
+}
+
+function test_wait
+{
+ log_bkgrnd zpool wait -t free $TESTPOOL
+ pid=$!
+ check_while_waiting $pid '[[ $(get_pool_prop freeing $TESTPOOL) != "0" ]]'
+}
+
+typeset -r FS="$TESTPOOL/$TESTFS1"
+typeset -r SNAP="$FS@snap1"
+typeset -r CLONE="$TESTPOOL/clone"
+typeset pid default_max_livelist_entries default_min_pct_shared
+typeset default_async_block_max_blocks
+
+log_onexit cleanup
+
+log_must zpool create $TESTPOOL $DISK1
+
+#
+# Limit the number of blocks that can be freed in a single txg. This slows down
+# freeing so that we actually have something to wait for.
+#
+default_async_block_max_blocks=$(get_tunable ASYNC_BLOCK_MAX_BLOCKS)
+log_must set_tunable64 ASYNC_BLOCK_MAX_BLOCKS 8
+#
+# Space from clones gets freed one livelist per txg instead of being controlled
+# by zfs_async_block_max_blocks. Limit the rate at which space is freed by
+# limiting the size of livelists so that we end up with a number of them.
+#
+default_max_livelist_entries=$(get_tunable LIVELIST_MAX_ENTRIES)
+log_must set_tunable64 LIVELIST_MAX_ENTRIES 16
+# Don't disable livelists, no matter how much clone diverges from snapshot
+default_min_pct_shared=$(get_tunable LIVELIST_MIN_PERCENT_SHARED)
+log_must set_tunable64 LIVELIST_MIN_PERCENT_SHARED -1
+
+#
+# Test waiting for space from destroyed filesystem to be freed
+#
+log_must zfs create "$FS"
+log_must dd if=/dev/zero of="/$FS/testfile" bs=1M count=128
+log_must zfs destroy "$FS"
+test_wait
+
+#
+# Test waiting for space from destroyed snapshot to be freed
+#
+log_must zfs create "$FS"
+log_must dd if=/dev/zero of="/$FS/testfile" bs=1M count=128
+log_must zfs snapshot "$SNAP"
+# Make sure bulk of space is unique to snapshot
+log_must rm "/$FS/testfile"
+log_must zfs destroy "$SNAP"
+test_wait
+
+#
+# Test waiting for space from destroyed clone to be freed
+#
+log_must zfs snapshot "$SNAP"
+log_must zfs clone "$SNAP" "$CLONE"
+# Add some data to the clone
+for i in {1..50}; do
+ log_must dd if=/dev/urandom of="/$CLONE/testfile$i" bs=1k count=512
+ # Force each new file to be tracked by a new livelist
+ log_must zpool sync $TESTPOOL
+done
+log_must zfs destroy "$CLONE"
+test_wait
+
+log_pass "'zpool wait -t freeing' works."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_initialize_basic.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_initialize_basic.ksh
new file mode 100755
index 000000000000..924ae5f0d86d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_initialize_basic.ksh
@@ -0,0 +1,63 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' works when waiting for devices to complete initializing
+#
+# STRATEGY:
+# 1. Create a pool.
+# 2. Modify a tunable to make sure initializing is slow enough to observe.
+# 3. Start initializing the vdev in the pool.
+# 4. Start 'zpool wait'.
+# 5. Monitor the waiting process to make sure it returns neither too soon nor
+# too late.
+#
+
+function cleanup
+{
+ kill_if_running $pid
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+
+ [[ -d "$TESTDIR" ]] && log_must rm -r "$TESTDIR"
+
+ [[ "$default_chunk_sz" ]] && \
+ log_must set_tunable64 INITIALIZE_CHUNK_SIZE $default_chunk_sz
+}
+
+typeset -r FILE_VDEV="$TESTDIR/file_vdev"
+typeset pid default_chunk_sz
+
+log_onexit cleanup
+
+default_chunk_sz=$(get_tunable INITIALIZE_CHUNK_SIZE)
+log_must set_tunable64 INITIALIZE_CHUNK_SIZE 2048
+
+log_must mkdir "$TESTDIR"
+log_must mkfile 256M "$FILE_VDEV"
+log_must zpool create -f $TESTPOOL "$FILE_VDEV"
+
+log_must zpool initialize $TESTPOOL "$FILE_VDEV"
+
+log_bkgrnd zpool wait -t initialize $TESTPOOL
+pid=$!
+
+check_while_waiting $pid "is_vdev_initializing $TESTPOOL"
+
+log_pass "'zpool wait -t initialize' works."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_initialize_cancel.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_initialize_cancel.ksh
new file mode 100755
index 000000000000..8b19ee62aad3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_initialize_cancel.ksh
@@ -0,0 +1,77 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' works when an initialization operation is canceled.
+#
+# STRATEGY:
+# 1. Create a pool.
+# 2. Modify a tunable to make sure initializing is slow enough that it won't
+# complete before the test finishes.
+# 3. Start initializing the vdev in the pool.
+# 4. Start 'zpool wait'.
+# 5. Wait a few seconds and then check that the wait process is actually
+# waiting.
+# 6. Cancel the initialization of the device.
+# 7. Check that the wait process returns reasonably promptly.
+# 8. Repeat 3-7, except pause the initialization instead of canceling it.
+#
+
+function cleanup
+{
+ kill_if_running $pid
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+
+ [[ "$default_chunk_sz" ]] &&
+ log_must set_tunable64 INITIALIZE_CHUNK_SIZE $default_chunk_sz
+}
+
+function do_test
+{
+ typeset stop_cmd=$1
+
+ log_must zpool initialize $TESTPOOL $DISK1
+
+ log_bkgrnd zpool wait -t initialize $TESTPOOL
+ pid=$!
+
+ # Make sure that we are really waiting
+ log_must sleep 3
+ proc_must_exist $pid
+
+ # Stop initialization and make sure process returns
+ log_must eval "$stop_cmd"
+ bkgrnd_proc_succeeded $pid
+}
+
+typeset pid default_chunk_sz
+
+log_onexit cleanup
+
+# Make sure the initialization takes a while
+default_chunk_sz=$(get_tunable INITIALIZE_CHUNK_SIZE)
+log_must set_tunable64 INITIALIZE_CHUNK_SIZE 512
+
+log_must zpool create $TESTPOOL $DISK1
+
+do_test "zpool initialize -c $TESTPOOL $DISK1"
+do_test "zpool initialize -s $TESTPOOL $DISK1"
+
+log_pass "'zpool wait' works when initialization is stopped before completion."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_initialize_flag.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_initialize_flag.ksh
new file mode 100755
index 000000000000..8c8c45a51eec
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_initialize_flag.ksh
@@ -0,0 +1,88 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# -w flag for 'zpool initialize' waits for the completion of all and only those
+# initializations kicked off by that invocation.
+#
+# STRATEGY:
+# 1. Create a pool with 3 disks.
+# 2. Start initializing disks 1 and 2 with one invocation of
+# 'zpool initialize -w'
+# 3. Start initializing disk 3 with a second invocation of 'zpool initialize -w'
+# 4. Cancel the initialization of disk 1. Check that neither waiting process
+# exits.
+# 5. Cancel the initialization of disk 3. Check that only the second waiting
+# process exits.
+# 6. Cancel the initialization of disk 2. Check that the first waiting process
+# exits.
+#
+
+function cleanup
+{
+ kill_if_running $init12_pid
+ kill_if_running $init3_pid
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+
+ [[ "$default_chunk_sz" ]] &&
+ log_must set_tunable64 INITIALIZE_CHUNK_SIZE $default_chunk_sz
+}
+
+typeset init12_pid init3_pid default_chunk_sz
+
+log_onexit cleanup
+
+log_must zpool create -f $TESTPOOL $DISK1 $DISK2 $DISK3
+
+# Make sure the initialization takes a while
+default_chunk_sz=$(get_tunable INITIALIZE_CHUNK_SIZE)
+log_must set_tunable64 INITIALIZE_CHUNK_SIZE 512
+
+log_bkgrnd zpool initialize -w $TESTPOOL $DISK1 $DISK2
+init12_pid=$!
+log_bkgrnd zpool initialize -w $TESTPOOL $DISK3
+init3_pid=$!
+
+# Make sure that we are really waiting
+log_must sleep 3
+proc_must_exist $init12_pid
+proc_must_exist $init3_pid
+
+#
+# Cancel initialization of one of disks started by init12, make sure neither
+# process exits
+#
+log_must zpool initialize -c $TESTPOOL $DISK1
+proc_must_exist $init12_pid
+proc_must_exist $init3_pid
+
+#
+# Cancel initialization started by init3, make sure that process exits, but
+# init12 doesn't
+#
+log_must zpool initialize -c $TESTPOOL $DISK3
+proc_must_exist $init12_pid
+bkgrnd_proc_succeeded $init3_pid
+
+# Cancel last initialization started by init12, make sure it returns.
+log_must zpool initialize -c $TESTPOOL $DISK2
+bkgrnd_proc_succeeded $init12_pid
+
+log_pass "'zpool initialize -w' works."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_multiple.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_multiple.ksh
new file mode 100755
index 000000000000..a8107b94eb3b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_multiple.ksh
@@ -0,0 +1,83 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' works when waiting for multiple activities.
+#
+# STRATEGY:
+# 1. Create a pool with some data.
+# 2. Alterate running two different activities (scrub and initialize),
+# making sure that they overlap such that one of the two is always
+# running.
+# 3. Wait for both activities with a single invocation of zpool wait.
+# 4. Check that zpool wait doesn't return until both activities have
+# stopped.
+#
+
+function cleanup
+{
+ kill_if_running $pid
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+
+ [[ "$default_chunk_sz" ]] && log_must set_tunable64 \
+ INITIALIZE_CHUNK_SIZE $default_chunk_sz
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+}
+
+typeset pid default_chunk_sz
+
+log_onexit cleanup
+
+log_must zpool create -f $TESTPOOL $DISK1
+log_must dd if=/dev/urandom of="/$TESTPOOL/testfile" bs=64k count=1k
+
+default_chunk_sz=$(get_tunable INITIALIZE_CHUNK_SIZE)
+log_must set_tunable64 INITIALIZE_CHUNK_SIZE 512
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+
+log_must zpool scrub $TESTPOOL
+
+log_bkgrnd zpool wait -t scrub,initialize $TESTPOOL
+pid=$!
+
+log_must sleep 2
+
+log_must zpool initialize $TESTPOOL $DISK1
+log_must zpool scrub -s $TESTPOOL
+
+log_must sleep 2
+
+log_must zpool scrub $TESTPOOL
+log_must zpool initialize -s $TESTPOOL $DISK1
+
+log_must sleep 2
+
+log_must zpool initialize $TESTPOOL $DISK1
+log_must zpool scrub -s $TESTPOOL
+
+log_must sleep 2
+
+proc_must_exist $pid
+
+# Cancel last activity, zpool wait should return
+log_must zpool initialize -s $TESTPOOL $DISK1
+bkgrnd_proc_succeeded $pid
+
+log_pass "'zpool wait' works when waiting for multiple activities."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_no_activity.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_no_activity.ksh
new file mode 100755
index 000000000000..f4819f37adb7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_no_activity.ksh
@@ -0,0 +1,52 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' returns immediately when there is no activity in progress.
+#
+# STRATEGY:
+# 1. Create an empty pool with no activity
+# 2. Run zpool wait with various activities, make sure it always returns
+# promptly
+#
+
+function cleanup {
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+typeset -r TIMEOUT_SECS=1
+
+log_onexit cleanup
+log_must zpool create $TESTPOOL $DISK1
+
+# Wait for each activity
+typeset activities=(free discard initialize replace remove resilver scrub)
+for activity in ${activities[@]}; do
+ log_must timeout $TIMEOUT_SECS zpool wait -t $activity $TESTPOOL
+done
+
+# Wait for multiple activities at the same time
+log_must timeout $TIMEOUT_SECS zpool wait -t scrub,initialize $TESTPOOL
+log_must timeout $TIMEOUT_SECS zpool wait -t free,remove,discard $TESTPOOL
+
+# Wait for all activities at the same time
+log_must timeout $TIMEOUT_SECS zpool wait $TESTPOOL
+
+log_pass "'zpool wait' returns immediately when no activity is in progress."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_remove.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_remove.ksh
new file mode 100755
index 000000000000..19298d193cd0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_remove.ksh
@@ -0,0 +1,85 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' works when waiting for a device to be removed.
+#
+# STRATEGY:
+# 1. Create a pool with two disks and some data.
+# 2. Modify a tunable to make sure removal doesn't make any progress.
+# 3. Start removing one of the disks.
+# 4. Start 'zpool wait'.
+# 5. Sleep for a few seconds and check that the process is actually waiting.
+# 6. Modify tunable to allow removal to complete.
+# 7. Monitor the waiting process to make sure it returns neither too soon nor
+# too late.
+# 8. Repeat 1-7, except using the '-w' flag for 'zpool remove' instead of using
+# 'zpool wait'.
+#
+
+function cleanup
+{
+ kill_if_running $pid
+ log_must set_tunable32 REMOVAL_SUSPEND_PROGRESS 0
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+function do_test
+{
+ typeset use_flag=$1
+
+ log_must zpool create -f $TESTPOOL $DISK1 $DISK2
+ log_must dd if=/dev/urandom of="/$TESTPOOL/testfile" bs=1k count=16k
+
+ # Start removal, but don't allow it to make any progress at first
+ log_must set_tunable32 REMOVAL_SUSPEND_PROGRESS 1
+
+ if $use_flag; then
+ log_bkgrnd zpool remove -w $TESTPOOL $DISK1
+ pid=$!
+
+ while ! is_pool_removing $TESTPOOL && proc_exists $pid; do
+ log_must sleep .5
+ done
+ else
+ log_must zpool remove $TESTPOOL $DISK1
+ log_bkgrnd zpool wait -t remove $TESTPOOL
+ pid=$!
+ fi
+
+ # Make sure the 'zpool wait' is actually waiting
+ log_must sleep 3
+ proc_must_exist $pid
+
+ # Unpause removal, and wait for it to finish
+ log_must set_tunable32 REMOVAL_SUSPEND_PROGRESS 0
+ check_while_waiting $pid "is_pool_removing $TESTPOOL"
+
+ log_must zpool destroy $TESTPOOL
+}
+
+log_onexit cleanup
+
+typeset pid
+
+do_test true
+do_test false
+
+log_pass "'zpool wait -t remove' and 'zpool remove -w' work."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_remove_cancel.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_remove_cancel.ksh
new file mode 100755
index 000000000000..4373b5777978
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_remove_cancel.ksh
@@ -0,0 +1,62 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' works when device removal is canceled.
+#
+# STRATEGY:
+# 1. Create a pool with two disks and some data.
+# 2. Modify a tunable to make sure removal won't complete while test is running.
+# 3. Start removing one of the disks.
+# 4. Start 'zpool wait'.
+# 5. Sleep for a few seconds and check that the process is actually waiting.
+# 6. Cancel the removal of the device.
+# 7. Check that the wait process returns reasonably promptly.
+#
+
+function cleanup
+{
+ kill_if_running $pid
+ log_must set_tunable32 REMOVAL_SUSPEND_PROGRESS 0
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+typeset pid
+
+log_must zpool create -f $TESTPOOL $DISK1 $DISK2
+
+log_must dd if=/dev/urandom of="/$TESTPOOL/testfile" bs=1k count=16k
+
+# Start removal, but don't allow it to make any progress
+log_must set_tunable32 REMOVAL_SUSPEND_PROGRESS 1
+log_must zpool remove $TESTPOOL $DISK1
+
+log_bkgrnd zpool wait -t remove $TESTPOOL
+pid=$!
+
+log_must sleep 3
+proc_must_exist $pid
+
+log_must zpool remove -s $TESTPOOL
+bkgrnd_proc_succeeded $pid
+
+log_pass "'zpool wait -t remove' works when removal is canceled."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_basic.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_basic.ksh
new file mode 100755
index 000000000000..f047050ea0d2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_basic.ksh
@@ -0,0 +1,68 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' works when waiting for devices to finish being trimmed
+#
+# STRATEGY:
+# 1. Create a pool.
+# 2. Start trimming the vdev in the pool, making sure the rate is slow enough
+# that the trim can be observed.
+# 3. Start 'zpool wait'.
+# 4. Monitor the waiting process to make sure it returns neither too soon nor
+# too late.
+#
+
+function cleanup
+{
+ kill_if_running $pid
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+
+ [[ -d "$TESTDIR" ]] && log_must rm -r "$TESTDIR"
+}
+
+# Check whether any vdevs in given pool are being trimmed
+function trim_in_progress
+{
+ typeset pool="$1"
+ zpool status -t "$pool" | grep "trimmed, started"
+}
+
+if is_freebsd; then
+ log_unsupported "FreeBSD has no hole punching mechanism for the time being."
+fi
+
+typeset -r FILE_VDEV="$TESTDIR/file_vdev"
+typeset pid
+
+log_onexit cleanup
+
+log_must mkdir "$TESTDIR"
+log_must truncate -s 10G "$FILE_VDEV"
+log_must zpool create -f $TESTPOOL "$FILE_VDEV"
+
+log_must zpool trim -r 2G $TESTPOOL "$FILE_VDEV"
+
+log_bkgrnd zpool wait -t trim $TESTPOOL
+pid=$!
+
+check_while_waiting $pid "trim_in_progress $TESTPOOL"
+
+log_pass "'zpool wait -t trim' works."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_cancel.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_cancel.ksh
new file mode 100755
index 000000000000..26e1aa68e644
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_cancel.ksh
@@ -0,0 +1,77 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' works when a trim operation is canceled.
+#
+# STRATEGY:
+# 1. Create a pool.
+# 2. Start trimming the vdev in the pool, setting the rate low enough that the
+# operation won't complete before the test finishes.
+# 3. Start 'zpool wait'.
+# 4. Wait a few seconds and then check that the wait process is actually
+# waiting.
+# 5. Cancel the trim.
+# 6. Check that the wait process returns reasonably promptly.
+# 7. Repeat 3-7, except pause the trim instead of canceling it.
+#
+
+function cleanup
+{
+ kill_if_running $pid
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ [[ -d "$TESTDIR" ]] && log_must rm -r "$TESTDIR"
+}
+
+function do_test
+{
+ typeset stop_cmd=$1
+
+ log_must zpool trim -r 1M $TESTPOOL "$FILE_VDEV"
+
+ log_bkgrnd zpool wait -t trim $TESTPOOL
+ pid=$!
+
+ # Make sure that we are really waiting
+ log_must sleep 3
+ proc_must_exist $pid
+
+ # Stop trimming and make sure process returns
+ log_must eval "$stop_cmd"
+ bkgrnd_proc_succeeded $pid
+}
+
+if is_freebsd; then
+ log_unsupported "FreeBSD has no hole punching mechanism for the time being."
+fi
+
+typeset pid
+typeset -r FILE_VDEV="$TESTDIR/file_vdev1"
+
+log_onexit cleanup
+
+log_must mkdir "$TESTDIR"
+log_must truncate -s 10G "$FILE_VDEV"
+log_must zpool create -f $TESTPOOL "$FILE_VDEV"
+
+do_test "zpool trim -c $TESTPOOL $FILE_VDEV"
+do_test "zpool trim -s $TESTPOOL $FILE_VDEV"
+
+log_pass "'zpool wait' works when trim is stopped before completion."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_flag.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_flag.ksh
new file mode 100755
index 000000000000..effccc1c340f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_flag.ksh
@@ -0,0 +1,88 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# -w flag for 'zpool trim' waits for trimming to complete for all and only those
+# vdevs kicked off by that invocation.
+#
+# STRATEGY:
+# 1. Create a pool with 3 vdevs.
+# 2. Start trimming vdevs 1 and 2 with one invocation of 'zpool trim -w'
+# 3. Start trimming vdev 3 with a second invocation of 'zpool trim -w'
+# 4. Cancel the trim of vdev 1. Check that neither waiting process exits.
+# 5. Cancel the trim of vdev 3. Check that only the second waiting process
+# exits.
+# 6. Cancel the trim of vdev 2. Check that the first waiting process exits.
+#
+
+function cleanup
+{
+ kill_if_running $trim12_pid
+ kill_if_running $trim3_pid
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ [[ -d "$TESTDIR" ]] && log_must rm -r "$TESTDIR"
+}
+
+if is_freebsd; then
+ log_unsupported "FreeBSD has no hole punching mechanism for the time being."
+fi
+
+typeset trim12_pid trim3_pid
+typeset -r VDEV1="$TESTDIR/file_vdev1"
+typeset -r VDEV2="$TESTDIR/file_vdev2"
+typeset -r VDEV3="$TESTDIR/file_vdev3"
+
+log_onexit cleanup
+
+log_must mkdir "$TESTDIR"
+log_must truncate -s 10G "$VDEV1" "$VDEV2" "$VDEV3"
+log_must zpool create -f $TESTPOOL "$VDEV1" "$VDEV2" "$VDEV3"
+
+log_bkgrnd zpool trim -r 1M -w $TESTPOOL "$VDEV1" "$VDEV2"
+trim12_pid=$!
+log_bkgrnd zpool trim -r 1M -w $TESTPOOL "$VDEV3"
+trim3_pid=$!
+
+# Make sure that we are really waiting
+log_must sleep 3
+proc_must_exist $trim12_pid
+proc_must_exist $trim3_pid
+
+#
+# Cancel trim of one of disks started by trim12, make sure neither
+# process exits
+#
+log_must zpool trim -c $TESTPOOL "$VDEV1"
+proc_must_exist $trim12_pid
+proc_must_exist $trim3_pid
+
+#
+# Cancel trim started by trim3, make sure that process exits, but
+# trim12 doesn't
+#
+log_must zpool trim -c $TESTPOOL "$VDEV3"
+proc_must_exist $trim12_pid
+bkgrnd_proc_succeeded $trim3_pid
+
+# Cancel last trim started by trim12, make sure it returns.
+log_must zpool trim -c $TESTPOOL "$VDEV2"
+bkgrnd_proc_succeeded $trim12_pid
+
+log_pass "'zpool trim -w' works."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_usage.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_usage.ksh
new file mode 100755
index 000000000000..2d6f897092fe
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_usage.ksh
@@ -0,0 +1,47 @@
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_wait/zpool_wait.kshlib
+
+#
+# DESCRIPTION:
+# 'zpool wait' behaves sensibly when invoked incorrectly.
+#
+# STRATEGY:
+# 1. Invoke 'zpool wait' incorrectly and check that it exits with a non-zero
+# status.
+# 2. Invoke 'zpool wait' with missing or bad arguments and check that it prints
+# some sensible error message.
+#
+
+function cleanup {
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+log_must zpool create $TESTPOOL $DISK1
+
+log_mustnot zpool wait
+
+zpool wait 2>&1 | grep -i usage || \
+ log_fail "Usage message did not contain the word 'usage'."
+zpool wait -t scrub fakepool 2>&1 | grep -i 'no such pool' || \
+ log_fail "Error message did not contain phrase 'no such pool'."
+zpool wait -t foo $TESTPOOL 2>&1 | grep -i 'invalid activity' || \
+ log_fail "Error message did not contain phrase 'invalid activity'."
+
+log_pass "'zpool wait' behaves sensibly when invoked incorrectly."